aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_main.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-30 01:34:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 12:41:50 -0400
commit5b8669dfd110a62a74eea525a009342f73987ea0 (patch)
tree04572d8508f450131298b6ec072e97aa9fdba539 /drivers/misc/sgi-xp/xpc_main.c
parent83469b5525b4a35be40b17cb41d64118d84d9f80 (diff)
sgi-xp: setup the activate GRU message queue
Setup the activate GRU message queue that is used for partition activation and channel connection on UV systems. Signed-off-by: Dean Nelson <dcn@sgi.com> Cc: Jack Steiner <steiner@sgi.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_main.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c329
1 files changed, 246 insertions, 83 deletions
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index b303c130bba8..13ec47928994 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -141,8 +141,9 @@ static struct ctl_table_header *xpc_sysctl;
141/* non-zero if any remote partition disengage was timed out */ 141/* non-zero if any remote partition disengage was timed out */
142int xpc_disengage_timedout; 142int xpc_disengage_timedout;
143 143
144/* #of activate IRQs received */ 144/* #of activate IRQs received and not yet processed */
145atomic_t xpc_activate_IRQ_rcvd = ATOMIC_INIT(0); 145int xpc_activate_IRQ_rcvd;
146DEFINE_SPINLOCK(xpc_activate_IRQ_rcvd_lock);
146 147
147/* IRQ handler notifies this wait queue on receipt of an IRQ */ 148/* IRQ handler notifies this wait queue on receipt of an IRQ */
148DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq); 149DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq);
@@ -169,10 +170,11 @@ static struct notifier_block xpc_die_notifier = {
169 .notifier_call = xpc_system_die, 170 .notifier_call = xpc_system_die,
170}; 171};
171 172
173int (*xpc_setup_partitions_sn) (void);
172enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie, 174enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie,
173 unsigned long *rp_pa, 175 unsigned long *rp_pa,
174 size_t *len); 176 size_t *len);
175enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *rp); 177int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp);
176void (*xpc_heartbeat_init) (void); 178void (*xpc_heartbeat_init) (void);
177void (*xpc_heartbeat_exit) (void); 179void (*xpc_heartbeat_exit) (void);
178void (*xpc_increment_heartbeat) (void); 180void (*xpc_increment_heartbeat) (void);
@@ -183,8 +185,8 @@ enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *part);
183enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); 185enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part);
184void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch); 186void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch);
185u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part); 187u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part);
186enum xp_retval (*xpc_allocate_msgqueues) (struct xpc_channel *ch); 188enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *ch);
187void (*xpc_free_msgqueues) (struct xpc_channel *ch); 189void (*xpc_teardown_msg_structures) (struct xpc_channel *ch);
188void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number); 190void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number);
189int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch); 191int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch);
190struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); 192struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch);
@@ -196,9 +198,9 @@ void (*xpc_request_partition_reactivation) (struct xpc_partition *part);
196void (*xpc_request_partition_deactivation) (struct xpc_partition *part); 198void (*xpc_request_partition_deactivation) (struct xpc_partition *part);
197void (*xpc_cancel_partition_deactivation_request) (struct xpc_partition *part); 199void (*xpc_cancel_partition_deactivation_request) (struct xpc_partition *part);
198 200
199void (*xpc_process_activate_IRQ_rcvd) (int n_IRQs_expected); 201void (*xpc_process_activate_IRQ_rcvd) (void);
200enum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *part); 202enum xp_retval (*xpc_setup_ch_structures_sn) (struct xpc_partition *part);
201void (*xpc_teardown_infrastructure) (struct xpc_partition *part); 203void (*xpc_teardown_ch_structures_sn) (struct xpc_partition *part);
202 204
203void (*xpc_indicate_partition_engaged) (struct xpc_partition *part); 205void (*xpc_indicate_partition_engaged) (struct xpc_partition *part);
204int (*xpc_partition_engaged) (short partid); 206int (*xpc_partition_engaged) (short partid);
@@ -215,6 +217,9 @@ void (*xpc_send_chctl_openrequest) (struct xpc_channel *ch,
215void (*xpc_send_chctl_openreply) (struct xpc_channel *ch, 217void (*xpc_send_chctl_openreply) (struct xpc_channel *ch,
216 unsigned long *irq_flags); 218 unsigned long *irq_flags);
217 219
220void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch,
221 unsigned long msgqueue_pa);
222
218enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags, 223enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags,
219 void *payload, u16 payload_size, u8 notify_type, 224 void *payload, u16 payload_size, u8 notify_type,
220 xpc_notify_func func, void *key); 225 xpc_notify_func func, void *key);
@@ -308,8 +313,6 @@ xpc_check_remote_hb(void)
308static int 313static int
309xpc_hb_checker(void *ignore) 314xpc_hb_checker(void *ignore)
310{ 315{
311 int last_IRQ_count = 0;
312 int new_IRQ_count;
313 int force_IRQ = 0; 316 int force_IRQ = 0;
314 317
315 /* this thread was marked active by xpc_hb_init() */ 318 /* this thread was marked active by xpc_hb_init() */
@@ -325,43 +328,37 @@ xpc_hb_checker(void *ignore)
325 dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have " 328 dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
326 "been received\n", 329 "been received\n",
327 (int)(xpc_hb_check_timeout - jiffies), 330 (int)(xpc_hb_check_timeout - jiffies),
328 atomic_read(&xpc_activate_IRQ_rcvd) - last_IRQ_count); 331 xpc_activate_IRQ_rcvd);
329 332
330 /* checking of remote heartbeats is skewed by IRQ handling */ 333 /* checking of remote heartbeats is skewed by IRQ handling */
331 if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) { 334 if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) {
335 xpc_hb_check_timeout = jiffies +
336 (xpc_hb_check_interval * HZ);
337
332 dev_dbg(xpc_part, "checking remote heartbeats\n"); 338 dev_dbg(xpc_part, "checking remote heartbeats\n");
333 xpc_check_remote_hb(); 339 xpc_check_remote_hb();
334 340
335 /* 341 /*
336 * We need to periodically recheck to ensure no 342 * On sn2 we need to periodically recheck to ensure no
337 * IRQ/amo pairs have been missed. That check 343 * IRQ/amo pairs have been missed.
338 * must always reset xpc_hb_check_timeout.
339 */ 344 */
340 force_IRQ = 1; 345 if (is_shub())
346 force_IRQ = 1;
341 } 347 }
342 348
343 /* check for outstanding IRQs */ 349 /* check for outstanding IRQs */
344 new_IRQ_count = atomic_read(&xpc_activate_IRQ_rcvd); 350 if (xpc_activate_IRQ_rcvd > 0 || force_IRQ != 0) {
345 if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
346 force_IRQ = 0; 351 force_IRQ = 0;
347 352 dev_dbg(xpc_part, "processing activate IRQs "
348 dev_dbg(xpc_part, "found an IRQ to process; will be " 353 "received\n");
349 "resetting xpc_hb_check_timeout\n"); 354 xpc_process_activate_IRQ_rcvd();
350
351 xpc_process_activate_IRQ_rcvd(new_IRQ_count -
352 last_IRQ_count);
353 last_IRQ_count = new_IRQ_count;
354
355 xpc_hb_check_timeout = jiffies +
356 (xpc_hb_check_interval * HZ);
357 } 355 }
358 356
359 /* wait for IRQ or timeout */ 357 /* wait for IRQ or timeout */
360 (void)wait_event_interruptible(xpc_activate_IRQ_wq, 358 (void)wait_event_interruptible(xpc_activate_IRQ_wq,
361 (last_IRQ_count < atomic_read( 359 (time_is_before_eq_jiffies(
362 &xpc_activate_IRQ_rcvd)
363 || time_is_before_eq_jiffies(
364 xpc_hb_check_timeout) || 360 xpc_hb_check_timeout) ||
361 xpc_activate_IRQ_rcvd > 0 ||
365 xpc_exiting)); 362 xpc_exiting));
366 } 363 }
367 364
@@ -437,6 +434,153 @@ xpc_channel_mgr(struct xpc_partition *part)
437} 434}
438 435
439/* 436/*
437 * Guarantee that the kzalloc'd memory is cacheline aligned.
438 */
439void *
440xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
441{
442 /* see if kzalloc will give us cachline aligned memory by default */
443 *base = kzalloc(size, flags);
444 if (*base == NULL)
445 return NULL;
446
447 if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
448 return *base;
449
450 kfree(*base);
451
452 /* nope, we'll have to do it ourselves */
453 *base = kzalloc(size + L1_CACHE_BYTES, flags);
454 if (*base == NULL)
455 return NULL;
456
457 return (void *)L1_CACHE_ALIGN((u64)*base);
458}
459
460/*
461 * Setup the channel structures necessary to support XPartition Communication
462 * between the specified remote partition and the local one.
463 */
464static enum xp_retval
465xpc_setup_ch_structures(struct xpc_partition *part)
466{
467 enum xp_retval ret;
468 int ch_number;
469 struct xpc_channel *ch;
470 short partid = XPC_PARTID(part);
471
472 /*
473 * Allocate all of the channel structures as a contiguous chunk of
474 * memory.
475 */
476 DBUG_ON(part->channels != NULL);
477 part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS,
478 GFP_KERNEL);
479 if (part->channels == NULL) {
480 dev_err(xpc_chan, "can't get memory for channels\n");
481 return xpNoMemory;
482 }
483
484 /* allocate the remote open and close args */
485
486 part->remote_openclose_args =
487 xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
488 GFP_KERNEL, &part->
489 remote_openclose_args_base);
490 if (part->remote_openclose_args == NULL) {
491 dev_err(xpc_chan, "can't get memory for remote connect args\n");
492 ret = xpNoMemory;
493 goto out_1;
494 }
495
496 part->chctl.all_flags = 0;
497 spin_lock_init(&part->chctl_lock);
498
499 atomic_set(&part->channel_mgr_requests, 1);
500 init_waitqueue_head(&part->channel_mgr_wq);
501
502 part->nchannels = XPC_MAX_NCHANNELS;
503
504 atomic_set(&part->nchannels_active, 0);
505 atomic_set(&part->nchannels_engaged, 0);
506
507 for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
508 ch = &part->channels[ch_number];
509
510 ch->partid = partid;
511 ch->number = ch_number;
512 ch->flags = XPC_C_DISCONNECTED;
513
514 atomic_set(&ch->kthreads_assigned, 0);
515 atomic_set(&ch->kthreads_idle, 0);
516 atomic_set(&ch->kthreads_active, 0);
517
518 atomic_set(&ch->references, 0);
519 atomic_set(&ch->n_to_notify, 0);
520
521 spin_lock_init(&ch->lock);
522 init_completion(&ch->wdisconnect_wait);
523
524 atomic_set(&ch->n_on_msg_allocate_wq, 0);
525 init_waitqueue_head(&ch->msg_allocate_wq);
526 init_waitqueue_head(&ch->idle_wq);
527 }
528
529 ret = xpc_setup_ch_structures_sn(part);
530 if (ret != xpSuccess)
531 goto out_2;
532
533 /*
534 * With the setting of the partition setup_state to XPC_P_SS_SETUP,
535 * we're declaring that this partition is ready to go.
536 */
537 part->setup_state = XPC_P_SS_SETUP;
538
539 return xpSuccess;
540
541 /* setup of ch structures failed */
542out_2:
543 kfree(part->remote_openclose_args_base);
544 part->remote_openclose_args = NULL;
545out_1:
546 kfree(part->channels);
547 part->channels = NULL;
548 return ret;
549}
550
551/*
552 * Teardown the channel structures necessary to support XPartition Communication
553 * between the specified remote partition and the local one.
554 */
555static void
556xpc_teardown_ch_structures(struct xpc_partition *part)
557{
558 DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
559 DBUG_ON(atomic_read(&part->nchannels_active) != 0);
560
561 /*
562 * Make this partition inaccessible to local processes by marking it
563 * as no longer setup. Then wait before proceeding with the teardown
564 * until all existing references cease.
565 */
566 DBUG_ON(part->setup_state != XPC_P_SS_SETUP);
567 part->setup_state = XPC_P_SS_WTEARDOWN;
568
569 wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
570
571 /* now we can begin tearing down the infrastructure */
572
573 xpc_teardown_ch_structures_sn(part);
574
575 kfree(part->remote_openclose_args_base);
576 part->remote_openclose_args = NULL;
577 kfree(part->channels);
578 part->channels = NULL;
579
580 part->setup_state = XPC_P_SS_TORNDOWN;
581}
582
583/*
440 * When XPC HB determines that a partition has come up, it will create a new 584 * When XPC HB determines that a partition has come up, it will create a new
441 * kthread and that kthread will call this function to attempt to set up the 585 * kthread and that kthread will call this function to attempt to set up the
442 * basic infrastructure used for Cross Partition Communication with the newly 586 * basic infrastructure used for Cross Partition Communication with the newly
@@ -476,7 +620,7 @@ xpc_activating(void *__partid)
476 620
477 xpc_allow_hb(partid); 621 xpc_allow_hb(partid);
478 622
479 if (xpc_setup_infrastructure(part) == xpSuccess) { 623 if (xpc_setup_ch_structures(part) == xpSuccess) {
480 (void)xpc_part_ref(part); /* this will always succeed */ 624 (void)xpc_part_ref(part); /* this will always succeed */
481 625
482 if (xpc_make_first_contact(part) == xpSuccess) { 626 if (xpc_make_first_contact(part) == xpSuccess) {
@@ -486,7 +630,7 @@ xpc_activating(void *__partid)
486 } 630 }
487 631
488 xpc_part_deref(part); 632 xpc_part_deref(part);
489 xpc_teardown_infrastructure(part); 633 xpc_teardown_ch_structures(part);
490 } 634 }
491 635
492 xpc_disallow_hb(partid); 636 xpc_disallow_hb(partid);
@@ -806,6 +950,56 @@ xpc_disconnect_wait(int ch_number)
806 } 950 }
807} 951}
808 952
953static int
954xpc_setup_partitions(void)
955{
956 short partid;
957 struct xpc_partition *part;
958
959 xpc_partitions = kzalloc(sizeof(struct xpc_partition) *
960 xp_max_npartitions, GFP_KERNEL);
961 if (xpc_partitions == NULL) {
962 dev_err(xpc_part, "can't get memory for partition structure\n");
963 return -ENOMEM;
964 }
965
966 /*
967 * The first few fields of each entry of xpc_partitions[] need to
968 * be initialized now so that calls to xpc_connect() and
969 * xpc_disconnect() can be made prior to the activation of any remote
970 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
971 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
972 * PARTITION HAS BEEN ACTIVATED.
973 */
974 for (partid = 0; partid < xp_max_npartitions; partid++) {
975 part = &xpc_partitions[partid];
976
977 DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));
978
979 part->activate_IRQ_rcvd = 0;
980 spin_lock_init(&part->act_lock);
981 part->act_state = XPC_P_AS_INACTIVE;
982 XPC_SET_REASON(part, 0, 0);
983
984 init_timer(&part->disengage_timer);
985 part->disengage_timer.function =
986 xpc_timeout_partition_disengage;
987 part->disengage_timer.data = (unsigned long)part;
988
989 part->setup_state = XPC_P_SS_UNSET;
990 init_waitqueue_head(&part->teardown_wq);
991 atomic_set(&part->references, 0);
992 }
993
994 return xpc_setup_partitions_sn();
995}
996
997static void
998xpc_teardown_partitions(void)
999{
1000 kfree(xpc_partitions);
1001}
1002
809static void 1003static void
810xpc_do_exit(enum xp_retval reason) 1004xpc_do_exit(enum xp_retval reason)
811{ 1005{
@@ -892,8 +1086,7 @@ xpc_do_exit(enum xp_retval reason)
892 DBUG_ON(xpc_any_partition_engaged()); 1086 DBUG_ON(xpc_any_partition_engaged());
893 DBUG_ON(xpc_any_hbs_allowed() != 0); 1087 DBUG_ON(xpc_any_hbs_allowed() != 0);
894 1088
895 /* a zero timestamp indicates our rsvd page is not initialized */ 1089 xpc_teardown_rsvd_page();
896 xpc_rsvd_page->ts_jiffies = 0;
897 1090
898 if (reason == xpUnloading) { 1091 if (reason == xpUnloading) {
899 (void)unregister_die_notifier(&xpc_die_notifier); 1092 (void)unregister_die_notifier(&xpc_die_notifier);
@@ -906,7 +1099,7 @@ xpc_do_exit(enum xp_retval reason)
906 if (xpc_sysctl) 1099 if (xpc_sysctl)
907 unregister_sysctl_table(xpc_sysctl); 1100 unregister_sysctl_table(xpc_sysctl);
908 1101
909 kfree(xpc_partitions); 1102 xpc_teardown_partitions();
910 1103
911 if (is_shub()) 1104 if (is_shub())
912 xpc_exit_sn2(); 1105 xpc_exit_sn2();
@@ -1062,8 +1255,6 @@ int __init
1062xpc_init(void) 1255xpc_init(void)
1063{ 1256{
1064 int ret; 1257 int ret;
1065 short partid;
1066 struct xpc_partition *part;
1067 struct task_struct *kthread; 1258 struct task_struct *kthread;
1068 1259
1069 snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); 1260 snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
@@ -1076,56 +1267,29 @@ xpc_init(void)
1076 * further to only support exactly 64 partitions on this 1267 * further to only support exactly 64 partitions on this
1077 * architecture, no less. 1268 * architecture, no less.
1078 */ 1269 */
1079 if (xp_max_npartitions != 64) 1270 if (xp_max_npartitions != 64) {
1080 return -EINVAL; 1271 dev_err(xpc_part, "max #of partitions not set to 64\n");
1081 1272 ret = -EINVAL;
1082 ret = xpc_init_sn2(); 1273 } else {
1083 if (ret != 0) 1274 ret = xpc_init_sn2();
1084 return ret; 1275 }
1085 1276
1086 } else if (is_uv()) { 1277 } else if (is_uv()) {
1087 xpc_init_uv(); 1278 ret = xpc_init_uv();
1088 1279
1089 } else { 1280 } else {
1090 return -ENODEV; 1281 ret = -ENODEV;
1091 } 1282 }
1092 1283
1093 xpc_partitions = kzalloc(sizeof(struct xpc_partition) * 1284 if (ret != 0)
1094 xp_max_npartitions, GFP_KERNEL); 1285 return ret;
1095 if (xpc_partitions == NULL) { 1286
1287 ret = xpc_setup_partitions();
1288 if (ret != 0) {
1096 dev_err(xpc_part, "can't get memory for partition structure\n"); 1289 dev_err(xpc_part, "can't get memory for partition structure\n");
1097 ret = -ENOMEM;
1098 goto out_1; 1290 goto out_1;
1099 } 1291 }
1100 1292
1101 /*
1102 * The first few fields of each entry of xpc_partitions[] need to
1103 * be initialized now so that calls to xpc_connect() and
1104 * xpc_disconnect() can be made prior to the activation of any remote
1105 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
1106 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
1107 * PARTITION HAS BEEN ACTIVATED.
1108 */
1109 for (partid = 0; partid < xp_max_npartitions; partid++) {
1110 part = &xpc_partitions[partid];
1111
1112 DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));
1113
1114 part->activate_IRQ_rcvd = 0;
1115 spin_lock_init(&part->act_lock);
1116 part->act_state = XPC_P_AS_INACTIVE;
1117 XPC_SET_REASON(part, 0, 0);
1118
1119 init_timer(&part->disengage_timer);
1120 part->disengage_timer.function =
1121 xpc_timeout_partition_disengage;
1122 part->disengage_timer.data = (unsigned long)part;
1123
1124 part->setup_state = XPC_P_SS_UNSET;
1125 init_waitqueue_head(&part->teardown_wq);
1126 atomic_set(&part->references, 0);
1127 }
1128
1129 xpc_sysctl = register_sysctl_table(xpc_sys_dir); 1293 xpc_sysctl = register_sysctl_table(xpc_sys_dir);
1130 1294
1131 /* 1295 /*
@@ -1133,10 +1297,9 @@ xpc_init(void)
1133 * other partitions to discover we are alive and establish initial 1297 * other partitions to discover we are alive and establish initial
1134 * communications. 1298 * communications.
1135 */ 1299 */
1136 xpc_rsvd_page = xpc_setup_rsvd_page(); 1300 ret = xpc_setup_rsvd_page();
1137 if (xpc_rsvd_page == NULL) { 1301 if (ret != 0) {
1138 dev_err(xpc_part, "can't setup our reserved page\n"); 1302 dev_err(xpc_part, "can't setup our reserved page\n");
1139 ret = -EBUSY;
1140 goto out_2; 1303 goto out_2;
1141 } 1304 }
1142 1305
@@ -1187,15 +1350,15 @@ xpc_init(void)
1187 1350
1188 /* initialization was not successful */ 1351 /* initialization was not successful */
1189out_3: 1352out_3:
1190 /* a zero timestamp indicates our rsvd page is not initialized */ 1353 xpc_teardown_rsvd_page();
1191 xpc_rsvd_page->ts_jiffies = 0;
1192 1354
1193 (void)unregister_die_notifier(&xpc_die_notifier); 1355 (void)unregister_die_notifier(&xpc_die_notifier);
1194 (void)unregister_reboot_notifier(&xpc_reboot_notifier); 1356 (void)unregister_reboot_notifier(&xpc_reboot_notifier);
1195out_2: 1357out_2:
1196 if (xpc_sysctl) 1358 if (xpc_sysctl)
1197 unregister_sysctl_table(xpc_sysctl); 1359 unregister_sysctl_table(xpc_sysctl);
1198 kfree(xpc_partitions); 1360
1361 xpc_teardown_partitions();
1199out_1: 1362out_1:
1200 if (is_shub()) 1363 if (is_shub())
1201 xpc_exit_sn2(); 1364 xpc_exit_sn2();