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 * 6a374c57b0764432a80303abee3d1afd1939b5a0aRobin Holt * Copyright (c) 2004-2009 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 * 287fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * . Currently on sn2, we have no way to determine which nasid an IRQ 29c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * came from. Thus, xpc_send_IRQ_sn2() does a remote amo write 30c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * followed by an IPI. The amo indicates where data is to be pulled 31c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * from, so after the IPI arrives, the remote partition checks the amo 32c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * word. The IPI can actually arrive before the amo however, so other 33c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * code must periodically check for this case. Also, remote amo 347fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * operations do not reliably time out. Thus we do a remote PIO read 357fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * solely to know whether the remote partition is down and whether we 367fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * should stop sending IPIs to it. This remote PIO read operation is 377fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * set up in a special nofault region so SAL knows to ignore (and 38c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * cleanup) any errors due to the remote amo write, PIO read, and/or 397fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson * PIO 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/module.h> 475a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 48261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#include <linux/sysctl.h> 49261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#include <linux/device.h> 50699139279d29e36e39d353b0536b510dab2e5ffaNishanth Aravamudan#include <linux/delay.h> 51a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson#include <linux/reboot.h> 521eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig#include <linux/kdebug.h> 532c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson#include <linux/kthread.h> 5445d9ca492e4bd1522d1b5bd125c2908f1cee3d4aDean Nelson#include "xpc.h" 5589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* define two XPC debug device structures to be used with dev_dbg() et al */ 5789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device_driver xpc_dbg_name = { 5989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .name = "xpc" 6089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 6189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device xpc_part_dbg_subname = { 63bb0dc43eeeea6a3ace7fae42e583a9be176eb1f9Kay Sievers .init_name = "", /* set to "part" at xpc_init() time */ 6489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .driver = &xpc_dbg_name 6589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 6689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device xpc_chan_dbg_subname = { 68bb0dc43eeeea6a3ace7fae42e583a9be176eb1f9Kay Sievers .init_name = "", /* set to "chan" at xpc_init() time */ 6989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson .driver = &xpc_dbg_name 7089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 7189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 7289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device *xpc_part = &xpc_part_dbg_subname; 7389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstruct device *xpc_chan = &xpc_chan_dbg_subname; 7489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 751f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelsonstatic int xpc_kdebug_ignore; 761f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 7789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* systune related variables for /proc/sys directories */ 7889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 79a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; 80a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_min_interval = 1; 81a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_max_interval = 10; 8289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 83a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL; 84a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_min_interval = 10; 85a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_hb_check_max_interval = 120; 8689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 87a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint xpc_disengage_timelimit = XPC_DISENGAGE_DEFAULT_TIMELIMIT; 88a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonstatic int xpc_disengage_min_timelimit; /* = 0 */ 89a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonstatic int xpc_disengage_max_timelimit = 120; 9089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 9189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_xpc_hb_dir[] = { 9289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 9335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb_interval", 9435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .data = &xpc_hb_interval, 9535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 9635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 976d4561110a3e9fa742aeec6717248a491dfb1878Eric W. Biederman .proc_handler = proc_dointvec_minmax, 9835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra1 = &xpc_hb_min_interval, 9935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra2 = &xpc_hb_max_interval}, 10089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 10135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb_check_interval", 10235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .data = &xpc_hb_check_interval, 10335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 10435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 1056d4561110a3e9fa742aeec6717248a491dfb1878Eric W. Biederman .proc_handler = proc_dointvec_minmax, 10635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra1 = &xpc_hb_check_min_interval, 10735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .extra2 = &xpc_hb_check_max_interval}, 10868cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 10989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 11089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_xpc_dir[] = { 11189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 11235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "hb", 11335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0555, 11435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .child = xpc_sys_xpc_hb_dir}, 115e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson { 116a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .procname = "disengage_timelimit", 117a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .data = &xpc_disengage_timelimit, 11835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .maxlen = sizeof(int), 11935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0644, 1206d4561110a3e9fa742aeec6717248a491dfb1878Eric W. Biederman .proc_handler = proc_dointvec_minmax, 121a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .extra1 = &xpc_disengage_min_timelimit, 122a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson .extra2 = &xpc_disengage_max_timelimit}, 12368cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 12489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 12589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic ctl_table xpc_sys_dir[] = { 12689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson { 12735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .procname = "xpc", 12835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .mode = 0555, 12935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson .child = xpc_sys_xpc_dir}, 13068cbf0753681b3f79437f16d2f9a259b9346cf84Eric W. Biederman {} 13189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson}; 13289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic struct ctl_table_header *xpc_sysctl; 13389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 134a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson/* non-zero if any remote partition disengage was timed out */ 135a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonint xpc_disengage_timedout; 13689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson/* #of activate IRQs received and not yet processed */ 1385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonint xpc_activate_IRQ_rcvd; 1395b8669dfd110a62a74eea525a009342f73987ea0Dean NelsonDEFINE_SPINLOCK(xpc_activate_IRQ_rcvd_lock); 14089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 14189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* IRQ handler notifies this wait queue on receipt of an IRQ */ 1426e41017aad9ed175ca51e4828eabc8c5cf5910beDean NelsonDECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq); 14389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 14489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic unsigned long xpc_hb_check_timeout; 14533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic struct timer_list xpc_hb_timer; 14689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 147e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson/* notification that the xpc_hb_checker thread has exited */ 148f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensenstatic DECLARE_COMPLETION(xpc_hb_checker_exited); 14989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 150e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson/* notification that the xpc_discovery thread has exited */ 151f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensenstatic DECLARE_COMPLETION(xpc_discovery_exited); 15289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 15389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *); 15489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 155a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic int xpc_system_reboot(struct notifier_block *, unsigned long, void *); 156a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic struct notifier_block xpc_reboot_notifier = { 157a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson .notifier_call = xpc_system_reboot, 158a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson}; 159a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 160780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic int xpc_system_die(struct notifier_block *, unsigned long, void *); 161780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic struct notifier_block xpc_die_notifier = { 162780d09e895032207a6b070a44d392a3c60574b70Dean Nelson .notifier_call = xpc_system_die, 163780d09e895032207a6b070a44d392a3c60574b70Dean Nelson}; 164780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 165a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holtstruct xpc_arch_operations xpc_arch_ops; 16694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 167a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson/* 168a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Timer function to enforce the timelimit on the partition disengage. 169a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson */ 170a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelsonstatic void 171a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_timeout_partition_disengage(unsigned long data) 172a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson{ 17335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson struct xpc_partition *part = (struct xpc_partition *)data; 174a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 175a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(time_is_after_jiffies(part->disengage_timeout)); 176a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 17735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)xpc_partition_disengaged(part); 178a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 179a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson DBUG_ON(part->disengage_timeout != 0); 180a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt DBUG_ON(xpc_arch_ops.partition_engaged(XPC_PARTID(part))); 181a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson} 182a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 18389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 18489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Timer to produce the heartbeat. The timer structures function is 18589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * already set when this is initially called. A tunable is used to 18689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * specify when the next timeout should occur. 18789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 18889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 18989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_hb_beater(unsigned long dummy) 19089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 191a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.increment_heartbeat(); 19289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 193aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) 1946e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson wake_up_interruptible(&xpc_activate_IRQ_wq); 19589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 19689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ); 19789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson add_timer(&xpc_hb_timer); 19889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 19989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 20033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void 20133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_start_hb_beater(void) 20233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{ 203a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.heartbeat_init(); 20433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson init_timer(&xpc_hb_timer); 20533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_hb_timer.function = xpc_hb_beater; 20633ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_hb_beater(0); 20733ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson} 20833ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 20933ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonstatic void 21033ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelsonxpc_stop_hb_beater(void) 21133ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson{ 21233ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson del_timer_sync(&xpc_hb_timer); 213a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.heartbeat_exit(); 21433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson} 21533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 21689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 21761deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson * At periodic intervals, scan through all active partitions and ensure 21861deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson * their heartbeat is still active. If not, the partition is deactivated. 21961deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson */ 22061deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelsonstatic void 22161deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelsonxpc_check_remote_hb(void) 22261deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson{ 22361deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson struct xpc_partition *part; 22461deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson short partid; 22561deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson enum xp_retval ret; 22661deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 22761deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 22861deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 22961deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson if (xpc_exiting) 23061deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson break; 23161deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 23261deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson if (partid == xp_partition_id) 23361deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson continue; 23461deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 23561deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson part = &xpc_partitions[partid]; 23661deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 23783469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson if (part->act_state == XPC_P_AS_INACTIVE || 23883469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state == XPC_P_AS_DEACTIVATING) { 23961deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson continue; 24061deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson } 24161deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 242a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt ret = xpc_arch_ops.get_remote_heartbeat(part); 24361deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson if (ret != xpSuccess) 24461deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson XPC_DEACTIVATE_PARTITION(part, ret); 24561deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson } 24661deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson} 24761deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson 24861deb86e98f51151b225f7563ee1cf2b50857d10Dean Nelson/* 24989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This thread is responsible for nearly all of the partition 25089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * activation/deactivation. 25189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 25289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 25389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_hb_checker(void *ignore) 25489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 25535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson int force_IRQ = 0; 25689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 25789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* this thread was marked active by xpc_hb_init() */ 25889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 259f7df8ed164996cd2c6aca9674388be6ef78d8b37Rusty Russell set_cpus_allowed_ptr(current, cpumask_of(XPC_HB_CHECK_CPU)); 26089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 2614c013f5c7ea39cd62e02c80408560751b4e8c0deDean Nelson /* set our heartbeating to other partitions into motion */ 26289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); 26333ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_start_hb_beater(); 26489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 2652c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson while (!xpc_exiting) { 26689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 26789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have " 26889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "been received\n", 26935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (int)(xpc_hb_check_timeout - jiffies), 2705b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_activate_IRQ_rcvd); 27189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 27289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* checking of remote heartbeats is skewed by IRQ handling */ 273aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) { 2745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_hb_check_timeout = jiffies + 2755b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson (xpc_hb_check_interval * HZ); 2765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 27789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "checking remote heartbeats\n"); 27889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_check_remote_hb(); 27989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 28089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 2815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * On sn2 we need to periodically recheck to ensure no 2825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * IRQ/amo pairs have been missed. 28389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 2845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (is_shub()) 2855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson force_IRQ = 1; 28689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 28789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 288a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* check for outstanding IRQs */ 2895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (xpc_activate_IRQ_rcvd > 0 || force_IRQ != 0) { 29089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson force_IRQ = 0; 2915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson dev_dbg(xpc_part, "processing activate IRQs " 2925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson "received\n"); 293a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.process_activate_IRQ_rcvd(); 29489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 295a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 296a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* wait for IRQ or timeout */ 2976e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson (void)wait_event_interruptible(xpc_activate_IRQ_wq, 2985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson (time_is_before_eq_jiffies( 299aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson xpc_hb_check_timeout) || 3005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_activate_IRQ_rcvd > 0 || 3012c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson xpc_exiting)); 30289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 30389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 30433ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson xpc_stop_hb_beater(); 30533ba3c7724be79f7cdbfc611335572c056d9a05aDean Nelson 30689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "heartbeat checker is exiting\n"); 30789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 308e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* mark this thread as having exited */ 309f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_hb_checker_exited); 31089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 31189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 31289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 31389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 31489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This thread will attempt to discover other partitions to activate 31589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * based on info provided by SAL. This new thread is short lived and 31689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * will exit once discovery is complete. 31789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 31889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 31989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_initiate_discovery(void *ignore) 32089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 32189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_discovery(); 32289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 32389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_part, "discovery thread is exiting\n"); 32489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 325e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* mark this thread as having exited */ 326f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_discovery_exited); 32789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 32889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 32989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 33089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 33189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The first kthread assigned to a newly activated partition is the one 332e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * created by XPC HB with which it calls xpc_activating(). XPC hangs on to 33389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that kthread until the partition is brought down, at which time that kthread 33489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * returns back to XPC HB. (The return of that kthread will signify to XPC HB 33589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that XPC has dismantled all communication infrastructure for the associated 33689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition.) This kthread becomes the channel manager for that partition. 33789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 33889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Each active partition has a channel manager, who, besides connecting and 33989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * disconnecting channels, will ensure that each of the partition's connected 34089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * channels has the required number of assigned kthreads to get the work done. 34189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 34289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 34389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_channel_mgr(struct xpc_partition *part) 34489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 34583469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson while (part->act_state != XPC_P_AS_DEACTIVATING || 34635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson atomic_read(&part->nchannels_active) > 0 || 34735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson !xpc_partition_disengaged(part)) { 34889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 3497fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson xpc_process_sent_chctl_flags(part); 35089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 35189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 35289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Wait until we've been requested to activate kthreads or 35389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * all of the channel's message queues have been torn down or 35489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * a signal is pending. 35589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 35689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The channel_mgr_requests is set to 1 after being awakened, 35789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This is done to prevent the channel mgr from making one pass 35889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * through the loop for each request, since he will 35989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * be servicing all the requests in one pass. The reason it's 36089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * set to 1 instead of 0 is so that other kthreads will know 36189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * that the channel mgr is running and won't bother trying to 36289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * wake him up. 36389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 36489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&part->channel_mgr_requests); 36535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)wait_event_interruptible(part->channel_mgr_wq, 3662c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson (atomic_read(&part->channel_mgr_requests) > 0 || 3677fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson part->chctl.all_flags != 0 || 36883469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson (part->act_state == XPC_P_AS_DEACTIVATING && 3692c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson atomic_read(&part->nchannels_active) == 0 && 3702c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson xpc_partition_disengaged(part)))); 37189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_set(&part->channel_mgr_requests, 1); 37289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 37389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 37489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 37589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 3765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Guarantee that the kzalloc'd memory is cacheline aligned. 3775b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 3785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonvoid * 3795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) 3805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{ 3815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* see if kzalloc will give us cachline aligned memory by default */ 3825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson *base = kzalloc(size, flags); 3835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (*base == NULL) 3845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return NULL; 3855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 3865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if ((u64)*base == L1_CACHE_ALIGN((u64)*base)) 3875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return *base; 3885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 3895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(*base); 3905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 3915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* nope, we'll have to do it ourselves */ 3925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson *base = kzalloc(size + L1_CACHE_BYTES, flags); 3935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (*base == NULL) 3945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return NULL; 3955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 3965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return (void *)L1_CACHE_ALIGN((u64)*base); 3975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson} 3985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 3995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson/* 4005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Setup the channel structures necessary to support XPartition Communication 4015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * between the specified remote partition and the local one. 4025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 4035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic enum xp_retval 4045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_ch_structures(struct xpc_partition *part) 4055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{ 4065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson enum xp_retval ret; 4075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson int ch_number; 4085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson struct xpc_channel *ch; 4095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson short partid = XPC_PARTID(part); 4105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* 4125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Allocate all of the channel structures as a contiguous chunk of 4135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * memory. 4145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 4155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson DBUG_ON(part->channels != NULL); 4165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS, 4175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson GFP_KERNEL); 4185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (part->channels == NULL) { 4195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson dev_err(xpc_chan, "can't get memory for channels\n"); 4205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return xpNoMemory; 4215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 4225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4235b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* allocate the remote open and close args */ 4245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->remote_openclose_args = 4265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, 4275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson GFP_KERNEL, &part-> 4285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson remote_openclose_args_base); 4295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (part->remote_openclose_args == NULL) { 4305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson dev_err(xpc_chan, "can't get memory for remote connect args\n"); 4315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = xpNoMemory; 4325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson goto out_1; 4335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 4345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->chctl.all_flags = 0; 4365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson spin_lock_init(&part->chctl_lock); 4375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&part->channel_mgr_requests, 1); 4395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_waitqueue_head(&part->channel_mgr_wq); 4405b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->nchannels = XPC_MAX_NCHANNELS; 4425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&part->nchannels_active, 0); 4445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&part->nchannels_engaged, 0); 4455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson for (ch_number = 0; ch_number < part->nchannels; ch_number++) { 4475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ch = &part->channels[ch_number]; 4485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ch->partid = partid; 4505b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ch->number = ch_number; 4515b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ch->flags = XPC_C_DISCONNECTED; 4525b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4535b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->kthreads_assigned, 0); 4545b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->kthreads_idle, 0); 4555b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->kthreads_active, 0); 4565b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4575b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->references, 0); 4585b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->n_to_notify, 0); 4595b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4605b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson spin_lock_init(&ch->lock); 4615b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_completion(&ch->wdisconnect_wait); 4625b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4635b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&ch->n_on_msg_allocate_wq, 0); 4645b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_waitqueue_head(&ch->msg_allocate_wq); 4655b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_waitqueue_head(&ch->idle_wq); 4665b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 4675b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 468a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt ret = xpc_arch_ops.setup_ch_structures(part); 4695b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (ret != xpSuccess) 4705b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson goto out_2; 4715b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* 4735b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * With the setting of the partition setup_state to XPC_P_SS_SETUP, 4745b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * we're declaring that this partition is ready to go. 4755b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 4765b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->setup_state = XPC_P_SS_SETUP; 4775b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4785b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return xpSuccess; 4795b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4805b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* setup of ch structures failed */ 4815b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonout_2: 4825b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(part->remote_openclose_args_base); 4835b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->remote_openclose_args = NULL; 4845b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonout_1: 4855b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(part->channels); 4865b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->channels = NULL; 4875b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return ret; 4885b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson} 4895b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 4905b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson/* 4915b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Teardown the channel structures necessary to support XPartition Communication 4925b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * between the specified remote partition and the local one. 4935b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 4945b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void 4955b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_teardown_ch_structures(struct xpc_partition *part) 4965b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{ 4975b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson DBUG_ON(atomic_read(&part->nchannels_engaged) != 0); 4985b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson DBUG_ON(atomic_read(&part->nchannels_active) != 0); 4995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* 5015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * Make this partition inaccessible to local processes by marking it 5025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * as no longer setup. Then wait before proceeding with the teardown 5035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * until all existing references cease. 5045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 5055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson DBUG_ON(part->setup_state != XPC_P_SS_SETUP); 5065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->setup_state = XPC_P_SS_WTEARDOWN; 5075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson wait_event(part->teardown_wq, (atomic_read(&part->references) == 0)); 5095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* now we can begin tearing down the infrastructure */ 5115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 512a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.teardown_ch_structures(part); 5135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(part->remote_openclose_args_base); 5155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->remote_openclose_args = NULL; 5165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(part->channels); 5175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->channels = NULL; 5185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->setup_state = XPC_P_SS_TORNDOWN; 5205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson} 5215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 5225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson/* 52389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * When XPC HB determines that a partition has come up, it will create a new 52489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * kthread and that kthread will call this function to attempt to set up the 52589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * basic infrastructure used for Cross Partition Communication with the newly 52689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * upped partition. 52789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 52889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The kthread that was created by XPC HB and which setup the XPC 529e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * infrastructure will remain assigned to the partition becoming the channel 530e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * manager for that partition until the partition is deactivating, at which 531e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson * time the kthread will teardown the XPC infrastructure and then exit. 53289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 53389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 53489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activating(void *__partid) 53589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 53664d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = (u64)__partid; 53789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part = &xpc_partitions[partid]; 53889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 53989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 540bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson DBUG_ON(partid < 0 || partid >= xp_max_npartitions); 54189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 54289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&part->act_lock, irq_flags); 54389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 54483469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson if (part->act_state == XPC_P_AS_DEACTIVATING) { 54583469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state = XPC_P_AS_INACTIVE; 54689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 54789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part->remote_rp_pa = 0; 54889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 54989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 55089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 55189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* indicate the thread is activating */ 55283469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson DBUG_ON(part->act_state != XPC_P_AS_ACTIVATION_REQ); 55383469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state = XPC_P_AS_ACTIVATING; 55489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 55589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson XPC_SET_REASON(part, 0, 0); 55689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 55789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 558e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson dev_dbg(xpc_part, "activating partition %d\n", partid); 55989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 560a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.allow_hb(partid); 56189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 5625b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (xpc_setup_ch_structures(part) == xpSuccess) { 563e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson (void)xpc_part_ref(part); /* this will always succeed */ 564e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson 565a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt if (xpc_arch_ops.make_first_contact(part) == xpSuccess) { 566e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_mark_partition_active(part); 567e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_channel_mgr(part); 568e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson /* won't return until partition is deactivating */ 569e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson } 570e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson 571e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson xpc_part_deref(part); 5725b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_teardown_ch_structures(part); 573e17d416b1bc947df68499863f13b401fb42b48f6Dean Nelson } 57489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 575a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.disallow_hb(partid); 57689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_mark_partition_inactive(part); 57789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 57865c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson if (part->reason == xpReactivating) { 57989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* interrupting ourselves results in activating partition */ 580a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.request_partition_reactivation(part); 58189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 58289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 58389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 58489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 58589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 58689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 58789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activate_partition(struct xpc_partition *part) 58889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 58964d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = XPC_PARTID(part); 59089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 5912c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 59289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 59389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&part->act_lock, irq_flags); 59489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 59583469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson DBUG_ON(part->act_state != XPC_P_AS_INACTIVE); 59689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 59783469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state = XPC_P_AS_ACTIVATION_REQ; 59865c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_SET_REASON(part, xpCloneKThread, __LINE__); 59989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 60089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&part->act_lock, irq_flags); 6017c6c66362941df847957766ad133ff5fde67579cRobin Holt 6022c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_activating, (void *)((u64)partid), "xpc%02d", 6032c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson partid); 6042c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 6057c6c66362941df847957766ad133ff5fde67579cRobin Holt spin_lock_irqsave(&part->act_lock, irq_flags); 60683469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state = XPC_P_AS_INACTIVE; 60765c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_SET_REASON(part, xpCloneKThreadFailed, __LINE__); 6087c6c66362941df847957766ad133ff5fde67579cRobin Holt spin_unlock_irqrestore(&part->act_lock, irq_flags); 6097c6c66362941df847957766ad133ff5fde67579cRobin Holt } 61089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 61189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 61289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 61389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_activate_kthreads(struct xpc_channel *ch, int needed) 61489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 61589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int idle = atomic_read(&ch->kthreads_idle); 61689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int assigned = atomic_read(&ch->kthreads_assigned); 61789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int wakeup; 61889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 61989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson DBUG_ON(needed <= 0); 62089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 62189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (idle > 0) { 62289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson wakeup = (needed > idle) ? idle : needed; 62389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed -= wakeup; 62489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 62589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, " 62689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "channel=%d\n", wakeup, ch->partid, ch->number); 62789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 62889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* only wakeup the requested number of kthreads */ 62989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson wake_up_nr(&ch->idle_wq, wakeup); 63089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 63189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6322c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (needed <= 0) 63389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return; 63489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 63589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (needed + assigned > ch->kthreads_assigned_limit) { 63689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed = ch->kthreads_assigned_limit - assigned; 6372c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (needed <= 0) 63889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return; 63989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 64089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 64189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n", 64289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson needed, ch->partid, ch->number); 64389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 644a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson xpc_create_kthreads(ch, needed, 0); 64589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 64689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 64789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 64889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * This function is where XPC's kthreads wait for messages to deliver. 64989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 65089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 65189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch) 65289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 653a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt int (*n_of_deliverable_payloads) (struct xpc_channel *) = 654a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.n_of_deliverable_payloads; 655a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt 65689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson do { 65789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* deliver messages to their intended recipients */ 65889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 659a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt while (n_of_deliverable_payloads(ch) > 0 && 6602c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson !(ch->flags & XPC_C_DISCONNECTING)) { 661bd3e64c1759e4930315ebf022611468ee9621486Dean Nelson xpc_deliver_payload(ch); 66289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 66389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 66489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (atomic_inc_return(&ch->kthreads_idle) > 66535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->kthreads_idle_limit) { 66689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* too many idle kthreads on this channel */ 66789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&ch->kthreads_idle); 66889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson break; 66989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 67089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 67189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "idle kthread calling " 67289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson "wait_event_interruptible_exclusive()\n"); 67389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 67435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)wait_event_interruptible_exclusive(ch->idle_wq, 675a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt (n_of_deliverable_payloads(ch) > 0 || 6762c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson (ch->flags & XPC_C_DISCONNECTING))); 67789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 67889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson atomic_dec(&ch->kthreads_idle); 67989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 6802c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson } while (!(ch->flags & XPC_C_DISCONNECTING)); 68189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 68289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 68389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic int 6842c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelsonxpc_kthread_start(void *args) 68589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 68664d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid = XPC_UNPACK_ARG1(args); 68789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson u16 ch_number = XPC_UNPACK_ARG2(args); 68889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part = &xpc_partitions[partid]; 68989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_channel *ch; 69089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int n_needed; 691e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson unsigned long irq_flags; 692a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt int (*n_of_deliverable_payloads) (struct xpc_channel *) = 693a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.n_of_deliverable_payloads; 69489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 69589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n", 69689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson partid, ch_number); 69789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 69889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson ch = &part->channels[ch_number]; 69989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 70089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (!(ch->flags & XPC_C_DISCONNECTING)) { 70189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 70289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* let registerer know that connection has been established */ 70389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 704e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 7054c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { 7064c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson ch->flags |= XPC_C_CONNECTEDCALLOUT; 707e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 708e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 70989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_connected_callout(ch); 71089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 7114c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 7124c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE; 7134c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 7144c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson 71589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 71689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * It is possible that while the callout was being 71789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * made that the remote partition sent some messages. 71889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * If that is the case, we may need to activate 71989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * additional kthreads to help deliver them. We only 72089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * need one less than total #of messages to deliver. 72189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 722a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt n_needed = n_of_deliverable_payloads(ch) - 1; 7232c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING)) 72489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_activate_kthreads(ch, n_needed); 7252c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 726e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } else { 727e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 72889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 72989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 73089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_kthread_waitmsgs(part, ch); 73189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 73289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 733a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* let registerer know that connection is disconnecting */ 734e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 735a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 736a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && 73735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { 738a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson ch->flags |= XPC_C_DISCONNECTINGCALLOUT; 7394c2cd96696ae0896ce4bcf725b9f0eaffafeb640Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 740a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 74165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_disconnect_callout(ch, xpDisconnecting); 742a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 743a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 744a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; 745a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 746a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 747a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 748a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (atomic_dec_return(&ch->kthreads_assigned) == 0 && 749a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson atomic_dec_return(&part->nchannels_engaged) == 0) { 750a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.indicate_partition_disengaged(part); 75189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 75289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 75389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_msgqueue_deref(ch); 75489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 75589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n", 75689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson partid, ch_number); 75789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 75889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_part_deref(part); 75989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 76089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 76189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 76289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson/* 76389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * For each partition that XPC has established communications with, there is 76489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * a minimum of one kernel thread assigned to perform any operation that 76589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * may potentially sleep or block (basically the callouts to the asynchronous 76689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * functions registered via xpc_connect()). 76789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 76889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Additional kthreads are created and destroyed by XPC as the workload 76989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * demands. 77089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * 77189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * A kthread is assigned to one of the active channels that exists for a given 77289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * partition. 77389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 77489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 775a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelsonxpc_create_kthreads(struct xpc_channel *ch, int needed, 77635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson int ignore_disconnecting) 77789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 77889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unsigned long irq_flags; 77989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson u64 args = XPC_PACK_ARGS(ch->partid, ch->number); 780a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson struct xpc_partition *part = &xpc_partitions[ch->partid]; 7812c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 782a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt void (*indicate_partition_disengaged) (struct xpc_partition *) = 783a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.indicate_partition_disengaged; 78489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 78589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson while (needed-- > 0) { 786e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 787e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* 788e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * The following is done on behalf of the newly created 789e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * kthread. That kthread is responsible for doing the 790e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson * counterpart to the following before it exits. 791e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson */ 792a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if (ignore_disconnecting) { 793a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson if (!atomic_inc_not_zero(&ch->kthreads_assigned)) { 794a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* kthreads assigned had gone to zero */ 795a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson BUG_ON(!(ch->flags & 79635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson XPC_C_DISCONNECTINGCALLOUT_MADE)); 797a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson break; 798a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 799a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 800a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } else if (ch->flags & XPC_C_DISCONNECTING) { 801a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson break; 802a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 803a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson } else if (atomic_inc_return(&ch->kthreads_assigned) == 1 && 804a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson atomic_inc_return(&part->nchannels_engaged) == 1) { 805a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.indicate_partition_engaged(part); 806a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson } 80735190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)xpc_part_ref(part); 808e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_msgqueue_ref(ch); 809e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 8102c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_kthread_start, (void *)args, 8112c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson "xpc%02dc%d", ch->partid, ch->number); 8122c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 81389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* the fork failed */ 814a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 815a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson /* 816a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * NOTE: if (ignore_disconnecting && 817a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true, 818a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * then we'll deadlock if all other kthreads assigned 819a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * to this channel are blocked in the channel's 820a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson * registerer, because the only thing that will unblock 82165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson * them is the xpDisconnecting callout that this 8222c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson * failed kthread_run() would have made. 823a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson */ 824a460ef8d0a98ac9ef6b829ae292c9b6c13bc0120Dean Nelson 825e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (atomic_dec_return(&ch->kthreads_assigned) == 0 && 826e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson atomic_dec_return(&part->nchannels_engaged) == 0) { 827a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt indicate_partition_disengaged(part); 828e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } 829e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_msgqueue_deref(ch); 830e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_part_deref(part); 83189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 83289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson if (atomic_read(&ch->kthreads_assigned) < 83335190506b1a18eda7df24b285fdcd94dec7800efDean Nelson ch->kthreads_idle_limit) { 83489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 83589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Flag this as an error only if we have an 83689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * insufficient #of kthreads for the channel 83789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * to function. 83889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 83989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 84065c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson XPC_DISCONNECT_CHANNEL(ch, xpLackOfResources, 84135190506b1a18eda7df24b285fdcd94dec7800efDean Nelson &irq_flags); 84289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 84389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 84489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson break; 84589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 84689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 84789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 84889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 84989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid 85089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_disconnect_wait(int ch_number) 85189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 852a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson unsigned long irq_flags; 85364d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 85489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part; 85589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_channel *ch; 856e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson int wakeup_channel_mgr; 85789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 85889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* now wait for all callouts to the caller's function to cease */ 859bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 86089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part = &xpc_partitions[partid]; 86189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 8622c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_part_ref(part)) 863e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson continue; 86489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 865e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson ch = &part->channels[ch_number]; 86689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 867e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson if (!(ch->flags & XPC_C_WDISCONNECT)) { 86889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_part_deref(part); 869e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson continue; 87089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 871e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 872f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&ch->wdisconnect_wait); 873e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 874e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_lock_irqsave(&ch->lock, irq_flags); 875e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); 876e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson wakeup_channel_mgr = 0; 877e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 8787fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson if (ch->delayed_chctl_flags) { 87983469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson if (part->act_state != XPC_P_AS_DEACTIVATING) { 8807fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson spin_lock(&part->chctl_lock); 8817fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson part->chctl.flags[ch->number] |= 8827fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson ch->delayed_chctl_flags; 8837fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson spin_unlock(&part->chctl_lock); 884e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson wakeup_channel_mgr = 1; 885e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson } 8867fb5e59d63deda89a8eefdbd5b3c8d622076afd4Dean Nelson ch->delayed_chctl_flags = 0; 88789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 888e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 889e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson ch->flags &= ~XPC_C_WDISCONNECT; 890e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson spin_unlock_irqrestore(&ch->lock, irq_flags); 891e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 8922c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (wakeup_channel_mgr) 893e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_wakeup_channel_mgr(part); 894e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 895e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson xpc_part_deref(part); 89689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 89789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 89889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 8995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic int 9005b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_setup_partitions(void) 9015b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{ 9025b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson short partid; 9035b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson struct xpc_partition *part; 9045b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9055b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_partitions = kzalloc(sizeof(struct xpc_partition) * 9065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xp_max_npartitions, GFP_KERNEL); 9075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (xpc_partitions == NULL) { 9085b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson dev_err(xpc_part, "can't get memory for partition structure\n"); 9095b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return -ENOMEM; 9105b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 9115b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9125b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson /* 9135b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * The first few fields of each entry of xpc_partitions[] need to 9145b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * be initialized now so that calls to xpc_connect() and 9155b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * xpc_disconnect() can be made prior to the activation of any remote 9165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE 9175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING 9185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson * PARTITION HAS BEEN ACTIVATED. 9195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson */ 9205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 9215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part = &xpc_partitions[partid]; 9225b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9235b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part)); 9245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9255b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->activate_IRQ_rcvd = 0; 9265b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson spin_lock_init(&part->act_lock); 9275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->act_state = XPC_P_AS_INACTIVE; 9285b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson XPC_SET_REASON(part, 0, 0); 9295b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_timer(&part->disengage_timer); 9315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->disengage_timer.function = 9325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_timeout_partition_disengage; 9335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->disengage_timer.data = (unsigned long)part; 9345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson part->setup_state = XPC_P_SS_UNSET; 9365b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson init_waitqueue_head(&part->teardown_wq); 9375b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson atomic_set(&part->references, 0); 9385b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 9395b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 940a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt return xpc_arch_ops.setup_partitions(); 9415b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson} 9425b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 9435b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonstatic void 9445b8669dfd110a62a74eea525a009342f73987ea0Dean Nelsonxpc_teardown_partitions(void) 9455b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson{ 946a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.teardown_partitions(); 9475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson kfree(xpc_partitions); 9485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson} 9495b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 95089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonstatic void 95165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelsonxpc_do_exit(enum xp_retval reason) 95289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 95364d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 9541ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson int active_part_count, printed_waiting_msg = 0; 95589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson struct xpc_partition *part; 956a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson unsigned long printmsg_time, disengage_timeout = 0; 95789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 958a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ 959a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson DBUG_ON(xpc_exiting == 1); 96089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 96189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 962a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * Let the heartbeat checker thread and the discovery thread 963a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * (if one is running) know that they should exit. Also wake up 964a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson * the heartbeat checker thread in case it's sleeping. 96589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 96689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_exiting = 1; 9676e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson wake_up_interruptible(&xpc_activate_IRQ_wq); 96889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 969e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* wait for the discovery thread to exit */ 970f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&xpc_discovery_exited); 97189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 972e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson /* wait for the heartbeat checker thread to exit */ 973f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen wait_for_completion(&xpc_hb_checker_exited); 97489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 975a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* sleep for a 1/3 of a second or so */ 97635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)msleep_interruptible(300); 97789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 97889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* wait for all partitions to become inactive */ 97989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 980a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson printmsg_time = jiffies + (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ); 981a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_disengage_timedout = 0; 982a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 98389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson do { 98489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson active_part_count = 0; 98589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 986bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 98789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson part = &xpc_partitions[partid]; 98889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 989a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson if (xpc_partition_disengaged(part) && 99083469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state == XPC_P_AS_INACTIVE) { 991a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson continue; 99289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 993a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 994a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson active_part_count++; 995a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 996a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson XPC_DEACTIVATE_PARTITION(part, reason); 99789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 998a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (part->disengage_timeout > disengage_timeout) 999a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson disengage_timeout = part->disengage_timeout; 1000a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson } 100189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1002a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt if (xpc_arch_ops.any_partition_engaged()) { 1003aaa3cd694c0c4ae534e8aafdf4227e395c57d6bdDean Nelson if (time_is_before_jiffies(printmsg_time)) { 10041ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "waiting for remote " 1005a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "partitions to deactivate, timeout in " 1006a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "%ld seconds\n", (disengage_timeout - 1007a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson jiffies) / HZ); 10081ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printmsg_time = jiffies + 1009a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ); 10101ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printed_waiting_msg = 1; 10111ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 10121ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 10131ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } else if (active_part_count > 0) { 10141ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson if (printed_waiting_msg) { 10151ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "waiting for local partition" 1016a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson " to deactivate\n"); 10171ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson printed_waiting_msg = 0; 10181ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 10191ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 10201ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } else { 1021a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (!xpc_disengage_timedout) { 10221ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson dev_info(xpc_part, "all partitions have " 1023a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "deactivated\n"); 10241ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 10251ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 102689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 102789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1028a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* sleep for a 1/3 of a second or so */ 102935190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)msleep_interruptible(300); 1030a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 1031a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson } while (1); 1032a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 1033a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt DBUG_ON(xpc_arch_ops.any_partition_engaged()); 1034a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 10355b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_teardown_rsvd_page(); 1036a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 103765c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson if (reason == xpUnloading) { 103835190506b1a18eda7df24b285fdcd94dec7800efDean Nelson (void)unregister_die_notifier(&xpc_die_notifier); 1039bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_reboot_notifier(&xpc_reboot_notifier); 10400752c670d83362609c7f3f59ffa0e180709c60c2Dean Nelson } 1041780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 104289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* clear the interface to XPC's functions */ 104389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_clear_interface(); 104489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 10452c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (xpc_sysctl) 104689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson unregister_sysctl_table(xpc_sysctl); 10477682a4c624e0011b5f3e8dd3021dc54961260d97Dean Nelson 10485b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_teardown_partitions(); 10496e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson 10506e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson if (is_shub()) 10516e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_sn2(); 1052b7f7b07479de2d91443b81938db1e1940c56b13cDean Nelson else if (is_uv()) 10536e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_uv(); 105489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 105589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1056a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson/* 1057d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson * This function is called when the system is being rebooted. 1058d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson */ 1059d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelsonstatic int 1060d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelsonxpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) 1061d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson{ 106265c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson enum xp_retval reason; 1063d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 1064d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson switch (event) { 1065d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_RESTART: 106665c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemReboot; 1067d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 1068d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_HALT: 106965c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemHalt; 1070d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 1071d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson case SYS_POWER_OFF: 107265c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemPoweroff; 1073d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson break; 1074d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson default: 107565c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson reason = xpSystemGoingDown; 1076d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson } 1077d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 1078d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson xpc_do_exit(reason); 1079d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson return NOTIFY_DONE; 1080d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson} 1081d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson 1082d6ad033a88b42420ddb6c62c95e42f88d862b246Dean Nelson/* 1083a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Notify other partitions to deactivate from us by first disengaging from all 1084a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * references to our memory. 1085780d09e895032207a6b070a44d392a3c60574b70Dean Nelson */ 1086780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic void 1087a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonxpc_die_deactivate(void) 1088780d09e895032207a6b070a44d392a3c60574b70Dean Nelson{ 1089780d09e895032207a6b070a44d392a3c60574b70Dean Nelson struct xpc_partition *part; 109064d032ba434ad41586460811148f01511e5612f9Dean Nelson short partid; 1091a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson int any_engaged; 1092261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson long keep_waiting; 1093261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson long wait_to_print; 1094780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1095780d09e895032207a6b070a44d392a3c60574b70Dean Nelson /* keep xpc_hb_checker thread from doing anything (just in case) */ 1096780d09e895032207a6b070a44d392a3c60574b70Dean Nelson xpc_exiting = 1; 1097780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1098a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.disallow_all_hbs(); /*indicate we're deactivated */ 1099780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1100bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; partid++) { 1101780d09e895032207a6b070a44d392a3c60574b70Dean Nelson part = &xpc_partitions[partid]; 1102780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1103a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt if (xpc_arch_ops.partition_engaged(partid) || 110483469b5525b4a35be40b17cb41d64118d84d9f80Dean Nelson part->act_state != XPC_P_AS_INACTIVE) { 1105a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.request_partition_deactivation(part); 1106a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.indicate_partition_disengaged(part); 1107780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1108780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1109780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1110a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson /* 1111a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson * Though we requested that all other partitions deactivate from us, 1112261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * we only wait until they've all disengaged or we've reached the 1113261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * defined timelimit. 1114261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * 1115261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * Given that one iteration through the following while-loop takes 1116261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * approximately 200 microseconds, calculate the #of loops to take 1117261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson * before bailing and the #of loops before printing a waiting message. 1118a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson */ 1119261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson keep_waiting = xpc_disengage_timelimit * 1000 * 5; 1120261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1000 * 5; 1121780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 11221ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson while (1) { 1123a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt any_engaged = xpc_arch_ops.any_partition_engaged(); 1124a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson if (!any_engaged) { 1125a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson dev_info(xpc_part, "all partitions have deactivated\n"); 11261ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 11271ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 1128780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1129261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson if (!keep_waiting--) { 1130bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson for (partid = 0; partid < xp_max_npartitions; 1131bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson partid++) { 1132a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt if (xpc_arch_ops.partition_engaged(partid)) { 1133a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson dev_info(xpc_part, "deactivate from " 113435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "remote partition %d timed " 113535190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "out\n", partid); 11361ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 11371ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 11381ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson break; 11391ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson } 11401ecaded80f94f2779160529aef7d6f37a22c2f60Dean Nelson 1141261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson if (!wait_to_print--) { 1142780d09e895032207a6b070a44d392a3c60574b70Dean Nelson dev_info(xpc_part, "waiting for remote partitions to " 1143a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "deactivate, timeout in %ld seconds\n", 1144261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson keep_waiting / (1000 * 5)); 1145261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1146261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson 1000 * 5; 1147780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1148261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson 1149261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson udelay(200); 1150780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1151780d09e895032207a6b070a44d392a3c60574b70Dean Nelson} 1152780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1153780d09e895032207a6b070a44d392a3c60574b70Dean Nelson/* 11541f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * This function is called when the system is being restarted or halted due 11551f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * to some sort of system failure. If this is the case we need to notify the 11561f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * other partitions to disengage from all references to our memory. 11571f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * This function can also be called when our heartbeater could be offlined 11581f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * for a time. In this case we need to notify other partitions to not worry 11591f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson * about the lack of a heartbeat. 1160780d09e895032207a6b070a44d392a3c60574b70Dean Nelson */ 1161780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonstatic int 1162780d09e895032207a6b070a44d392a3c60574b70Dean Nelsonxpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) 1163780d09e895032207a6b070a44d392a3c60574b70Dean Nelson{ 1164261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#ifdef CONFIG_IA64 /* !!! temporary kludge */ 1165780d09e895032207a6b070a44d392a3c60574b70Dean Nelson switch (event) { 1166780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MACHINE_RESTART: 1167780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MACHINE_HALT: 1168a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson xpc_die_deactivate(); 1169780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 11701f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 11711f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson case DIE_KDEBUG_ENTER: 11721f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* Should lack of heartbeat be ignored by other partitions? */ 11732c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_kdebug_ignore) 11741f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson break; 11752c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 11761f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* fall through */ 1177780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MCA_MONARCH_ENTER: 1178780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_INIT_MONARCH_ENTER: 1179a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.offline_heartbeat(); 1180780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 11811f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson 11821f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson case DIE_KDEBUG_LEAVE: 11831f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* Is lack of heartbeat being ignored by other partitions? */ 11842c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (!xpc_kdebug_ignore) 11851f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson break; 11862c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson 11871f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelson /* fall through */ 1188780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_MCA_MONARCH_LEAVE: 1189780d09e895032207a6b070a44d392a3c60574b70Dean Nelson case DIE_INIT_MONARCH_LEAVE: 1190a7665b0a380585fbd70a2275f3120c6086e0c92dRobin Holt xpc_arch_ops.online_heartbeat(); 1191780d09e895032207a6b070a44d392a3c60574b70Dean Nelson break; 1192780d09e895032207a6b070a44d392a3c60574b70Dean Nelson } 1193261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#else 1194261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson xpc_die_deactivate(); 1195261f3b4979db88d29fc86aad9f76fbc0c2c6d21aDean Nelson#endif 1196780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 1197780d09e895032207a6b070a44d392a3c60574b70Dean Nelson return NOTIFY_DONE; 1198780d09e895032207a6b070a44d392a3c60574b70Dean Nelson} 1199780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 120089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonint __init 120189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_init(void) 120289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 120389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson int ret; 12042c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson struct task_struct *kthread; 1205ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelson 1206bb0dc43eeeea6a3ace7fae42e583a9be176eb1f9Kay Sievers dev_set_name(xpc_part, "part"); 1207bb0dc43eeeea6a3ace7fae42e583a9be176eb1f9Kay Sievers dev_set_name(xpc_chan, "chan"); 120889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 120994bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson if (is_shub()) { 121094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson /* 121194bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * The ia64-sn2 architecture supports at most 64 partitions. 1212c39838ce21ca8e05857ed7f4be5d289011561905Dean Nelson * And the inability to unregister remote amos restricts us 121394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * further to only support exactly 64 partitions on this 121494bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson * architecture, no less. 121594bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson */ 12165b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (xp_max_npartitions != 64) { 12175b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson dev_err(xpc_part, "max #of partitions not set to 64\n"); 12185b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = -EINVAL; 12195b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } else { 12205b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = xpc_init_sn2(); 12215b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson } 122294bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 122394bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } else if (is_uv()) { 12245b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = xpc_init_uv(); 122594bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 122694bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } else { 12275b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = -ENODEV; 122894bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson } 1229408865ce4829376120489ac8011b72125453dcffDean Nelson 12305b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (ret != 0) 12315b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson return ret; 12325b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 12335b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = xpc_setup_partitions(); 12345b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (ret != 0) { 1235bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson dev_err(xpc_part, "can't get memory for partition structure\n"); 1236ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelson goto out_1; 1237bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson } 123889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1239bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson xpc_sysctl = register_sysctl_table(xpc_sys_dir); 1240bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson 124189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 124289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Fill the partition reserved page with the information needed by 124389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * other partitions to discover we are alive and establish initial 124489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * communications. 124589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 12465b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson ret = xpc_setup_rsvd_page(); 12475b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson if (ret != 0) { 1248bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson dev_err(xpc_part, "can't setup our reserved page\n"); 1249ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelson goto out_2; 125089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 125189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1252a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson /* add ourselves to the reboot_notifier_list */ 1253a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson ret = register_reboot_notifier(&xpc_reboot_notifier); 12542c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (ret != 0) 1255a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson dev_warn(xpc_part, "can't register reboot notifier\n"); 1256a607c38971fd078865fa9bef39e6c1d4435680c8Dean Nelson 12571eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig /* add ourselves to the die_notifier list */ 1258780d09e895032207a6b070a44d392a3c60574b70Dean Nelson ret = register_die_notifier(&xpc_die_notifier); 12592c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (ret != 0) 1260780d09e895032207a6b070a44d392a3c60574b70Dean Nelson dev_warn(xpc_part, "can't register die notifier\n"); 1261780d09e895032207a6b070a44d392a3c60574b70Dean Nelson 126289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 126389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * The real work-horse behind xpc. This processes incoming 126489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * interrupts and monitors remote heartbeats. 126589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 12662c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME); 12672c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 126889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_err(xpc_part, "failed while forking hb check thread\n"); 1269bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson ret = -EBUSY; 1270ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelson goto out_3; 127189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 127289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 127389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* 127489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * Startup a thread that will attempt to discover other partitions to 127589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * activate based on info provided by SAL. This new thread is short 127689eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson * lived and will exit once discovery is complete. 127789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson */ 12782c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson kthread = kthread_run(xpc_initiate_discovery, NULL, 12792c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson XPC_DISCOVERY_THREAD_NAME); 12802c2b94f93f4732c3b9703ce62627e6187e7d6128Dean Nelson if (IS_ERR(kthread)) { 128189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson dev_err(xpc_part, "failed while forking discovery thread\n"); 128289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 128389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* mark this new thread as a non-starter */ 1284f9e505a9a03df5acace6e758c8d12982635a1c64Jes Sorensen complete(&xpc_discovery_exited); 128589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 128665c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_do_exit(xpUnloading); 128789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return -EBUSY; 128889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson } 128989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 129089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson /* set the interface to point at XPC's functions */ 129189eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect, 129297bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson xpc_initiate_send, xpc_initiate_send_notify, 129397bf1aa1e1bb18de9bb1987c6eb9ad751bf08aabDean Nelson xpc_initiate_received, xpc_initiate_partid_to_nasids); 129489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 129589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson return 0; 1296bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson 1297bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson /* initialization was not successful */ 1298ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelsonout_3: 12995b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_teardown_rsvd_page(); 130094bd2708d4a95d7da5a1c7c28a063eccd127fb69Dean Nelson 1301bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_die_notifier(&xpc_die_notifier); 1302bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson (void)unregister_reboot_notifier(&xpc_reboot_notifier); 1303ee6665e3b6e1283c30ae240732af1345bc02154eDean Nelsonout_2: 1304bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson if (xpc_sysctl) 1305bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson unregister_sysctl_table(xpc_sysctl); 13065b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson 13075b8669dfd110a62a74eea525a009342f73987ea0Dean Nelson xpc_teardown_partitions(); 13086e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelsonout_1: 13096e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson if (is_shub()) 13106e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_sn2(); 1311b7f7b07479de2d91443b81938db1e1940c56b13cDean Nelson else if (is_uv()) 13126e41017aad9ed175ca51e4828eabc8c5cf5910beDean Nelson xpc_exit_uv(); 1313bc63d387e4f5dbbe4ea0c5ade862c38073fd7fa3Dean Nelson return ret; 131489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 131589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 131635190506b1a18eda7df24b285fdcd94dec7800efDean Nelsonmodule_init(xpc_init); 131789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 131889eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonvoid __exit 131989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonxpc_exit(void) 132089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson{ 132165c17b801e03e40acdca0cd34e8eb1b8a347b539Dean Nelson xpc_do_exit(xpUnloading); 132289eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson} 132389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 132435190506b1a18eda7df24b285fdcd94dec7800efDean Nelsonmodule_exit(xpc_exit); 132589eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 132689eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_AUTHOR("Silicon Graphics, Inc."); 132789eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_DESCRIPTION("Cross Partition Communication (XPC) support"); 132889eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_LICENSE("GPL"); 132989eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 133089eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonmodule_param(xpc_hb_interval, int, 0); 133189eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between " 133235190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "heartbeat increments."); 133389eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 133489eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelsonmodule_param(xpc_hb_check_interval, int, 0); 133589eb8eb927e324366c3ac0458998aaf9953fc5cdDean NelsonMODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between " 133635190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "heartbeat checks."); 133789eb8eb927e324366c3ac0458998aaf9953fc5cdDean Nelson 1338a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelsonmodule_param(xpc_disengage_timelimit, int, 0); 1339a47d5dac9d8481766382f8cf1483dd581df38b99Dean NelsonMODULE_PARM_DESC(xpc_disengage_timelimit, "Number of seconds to wait " 1340a47d5dac9d8481766382f8cf1483dd581df38b99Dean Nelson "for disengage to complete."); 1341e54af724c1ae3530c95135157776c9be65cdb747Dean Nelson 13421f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean Nelsonmodule_param(xpc_kdebug_ignore, int, 0); 13431f4674b2d5f63bac4c393ac4de1d6c1b6b72c09cDean NelsonMODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by " 134435190506b1a18eda7df24b285fdcd94dec7800efDean Nelson "other partitions when dropping into kdebug."); 1345