17 #include <linux/slab.h>
18 #include <asm/uncached.h>
29 #define XPC_MAX_PHYSNODES_SN2 (MAX_NUMALINK_NODES / 2)
30 #define XP_NASID_MASK_BYTES_SN2 ((XPC_MAX_PHYSNODES_SN2 + 7) / 8)
31 #define XP_NASID_MASK_WORDS_SN2 ((XPC_MAX_PHYSNODES_SN2 + 63) / 64)
46 #define XPC_NOTIFY_IRQ_AMOS_SN2 0
47 #define XPC_ACTIVATE_IRQ_AMOS_SN2 (XPC_NOTIFY_IRQ_AMOS_SN2 + \
48 XP_MAX_NPARTITIONS_SN2)
49 #define XPC_ENGAGED_PARTITIONS_AMO_SN2 (XPC_ACTIVATE_IRQ_AMOS_SN2 + \
50 XP_NASID_MASK_WORDS_SN2)
51 #define XPC_DEACTIVATE_REQUEST_AMO_SN2 (XPC_ENGAGED_PARTITIONS_AMO_SN2 + 1)
57 static void *xpc_remote_copy_buffer_base_sn2;
58 static char *xpc_remote_copy_buffer_sn2;
64 xpc_setup_partitions_sn2(
void)
71 xpc_teardown_partitions_sn2(
void)
77 static u64 xpc_sh1_IPI_access_sn2;
78 static u64 xpc_sh2_IPI_access0_sn2;
79 static u64 xpc_sh2_IPI_access1_sn2;
80 static u64 xpc_sh2_IPI_access2_sn2;
81 static u64 xpc_sh2_IPI_access3_sn2;
87 xpc_allow_IPI_ops_sn2(
void)
94 xpc_sh2_IPI_access0_sn2 =
96 xpc_sh2_IPI_access1_sn2 =
98 xpc_sh2_IPI_access2_sn2 =
100 xpc_sh2_IPI_access3_sn2 =
115 xpc_sh1_IPI_access_sn2 =
130 xpc_disallow_IPI_ops_sn2(
void)
140 xpc_sh2_IPI_access0_sn2);
142 xpc_sh2_IPI_access1_sn2);
144 xpc_sh2_IPI_access2_sn2);
146 xpc_sh2_IPI_access3_sn2);
152 xpc_sh1_IPI_access_sn2);
165 xpc_receive_IRQ_amo_sn2(
struct amo *amo)
175 unsigned long irq_flags;
197 xpc_init_IRQ_amo_sn2(
int index)
201 (
void)xpc_receive_IRQ_amo_sn2(amo);
213 xpc_handle_activate_IRQ_sn2(
int irq,
void *
dev_id)
215 unsigned long irq_flags;
219 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
229 xpc_send_activate_IRQ_sn2(
unsigned long amos_page_pa,
int from_nasid,
230 int to_nasid,
int to_phys_cpuid)
232 struct amo *amos = (
struct amo *)
__va(amos_page_pa +
234 sizeof(
struct amo)));
242 xpc_send_local_activate_IRQ_sn2(
int from_nasid)
244 unsigned long irq_flags;
247 sizeof(
struct amo)));
255 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
271 unsigned long irq_flags;
275 if (chctl.all_flags == 0)
280 spin_unlock_irqrestore(&part->
chctl_lock, irq_flags);
282 dev_dbg(
xpc_chan,
"received notify IRQ from partid=%d, chctl.all_flags="
283 "0x%llx\n",
XPC_PARTID(part), chctl.all_flags);
285 xpc_wakeup_channel_mgr(part);
305 xpc_handle_notify_IRQ_sn2(
int irq,
void *
dev_id)
312 if (xpc_part_ref(part)) {
313 xpc_check_for_sent_chctl_flags_sn2(part);
315 xpc_part_deref(part);
326 xpc_check_for_dropped_notify_IRQ_sn2(
struct xpc_partition *part)
330 if (xpc_part_ref(part)) {
331 xpc_check_for_sent_chctl_flags_sn2(part);
336 xpc_part_deref(part);
345 xpc_send_notify_IRQ_sn2(
struct xpc_channel *ch,
u8 chctl_flag,
346 char *chctl_flag_string,
unsigned long *irq_flags)
363 if (irq_flags !=
NULL)
364 spin_unlock_irqrestore(&ch->
lock, *irq_flags);
366 if (irq_flags !=
NULL)
372 #define XPC_SEND_NOTIFY_IRQ_SN2(_ch, _ipi_f, _irq_f) \
373 xpc_send_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
381 xpc_send_local_notify_IRQ_sn2(
struct xpc_channel *ch,
u8 chctl_flag,
382 char *chctl_flag_string)
394 #define XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(_ch, _ipi_f) \
395 xpc_send_local_notify_IRQ_sn2(_ch, _ipi_f, #_ipi_f)
398 xpc_send_chctl_closerequest_sn2(
struct xpc_channel *ch,
399 unsigned long *irq_flags)
408 xpc_send_chctl_closereply_sn2(
struct xpc_channel *ch,
unsigned long *irq_flags)
414 xpc_send_chctl_openrequest_sn2(
struct xpc_channel *ch,
unsigned long *irq_flags)
424 xpc_send_chctl_openreply_sn2(
struct xpc_channel *ch,
unsigned long *irq_flags)
435 xpc_send_chctl_opencomplete_sn2(
struct xpc_channel *ch,
436 unsigned long *irq_flags)
442 xpc_send_chctl_msgrequest_sn2(
struct xpc_channel *ch)
448 xpc_send_chctl_local_msgrequest_sn2(
struct xpc_channel *ch)
454 xpc_save_remote_msgqueue_pa_sn2(
struct xpc_channel *ch,
455 unsigned long msgqueue_pa)
457 ch->
sn.
sn2.remote_msgqueue_pa = msgqueue_pa;
467 xpc_indicate_partition_engaged_sn2(
struct xpc_partition *part)
469 unsigned long irq_flags;
470 struct amo *amo = (
struct amo *)
__va(part->
sn.
sn2.remote_amos_page_pa +
472 sizeof(
struct amo)));
494 xpc_indicate_partition_disengaged_sn2(
struct xpc_partition *part)
497 unsigned long irq_flags;
500 sizeof(
struct amo)));
531 xpc_assume_partition_disengaged_sn2(
short partid)
533 struct amo *amo = xpc_vars_sn2->
amos_page +
542 xpc_partition_engaged_sn2(
short partid)
544 struct amo *amo = xpc_vars_sn2->
amos_page +
553 xpc_any_partition_engaged_sn2(
void)
555 struct amo *amo = xpc_vars_sn2->
amos_page +
569 xpc_allow_amo_ops_sn2(
struct amo *amos_page)
588 xpc_allow_amo_ops_shub_wars_1_1_sn2(
void)
599 xpc_prot_vec_sn2[
node] =
613 xpc_get_partition_rsvd_page_pa_sn2(
void *
buf,
u64 *
cookie,
unsigned long *rp_pa,
619 status = sn_partition_reserved_page_pa((
u64)buf, cookie,
620 (
u64 *)rp_pa, (
u64 *)len);
635 struct amo *amos_page;
644 xpc_vars_part_sn2 = (
struct xpc_vars_part_sn2 *)((
u8 *)
XPC_RP_VARS(rp) +
660 if (amos_page ==
NULL) {
662 if (amos_page ==
NULL) {
671 ret = xpc_allow_amo_ops_sn2(amos_page);
681 memset(xpc_vars_sn2, 0,
sizeof(
struct xpc_vars_sn2));
691 memset((
u64 *)xpc_vars_part_sn2, 0,
sizeof(
struct xpc_vars_part_sn2) *
706 xpc_hb_allowed_sn2(
short partid,
void *heartbeating_to_mask)
708 return test_bit(partid, heartbeating_to_mask);
712 xpc_allow_hb_sn2(
short partid)
715 set_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
719 xpc_disallow_hb_sn2(
short partid)
722 clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask);
726 xpc_disallow_all_hbs_sn2(
void)
733 xpc_increment_heartbeat_sn2(
void)
739 xpc_offline_heartbeat_sn2(
void)
741 xpc_increment_heartbeat_sn2();
746 xpc_online_heartbeat_sn2(
void)
748 xpc_increment_heartbeat_sn2();
753 xpc_heartbeat_init_sn2(
void)
758 xpc_online_heartbeat_sn2();
762 xpc_heartbeat_exit_sn2(
void)
764 xpc_offline_heartbeat_sn2();
770 struct xpc_vars_sn2 *remote_vars;
773 remote_vars = (
struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
777 part->
sn.
sn2.remote_vars_pa,
783 "heartbeat_offline=%lld, HB_mask[0]=0x%lx\n",
XPC_PARTID(part),
786 remote_vars->heartbeating_to_mask[0]);
791 remote_vars->heartbeating_to_mask)) {
807 xpc_get_remote_vars_sn2(
unsigned long remote_vars_pa,
808 struct xpc_vars_sn2 *remote_vars)
812 if (remote_vars_pa == 0)
830 xpc_request_partition_activation_sn2(
struct xpc_rsvd_page *remote_rp,
831 unsigned long remote_rp_pa,
int nasid)
833 xpc_send_local_activate_IRQ_sn2(nasid);
837 xpc_request_partition_reactivation_sn2(
struct xpc_partition *part)
839 xpc_send_local_activate_IRQ_sn2(part->
sn.
sn2.activate_IRQ_nasid);
843 xpc_request_partition_deactivation_sn2(
struct xpc_partition *part)
846 unsigned long irq_flags;
849 sizeof(
struct amo)));
880 xpc_cancel_partition_deactivation_request_sn2(
struct xpc_partition *part)
882 unsigned long irq_flags;
883 struct amo *amo = (
struct amo *)
__va(part->
sn.
sn2.remote_amos_page_pa +
885 sizeof(
struct amo)));
907 xpc_partition_deactivation_requested_sn2(
short partid)
909 struct amo *amo = xpc_vars_sn2->
amos_page +
921 xpc_update_partition_info_sn2(
struct xpc_partition *part,
u8 remote_rp_version,
922 unsigned long *remote_rp_ts_jiffies,
923 unsigned long remote_rp_pa,
924 unsigned long remote_vars_pa,
925 struct xpc_vars_sn2 *remote_vars)
985 xpc_identify_activate_IRQ_req_sn2(
int nasid)
988 struct xpc_vars_sn2 *remote_vars;
989 unsigned long remote_rp_pa;
990 unsigned long remote_vars_pa;
991 int remote_rp_version;
993 unsigned long remote_rp_ts_jiffies = 0;
1001 remote_rp = (
struct xpc_rsvd_page *)xpc_remote_copy_buffer_sn2;
1006 "which sent interrupt, reason=%d\n", nasid, ret);
1010 remote_vars_pa = remote_rp->
sn.
sn2.vars_pa;
1011 remote_rp_version = remote_rp->
version;
1012 remote_rp_ts_jiffies = remote_rp->
ts_jiffies;
1016 part_sn2 = &part->
sn.
sn2;
1020 remote_vars = (
struct xpc_vars_sn2 *)xpc_remote_copy_buffer_sn2;
1022 ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
1025 "which sent interrupt, reason=%d\n", nasid, ret);
1034 "%lld:0x%lx\n", (
int)nasid, (
int)partid,
1036 remote_vars->
heartbeat, remote_vars->heartbeating_to_mask[0]);
1041 xpc_update_partition_info_sn2(part, remote_rp_version,
1042 &remote_rp_ts_jiffies,
1043 remote_rp_pa, remote_vars_pa,
1046 if (xpc_partition_deactivation_requested_sn2(partid)) {
1065 DBUG_ON(xpc_partition_engaged_sn2(partid));
1066 DBUG_ON(xpc_partition_deactivation_requested_sn2(partid));
1068 xpc_update_partition_info_sn2(part, remote_rp_version,
1069 &remote_rp_ts_jiffies,
1070 remote_rp_pa, remote_vars_pa,
1082 else if (xpc_partition_deactivation_requested_sn2(partid))
1098 unsigned long nasid_mask_long;
1100 int n_IRQs_detected = 0;
1101 struct amo *act_amos;
1111 nasid_mask_long = xpc_receive_IRQ_amo_sn2(&act_amos[l]);
1136 xpc_identify_activate_IRQ_req_sn2(nasid);
1142 return n_IRQs_detected;
1146 xpc_process_activate_IRQ_rcvd_sn2(
void)
1148 unsigned long irq_flags;
1149 int n_IRQs_expected;
1150 int n_IRQs_detected;
1155 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1158 if (n_IRQs_detected < n_IRQs_expected) {
1207 local_openclose_args_base);
1225 (
void *)(
u64)partid);
1228 "errno=%d\n", -ret);
1237 (
void (*)(
unsigned long))xpc_check_for_dropped_notify_IRQ_sn2;
1242 for (ch_number = 0; ch_number < part->
nchannels; ch_number++) {
1243 ch_sn2 = &part->
channels[ch_number].sn.sn2;
1299 xpc_vars_part_sn2[partid].
magic = 0;
1325 const unsigned long src_pa,
size_t cnt)
1353 struct xpc_vars_part_sn2 *pulled_entry_cacheline =
1355 struct xpc_vars_part_sn2 *pulled_entry;
1356 unsigned long remote_entry_cacheline_pa;
1357 unsigned long remote_entry_pa;
1370 remote_entry_cacheline_pa = (remote_entry_pa & ~(
L1_CACHE_BYTES - 1));
1372 pulled_entry = (
struct xpc_vars_part_sn2 *)((
u64)pulled_entry_cacheline
1373 + (remote_entry_pa &
1376 ret = xpc_pull_remote_cachelines_sn2(part, pulled_entry_cacheline,
1377 remote_entry_cacheline_pa,
1381 "partition %d, ret=%d\n", partid, ret);
1390 if (pulled_entry->
magic != 0) {
1392 "partition %d has bad magic value (=0x%llx)\n",
1405 if (pulled_entry->
GPs_pa == 0 ||
1410 "partition %d are not valid\n", partid,
1480 while ((ret = xpc_pull_remote_vars_part_sn2(part)) !=
xpSuccess) {
1506 unsigned long irq_flags;
1515 chctl = part->
chctl;
1519 spin_unlock_irqrestore(&part->
chctl_lock, irq_flags);
1521 if (xpc_any_openclose_chctl_flags_set(&chctl)) {
1522 ret = xpc_pull_remote_cachelines_sn2(part, part->
1523 remote_openclose_args,
1525 remote_openclose_args_pa,
1539 if (xpc_any_msg_chctl_flags_set(&chctl)) {
1540 ret = xpc_pull_remote_cachelines_sn2(part, part_sn2->
remote_GPs,
1561 xpc_allocate_local_msgqueue_sn2(
struct xpc_channel *ch)
1564 unsigned long irq_flags;
1586 if (nentries < ch->local_nentries) {
1588 "partid=%d, channel=%d\n", nentries,
1593 spin_unlock_irqrestore(&ch->
lock, irq_flags);
1597 dev_dbg(
xpc_chan,
"can't get memory for local message queue and notify "
1598 "queue, partid=%d, channel=%d\n", ch->
partid, ch->
number);
1606 xpc_allocate_remote_msgqueue_sn2(
struct xpc_channel *ch)
1609 unsigned long irq_flags;
1625 if (nentries < ch->remote_nentries) {
1627 "partid=%d, channel=%d\n", nentries,
1632 spin_unlock_irqrestore(&ch->
lock, irq_flags);
1636 dev_dbg(
xpc_chan,
"can't get memory for cached remote message queue, "
1647 xpc_setup_msg_structures_sn2(
struct xpc_channel *ch)
1654 ret = xpc_allocate_local_msgqueue_sn2(ch);
1657 ret = xpc_allocate_remote_msgqueue_sn2(ch);
1673 xpc_teardown_msg_structures_sn2(
struct xpc_channel *ch)
1712 s64 get = ch->
sn.
sn2.w_remote_GP.get - 1;
1724 notify_type = notify->
type;
1725 if (notify_type == 0 ||
1726 cmpxchg(¬ify->
type, notify_type, 0) != notify_type) {
1736 "msg_number=%lld partid=%d channel=%d\n",
1743 " msg_number=%lld partid=%d channel=%d\n",
1750 xpc_notify_senders_of_disconnect_sn2(
struct xpc_channel *ch)
1752 xpc_notify_senders_sn2(ch, ch->
reason, ch->
sn.
sn2.w_local_GP.put);
1759 xpc_clear_local_msgqueue_flags_sn2(
struct xpc_channel *ch)
1772 }
while (++get < ch_sn2->remote_GP.get);
1779 xpc_clear_remote_msgqueue_flags_sn2(
struct xpc_channel *ch)
1786 if (ch_sn2->
remote_GP.put < remote_nentries)
1792 (put % remote_nentries) *
1798 }
while (++put < ch_sn2->remote_GP.put);
1802 xpc_n_of_deliverable_payloads_sn2(
struct xpc_channel *ch)
1804 return ch->
sn.
sn2.w_remote_GP.put - ch->
sn.
sn2.w_local_GP.get;
1808 xpc_process_msg_chctl_flags_sn2(
struct xpc_partition *part,
int ch_number)
1818 xpc_msgqueue_ref(ch);
1823 xpc_msgqueue_deref(ch);
1828 xpc_msgqueue_deref(ch);
1860 xpc_clear_local_msgqueue_flags_sn2(ch);
1886 xpc_clear_remote_msgqueue_flags_sn2(ch);
1895 npayloads_sent = xpc_n_of_deliverable_payloads_sn2(ch);
1896 if (npayloads_sent > 0) {
1898 "delivered=%d, partid=%d, channel=%d\n",
1906 xpc_msgqueue_deref(ch);
1914 unsigned long remote_msg_pa;
1944 ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa,
1949 " msg %lld from partition %d, channel=%d, "
1975 xpc_get_deliverable_payload_sn2(
struct xpc_channel *ch)
2002 "partid=%d, channel=%d\n",
get + 1,
2007 msg = xpc_pull_remote_msg_sn2(ch,
get);
2034 s64 put = initial_put + 1;
2035 int send_msgrequest = 0;
2044 local_msgqueue + (put %
2054 if (put == initial_put) {
2071 send_msgrequest = 1;
2081 if (send_msgrequest)
2082 xpc_send_chctl_msgrequest_sn2(ch);
2135 xpc_send_chctl_local_msgrequest_sn2(ch);
2154 "msg_number=%lld, partid=%d, channel=%d\n", put + 1,
2157 *address_of_msg =
msg;
2167 xpc_send_payload_sn2(
struct xpc_channel *ch,
u32 flags,
void *payload,
2183 xpc_msgqueue_ref(ch);
2194 ret = xpc_allocate_msg_sn2(ch, flags, &msg);
2198 msg_number = msg->
number;
2200 if (notify_type != 0) {
2246 if (put == msg_number)
2247 xpc_send_msgs_sn2(ch, put);
2250 xpc_msgqueue_deref(ch);
2263 xpc_acknowledge_msgs_sn2(
struct xpc_channel *ch,
s64 initial_get,
u8 msg_flags)
2267 s64 get = initial_get + 1;
2268 int send_msgrequest = 0;
2277 remote_msgqueue + (
get %
2284 msg_flags |= msg->
flags;
2288 if (
get == initial_get) {
2315 if (send_msgrequest)
2316 xpc_send_chctl_msgrequest_sn2(ch);
2320 xpc_received_payload_sn2(
struct xpc_channel *ch,
void *payload)
2327 msg_number = msg->
number;
2329 dev_dbg(
xpc_chan,
"msg=0x%p, msg_number=%lld, partid=%d, channel=%d\n",
2349 get = ch->
sn.
sn2.local_GP->get;
2350 if (
get == msg_number)
2351 xpc_acknowledge_msgs_sn2(ch,
get, msg->
flags);
2355 .setup_partitions = xpc_setup_partitions_sn2,
2356 .teardown_partitions = xpc_teardown_partitions_sn2,
2357 .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2,
2358 .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2,
2359 .setup_rsvd_page = xpc_setup_rsvd_page_sn2,
2361 .allow_hb = xpc_allow_hb_sn2,
2362 .disallow_hb = xpc_disallow_hb_sn2,
2363 .disallow_all_hbs = xpc_disallow_all_hbs_sn2,
2364 .increment_heartbeat = xpc_increment_heartbeat_sn2,
2365 .offline_heartbeat = xpc_offline_heartbeat_sn2,
2366 .online_heartbeat = xpc_online_heartbeat_sn2,
2367 .heartbeat_init = xpc_heartbeat_init_sn2,
2368 .heartbeat_exit = xpc_heartbeat_exit_sn2,
2369 .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2,
2371 .request_partition_activation =
2372 xpc_request_partition_activation_sn2,
2373 .request_partition_reactivation =
2374 xpc_request_partition_reactivation_sn2,
2375 .request_partition_deactivation =
2376 xpc_request_partition_deactivation_sn2,
2377 .cancel_partition_deactivation_request =
2378 xpc_cancel_partition_deactivation_request_sn2,
2380 .setup_ch_structures = xpc_setup_ch_structures_sn2,
2381 .teardown_ch_structures = xpc_teardown_ch_structures_sn2,
2383 .make_first_contact = xpc_make_first_contact_sn2,
2385 .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2,
2386 .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2,
2387 .send_chctl_closereply = xpc_send_chctl_closereply_sn2,
2388 .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2,
2389 .send_chctl_openreply = xpc_send_chctl_openreply_sn2,
2390 .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2,
2391 .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2,
2393 .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2,
2395 .setup_msg_structures = xpc_setup_msg_structures_sn2,
2396 .teardown_msg_structures = xpc_teardown_msg_structures_sn2,
2398 .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2,
2399 .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2,
2400 .partition_engaged = xpc_partition_engaged_sn2,
2401 .any_partition_engaged = xpc_any_partition_engaged_sn2,
2402 .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2,
2404 .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2,
2405 .send_payload = xpc_send_payload_sn2,
2406 .get_deliverable_payload = xpc_get_deliverable_payload_sn2,
2407 .received_payload = xpc_received_payload_sn2,
2408 .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2,
2429 &xpc_remote_copy_buffer_base_sn2);
2430 if (xpc_remote_copy_buffer_sn2 ==
NULL) {
2436 xpc_allow_IPI_ops_sn2();
2437 xpc_allow_amo_ops_shub_wars_1_1_sn2();
2449 "errno=%d\n", -ret);
2450 xpc_disallow_IPI_ops_sn2();
2451 kfree(xpc_remote_copy_buffer_base_sn2);
2460 xpc_disallow_IPI_ops_sn2();
2461 kfree(xpc_remote_copy_buffer_base_sn2);