xpc_uv.c revision 2525789b4694d78df4f001063f042b2b74227d26
194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson/*
294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * This file is subject to the terms and conditions of the GNU General Public
394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * License.  See the file "COPYING" in the main directory of this archive
494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * for more details.
594bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson *
694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
794bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson */
894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson/*
1094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * Cross Partition Communication (XPC) uv-based functions.
1194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson *
1294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson *     Architecture specific implementation of common functions.
1394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson *
1494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson */
1594bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
1694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson#include <linux/kernel.h>
175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#include <linux/mm.h>
185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#include <linux/interrupt.h>
195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#include <linux/delay.h>
205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#include <linux/device.h>
212525789b4694d78df4f001063f042b2b74227d26Dean Nelson#include <linux/err.h>
22261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#include <asm/uv/uv_hub.h>
232525789b4694d78df4f001063f042b2b74227d26Dean Nelson#if defined CONFIG_X86_64
242525789b4694d78df4f001063f042b2b74227d26Dean Nelson#include <asm/uv/bios.h>
252525789b4694d78df4f001063f042b2b74227d26Dean Nelson#include <asm/uv/uv_irq.h>
262525789b4694d78df4f001063f042b2b74227d26Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
272525789b4694d78df4f001063f042b2b74227d26Dean Nelson#include <asm/sn/intr.h>
282525789b4694d78df4f001063f042b2b74227d26Dean Nelson#include <asm/sn/sn_sal.h>
292525789b4694d78df4f001063f042b2b74227d26Dean Nelson#endif
305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#include "../sgi-gru/gru.h"
31261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#include "../sgi-gru/grukservices.h"
3294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson#include "xpc.h"
3394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic atomic64_t xpc_heartbeat_uv;
3533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV);
3633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson#define XPC_ACTIVATE_MSG_SIZE_UV	(1 * GRU_CACHE_LINE_BYTES)
382525789b4694d78df4f001063f042b2b74227d26Dean Nelson#define XPC_ACTIVATE_MQ_SIZE_UV		(4 * XP_MAX_NPARTITIONS_UV * \
392525789b4694d78df4f001063f042b2b74227d26Dean Nelson					 XPC_ACTIVATE_MSG_SIZE_UV)
402525789b4694d78df4f001063f042b2b74227d26Dean Nelson#define XPC_ACTIVATE_IRQ_NAME		"xpc_activate"
415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
422525789b4694d78df4f001063f042b2b74227d26Dean Nelson#define XPC_NOTIFY_MSG_SIZE_UV		(2 * GRU_CACHE_LINE_BYTES)
432525789b4694d78df4f001063f042b2b74227d26Dean Nelson#define XPC_NOTIFY_MQ_SIZE_UV		(4 * XP_MAX_NPARTITIONS_UV * \
442525789b4694d78df4f001063f042b2b74227d26Dean Nelson					 XPC_NOTIFY_MSG_SIZE_UV)
452525789b4694d78df4f001063f042b2b74227d26Dean Nelson#define XPC_NOTIFY_IRQ_NAME		"xpc_notify"
465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
472525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic struct xpc_gru_mq_uv *xpc_activate_mq_uv;
482525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic struct xpc_gru_mq_uv *xpc_notify_mq_uv;
495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int
515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_partitions_sn_uv(void)
525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	short partid;
545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition_uv *part_uv;
555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part_uv = &xpc_partitions[partid].sn.uv;
585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
595b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		spin_lock_init(&part_uv->flags_lock);
605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part_uv->remote_act_state = XPC_P_AS_INACTIVE;
615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
625b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return 0;
635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
652525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic int
662525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
672525789b4694d78df4f001063f042b2b74227d26Dean Nelson{
682525789b4694d78df4f001063f042b2b74227d26Dean Nelson#if defined CONFIG_X86_64
692525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset);
702525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (mq->irq < 0) {
712525789b4694d78df4f001063f042b2b74227d26Dean Nelson		dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
722525789b4694d78df4f001063f042b2b74227d26Dean Nelson			mq->irq);
732525789b4694d78df4f001063f042b2b74227d26Dean Nelson	}
742525789b4694d78df4f001063f042b2b74227d26Dean Nelson
752525789b4694d78df4f001063f042b2b74227d26Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
762525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int mmr_pnode;
772525789b4694d78df4f001063f042b2b74227d26Dean Nelson	unsigned long mmr_value;
782525789b4694d78df4f001063f042b2b74227d26Dean Nelson
792525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0)
802525789b4694d78df4f001063f042b2b74227d26Dean Nelson		mq->irq = SGI_XPC_ACTIVATE;
812525789b4694d78df4f001063f042b2b74227d26Dean Nelson	else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0)
822525789b4694d78df4f001063f042b2b74227d26Dean Nelson		mq->irq = SGI_XPC_NOTIFY;
832525789b4694d78df4f001063f042b2b74227d26Dean Nelson	else
842525789b4694d78df4f001063f042b2b74227d26Dean Nelson		return -EINVAL;
852525789b4694d78df4f001063f042b2b74227d26Dean Nelson
862525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
872525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq;
882525789b4694d78df4f001063f042b2b74227d26Dean Nelson
892525789b4694d78df4f001063f042b2b74227d26Dean Nelson	uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mmr_value);
902525789b4694d78df4f001063f042b2b74227d26Dean Nelson#else
912525789b4694d78df4f001063f042b2b74227d26Dean Nelson	#error not a supported configuration
922525789b4694d78df4f001063f042b2b74227d26Dean Nelson#endif
932525789b4694d78df4f001063f042b2b74227d26Dean Nelson
942525789b4694d78df4f001063f042b2b74227d26Dean Nelson	return 0;
952525789b4694d78df4f001063f042b2b74227d26Dean Nelson}
962525789b4694d78df4f001063f042b2b74227d26Dean Nelson
972525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic void
982525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
992525789b4694d78df4f001063f042b2b74227d26Dean Nelson{
1002525789b4694d78df4f001063f042b2b74227d26Dean Nelson#if defined CONFIG_X86_64
1012525789b4694d78df4f001063f042b2b74227d26Dean Nelson	uv_teardown_irq(mq->irq, mq->mmr_blade, mq->mmr_offset);
1022525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1032525789b4694d78df4f001063f042b2b74227d26Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
1042525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int mmr_pnode;
1052525789b4694d78df4f001063f042b2b74227d26Dean Nelson	unsigned long mmr_value;
1062525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1072525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
1082525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mmr_value = 1UL << 16;
1092525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1102525789b4694d78df4f001063f042b2b74227d26Dean Nelson	uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mmr_value);
1112525789b4694d78df4f001063f042b2b74227d26Dean Nelson#else
1122525789b4694d78df4f001063f042b2b74227d26Dean Nelson	#error not a supported configuration
1132525789b4694d78df4f001063f042b2b74227d26Dean Nelson#endif
1142525789b4694d78df4f001063f042b2b74227d26Dean Nelson}
1152525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1162525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic int
1172525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq)
1182525789b4694d78df4f001063f042b2b74227d26Dean Nelson{
1192525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int ret;
1202525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1212525789b4694d78df4f001063f042b2b74227d26Dean Nelson#if defined CONFIG_X86_64
1222525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = uv_bios_mq_watchlist_alloc(mq->mmr_blade, mq->address, mq->order,
1232525789b4694d78df4f001063f042b2b74227d26Dean Nelson					 &mq->mmr_offset);
1242525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (ret < 0) {
1252525789b4694d78df4f001063f042b2b74227d26Dean Nelson		dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
1262525789b4694d78df4f001063f042b2b74227d26Dean Nelson			"ret=%d\n", ret);
1272525789b4694d78df4f001063f042b2b74227d26Dean Nelson		return ret;
1282525789b4694d78df4f001063f042b2b74227d26Dean Nelson	}
1292525789b4694d78df4f001063f042b2b74227d26Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
1302525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = sn_mq_watchlist_alloc(mq->mmr_blade, mq->address, mq->order,
1312525789b4694d78df4f001063f042b2b74227d26Dean Nelson				    &mq->mmr_offset);
1322525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (ret < 0) {
1332525789b4694d78df4f001063f042b2b74227d26Dean Nelson		dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n",
1342525789b4694d78df4f001063f042b2b74227d26Dean Nelson			ret);
1352525789b4694d78df4f001063f042b2b74227d26Dean Nelson		return -EBUSY;
1362525789b4694d78df4f001063f042b2b74227d26Dean Nelson	}
1372525789b4694d78df4f001063f042b2b74227d26Dean Nelson#else
1382525789b4694d78df4f001063f042b2b74227d26Dean Nelson	#error not a supported configuration
1392525789b4694d78df4f001063f042b2b74227d26Dean Nelson#endif
1402525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1412525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq->watchlist_num = ret;
1422525789b4694d78df4f001063f042b2b74227d26Dean Nelson	return 0;
1432525789b4694d78df4f001063f042b2b74227d26Dean Nelson}
1442525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1452525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic void
1462525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
1472525789b4694d78df4f001063f042b2b74227d26Dean Nelson{
1482525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int ret;
1492525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1502525789b4694d78df4f001063f042b2b74227d26Dean Nelson#if defined CONFIG_X86_64
1512525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = uv_bios_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num);
1522525789b4694d78df4f001063f042b2b74227d26Dean Nelson	BUG_ON(ret != BIOS_STATUS_SUCCESS);
1532525789b4694d78df4f001063f042b2b74227d26Dean Nelson#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
1542525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = sn_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num);
1552525789b4694d78df4f001063f042b2b74227d26Dean Nelson	BUG_ON(ret != SALRET_OK);
1562525789b4694d78df4f001063f042b2b74227d26Dean Nelson#else
1572525789b4694d78df4f001063f042b2b74227d26Dean Nelson	#error not a supported configuration
1582525789b4694d78df4f001063f042b2b74227d26Dean Nelson#endif
1592525789b4694d78df4f001063f042b2b74227d26Dean Nelson}
1602525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1612525789b4694d78df4f001063f042b2b74227d26Dean Nelsonstatic struct xpc_gru_mq_uv *
1622525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
1635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		     irq_handler_t irq_handler)
1645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
1652525789b4694d78df4f001063f042b2b74227d26Dean Nelson	enum xp_retval xp_ret;
1665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	int ret;
1675b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	int nid;
1682525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int pg_order;
1695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct page *page;
1702525789b4694d78df4f001063f042b2b74227d26Dean Nelson	struct xpc_gru_mq_uv *mq;
1712525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1722525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL);
1732525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (mq == NULL) {
1742525789b4694d78df4f001063f042b2b74227d26Dean Nelson		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
1752525789b4694d78df4f001063f042b2b74227d26Dean Nelson			"a xpc_gru_mq_uv structure\n");
1762525789b4694d78df4f001063f042b2b74227d26Dean Nelson		ret = -ENOMEM;
1772525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_1;
1782525789b4694d78df4f001063f042b2b74227d26Dean Nelson	}
1795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1802525789b4694d78df4f001063f042b2b74227d26Dean Nelson	pg_order = get_order(mq_size);
1812525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq->order = pg_order + PAGE_SHIFT;
1822525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq_size = 1UL << mq->order;
1832525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1842525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq->mmr_blade = uv_cpu_to_blade_id(cpu);
1852525789b4694d78df4f001063f042b2b74227d26Dean Nelson
1862525789b4694d78df4f001063f042b2b74227d26Dean Nelson	nid = cpu_to_node(cpu);
1875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
1882525789b4694d78df4f001063f042b2b74227d26Dean Nelson				pg_order);
189bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (page == NULL) {
190bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
191bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			"bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
1922525789b4694d78df4f001063f042b2b74227d26Dean Nelson		ret = -ENOMEM;
1932525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_2;
194bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1952525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq->address = page_address(page);
1965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1972525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = gru_create_message_queue(mq->address, mq_size);
1985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (ret != 0) {
1995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		dev_err(xpc_part, "gru_create_message_queue() returned "
2005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			"error=%d\n", ret);
2012525789b4694d78df4f001063f042b2b74227d26Dean Nelson		ret = -EINVAL;
2022525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_3;
2035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
2045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2052525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* enable generation of irq when GRU mq operation occurs to this mq */
2062525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = xpc_gru_mq_watchlist_alloc_uv(mq);
2072525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (ret != 0)
2082525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_3;
2095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2102525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = xpc_get_gru_mq_irq_uv(mq, cpu, irq_name);
2112525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (ret != 0)
2122525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_4;
2132525789b4694d78df4f001063f042b2b74227d26Dean Nelson
2142525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL);
2155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (ret != 0) {
2165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n",
2172525789b4694d78df4f001063f042b2b74227d26Dean Nelson			mq->irq, ret);
2182525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_5;
2195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
2205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2212525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* allow other partitions to access this GRU mq */
2222525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size);
2232525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (xp_ret != xpSuccess) {
2242525789b4694d78df4f001063f042b2b74227d26Dean Nelson		ret = -EACCES;
2252525789b4694d78df4f001063f042b2b74227d26Dean Nelson		goto out_6;
2262525789b4694d78df4f001063f042b2b74227d26Dean Nelson	}
2275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return mq;
2292525789b4694d78df4f001063f042b2b74227d26Dean Nelson
2302525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* something went wrong */
2312525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_6:
2322525789b4694d78df4f001063f042b2b74227d26Dean Nelson	free_irq(mq->irq, NULL);
2332525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_5:
2342525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_release_gru_mq_irq_uv(mq);
2352525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_4:
2362525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_gru_mq_watchlist_free_uv(mq);
2372525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_3:
2382525789b4694d78df4f001063f042b2b74227d26Dean Nelson	free_pages((unsigned long)mq->address, pg_order);
2392525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_2:
2402525789b4694d78df4f001063f042b2b74227d26Dean Nelson	kfree(mq);
2412525789b4694d78df4f001063f042b2b74227d26Dean Nelsonout_1:
2422525789b4694d78df4f001063f042b2b74227d26Dean Nelson	return ERR_PTR(ret);
2435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
24494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
24533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void
2462525789b4694d78df4f001063f042b2b74227d26Dean Nelsonxpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq)
2475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
2482525789b4694d78df4f001063f042b2b74227d26Dean Nelson	unsigned int mq_size;
2492525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int pg_order;
2502525789b4694d78df4f001063f042b2b74227d26Dean Nelson	int ret;
2512525789b4694d78df4f001063f042b2b74227d26Dean Nelson
2522525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* disallow other partitions to access GRU mq */
2532525789b4694d78df4f001063f042b2b74227d26Dean Nelson	mq_size = 1UL << mq->order;
2542525789b4694d78df4f001063f042b2b74227d26Dean Nelson	ret = xp_restrict_memprotect(xp_pa(mq->address), mq_size);
2552525789b4694d78df4f001063f042b2b74227d26Dean Nelson	BUG_ON(ret != xpSuccess);
2562525789b4694d78df4f001063f042b2b74227d26Dean Nelson
2572525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* unregister irq handler and release mq irq/vector mapping */
2582525789b4694d78df4f001063f042b2b74227d26Dean Nelson	free_irq(mq->irq, NULL);
2592525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_release_gru_mq_irq_uv(mq);
2605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2612525789b4694d78df4f001063f042b2b74227d26Dean Nelson	/* disable generation of irq when GRU mq op occurs to this mq */
2622525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_gru_mq_watchlist_free_uv(mq);
2635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2642525789b4694d78df4f001063f042b2b74227d26Dean Nelson	pg_order = mq->order - PAGE_SHIFT;
2652525789b4694d78df4f001063f042b2b74227d26Dean Nelson	free_pages((unsigned long)mq->address, pg_order);
2665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2672525789b4694d78df4f001063f042b2b74227d26Dean Nelson	kfree(mq);
2685b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
2695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2705b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic enum xp_retval
2715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_gru_msg(unsigned long mq_gpa, void *msg, size_t msg_size)
27233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{
2735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	enum xp_retval xp_ret;
2745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	int ret;
2755b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	while (1) {
2775b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		ret = gru_send_message_gpa(mq_gpa, msg, msg_size);
2785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (ret == MQE_OK) {
2795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			xp_ret = xpSuccess;
2805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			break;
2815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		}
2825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
2835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (ret == MQE_QUEUE_FULL) {
2845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
2855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				"error=MQE_QUEUE_FULL\n");
2865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			/* !!! handle QLimit reached; delay & try again */
2875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			/* ??? Do we add a limit to the number of retries? */
2885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			(void)msleep_interruptible(10);
2895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		} else if (ret == MQE_CONGESTION) {
2905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
2915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				"error=MQE_CONGESTION\n");
2925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			/* !!! handle LB Overflow; simply try again */
2935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			/* ??? Do we add a limit to the number of retries? */
2945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		} else {
2955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			/* !!! Currently this is MQE_UNEXPECTED_CB_ERR */
2965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			dev_err(xpc_chan, "gru_send_message_gpa() returned "
2975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				"error=%d\n", ret);
2985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			xp_ret = xpGruSendMqError;
2995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			break;
3005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		}
3015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
3025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return xp_ret;
3035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
3045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
3065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_process_activate_IRQ_rcvd_uv(void)
3075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
3085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	unsigned long irq_flags;
3095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	short partid;
3105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition *part;
3115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	u8 act_state_req;
3125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	DBUG_ON(xpc_activate_IRQ_rcvd == 0);
3145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
3165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
3175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part = &xpc_partitions[partid];
3185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (part->sn.uv.act_state_req == 0)
3205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			continue;
3215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_activate_IRQ_rcvd--;
3235b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		BUG_ON(xpc_activate_IRQ_rcvd < 0);
3245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		act_state_req = part->sn.uv.act_state_req;
3265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part->sn.uv.act_state_req = 0;
3275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
3285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (act_state_req == XPC_P_ASR_ACTIVATE_UV) {
3305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			if (part->act_state == XPC_P_AS_INACTIVE)
3315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				xpc_activate_partition(part);
3325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			else if (part->act_state == XPC_P_AS_DEACTIVATING)
3335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				XPC_DEACTIVATE_PARTITION(part, xpReactivating);
3345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		} else if (act_state_req == XPC_P_ASR_REACTIVATE_UV) {
3365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			if (part->act_state == XPC_P_AS_INACTIVE)
3375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				xpc_activate_partition(part);
3385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			else
3395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				XPC_DEACTIVATE_PARTITION(part, xpReactivating);
3405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		} else if (act_state_req == XPC_P_ASR_DEACTIVATE_UV) {
3425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			XPC_DEACTIVATE_PARTITION(part, part->sn.uv.reason);
3435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		} else {
3455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			BUG();
3465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		}
3475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
3495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (xpc_activate_IRQ_rcvd == 0)
3505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			break;
3515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
3525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
3535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
3545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
3555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
356bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
357bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
358bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			      struct xpc_activate_mq_msghdr_uv *msg_hdr,
359bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			      int *wakeup_hb_checker)
3605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
3615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	unsigned long irq_flags;
362bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_partition_uv *part_uv = &part->sn.uv;
3635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_openclose_args *args;
3645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
365bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	part_uv->remote_act_state = msg_hdr->act_state;
3665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
367bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	switch (msg_hdr->type) {
368bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV:
369bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/* syncing of remote_act_state was just done above */
370bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
3715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
372bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: {
373bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
3745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
375bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr,
376bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   struct xpc_activate_mq_msg_heartbeat_req_uv,
377bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
378bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->heartbeat = msg->heartbeat;
379bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
380bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
381bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: {
382bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
383bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
384bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr,
385bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   struct xpc_activate_mq_msg_heartbeat_req_uv,
386bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
387bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->heartbeat = msg->heartbeat;
388bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
389bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
390bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV;
391bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
392bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
393bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
394bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: {
395bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
396bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
397bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr,
398bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   struct xpc_activate_mq_msg_heartbeat_req_uv,
399bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
400bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->heartbeat = msg->heartbeat;
401bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
402bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
403bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV;
404bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
405bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
406bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
407bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
408bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_activate_req_uv *msg;
4095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
410bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/*
411bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * ??? Do we deal here with ts_jiffies being different
412bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * ??? if act_state != XPC_P_AS_INACTIVE instead of
413bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * ??? below?
414bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 */
415bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
416bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_activate_req_uv, hdr);
4175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
418bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
419bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (part_uv->act_state_req == 0)
420bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_activate_IRQ_rcvd++;
421bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
422bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
423bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
424bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->remote_activate_mq_gpa = msg->activate_mq_gpa;
425bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
4265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
427bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		(*wakeup_hb_checker)++;
428bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
429bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
430bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
431bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_deactivate_req_uv *msg;
4325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
433bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
434bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_deactivate_req_uv, hdr);
4355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
436bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
437bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (part_uv->act_state_req == 0)
438bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_activate_IRQ_rcvd++;
439bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
440bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->reason = msg->reason;
441bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
442bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
443bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		(*wakeup_hb_checker)++;
444bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return;
445bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
446bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
447bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
4485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
449bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
450bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_chctl_closerequest_uv,
451bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
452bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args = &part->remote_openclose_args[msg->ch_number];
453bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->reason = msg->reason;
4545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
455bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part->chctl_lock, irq_flags);
456bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREQUEST;
457bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
4585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
459bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_wakeup_channel_mgr(part);
460bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
461bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
462bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
463bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
4645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
465bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
466bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_chctl_closereply_uv,
467bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
4685b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
469bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part->chctl_lock, irq_flags);
470bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREPLY;
471bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
4725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
473bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_wakeup_channel_mgr(part);
474bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
475bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
476bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
477bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
478bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
479bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
480bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_chctl_openrequest_uv,
481bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   hdr);
482bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args = &part->remote_openclose_args[msg->ch_number];
483bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->entry_size = msg->entry_size;
484bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->local_nentries = msg->local_nentries;
485bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
486bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part->chctl_lock, irq_flags);
487bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREQUEST;
488bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
489bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
490bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_wakeup_channel_mgr(part);
491bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
492bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
493bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
494bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
495bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
496bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg = container_of(msg_hdr, struct
497bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				   xpc_activate_mq_msg_chctl_openreply_uv, hdr);
498bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args = &part->remote_openclose_args[msg->ch_number];
499bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->remote_nentries = msg->remote_nentries;
500bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->local_nentries = msg->local_nentries;
501bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		args->local_msgqueue_pa = msg->local_notify_mq_gpa;
502bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
503bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part->chctl_lock, irq_flags);
504bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY;
505bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
506bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
507bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_wakeup_channel_mgr(part);
508bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
509bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
510bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
511bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
512bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->flags |= XPC_P_ENGAGED_UV;
513bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
514bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
515bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
516bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV:
517bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
518bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->flags &= ~XPC_P_ENGAGED_UV;
519bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
520bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		break;
521bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
522bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	default:
523bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_err(xpc_part, "received unknown activate_mq msg type=%d "
524bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			"from partition=%d\n", msg_hdr->type, XPC_PARTID(part));
525bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
526bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/* get hb checker to deactivate from the remote partition */
527bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
528bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (part_uv->act_state_req == 0)
529bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_activate_IRQ_rcvd++;
530bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
531bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->reason = xpBadMsgType;
532bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
5335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
534bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		(*wakeup_hb_checker)++;
535bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return;
536bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
5375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
538bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies &&
539bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	    part->remote_rp_ts_jiffies != 0) {
540bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/*
541bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * ??? Does what we do here need to be sensitive to
542bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * ??? act_state or remote_act_state?
543bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 */
544bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
545bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (part_uv->act_state_req == 0)
546bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_activate_IRQ_rcvd++;
547bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV;
548bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
5495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
550bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		(*wakeup_hb_checker)++;
551bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
552bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
553bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
554bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic irqreturn_t
555bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_handle_activate_IRQ_uv(int irq, void *dev_id)
556bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
557bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_activate_mq_msghdr_uv *msg_hdr;
558bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	short partid;
559bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_partition *part;
560bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int wakeup_hb_checker = 0;
561bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
5622525789b4694d78df4f001063f042b2b74227d26Dean Nelson	while (1) {
5632525789b4694d78df4f001063f042b2b74227d26Dean Nelson		msg_hdr = gru_get_next_message(xpc_activate_mq_uv->address);
5642525789b4694d78df4f001063f042b2b74227d26Dean Nelson		if (msg_hdr == NULL)
5652525789b4694d78df4f001063f042b2b74227d26Dean Nelson			break;
566bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
567bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		partid = msg_hdr->partid;
568bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
569bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() "
570bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				"received invalid partid=0x%x in message\n",
571bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				partid);
572bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		} else {
573bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			part = &xpc_partitions[partid];
574bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			if (xpc_part_ref(part)) {
575bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				xpc_handle_activate_mq_msg_uv(part, msg_hdr,
576bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson							    &wakeup_hb_checker);
577bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				xpc_part_deref(part);
578bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			}
5795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		}
5805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5812525789b4694d78df4f001063f042b2b74227d26Dean Nelson		gru_free_message(xpc_activate_mq_uv->address, msg_hdr);
5825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
5835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (wakeup_hb_checker)
5855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		wake_up_interruptible(&xpc_activate_IRQ_wq);
5865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return IRQ_HANDLED;
5885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
5895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic enum xp_retval
5915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size,
5925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			 int msg_type)
5935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
5945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msghdr_uv *msg_hdr = msg;
5955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV);
5975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
5985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg_hdr->type = msg_type;
5995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg_hdr->partid = XPC_PARTID(part);
6005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg_hdr->act_state = part->act_state;
6015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies;
6025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */
6045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return xpc_send_gru_msg(part->sn.uv.remote_activate_mq_gpa, msg,
6055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				msg_size);
6065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
6075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
6095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_activate_IRQ_part_uv(struct xpc_partition *part, void *msg,
6105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			      size_t msg_size, int msg_type)
6115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
6125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	enum xp_retval ret;
6135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
6155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (unlikely(ret != xpSuccess))
6165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		XPC_DEACTIVATE_PARTITION(part, ret);
6175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
6185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
6205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags,
6215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			 void *msg, size_t msg_size, int msg_type)
6225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
6235b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition *part = &xpc_partitions[ch->number];
6245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	enum xp_retval ret;
6255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
6275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (unlikely(ret != xpSuccess)) {
6285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (irq_flags != NULL)
6295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			spin_unlock_irqrestore(&ch->lock, *irq_flags);
6305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		XPC_DEACTIVATE_PARTITION(part, ret);
6325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (irq_flags != NULL)
6345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			spin_lock_irqsave(&ch->lock, *irq_flags);
6355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
6365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
6375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
6395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req)
6405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
6415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	unsigned long irq_flags;
6425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition_uv *part_uv = &part->sn.uv;
6435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
64433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	/*
645ea57f80c8c0e59cfc5095f7e856ce7c8e6ac2984Dean Nelson	 * !!! Make our side think that the remote parition sent an activate
6465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * !!! message our way by doing what the activate IRQ handler would
647ea57f80c8c0e59cfc5095f7e856ce7c8e6ac2984Dean Nelson	 * !!! do had one really been sent.
64833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	 */
6495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
6515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (part_uv->act_state_req == 0)
6525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_activate_IRQ_rcvd++;
6535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	part_uv->act_state_req = act_state_req;
6545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
6555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	wake_up_interruptible(&xpc_activate_IRQ_wq);
65733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson}
65833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
65994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelsonstatic enum xp_retval
6605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
6615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				  size_t *len)
66294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson{
6635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/* !!! call the UV version of sn_partition_reserved_page_pa() */
6645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return xpUnsupported;
6655b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
6665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6675b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int
6685b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp)
6695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
6702525789b4694d78df4f001063f042b2b74227d26Dean Nelson	rp->sn.activate_mq_gpa = uv_gpa(xpc_activate_mq_uv->address);
6715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return 0;
6725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
6735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
6755b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_heartbeat_uv(int msg_type)
6765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
6775b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	short partid;
6785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition *part;
6795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_heartbeat_req_uv msg;
6805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/*
6825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * !!! On uv we're broadcasting a heartbeat message every 5 seconds.
6835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * !!! Whereas on sn2 we're bte_copy'ng the heartbeat info every 20
6845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * !!! seconds. This is an increase in numalink traffic.
6855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * ??? Is this good?
6865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 */
6875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.heartbeat = atomic64_inc_return(&xpc_heartbeat_uv);
6895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	partid = find_first_bit(xpc_heartbeating_to_mask_uv,
6915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				XP_MAX_NPARTITIONS_UV);
6925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	while (partid < XP_MAX_NPARTITIONS_UV) {
6945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part = &xpc_partitions[partid];
6955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
6975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson					      msg_type);
6985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
6995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		partid = find_next_bit(xpc_heartbeating_to_mask_uv,
7005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				       XP_MAX_NPARTITIONS_UV, partid + 1);
7015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
70294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson}
70394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
70433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void
70533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_increment_heartbeat_uv(void)
70633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{
7075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV);
7085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
7095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
7115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_offline_heartbeat_uv(void)
7125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
7135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV);
7145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
7155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
7175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_online_heartbeat_uv(void)
7185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
7195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV);
72033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson}
72133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
72233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void
72333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_heartbeat_init_uv(void)
72433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{
7255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	atomic64_set(&xpc_heartbeat_uv, 0);
72633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	bitmap_zero(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV);
72733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	xpc_heartbeating_to_mask = &xpc_heartbeating_to_mask_uv[0];
72833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson}
72933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
73033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void
73133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_heartbeat_exit_uv(void)
73233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{
7335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV);
7345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
7355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic enum xp_retval
7375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_get_remote_heartbeat_uv(struct xpc_partition *part)
7385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
7395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition_uv *part_uv = &part->sn.uv;
7405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	enum xp_retval ret = xpNoHeartbeat;
7415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (part_uv->remote_act_state != XPC_P_AS_INACTIVE &&
7435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	    part_uv->remote_act_state != XPC_P_AS_DEACTIVATING) {
7445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (part_uv->heartbeat != part->last_heartbeat ||
7465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		    (part_uv->flags & XPC_P_HEARTBEAT_OFFLINE_UV)) {
7475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			part->last_heartbeat = part_uv->heartbeat;
7495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			ret = xpSuccess;
7505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		}
7515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
7525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return ret;
75333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson}
75433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
75533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void
756a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
7575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				    unsigned long remote_rp_gpa, int nasid)
75833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{
75933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	short partid = remote_rp->SAL_partid;
76033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	struct xpc_partition *part = &xpc_partitions[partid];
7615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_activate_req_uv msg;
76233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
7635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */
7645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	part->remote_rp_ts_jiffies = remote_rp->ts_jiffies;
7655b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	part->sn.uv.remote_activate_mq_gpa = remote_rp->sn.activate_mq_gpa;
7665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7675b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/*
7685b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * ??? Is it a good idea to make this conditional on what is
7695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * ??? potentially stale state information?
7705b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 */
7715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) {
7725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		msg.rp_gpa = uv_gpa(xpc_rsvd_page);
7735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		msg.activate_mq_gpa = xpc_rsvd_page->sn.activate_mq_gpa;
7745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
7755b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson					   XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV);
7765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
77733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
7785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (part->act_state == XPC_P_AS_INACTIVE)
7795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
78033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson}
78133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson
782a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonstatic void
783a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_request_partition_reactivation_uv(struct xpc_partition *part)
784a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson{
7855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
7865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
7875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
7895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_request_partition_deactivation_uv(struct xpc_partition *part)
7905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
7915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_deactivate_req_uv msg;
7925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
7935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/*
7945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * ??? Is it a good idea to make this conditional on what is
7955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * ??? potentially stale state information?
7965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 */
7975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (part->sn.uv.remote_act_state != XPC_P_AS_DEACTIVATING &&
7985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	    part->sn.uv.remote_act_state != XPC_P_AS_INACTIVE) {
7995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
8005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		msg.reason = part->reason;
8015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
8025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson					 XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV);
8035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
804a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson}
805a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson
806bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
807bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_cancel_partition_deactivation_request_uv(struct xpc_partition *part)
808bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
809bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* nothing needs to be done */
810bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return;
811bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
812bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
813bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
814bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_init_fifo_uv(struct xpc_fifo_head_uv *head)
815bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
816bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->first = NULL;
817bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->last = NULL;
818bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_lock_init(&head->lock);
819bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->n_entries = 0;
820bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
821bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
822bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void *
823bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head)
824bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
825bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
826bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_fifo_entry_uv *first;
827bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
828bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_lock_irqsave(&head->lock, irq_flags);
829bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	first = head->first;
830bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (head->first != NULL) {
831bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		head->first = first->next;
832bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (head->first == NULL)
833bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			head->last = NULL;
834bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
835bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->n_entries++;
836bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_unlock_irqrestore(&head->lock, irq_flags);
837bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	first->next = NULL;
838bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return first;
839bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
840bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
841bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
842bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head,
843bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		      struct xpc_fifo_entry_uv *last)
844bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
845bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
846bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
847bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	last->next = NULL;
848bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_lock_irqsave(&head->lock, irq_flags);
849bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (head->last != NULL)
850bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		head->last->next = last;
851bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	else
852bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		head->first = last;
853bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->last = last;
854bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	head->n_entries--;
855bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	BUG_ON(head->n_entries < 0);
856bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_unlock_irqrestore(&head->lock, irq_flags);
857bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
858bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
859bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic int
860bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
861bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
862bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return head->n_entries;
863bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
864bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
865e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson/*
8665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Setup the channel structures that are uv specific.
867e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson */
868e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonstatic enum xp_retval
8695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_ch_structures_sn_uv(struct xpc_partition *part)
870e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson{
871bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel_uv *ch_uv;
872bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int ch_number;
873bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
874bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
875bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ch_uv = &part->channels[ch_number].sn.uv;
876bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
877bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
878bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_init_fifo_uv(&ch_uv->recv_msg_list);
879bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
880bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
881bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return xpSuccess;
882e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson}
883e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson
884e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson/*
8855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Teardown the channel structures that are uv specific.
886e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson */
887e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonstatic void
8885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_teardown_ch_structures_sn_uv(struct xpc_partition *part)
889e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson{
890bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* nothing needs to be done */
891e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson	return;
892e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson}
893e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson
894e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonstatic enum xp_retval
895e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonxpc_make_first_contact_uv(struct xpc_partition *part)
896e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson{
8975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_uv msg;
8985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
8995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	/*
9005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * We send a sync msg to get the remote partition's remote_act_state
9015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * updated to our current act_state which at this point should
9025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 * be XPC_P_AS_ACTIVATING.
9035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	 */
9045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
9055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				      XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
9065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	while (part->sn.uv.remote_act_state != XPC_P_AS_ACTIVATING) {
9085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		dev_dbg(xpc_part, "waiting to make first contact with "
9105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			"partition %d\n", XPC_PARTID(part));
9115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		/* wait a 1/4 of a second or so */
9135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		(void)msleep_interruptible(250);
9145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if (part->act_state == XPC_P_AS_DEACTIVATING)
9165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			return part->reason;
9175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
9185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return xpSuccess;
920e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson}
921e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson
922e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonstatic u64
9237fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelsonxpc_get_chctl_all_flags_uv(struct xpc_partition *part)
924e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson{
9255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	unsigned long irq_flags;
9265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	union xpc_channel_ctl_flags chctl;
9275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_lock_irqsave(&part->chctl_lock, irq_flags);
9295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	chctl = part->chctl;
9305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	if (chctl.all_flags != 0)
9315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part->chctl.all_flags = 0;
9325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
9345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return chctl.all_flags;
9355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
9365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
9375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic enum xp_retval
938bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_allocate_send_msg_slot_uv(struct xpc_channel *ch)
939bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
940bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
941bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_send_msg_slot_uv *msg_slot;
942bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
943bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int nentries;
944bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int entry;
945bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	size_t nbytes;
946bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
947bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
948bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		nbytes = nentries * sizeof(struct xpc_send_msg_slot_uv);
949bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ch_uv->send_msg_slots = kzalloc(nbytes, GFP_KERNEL);
950bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (ch_uv->send_msg_slots == NULL)
951bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			continue;
952bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
953bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		for (entry = 0; entry < nentries; entry++) {
954bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot = &ch_uv->send_msg_slots[entry];
955bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
956bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot->msg_slot_number = entry;
957bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_put_fifo_entry_uv(&ch_uv->msg_slot_free_list,
958bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson					      &msg_slot->next);
959bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
960bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
961bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&ch->lock, irq_flags);
962bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (nentries < ch->local_nentries)
963bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			ch->local_nentries = nentries;
964bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&ch->lock, irq_flags);
965bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return xpSuccess;
966bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
967bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
968bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return xpNoMemory;
969bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
970bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
971bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic enum xp_retval
972bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
973bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
974bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
975bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg_slot;
976bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
977bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int nentries;
978bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int entry;
979bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	size_t nbytes;
980bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
981bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
982bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		nbytes = nentries * ch->entry_size;
983bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ch_uv->recv_msg_slots = kzalloc(nbytes, GFP_KERNEL);
984bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (ch_uv->recv_msg_slots == NULL)
985bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			continue;
986bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
987bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		for (entry = 0; entry < nentries; entry++) {
988bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot = ch_uv->recv_msg_slots + entry *
989bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			    ch->entry_size;
990bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
991bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot->hdr.msg_slot_number = entry;
992bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
993bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
994bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&ch->lock, irq_flags);
995bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (nentries < ch->remote_nentries)
996bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			ch->remote_nentries = nentries;
997bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&ch->lock, irq_flags);
998bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return xpSuccess;
999bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1000bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1001bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return xpNoMemory;
1002bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1003bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1004bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson/*
1005bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * Allocate msg_slots associated with the channel.
1006bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson */
1007bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic enum xp_retval
10085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_msg_structures_uv(struct xpc_channel *ch)
10095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
1010bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	static enum xp_retval ret;
1011bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1012bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1013bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	DBUG_ON(ch->flags & XPC_C_SETUP);
1014bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1015bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ret = xpc_allocate_send_msg_slot_uv(ch);
1016bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ret == xpSuccess) {
1017bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1018bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ret = xpc_allocate_recv_msg_slot_uv(ch);
1019bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (ret != xpSuccess) {
1020bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			kfree(ch_uv->send_msg_slots);
1021bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
1022bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
1023bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1024bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return ret;
10255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1027bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson/*
1028bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * Free up msg_slots and clear other stuff that were setup for the specified
1029bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * channel.
1030bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson */
10315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
10325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_teardown_msg_structures_uv(struct xpc_channel *ch)
10335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
10345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
10355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1036bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	DBUG_ON(!spin_is_locked(&ch->lock));
1037bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
10385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	ch_uv->remote_notify_mq_gpa = 0;
10395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1040bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ch->flags & XPC_C_SETUP) {
1041bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
1042bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		kfree(ch_uv->send_msg_slots);
1043bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_init_fifo_uv(&ch_uv->recv_msg_list);
1044bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		kfree(ch_uv->recv_msg_slots);
1045bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
10465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
10495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_chctl_closerequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
10505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
10515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_chctl_closerequest_uv msg;
10525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.ch_number = ch->number;
10545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.reason = ch->reason;
10555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
10565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				    XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV);
10575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10595b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
10605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_chctl_closereply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
10615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
10625b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_chctl_closereply_uv msg;
10635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.ch_number = ch->number;
10655b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
10665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				    XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV);
10675b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10685b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
10705b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_chctl_openrequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
10715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
10725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_chctl_openrequest_uv msg;
10735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.ch_number = ch->number;
1075bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg.entry_size = ch->entry_size;
10765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.local_nentries = ch->local_nentries;
10775b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
10785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				    XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV);
10795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
10825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
10835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
10845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_chctl_openreply_uv msg;
10855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.ch_number = ch->number;
10875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.local_nentries = ch->local_nentries;
10885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.remote_nentries = ch->remote_nentries;
10895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	msg.local_notify_mq_gpa = uv_gpa(xpc_notify_mq_uv);
10905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
10915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				    XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV);
10925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
10935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
10945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
1095bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
1096bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1097bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
1098bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1099bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_lock_irqsave(&part->chctl_lock, irq_flags);
1100bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	part->chctl.flags[ch_number] |= XPC_CHCTL_MSGREQUEST;
1101bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
1102bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1103bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_wakeup_channel_mgr(part);
1104bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1105bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1106bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
11075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch,
11085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			       unsigned long msgqueue_pa)
11095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	ch->sn.uv.remote_notify_mq_gpa = msgqueue_pa;
11115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
11125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
11145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_indicate_partition_engaged_uv(struct xpc_partition *part)
11155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_uv msg;
11175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
11195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				      XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV);
11205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
11215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
11235b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_indicate_partition_disengaged_uv(struct xpc_partition *part)
11245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_activate_mq_msg_uv msg;
11265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
11285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson				      XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV);
11295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
11305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void
11325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_assume_partition_disengaged_uv(short partid)
11335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition_uv *part_uv = &xpc_partitions[partid].sn.uv;
11355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	unsigned long irq_flags;
11365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
11385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	part_uv->flags &= ~XPC_P_ENGAGED_UV;
11395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
11405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
11415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int
11435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_partition_engaged_uv(short partid)
11445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return (xpc_partitions[partid].sn.uv.flags & XPC_P_ENGAGED_UV) != 0;
11465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson}
11475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int
11495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_any_partition_engaged_uv(void)
11505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{
11515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	struct xpc_partition_uv *part_uv;
11525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	short partid;
11535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
11545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
11555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		part_uv = &xpc_partitions[partid].sn.uv;
11565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson		if ((part_uv->flags & XPC_P_ENGAGED_UV) != 0)
11575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson			return 1;
11585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	}
11595b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return 0;
1160e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson}
1161e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson
1162bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic enum xp_retval
1163bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_allocate_msg_slot_uv(struct xpc_channel *ch, u32 flags,
1164bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			 struct xpc_send_msg_slot_uv **address_of_msg_slot)
1165bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1166bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	enum xp_retval ret;
1167bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_send_msg_slot_uv *msg_slot;
1168bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_fifo_entry_uv *entry;
1169bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1170bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	while (1) {
1171bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		entry = xpc_get_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list);
1172bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (entry != NULL)
1173bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			break;
1174bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1175bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (flags & XPC_NOWAIT)
1176bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			return xpNoWait;
1177bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1178bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ret = xpc_allocate_msg_wait(ch);
1179bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (ret != xpInterrupted && ret != xpTimeout)
1180bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			return ret;
1181bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1182bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1183bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg_slot = container_of(entry, struct xpc_send_msg_slot_uv, next);
1184bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	*address_of_msg_slot = msg_slot;
1185bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return xpSuccess;
1186bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1187bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1188bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1189bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_free_msg_slot_uv(struct xpc_channel *ch,
1190bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		     struct xpc_send_msg_slot_uv *msg_slot)
1191bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1192bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_put_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list, &msg_slot->next);
1193bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1194bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* wakeup anyone waiting for a free msg slot */
1195bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
1196bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		wake_up(&ch->msg_allocate_wq);
1197bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1198bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1199bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1200bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_notify_sender_uv(struct xpc_channel *ch,
1201bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		     struct xpc_send_msg_slot_uv *msg_slot,
1202bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		     enum xp_retval reason)
1203bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1204bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_notify_func func = msg_slot->func;
1205bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1206bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (func != NULL && cmpxchg(&msg_slot->func, func, NULL) == func) {
1207bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1208bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		atomic_dec(&ch->n_to_notify);
1209bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1210bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_dbg(xpc_chan, "msg_slot->func() called, msg_slot=0x%p "
1211bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			"msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1212bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot->msg_slot_number, ch->partid, ch->number);
1213bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1214bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		func(reason, ch->partid, ch->number, msg_slot->key);
1215bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1216bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_dbg(xpc_chan, "msg_slot->func() returned, msg_slot=0x%p "
1217bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			"msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1218bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg_slot->msg_slot_number, ch->partid, ch->number);
1219bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1220bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1221bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1222bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1223bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_handle_notify_mq_ack_uv(struct xpc_channel *ch,
1224bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			    struct xpc_notify_mq_msg_uv *msg)
1225bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1226bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_send_msg_slot_uv *msg_slot;
1227bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int entry = msg->hdr.msg_slot_number % ch->local_nentries;
1228bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1229bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg_slot = &ch->sn.uv.send_msg_slots[entry];
1230bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1231bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	BUG_ON(msg_slot->msg_slot_number != msg->hdr.msg_slot_number);
1232bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg_slot->msg_slot_number += ch->local_nentries;
1233bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1234bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (msg_slot->func != NULL)
1235bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_notify_sender_uv(ch, msg_slot, xpMsgDelivered);
1236bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1237bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_free_msg_slot_uv(ch, msg_slot);
1238bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1239bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1240bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1241bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
1242bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			    struct xpc_notify_mq_msg_uv *msg)
1243bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1244bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_partition_uv *part_uv = &part->sn.uv;
1245bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel *ch;
1246bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel_uv *ch_uv;
1247bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg_slot;
1248bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	unsigned long irq_flags;
1249bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int ch_number = msg->hdr.ch_number;
1250bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1251bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (unlikely(ch_number >= part->nchannels)) {
1252bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received invalid "
1253bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			"channel number=0x%x in message from partid=%d\n",
1254bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			ch_number, XPC_PARTID(part));
1255bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1256bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/* get hb checker to deactivate from the remote partition */
1257bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1258bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (part_uv->act_state_req == 0)
1259bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_activate_IRQ_rcvd++;
1260bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
1261bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		part_uv->reason = xpBadChannelNumber;
1262bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1263bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1264bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		wake_up_interruptible(&xpc_activate_IRQ_wq);
1265bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return;
1266bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1267bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1268bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ch = &part->channels[ch_number];
1269bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_ref(ch);
1270bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1271bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (!(ch->flags & XPC_C_CONNECTED)) {
1272bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_msgqueue_deref(ch);
1273bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return;
1274bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1275bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1276bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* see if we're really dealing with an ACK for a previously sent msg */
1277bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (msg->hdr.size == 0) {
1278bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_handle_notify_mq_ack_uv(ch, msg);
1279bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_msgqueue_deref(ch);
1280bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return;
1281bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1282bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1283bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* we're dealing with a normal message sent via the notify_mq */
1284bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ch_uv = &ch->sn.uv;
1285bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1286bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
1287bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		    (msg->hdr.msg_slot_number % ch->remote_nentries) *
1288bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		    ch->entry_size);
1289bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1290bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
1291bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	BUG_ON(msg_slot->hdr.size != 0);
1292bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1293bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	memcpy(msg_slot, msg, msg->hdr.size);
1294bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1295bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_put_fifo_entry_uv(&ch_uv->recv_msg_list, &msg_slot->hdr.u.next);
1296bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1297bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
1298bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/*
1299bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * If there is an existing idle kthread get it to deliver
1300bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * the payload, otherwise we'll have to get the channel mgr
1301bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * for this partition to create a kthread to do the delivery.
1302bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 */
1303bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (atomic_read(&ch->kthreads_idle) > 0)
1304bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			wake_up_nr(&ch->idle_wq, 1);
1305bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		else
1306bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_send_chctl_local_msgrequest_uv(part, ch->number);
1307bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1308bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_deref(ch);
1309bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1310bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1311bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic irqreturn_t
1312bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_handle_notify_IRQ_uv(int irq, void *dev_id)
1313bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1314bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg;
1315bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	short partid;
1316bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_partition *part;
1317bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1318bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	while ((msg = gru_get_next_message(xpc_notify_mq_uv)) != NULL) {
1319bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1320bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		partid = msg->hdr.partid;
1321bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
1322bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received "
1323bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				"invalid partid=0x%x in message\n", partid);
1324bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		} else {
1325bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			part = &xpc_partitions[partid];
1326bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1327bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			if (xpc_part_ref(part)) {
1328bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				xpc_handle_notify_mq_msg_uv(part, msg);
1329bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson				xpc_part_deref(part);
1330bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			}
1331bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
1332bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1333bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		gru_free_message(xpc_notify_mq_uv, msg);
1334bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1335bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1336bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return IRQ_HANDLED;
1337bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1338bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1339bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic int
1340bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_n_of_deliverable_payloads_uv(struct xpc_channel *ch)
1341bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1342bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return xpc_n_of_fifo_entries_uv(&ch->sn.uv.recv_msg_list);
1343bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1344bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1345bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1346bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_process_msg_chctl_flags_uv(struct xpc_partition *part, int ch_number)
1347bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1348bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_channel *ch = &part->channels[ch_number];
1349bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int ndeliverable_payloads;
1350bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1351bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_ref(ch);
1352bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1353bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ndeliverable_payloads = xpc_n_of_deliverable_payloads_uv(ch);
1354bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1355bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ndeliverable_payloads > 0 &&
1356bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	    (ch->flags & XPC_C_CONNECTED) &&
1357bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	    (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)) {
1358bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1359bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		xpc_activate_kthreads(ch, ndeliverable_payloads);
1360bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1361bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1362bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_deref(ch);
1363bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1364bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1365bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic enum xp_retval
1366bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
1367bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		    u16 payload_size, u8 notify_type, xpc_notify_func func,
1368bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		    void *key)
1369bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1370bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	enum xp_retval ret = xpSuccess;
1371bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_send_msg_slot_uv *msg_slot = NULL;
1372bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg;
1373bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	u8 msg_buffer[XPC_NOTIFY_MSG_SIZE_UV];
1374bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	size_t msg_size;
1375bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1376bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	DBUG_ON(notify_type != XPC_N_CALL);
1377bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1378bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg_size = sizeof(struct xpc_notify_mq_msghdr_uv) + payload_size;
1379bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (msg_size > ch->entry_size)
1380bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return xpPayloadTooBig;
1381bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1382bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_ref(ch);
1383bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1384bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ch->flags & XPC_C_DISCONNECTING) {
1385bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ret = ch->reason;
1386bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		goto out_1;
1387bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1388bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (!(ch->flags & XPC_C_CONNECTED)) {
1389bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		ret = xpNotConnected;
1390bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		goto out_1;
1391bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1392bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1393bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ret = xpc_allocate_msg_slot_uv(ch, flags, &msg_slot);
1394bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ret != xpSuccess)
1395bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		goto out_1;
1396bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1397bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (func != NULL) {
1398bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		atomic_inc(&ch->n_to_notify);
1399bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1400bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg_slot->key = key;
1401bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		wmb(); /* a non-NULL func must hit memory after the key */
1402bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg_slot->func = func;
1403bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1404bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (ch->flags & XPC_C_DISCONNECTING) {
1405bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			ret = ch->reason;
1406bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			goto out_2;
1407bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
1408bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1409bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1410bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg = (struct xpc_notify_mq_msg_uv *)&msg_buffer;
1411bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.partid = xp_partition_id;
1412bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.ch_number = ch->number;
1413bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.size = msg_size;
1414bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.msg_slot_number = msg_slot->msg_slot_number;
1415bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	memcpy(&msg->payload, payload, payload_size);
1416bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1417bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, msg_size);
1418bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ret == xpSuccess)
1419bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		goto out_1;
1420bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1421bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1422bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonout_2:
1423bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (func != NULL) {
1424bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		/*
1425bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * Try to NULL the msg_slot's func field. If we fail, then
1426bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * xpc_notify_senders_of_disconnect_uv() beat us to it, in which
1427bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * case we need to pretend we succeeded to send the message
1428bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * since the user will get a callout for the disconnect error
1429bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * by xpc_notify_senders_of_disconnect_uv(), and to also get an
1430bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * error returned here will confuse them. Additionally, since
1431bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * in this case the channel is being disconnected we don't need
1432bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 * to put the the msg_slot back on the free list.
1433bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		 */
1434bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (cmpxchg(&msg_slot->func, func, NULL) != func) {
1435bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			ret = xpSuccess;
1436bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			goto out_1;
1437bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
1438bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1439bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg_slot->key = NULL;
1440bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		atomic_dec(&ch->n_to_notify);
1441bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1442bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_free_msg_slot_uv(ch, msg_slot);
1443bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonout_1:
1444bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_msgqueue_deref(ch);
1445bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return ret;
1446bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1447bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1448bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson/*
1449bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * Tell the callers of xpc_send_notify() that the status of their payloads
1450bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * is unknown because the channel is now disconnecting.
1451bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson *
1452bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * We don't worry about putting these msg_slots on the free list since the
1453bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * msg_slots themselves are about to be kfree'd.
1454bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson */
1455bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1456bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_notify_senders_of_disconnect_uv(struct xpc_channel *ch)
1457bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1458bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_send_msg_slot_uv *msg_slot;
1459bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	int entry;
1460bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1461bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
1462bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1463bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	for (entry = 0; entry < ch->local_nentries; entry++) {
1464bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1465bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (atomic_read(&ch->n_to_notify) == 0)
1466bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			break;
1467bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1468bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		msg_slot = &ch->sn.uv.send_msg_slots[entry];
1469bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (msg_slot->func != NULL)
1470bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			xpc_notify_sender_uv(ch, msg_slot, ch->reason);
1471bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1472bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1473bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1474bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson/*
1475bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson * Get the next deliverable message's payload.
1476bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson */
1477bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void *
1478bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_get_deliverable_payload_uv(struct xpc_channel *ch)
1479bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson{
1480bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_fifo_entry_uv *entry;
1481bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg;
1482bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	void *payload = NULL;
1483bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1484bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (!(ch->flags & XPC_C_DISCONNECTING)) {
1485bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		entry = xpc_get_fifo_entry_uv(&ch->sn.uv.recv_msg_list);
1486bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		if (entry != NULL) {
1487bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			msg = container_of(entry, struct xpc_notify_mq_msg_uv,
1488bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson					   hdr.u.next);
1489bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			payload = &msg->payload;
1490bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		}
1491bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1492bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	return payload;
1493bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson}
1494bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1495bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonstatic void
1496bd3e64c1759e4930315ebf022611468ee9621486Dean Nelsonxpc_received_payload_uv(struct xpc_channel *ch, void *payload)
1497e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson{
1498bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	struct xpc_notify_mq_msg_uv *msg;
1499bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	enum xp_retval ret;
1500bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1501bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg = container_of(payload, struct xpc_notify_mq_msg_uv, payload);
1502bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1503bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	/* return an ACK to the sender of this message */
1504bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1505bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.partid = xp_partition_id;
1506bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.size = 0;	/* size of zero indicates this is an ACK */
1507bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1508bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg,
1509bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			       sizeof(struct xpc_notify_mq_msghdr_uv));
1510bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (ret != xpSuccess)
1511bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1512bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1513bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	msg->hdr.msg_slot_number += ch->remote_nentries;
1514e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson}
1515e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson
15165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonint
151794bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelsonxpc_init_uv(void)
151894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson{
15195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv;
15205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv;
15215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv;
15225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv;
152333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	xpc_increment_heartbeat = xpc_increment_heartbeat_uv;
15245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_offline_heartbeat = xpc_offline_heartbeat_uv;
15255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_online_heartbeat = xpc_online_heartbeat_uv;
152633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	xpc_heartbeat_init = xpc_heartbeat_init_uv;
152733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson	xpc_heartbeat_exit = xpc_heartbeat_exit_uv;
15285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_uv;
15295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1530a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson	xpc_request_partition_activation = xpc_request_partition_activation_uv;
1531a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson	xpc_request_partition_reactivation =
1532a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson	    xpc_request_partition_reactivation_uv;
15335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_request_partition_deactivation =
15345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	    xpc_request_partition_deactivation_uv;
1535bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_cancel_partition_deactivation_request =
1536bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	    xpc_cancel_partition_deactivation_request_uv;
15375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_uv;
15395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_uv;
15405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1541e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson	xpc_make_first_contact = xpc_make_first_contact_uv;
15425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15437fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson	xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_uv;
15445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_uv;
15455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_chctl_closereply = xpc_send_chctl_closereply_uv;
15465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_uv;
15475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_send_chctl_openreply = xpc_send_chctl_openreply_uv;
15485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv;
15505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_setup_msg_structures = xpc_setup_msg_structures_uv;
15525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_teardown_msg_structures = xpc_teardown_msg_structures_uv;
15535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_uv;
15555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_indicate_partition_disengaged =
15565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	    xpc_indicate_partition_disengaged_uv;
15575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_uv;
15585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_partition_engaged = xpc_partition_engaged_uv;
15595b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	xpc_any_partition_engaged = xpc_any_partition_engaged_uv;
15605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
1561bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv;
1562bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv;
1563bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_send_payload = xpc_send_payload_uv;
1564bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv;
1565bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_get_deliverable_payload = xpc_get_deliverable_payload_uv;
1566bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	xpc_received_payload = xpc_received_payload_uv;
1567bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
1568bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
1569bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
1570bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson			XPC_MSG_HDR_MAX_SIZE);
1571bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson		return -E2BIG;
1572bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
15735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15742525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0,
15752525789b4694d78df4f001063f042b2b74227d26Dean Nelson						  XPC_ACTIVATE_IRQ_NAME,
15765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson						  xpc_handle_activate_IRQ_uv);
15772525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (IS_ERR(xpc_activate_mq_uv))
15782525789b4694d78df4f001063f042b2b74227d26Dean Nelson		return PTR_ERR(xpc_activate_mq_uv);
15795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson
15802525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0,
15812525789b4694d78df4f001063f042b2b74227d26Dean Nelson						XPC_NOTIFY_IRQ_NAME,
1582bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson						xpc_handle_notify_IRQ_uv);
15832525789b4694d78df4f001063f042b2b74227d26Dean Nelson	if (IS_ERR(xpc_notify_mq_uv)) {
15842525789b4694d78df4f001063f042b2b74227d26Dean Nelson		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
15852525789b4694d78df4f001063f042b2b74227d26Dean Nelson		return PTR_ERR(xpc_notify_mq_uv);
1586bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson	}
1587bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson
15885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson	return 0;
158994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson}
159094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson
159194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelsonvoid
159294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelsonxpc_exit_uv(void)
159394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson{
15942525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
15952525789b4694d78df4f001063f042b2b74227d26Dean Nelson	xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
159694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson}
1597