xpc_main.c revision a47d5dac9d8481766382f8cf1483dd581df38b99
189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This file is subject to the terms and conditions of the GNU General Public 389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * License. See the file "COPYING" in the main directory of this archive 489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * for more details. 589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 645d9ca492e4bd1522d1b5bd125c2908f1cee3d4aDean Nelson * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. 789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 1089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Cross Partition Communication (XPC) support - standard version. 1189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 1289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * XPC provides a message passing capability that crosses partition 1389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * boundaries. This module is made up of two parts: 1489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 1589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition This part detects the presence/absence of other 1689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partitions. It provides a heartbeat and monitors 1789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * the heartbeats of other partitions. 1889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 1989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * channel This part manages the channels and sends/receives 2089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * messages across them to/from other partitions. 2189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 2289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * There are a couple of additional functions residing in XP, which 2389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * provide an interface to XPC for its users. 2489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 2589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 2689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Caveats: 2789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 2889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * . We currently have no way to determine which nasid an IPI came 29a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * from. Thus, >>> xpc_IPI_send() does a remote AMO write followed by 3089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * an IPI. The AMO indicates where data is to be pulled from, so 3189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * after the IPI arrives, the remote partition checks the AMO word. 3289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The IPI can actually arrive before the AMO however, so other code 3389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * must periodically check for this case. Also, remote AMO operations 3489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * do not reliably time out. Thus we do a remote PIO read solely to 3589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * know whether the remote partition is down and whether we should 3689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * stop sending IPIs to it. This remote PIO read operation is set up 3789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * in a special nofault region so SAL knows to ignore (and cleanup) 3889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * any errors due to the remote AMO write, PIO read, and/or PIO 3989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * write operations. 4089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 4189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * If/when new hardware solves this IPI problem, we should abandon 4289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * the current approach. 4389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 4489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 4589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 4689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <linux/kernel.h> 4789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <linux/module.h> 4889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <linux/init.h> 4989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <linux/cache.h> 5089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <linux/interrupt.h> 51699139279d29e36e39d353b0536b510dab2e5ffaNishanth Aravamudan#include <linux/delay.h> 52a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson#include <linux/reboot.h> 53f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen#include <linux/completion.h> 541eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig#include <linux/kdebug.h> 552c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson#include <linux/kthread.h> 562c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson#include <linux/uaccess.h> 5789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <asm/sn/intr.h> 5889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson#include <asm/sn/sn_sal.h> 5945d9ca492e4bd1522d1b5bd125c2908f1cee3d4aDean Nelson#include "xpc.h" 6089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* define two XPC debug device structures to be used with dev_dbg() et al */ 6289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device_driver xpc_dbg_name = { 6489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .name = "xpc" 6589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 6689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device xpc_part_dbg_subname = { 6889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .bus_id = {0}, /* set to "part" at xpc_init() time */ 6989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .driver = &xpc_dbg_name 7089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 7189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 7289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device xpc_chan_dbg_subname = { 7389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .bus_id = {0}, /* set to "chan" at xpc_init() time */ 7489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .driver = &xpc_dbg_name 7589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 7689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 7789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device *xpc_part = &xpc_part_dbg_subname; 7889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device *xpc_chan = &xpc_chan_dbg_subname; 7989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 801f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelsonstatic int xpc_kdebug_ignore; 811f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 8289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* systune related variables for /proc/sys directories */ 8389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 84a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; 85a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_min_interval = 1; 86a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_max_interval = 10; 8789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 88a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL; 89a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_min_interval = 10; 90a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_max_interval = 120; 9189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 92a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint xpc_disengage_timelimit = XPC_DISENGAGE_DEFAULT_TIMELIMIT; 93a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonstatic int xpc_disengage_min_timelimit; /* = 0 */ 94a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonstatic int xpc_disengage_max_timelimit = 120; 9589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 9689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_xpc_hb_dir[] = { 9789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 9835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .ctl_name = CTL_UNNUMBERED, 9935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb_interval", 10035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .data = &xpc_hb_interval, 10135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 10235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 10335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .proc_handler = &proc_dointvec_minmax, 10435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .strategy = &sysctl_intvec, 10535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra1 = &xpc_hb_min_interval, 10635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra2 = &xpc_hb_max_interval}, 10789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 10835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .ctl_name = CTL_UNNUMBERED, 10935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb_check_interval", 11035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .data = &xpc_hb_check_interval, 11135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 11235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 11335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .proc_handler = &proc_dointvec_minmax, 11435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .strategy = &sysctl_intvec, 11535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra1 = &xpc_hb_check_min_interval, 11635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra2 = &xpc_hb_check_max_interval}, 11768cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 11889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 11989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_xpc_dir[] = { 12089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 12135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .ctl_name = CTL_UNNUMBERED, 12235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb", 12335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0555, 12435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .child = xpc_sys_xpc_hb_dir}, 125e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson { 12635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .ctl_name = CTL_UNNUMBERED, 127a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .procname = "disengage_timelimit", 128a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .data = &xpc_disengage_timelimit, 12935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 13035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 13135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .proc_handler = &proc_dointvec_minmax, 13235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .strategy = &sysctl_intvec, 133a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .extra1 = &xpc_disengage_min_timelimit, 134a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .extra2 = &xpc_disengage_max_timelimit}, 13568cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 13689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 13789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_dir[] = { 13889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 13935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .ctl_name = CTL_UNNUMBERED, 14035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "xpc", 14135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0555, 14235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .child = xpc_sys_xpc_dir}, 14368cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 14489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 14589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic struct ctl_table_header *xpc_sysctl; 14689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 147a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson/* non-zero if any remote partition disengage was timed out */ 148a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint xpc_disengage_timedout; 14989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1506e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson/* #of activate IRQs received */ 1516e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelsonatomic_t xpc_activate_IRQ_rcvd = ATOMIC_INIT(0); 15289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 15389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* IRQ handler notifies this wait queue on receipt of an IRQ */ 1546e41017aad9ed175ca51e4828eabc8c5cf5910beDean NelsonDECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq); 15589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 15689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic unsigned long xpc_hb_check_timeout; 15733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic struct timer_list xpc_hb_timer; 15833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid *xpc_heartbeating_to_mask; 15989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 160e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson/* notification that the xpc_hb_checker thread has exited */ 161f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensenstatic DECLARE_COMPLETION(xpc_hb_checker_exited); 16289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 163e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson/* notification that the xpc_discovery thread has exited */ 164f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensenstatic DECLARE_COMPLETION(xpc_discovery_exited); 16589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 16689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *); 16789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 168a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_system_reboot(struct notifier_block *, unsigned long, void *); 169a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic struct notifier_block xpc_reboot_notifier = { 170a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson .notifier_call = xpc_system_reboot, 171a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson}; 172a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 173780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic int xpc_system_die(struct notifier_block *, unsigned long, void *); 174780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic struct notifier_block xpc_die_notifier = { 175780d09e895032207a6b070a44d392a3c60574b70Dean Nelson .notifier_call = xpc_system_die, 176780d09e895032207a6b070a44d392a3c60574b70Dean Nelson}; 177780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 17894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelsonenum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *rp); 17933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_heartbeat_init) (void); 18033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_heartbeat_exit) (void); 18133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_increment_heartbeat) (void); 18233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_offline_heartbeat) (void); 18333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_online_heartbeat) (void); 18433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_check_remote_hb) (void); 18533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 186e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonenum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); 187a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch); 188e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonu64 (*xpc_get_IPI_flags) (struct xpc_partition *part); 189a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_process_msg_IPI) (struct xpc_partition *part, int ch_number); 190a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch); 191e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonstruct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); 19233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 193a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_request_partition_activation) (struct xpc_rsvd_page *remote_rp, 194a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson u64 remote_rp_pa, int nasid); 195a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_request_partition_reactivation) (struct xpc_partition *part); 196a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_request_partition_deactivation) (struct xpc_partition *part); 197a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_cancel_partition_deactivation_request) (struct xpc_partition *part); 19833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 1996e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelsonvoid (*xpc_process_activate_IRQ_rcvd) (int n_IRQs_expected); 200e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonenum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *part); 201e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelsonvoid (*xpc_teardown_infrastructure) (struct xpc_partition *part); 202e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson 203a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_indicate_partition_engaged) (struct xpc_partition *part); 204a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint (*xpc_partition_engaged) (short partid); 205a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint (*xpc_any_partition_engaged) (void); 206a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_indicate_partition_disengaged) (struct xpc_partition *part); 207a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_assume_partition_disengaged) (short partid); 208a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson 209a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_send_channel_closerequest) (struct xpc_channel *ch, 210a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long *irq_flags); 211a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_send_channel_closereply) (struct xpc_channel *ch, 212a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long *irq_flags); 213a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_send_channel_openrequest) (struct xpc_channel *ch, 214a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long *irq_flags); 215a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonvoid (*xpc_send_channel_openreply) (struct xpc_channel *ch, 216a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long *irq_flags); 21733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 21897bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelsonenum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags, 21997bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson void *payload, u16 payload_size, u8 notify_type, 22097bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson xpc_notify_func func, void *key); 22133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonvoid (*xpc_received_msg) (struct xpc_channel *ch, struct xpc_msg *msg); 22294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 223a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson/* 224a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Timer function to enforce the timelimit on the partition disengage. 225a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson */ 226a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic void 227a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_timeout_partition_disengage(unsigned long data) 228a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson{ 22935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson struct xpc_partition *part = (struct xpc_partition *)data; 230a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 231a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(time_is_after_jiffies(part->disengage_timeout)); 232a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 23335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)xpc_partition_disengaged(part); 234a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 235a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(part->disengage_timeout != 0); 236a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(xpc_partition_engaged(XPC_PARTID(part))); 237a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson} 238a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 23989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 24089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Timer to produce the heartbeat. The timer structures function is 24189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * already set when this is initially called. A tunable is used to 24289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * specify when the next timeout should occur. 24389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 24489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 24589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_hb_beater(unsigned long dummy) 24689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 24733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_increment_heartbeat(); 24889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 249aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) 2506e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson wake_up_interruptible(&xpc_activate_IRQ_wq); 25189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 25289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ); 25389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson add_timer(&xpc_hb_timer); 25489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 25589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 25633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void 25733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_start_hb_beater(void) 25833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{ 25933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_heartbeat_init(); 26033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson init_timer(&xpc_hb_timer); 26133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_hb_timer.function = xpc_hb_beater; 26233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_hb_beater(0); 26333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson} 26433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 26533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void 26633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_stop_hb_beater(void) 26733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{ 26833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson del_timer_sync(&xpc_hb_timer); 26933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_heartbeat_exit(); 27033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson} 27133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 27289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 27389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This thread is responsible for nearly all of the partition 27489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * activation/deactivation. 27589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 27689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 27789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_hb_checker(void *ignore) 27889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 27989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int last_IRQ_count = 0; 28089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int new_IRQ_count; 28135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson int force_IRQ = 0; 28289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 28389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* this thread was marked active by xpc_hb_init() */ 28489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 2850bc3cc03fa6e1c20aecb5a33356bcaae410640b9Mike Travis set_cpus_allowed_ptr(current, &cpumask_of_cpu(XPC_HB_CHECK_CPU)); 28689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 2874c013f5c7ea39cd62e02c80408560751b4e8c0deDean Nelson /* set our heartbeating to other partitions into motion */ 28889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); 28933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_start_hb_beater(); 29089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 2912c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson while (!xpc_exiting) { 29289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 29389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have " 29489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "been received\n", 29535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (int)(xpc_hb_check_timeout - jiffies), 2966e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson atomic_read(&xpc_activate_IRQ_rcvd) - last_IRQ_count); 29789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 29889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* checking of remote heartbeats is skewed by IRQ handling */ 299aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) { 30089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "checking remote heartbeats\n"); 30189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_check_remote_hb(); 30289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 30389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 30489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * We need to periodically recheck to ensure no 30589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * IPI/AMO pairs have been missed. That check 30689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * must always reset xpc_hb_check_timeout. 30789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 30889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson force_IRQ = 1; 30989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 31089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 311a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* check for outstanding IRQs */ 3126e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson new_IRQ_count = atomic_read(&xpc_activate_IRQ_rcvd); 31389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) { 31489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson force_IRQ = 0; 31589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 31689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "found an IRQ to process; will be " 31789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "resetting xpc_hb_check_timeout\n"); 31889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 3196e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_process_activate_IRQ_rcvd(new_IRQ_count - 3206e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson last_IRQ_count); 32189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson last_IRQ_count = new_IRQ_count; 32289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 32389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_hb_check_timeout = jiffies + 32435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (xpc_hb_check_interval * HZ); 32589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 326a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 327a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* wait for IRQ or timeout */ 3286e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson (void)wait_event_interruptible(xpc_activate_IRQ_wq, 3296e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson (last_IRQ_count < atomic_read( 3306e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson &xpc_activate_IRQ_rcvd) 331aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson || time_is_before_eq_jiffies( 332aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson xpc_hb_check_timeout) || 3332c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson xpc_exiting)); 33489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 33589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 33633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_stop_hb_beater(); 33733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 33889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "heartbeat checker is exiting\n"); 33989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 340e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* mark this thread as having exited */ 341f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_hb_checker_exited); 34289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 34389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 34489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 34589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 34689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This thread will attempt to discover other partitions to activate 34789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * based on info provided by SAL. This new thread is short lived and 34889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * will exit once discovery is complete. 34989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 35089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 35189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_initiate_discovery(void *ignore) 35289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 35389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_discovery(); 35489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 35589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "discovery thread is exiting\n"); 35689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 357e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* mark this thread as having exited */ 358f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_discovery_exited); 35989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 36089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 36189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 36289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 36389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The first kthread assigned to a newly activated partition is the one 364e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * created by XPC HB with which it calls xpc_activating(). XPC hangs on to 36589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that kthread until the partition is brought down, at which time that kthread 36689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * returns back to XPC HB. (The return of that kthread will signify to XPC HB 36789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that XPC has dismantled all communication infrastructure for the associated 36889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition.) This kthread becomes the channel manager for that partition. 36989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 37089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Each active partition has a channel manager, who, besides connecting and 37189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * disconnecting channels, will ensure that each of the partition's connected 37289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * channels has the required number of assigned kthreads to get the work done. 37389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 37489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 37589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_channel_mgr(struct xpc_partition *part) 37689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 37789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson while (part->act_state != XPC_P_DEACTIVATING || 37835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson atomic_read(&part->nchannels_active) > 0 || 37935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson !xpc_partition_disengaged(part)) { 38089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 38189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_process_channel_activity(part); 38289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 38389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 38489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Wait until we've been requested to activate kthreads or 38589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * all of the channel's message queues have been torn down or 38689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * a signal is pending. 38789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 38889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The channel_mgr_requests is set to 1 after being awakened, 38989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This is done to prevent the channel mgr from making one pass 39089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * through the loop for each request, since he will 39189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * be servicing all the requests in one pass. The reason it's 39289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * set to 1 instead of 0 is so that other kthreads will know 39389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that the channel mgr is running and won't bother trying to 39489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * wake him up. 39589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 39689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&part->channel_mgr_requests); 39735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)wait_event_interruptible(part->channel_mgr_wq, 3982c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson (atomic_read(&part->channel_mgr_requests) > 0 || 3992c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson part->local_IPI_amo != 0 || 4002c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson (part->act_state == XPC_P_DEACTIVATING && 4012c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson atomic_read(&part->nchannels_active) == 0 && 4022c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson xpc_partition_disengaged(part)))); 40389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_set(&part->channel_mgr_requests, 1); 40489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 40589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 40689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 40789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 40889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * When XPC HB determines that a partition has come up, it will create a new 40989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * kthread and that kthread will call this function to attempt to set up the 41089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * basic infrastructure used for Cross Partition Communication with the newly 41189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * upped partition. 41289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 41389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The kthread that was created by XPC HB and which setup the XPC 414e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * infrastructure will remain assigned to the partition becoming the channel 415e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * manager for that partition until the partition is deactivating, at which 416e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * time the kthread will teardown the XPC infrastructure and then exit. 41789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 41889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 41989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activating(void *__partid) 42089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 42164d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = (u64)__partid; 42289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part = &xpc_partitions[partid]; 42389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 42489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 425bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson DBUG_ON(partid < 0 || partid >= xp_max_npartitions); 42689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 42789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&part->act_lock, irq_flags); 42889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 42989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (part->act_state == XPC_P_DEACTIVATING) { 43089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->act_state = XPC_P_INACTIVE; 43189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 43289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->remote_rp_pa = 0; 43389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 43489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 43589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 43689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* indicate the thread is activating */ 43789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ); 43889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->act_state = XPC_P_ACTIVATING; 43989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 44089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson XPC_SET_REASON(part, 0, 0); 44189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 44289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 443e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson dev_dbg(xpc_part, "activating partition %d\n", partid); 44489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 44533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_allow_hb(partid); 44689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 447e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson if (xpc_setup_infrastructure(part) == xpSuccess) { 448e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson (void)xpc_part_ref(part); /* this will always succeed */ 449e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson 450e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson if (xpc_make_first_contact(part) == xpSuccess) { 451e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_mark_partition_active(part); 452e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_channel_mgr(part); 453e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson /* won't return until partition is deactivating */ 454e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson } 455e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson 456e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_part_deref(part); 457e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_teardown_infrastructure(part); 458e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson } 45989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 46033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_disallow_hb(partid); 46189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_mark_partition_inactive(part); 46289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 46365c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson if (part->reason == xpReactivating) { 46489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* interrupting ourselves results in activating partition */ 465a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_request_partition_reactivation(part); 46689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 46789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 46889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 46989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 47089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 47189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 47289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activate_partition(struct xpc_partition *part) 47389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 47464d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = XPC_PARTID(part); 47589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 4762c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 47789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 47889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&part->act_lock, irq_flags); 47989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 48089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson DBUG_ON(part->act_state != XPC_P_INACTIVE); 48189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 4827c6c66362941df847957766ad133ff5fde67579cRobin Holt part->act_state = XPC_P_ACTIVATION_REQ; 48365c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_SET_REASON(part, xpCloneKThread, __LINE__); 48489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 48589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 4867c6c66362941df847957766ad133ff5fde67579cRobin Holt 4872c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_activating, (void *)((u64)partid), "xpc%02d", 4882c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson partid); 4892c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 4907c6c66362941df847957766ad133ff5fde67579cRobin Holt spin_lock_irqsave(&part->act_lock, irq_flags); 4917c6c66362941df847957766ad133ff5fde67579cRobin Holt part->act_state = XPC_P_INACTIVE; 49265c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_SET_REASON(part, xpCloneKThreadFailed, __LINE__); 4937c6c66362941df847957766ad133ff5fde67579cRobin Holt spin_unlock_irqrestore(&part->act_lock, irq_flags); 4947c6c66362941df847957766ad133ff5fde67579cRobin Holt } 49589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 49689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 49789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 49889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activate_kthreads(struct xpc_channel *ch, int needed) 49989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 50089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int idle = atomic_read(&ch->kthreads_idle); 50189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int assigned = atomic_read(&ch->kthreads_assigned); 50289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int wakeup; 50389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 50489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson DBUG_ON(needed <= 0); 50589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 50689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (idle > 0) { 50789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson wakeup = (needed > idle) ? idle : needed; 50889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed -= wakeup; 50989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 51089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, " 51189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "channel=%d\n", wakeup, ch->partid, ch->number); 51289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 51389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* only wakeup the requested number of kthreads */ 51489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson wake_up_nr(&ch->idle_wq, wakeup); 51589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 51689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5172c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (needed <= 0) 51889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return; 51989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 52089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (needed + assigned > ch->kthreads_assigned_limit) { 52189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed = ch->kthreads_assigned_limit - assigned; 5222c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (needed <= 0) 52389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return; 52489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 52589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 52689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n", 52789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed, ch->partid, ch->number); 52889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 529a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson xpc_create_kthreads(ch, needed, 0); 53089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 53189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 53289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 53389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This function is where XPC's kthreads wait for messages to deliver. 53489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 53589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 53689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch) 53789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 53889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson do { 53989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* deliver messages to their intended recipients */ 54089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 541a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson while (xpc_n_of_deliverable_msgs(ch) > 0 && 5422c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson !(ch->flags & XPC_C_DISCONNECTING)) { 54389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_deliver_msg(ch); 54489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 54589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 54689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (atomic_inc_return(&ch->kthreads_idle) > 54735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->kthreads_idle_limit) { 54889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* too many idle kthreads on this channel */ 54989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&ch->kthreads_idle); 55089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson break; 55189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 55289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 55389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "idle kthread calling " 55489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "wait_event_interruptible_exclusive()\n"); 55589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 55635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)wait_event_interruptible_exclusive(ch->idle_wq, 557a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (xpc_n_of_deliverable_msgs(ch) > 0 || 5582c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson (ch->flags & XPC_C_DISCONNECTING))); 55989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 56089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&ch->kthreads_idle); 56189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5622c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson } while (!(ch->flags & XPC_C_DISCONNECTING)); 56389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 56489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 56589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 5662c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelsonxpc_kthread_start(void *args) 56789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 56864d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = XPC_UNPACK_ARG1(args); 56989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson u16 ch_number = XPC_UNPACK_ARG2(args); 57089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part = &xpc_partitions[partid]; 57189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_channel *ch; 57289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int n_needed; 573e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson unsigned long irq_flags; 57489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 57589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n", 57689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson partid, ch_number); 57789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 57889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson ch = &part->channels[ch_number]; 57989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 58089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (!(ch->flags & XPC_C_DISCONNECTING)) { 58189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 58289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* let registerer know that connection has been established */ 58389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 584e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 5854c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { 5864c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson ch->flags |= XPC_C_CONNECTEDCALLOUT; 587e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 588e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 58989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_connected_callout(ch); 59089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5914c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 5924c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE; 5934c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 5944c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson 59589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 59689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * It is possible that while the callout was being 59789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * made that the remote partition sent some messages. 59889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * If that is the case, we may need to activate 59989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * additional kthreads to help deliver them. We only 60089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * need one less than total #of messages to deliver. 60189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 602a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson n_needed = xpc_n_of_deliverable_msgs(ch) - 1; 6032c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING)) 60489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_activate_kthreads(ch, n_needed); 6052c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 606e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } else { 607e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 60889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 60989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 61089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_kthread_waitmsgs(part, ch); 61189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 61289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 613a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* let registerer know that connection is disconnecting */ 614e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 615a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 616a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && 61735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { 618a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson ch->flags |= XPC_C_DISCONNECTINGCALLOUT; 6194c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 620a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 62165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_disconnect_callout(ch, xpDisconnecting); 622a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 623a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 624a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; 625a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 626a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 627a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 628a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (atomic_dec_return(&ch->kthreads_assigned) == 0 && 629a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson atomic_dec_return(&part->nchannels_engaged) == 0) { 630a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_indicate_partition_disengaged(part); 63189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 63289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 63389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_msgqueue_deref(ch); 63489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 63589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n", 63689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson partid, ch_number); 63789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 63889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_part_deref(part); 63989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 64089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 64189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 64289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 64389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * For each partition that XPC has established communications with, there is 64489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * a minimum of one kernel thread assigned to perform any operation that 64589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * may potentially sleep or block (basically the callouts to the asynchronous 64689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * functions registered via xpc_connect()). 64789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 64889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Additional kthreads are created and destroyed by XPC as the workload 64989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * demands. 65089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 65189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * A kthread is assigned to one of the active channels that exists for a given 65289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition. 65389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 65489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 655a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelsonxpc_create_kthreads(struct xpc_channel *ch, int needed, 65635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson int ignore_disconnecting) 65789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 65889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 65989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson u64 args = XPC_PACK_ARGS(ch->partid, ch->number); 660a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson struct xpc_partition *part = &xpc_partitions[ch->partid]; 6612c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 66289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 66389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson while (needed-- > 0) { 664e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 665e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* 666e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * The following is done on behalf of the newly created 667e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * kthread. That kthread is responsible for doing the 668e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * counterpart to the following before it exits. 669e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson */ 670a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if (ignore_disconnecting) { 671a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if (!atomic_inc_not_zero(&ch->kthreads_assigned)) { 672a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* kthreads assigned had gone to zero */ 673a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson BUG_ON(!(ch->flags & 67435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson XPC_C_DISCONNECTINGCALLOUT_MADE)); 675a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson break; 676a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 677a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 678a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } else if (ch->flags & XPC_C_DISCONNECTING) { 679a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson break; 680a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 681a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson } else if (atomic_inc_return(&ch->kthreads_assigned) == 1 && 682a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson atomic_inc_return(&part->nchannels_engaged) == 1) { 683a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_indicate_partition_engaged(part); 684a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 68535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)xpc_part_ref(part); 686e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_msgqueue_ref(ch); 687e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 6882c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_kthread_start, (void *)args, 6892c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson "xpc%02dc%d", ch->partid, ch->number); 6902c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 69189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* the fork failed */ 692a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 693a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* 694a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * NOTE: if (ignore_disconnecting && 695a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true, 696a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * then we'll deadlock if all other kthreads assigned 697a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * to this channel are blocked in the channel's 698a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * registerer, because the only thing that will unblock 69965c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson * them is the xpDisconnecting callout that this 7002c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson * failed kthread_run() would have made. 701a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson */ 702a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 703e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (atomic_dec_return(&ch->kthreads_assigned) == 0 && 704e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson atomic_dec_return(&part->nchannels_engaged) == 0) { 705a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_indicate_partition_disengaged(part); 706e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } 707e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_msgqueue_deref(ch); 708e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_part_deref(part); 70989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 71089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (atomic_read(&ch->kthreads_assigned) < 71135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->kthreads_idle_limit) { 71289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 71389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Flag this as an error only if we have an 71489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * insufficient #of kthreads for the channel 71589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * to function. 71689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 71789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 71865c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_DISCONNECT_CHANNEL(ch, xpLackOfResources, 71935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson &irq_flags); 72089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 72189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 72289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson break; 72389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 72489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 72589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 72689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 72789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 72889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_disconnect_wait(int ch_number) 72989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 730a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson unsigned long irq_flags; 73164d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 73289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part; 73389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_channel *ch; 734e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson int wakeup_channel_mgr; 73589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 73689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* now wait for all callouts to the caller's function to cease */ 737bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 73889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part = &xpc_partitions[partid]; 73989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 7402c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_part_ref(part)) 741e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson continue; 74289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 743e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson ch = &part->channels[ch_number]; 74489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 745e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (!(ch->flags & XPC_C_WDISCONNECT)) { 74689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_part_deref(part); 747e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson continue; 74889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 749e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 750f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&ch->wdisconnect_wait); 751e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 752e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 753e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); 754e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson wakeup_channel_mgr = 0; 755e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 756e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (ch->delayed_IPI_flags) { 757e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (part->act_state != XPC_P_DEACTIVATING) { 758e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_lock(&part->IPI_lock); 759e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson XPC_SET_IPI_FLAGS(part->local_IPI_amo, 76035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->number, 76135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->delayed_IPI_flags); 762e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock(&part->IPI_lock); 763e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson wakeup_channel_mgr = 1; 764e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } 765e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson ch->delayed_IPI_flags = 0; 76689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 767e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 768e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson ch->flags &= ~XPC_C_WDISCONNECT; 769e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 770e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 7712c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (wakeup_channel_mgr) 772e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_wakeup_channel_mgr(part); 773e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 774e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_part_deref(part); 77589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 77689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 77789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 77889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 77965c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelsonxpc_do_exit(enum xp_retval reason) 78089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 78164d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 7821ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson int active_part_count, printed_waiting_msg = 0; 78389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part; 784a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long printmsg_time, disengage_timeout = 0; 78589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 786a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ 787a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson DBUG_ON(xpc_exiting == 1); 78889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 78989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 790a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * Let the heartbeat checker thread and the discovery thread 791a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * (if one is running) know that they should exit. Also wake up 792a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * the heartbeat checker thread in case it's sleeping. 79389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 79489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_exiting = 1; 7956e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson wake_up_interruptible(&xpc_activate_IRQ_wq); 79689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 797e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* wait for the discovery thread to exit */ 798f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&xpc_discovery_exited); 79989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 800e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* wait for the heartbeat checker thread to exit */ 801f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&xpc_hb_checker_exited); 80289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 803a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* sleep for a 1/3 of a second or so */ 80435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)msleep_interruptible(300); 80589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 80689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* wait for all partitions to become inactive */ 80789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 808a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson printmsg_time = jiffies + (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ); 809a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_disengage_timedout = 0; 810a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 81189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson do { 81289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson active_part_count = 0; 81389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 814bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 81589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part = &xpc_partitions[partid]; 81689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 817a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson if (xpc_partition_disengaged(part) && 81835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson part->act_state == XPC_P_INACTIVE) { 819a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson continue; 82089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 821a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 822a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson active_part_count++; 823a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 824a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson XPC_DEACTIVATE_PARTITION(part, reason); 82589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 826a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (part->disengage_timeout > disengage_timeout) 827a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson disengage_timeout = part->disengage_timeout; 828a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson } 82989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 830a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (xpc_any_partition_engaged()) { 831aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_jiffies(printmsg_time)) { 8321ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "waiting for remote " 833a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "partitions to deactivate, timeout in " 834a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "%ld seconds\n", (disengage_timeout - 835a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson jiffies) / HZ); 8361ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printmsg_time = jiffies + 837a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ); 8381ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printed_waiting_msg = 1; 8391ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 8401ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 8411ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } else if (active_part_count > 0) { 8421ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson if (printed_waiting_msg) { 8431ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "waiting for local partition" 844a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson " to deactivate\n"); 8451ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printed_waiting_msg = 0; 8461ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 8471ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 8481ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } else { 849a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (!xpc_disengage_timedout) { 8501ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "all partitions have " 851a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "deactivated\n"); 8521ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 8531ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 85489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 85589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 856a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* sleep for a 1/3 of a second or so */ 85735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)msleep_interruptible(300); 858a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 859a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson } while (1); 860a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 861a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(xpc_any_partition_engaged()); 86233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson DBUG_ON(xpc_any_hbs_allowed() != 0); 863a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 864a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* indicate to others that our reserved page is uninitialized */ 865aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson xpc_rsvd_page->stamp = 0; 866a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 86765c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson if (reason == xpUnloading) { 86835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)unregister_die_notifier(&xpc_die_notifier); 869bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_reboot_notifier(&xpc_reboot_notifier); 8700752c670d83362609c7f3f59ffa0e180709c60c2Dean Nelson } 871780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 87289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* clear the interface to XPC's functions */ 87389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_clear_interface(); 87489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 8752c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (xpc_sysctl) 87689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unregister_sysctl_table(xpc_sysctl); 8777682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson 878bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson kfree(xpc_partitions); 8797682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson kfree(xpc_remote_copy_buffer_base); 8806e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson 8816e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson if (is_shub()) 8826e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_sn2(); 8836e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson else 8846e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_uv(); 88589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 88689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 887a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson/* 888d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson * This function is called when the system is being rebooted. 889d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson */ 890d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelsonstatic int 891d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelsonxpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) 892d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson{ 89365c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson enum xp_retval reason; 894d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 895d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson switch (event) { 896d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_RESTART: 89765c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemReboot; 898d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 899d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_HALT: 90065c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemHalt; 901d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 902d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_POWER_OFF: 90365c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemPoweroff; 904d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 905d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson default: 90665c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemGoingDown; 907d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson } 908d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 909d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson xpc_do_exit(reason); 910d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson return NOTIFY_DONE; 911d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson} 912d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 913d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson/* 914a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Notify other partitions to deactivate from us by first disengaging from all 915a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * references to our memory. 916780d09e895032207a6b070a44d392a3c60574b70Dean Nelson */ 917780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic void 918a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_die_deactivate(void) 919780d09e895032207a6b070a44d392a3c60574b70Dean Nelson{ 920780d09e895032207a6b070a44d392a3c60574b70Dean Nelson struct xpc_partition *part; 92164d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 922a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson int any_engaged; 923a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson long time, printmsg_time, disengage_timeout; 924780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 925780d09e895032207a6b070a44d392a3c60574b70Dean Nelson /* keep xpc_hb_checker thread from doing anything (just in case) */ 926780d09e895032207a6b070a44d392a3c60574b70Dean Nelson xpc_exiting = 1; 927780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 92833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_disallow_all_hbs(); /*indicate we're deactivated */ 929780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 930bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 931780d09e895032207a6b070a44d392a3c60574b70Dean Nelson part = &xpc_partitions[partid]; 932780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 933a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (xpc_partition_engaged(partid) || 93435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson part->act_state != XPC_P_INACTIVE) { 935a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_request_partition_deactivation(part); 936a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_indicate_partition_disengaged(part); 937780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 938780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 939780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 9401ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson time = rtc_time(); 9411ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printmsg_time = time + 942a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (XPC_DEACTIVATE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second); 943a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson disengage_timeout = time + 944a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (xpc_disengage_timelimit * sn_rtc_cycles_per_second); 945780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 946a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson /* 947a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Though we requested that all other partitions deactivate from us, 948a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * we only wait until they've all disengaged. 949a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson */ 950780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 9511ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson while (1) { 952a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson any_engaged = xpc_any_partition_engaged(); 953a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (!any_engaged) { 954a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson dev_info(xpc_part, "all partitions have deactivated\n"); 9551ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 9561ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 957780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 9581ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson time = rtc_time(); 959a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (time >= disengage_timeout) { 960bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; 961bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson partid++) { 962a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (xpc_partition_engaged(partid)) { 963a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson dev_info(xpc_part, "deactivate from " 96435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "remote partition %d timed " 96535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "out\n", partid); 9661ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 9671ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 9681ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 9691ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 9701ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 9711ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson if (time >= printmsg_time) { 972780d09e895032207a6b070a44d392a3c60574b70Dean Nelson dev_info(xpc_part, "waiting for remote partitions to " 973a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "deactivate, timeout in %ld seconds\n", 974a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (disengage_timeout - time) / 97535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson sn_rtc_cycles_per_second); 9761ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printmsg_time = time + 977a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (XPC_DEACTIVATE_PRINTMSG_INTERVAL * 97835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson sn_rtc_cycles_per_second); 979780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 980780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 981780d09e895032207a6b070a44d392a3c60574b70Dean Nelson} 982780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 983780d09e895032207a6b070a44d392a3c60574b70Dean Nelson/* 9841f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * This function is called when the system is being restarted or halted due 9851f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * to some sort of system failure. If this is the case we need to notify the 9861f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * other partitions to disengage from all references to our memory. 9871f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * This function can also be called when our heartbeater could be offlined 9881f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * for a time. In this case we need to notify other partitions to not worry 9891f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * about the lack of a heartbeat. 990780d09e895032207a6b070a44d392a3c60574b70Dean Nelson */ 991780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic int 992780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonxpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 993780d09e895032207a6b070a44d392a3c60574b70Dean Nelson{ 994780d09e895032207a6b070a44d392a3c60574b70Dean Nelson switch (event) { 995780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MACHINE_RESTART: 996780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MACHINE_HALT: 997a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_die_deactivate(); 998780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 9991f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 10001f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson case DIE_KDEBUG_ENTER: 10011f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* Should lack of heartbeat be ignored by other partitions? */ 10022c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_kdebug_ignore) 10031f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson break; 10042c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 10051f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* fall through */ 1006780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MCA_MONARCH_ENTER: 1007780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_INIT_MONARCH_ENTER: 100833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_offline_heartbeat(); 1009780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 10101f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 10111f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson case DIE_KDEBUG_LEAVE: 10121f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* Is lack of heartbeat being ignored by other partitions? */ 10132c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_kdebug_ignore) 10141f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson break; 10152c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 10161f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* fall through */ 1017780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MCA_MONARCH_LEAVE: 1018780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_INIT_MONARCH_LEAVE: 101933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_online_heartbeat(); 1020780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 1021780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1022780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1023780d09e895032207a6b070a44d392a3c60574b70Dean Nelson return NOTIFY_DONE; 1024780d09e895032207a6b070a44d392a3c60574b70Dean Nelson} 1025780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 102689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonint __init 102789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_init(void) 102889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 102989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int ret; 103064d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 103189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part; 10322c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 10337682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson size_t buf_size; 103489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 103594bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson if (is_shub()) { 103694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson /* 103794bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * The ia64-sn2 architecture supports at most 64 partitions. 103894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * And the inability to unregister remote AMOs restricts us 103994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * further to only support exactly 64 partitions on this 104094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * architecture, no less. 104194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson */ 104294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson if (xp_max_npartitions != 64) 104394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson return -EINVAL; 104494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 10456e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson ret = xpc_init_sn2(); 10466e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson if (ret != 0) 10476e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson return ret; 104894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 104994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } else if (is_uv()) { 105094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson xpc_init_uv(); 105194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 105294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } else { 1053408865ce4829376120489ac8011b72125453dcffDean Nelson return -ENODEV; 105494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } 1055408865ce4829376120489ac8011b72125453dcffDean Nelson 1056bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); 1057bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); 1058bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson 10597682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson buf_size = max(XPC_RP_VARS_SIZE, 106035190506b1a18eda7df24b285fdcd94dec7800efDean Nelson XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES); 10617682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size, 106235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson GFP_KERNEL, 10632c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson &xpc_remote_copy_buffer_base); 1064bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson if (xpc_remote_copy_buffer == NULL) { 1065bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson dev_err(xpc_part, "can't get memory for remote copy buffer\n"); 10666e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson ret = -ENOMEM; 10676e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson goto out_1; 1068bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson } 106989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1070bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson xpc_partitions = kzalloc(sizeof(struct xpc_partition) * 1071bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson xp_max_npartitions, GFP_KERNEL); 1072bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson if (xpc_partitions == NULL) { 1073bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson dev_err(xpc_part, "can't get memory for partition structure\n"); 1074bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson ret = -ENOMEM; 10756e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson goto out_2; 1076bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson } 107789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 107889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 107989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The first few fields of each entry of xpc_partitions[] need to 108089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * be initialized now so that calls to xpc_connect() and 108189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * xpc_disconnect() can be made prior to the activation of any remote 108289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE 108389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING 108489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * PARTITION HAS BEEN ACTIVATED. 108589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 1086bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 108789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part = &xpc_partitions[partid]; 108889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 108935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part)); 109089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 10916e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson part->activate_IRQ_rcvd = 0; 109289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_init(&part->act_lock); 109389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->act_state = XPC_P_INACTIVE; 109489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson XPC_SET_REASON(part, 0, 0); 1095a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 1096a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson init_timer(&part->disengage_timer); 1097a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson part->disengage_timer.function = 1098a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_timeout_partition_disengage; 1099a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson part->disengage_timer.data = (unsigned long)part; 1100a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 110189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->setup_state = XPC_P_UNSET; 110289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson init_waitqueue_head(&part->teardown_wq); 110389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_set(&part->references, 0); 110489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 110589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1106bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson xpc_sysctl = register_sysctl_table(xpc_sys_dir); 1107bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson 110889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 110989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Fill the partition reserved page with the information needed by 111089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * other partitions to discover we are alive and establish initial 111189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * communications. 111289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 111394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson xpc_rsvd_page = xpc_setup_rsvd_page(); 111489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (xpc_rsvd_page == NULL) { 1115bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson dev_err(xpc_part, "can't setup our reserved page\n"); 1116bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson ret = -EBUSY; 1117bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson goto out_3; 111889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 111989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1120a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* add ourselves to the reboot_notifier_list */ 1121a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson ret = register_reboot_notifier(&xpc_reboot_notifier); 11222c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (ret != 0) 1123a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson dev_warn(xpc_part, "can't register reboot notifier\n"); 1124a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 11251eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig /* add ourselves to the die_notifier list */ 1126780d09e895032207a6b070a44d392a3c60574b70Dean Nelson ret = register_die_notifier(&xpc_die_notifier); 11272c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (ret != 0) 1128780d09e895032207a6b070a44d392a3c60574b70Dean Nelson dev_warn(xpc_part, "can't register die notifier\n"); 1129780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 113089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 113189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The real work-horse behind xpc. This processes incoming 113289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * interrupts and monitors remote heartbeats. 113389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 11342c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME); 11352c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 113689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_err(xpc_part, "failed while forking hb check thread\n"); 1137bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson ret = -EBUSY; 1138bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson goto out_4; 113989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 114089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 114189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 114289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Startup a thread that will attempt to discover other partitions to 114389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * activate based on info provided by SAL. This new thread is short 114489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * lived and will exit once discovery is complete. 114589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 11462c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_initiate_discovery, NULL, 11472c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson XPC_DISCOVERY_THREAD_NAME); 11482c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 114989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_err(xpc_part, "failed while forking discovery thread\n"); 115089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 115189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* mark this new thread as a non-starter */ 1152f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_discovery_exited); 115389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 115465c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_do_exit(xpUnloading); 115589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return -EBUSY; 115689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 115789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 115889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* set the interface to point at XPC's functions */ 115989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect, 116097bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson xpc_initiate_send, xpc_initiate_send_notify, 116197bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson xpc_initiate_received, xpc_initiate_partid_to_nasids); 116289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 116389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 1164bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson 1165bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson /* initialization was not successful */ 1166bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonout_4: 1167bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson /* indicate to others that our reserved page is uninitialized */ 1168aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson xpc_rsvd_page->stamp = 0; 116994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 1170bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_die_notifier(&xpc_die_notifier); 1171bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_reboot_notifier(&xpc_reboot_notifier); 1172bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelsonout_3: 1173bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson if (xpc_sysctl) 1174bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson unregister_sysctl_table(xpc_sysctl); 1175bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson kfree(xpc_partitions); 11766e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelsonout_2: 1177bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson kfree(xpc_remote_copy_buffer_base); 11786e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelsonout_1: 11796e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson if (is_shub()) 11806e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_sn2(); 11816e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson else 11826e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_uv(); 1183bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson return ret; 118489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 118589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 118635190506b1a18eda7df24b285fdcd94dec7800efDean Nelsonmodule_init(xpc_init); 118789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 118889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid __exit 118989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_exit(void) 119089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 119165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_do_exit(xpUnloading); 119289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 119389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 119435190506b1a18eda7df24b285fdcd94dec7800efDean Nelsonmodule_exit(xpc_exit); 119589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 119689eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_AUTHOR("Silicon Graphics, Inc."); 119789eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_DESCRIPTION("Cross Partition Communication (XPC) support"); 119889eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_LICENSE("GPL"); 119989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 120089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonmodule_param(xpc_hb_interval, int, 0); 120189eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between " 120235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "heartbeat increments."); 120389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 120489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonmodule_param(xpc_hb_check_interval, int, 0); 120589eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between " 120635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "heartbeat checks."); 120789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1208a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonmodule_param(xpc_disengage_timelimit, int, 0); 1209a47d5dac9d8481766382f8cf1483dd581df38b99Dean NelsonMODULE_PARM_DESC(xpc_disengage_timelimit, "Number of seconds to wait " 1210a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "for disengage to complete."); 1211e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 12121f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelsonmodule_param(xpc_kdebug_ignore, int, 0); 12131f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean NelsonMODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by " 121435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "other partitions when dropping into kdebug."); 1215