diff options
author | Dean Nelson <dcn@sgi.com> | 2008-07-30 01:34:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-30 12:41:49 -0400 |
commit | 33ba3c7724be79f7cdbfc611335572c056d9a05a (patch) | |
tree | db0371c031b0bbab13ccb2aeaf015424633cf2d8 /drivers/misc/sgi-xp/xpc_main.c | |
parent | e17d416b1bc947df68499863f13b401fb42b48f6 (diff) |
sgi-xp: isolate xpc_vars structure to sn2 only
Isolate the xpc_vars structure of XPC's reserved page to sn2 only.
Signed-off-by: Dean Nelson <dcn@sgi.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.c | 152 |
1 files changed, 101 insertions, 51 deletions
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index be3a48539307..10dac3652b23 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
@@ -148,12 +148,14 @@ static struct ctl_table_header *xpc_sysctl; | |||
148 | int xpc_disengage_request_timedout; | 148 | int xpc_disengage_request_timedout; |
149 | 149 | ||
150 | /* #of IRQs received */ | 150 | /* #of IRQs received */ |
151 | static atomic_t xpc_act_IRQ_rcvd; | 151 | atomic_t xpc_act_IRQ_rcvd; |
152 | 152 | ||
153 | /* IRQ handler notifies this wait queue on receipt of an IRQ */ | 153 | /* IRQ handler notifies this wait queue on receipt of an IRQ */ |
154 | static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq); | 154 | DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq); |
155 | 155 | ||
156 | static unsigned long xpc_hb_check_timeout; | 156 | static unsigned long xpc_hb_check_timeout; |
157 | static struct timer_list xpc_hb_timer; | ||
158 | void *xpc_heartbeating_to_mask; | ||
157 | 159 | ||
158 | /* notification that the xpc_hb_checker thread has exited */ | 160 | /* notification that the xpc_hb_checker thread has exited */ |
159 | static DECLARE_COMPLETION(xpc_hb_checker_exited); | 161 | static DECLARE_COMPLETION(xpc_hb_checker_exited); |
@@ -161,8 +163,6 @@ static DECLARE_COMPLETION(xpc_hb_checker_exited); | |||
161 | /* notification that the xpc_discovery thread has exited */ | 163 | /* notification that the xpc_discovery thread has exited */ |
162 | static DECLARE_COMPLETION(xpc_discovery_exited); | 164 | static DECLARE_COMPLETION(xpc_discovery_exited); |
163 | 165 | ||
164 | static struct timer_list xpc_hb_timer; | ||
165 | |||
166 | static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *); | 166 | static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *); |
167 | 167 | ||
168 | static int xpc_system_reboot(struct notifier_block *, unsigned long, void *); | 168 | static int xpc_system_reboot(struct notifier_block *, unsigned long, void *); |
@@ -176,12 +176,54 @@ static struct notifier_block xpc_die_notifier = { | |||
176 | }; | 176 | }; |
177 | 177 | ||
178 | enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *rp); | 178 | enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *rp); |
179 | void (*xpc_heartbeat_init) (void); | ||
180 | void (*xpc_heartbeat_exit) (void); | ||
181 | void (*xpc_increment_heartbeat) (void); | ||
182 | void (*xpc_offline_heartbeat) (void); | ||
183 | void (*xpc_online_heartbeat) (void); | ||
184 | void (*xpc_check_remote_hb) (void); | ||
185 | |||
179 | enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); | 186 | enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); |
180 | u64 (*xpc_get_IPI_flags) (struct xpc_partition *part); | 187 | u64 (*xpc_get_IPI_flags) (struct xpc_partition *part); |
181 | struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); | 188 | struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); |
189 | |||
190 | void (*xpc_initiate_partition_activation) (struct xpc_rsvd_page *remote_rp, | ||
191 | u64 remote_rp_pa, int nasid); | ||
192 | |||
193 | void (*xpc_process_act_IRQ_rcvd) (int n_IRQs_expected); | ||
182 | enum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *part); | 194 | enum xp_retval (*xpc_setup_infrastructure) (struct xpc_partition *part); |
183 | void (*xpc_teardown_infrastructure) (struct xpc_partition *part); | 195 | void (*xpc_teardown_infrastructure) (struct xpc_partition *part); |
184 | 196 | ||
197 | void (*xpc_mark_partition_engaged) (struct xpc_partition *part); | ||
198 | void (*xpc_mark_partition_disengaged) (struct xpc_partition *part); | ||
199 | void (*xpc_request_partition_disengage) (struct xpc_partition *part); | ||
200 | void (*xpc_cancel_partition_disengage_request) (struct xpc_partition *part); | ||
201 | u64 (*xpc_partition_engaged) (u64 partid_mask); | ||
202 | u64 (*xpc_partition_disengage_requested) (u64 partid_mask); | ||
203 | void (*xpc_clear_partition_engaged) (u64 partid_mask); | ||
204 | void (*xpc_clear_partition_disengage_request) (u64 partid_mask); | ||
205 | |||
206 | void (*xpc_IPI_send_local_activate) (int from_nasid); | ||
207 | void (*xpc_IPI_send_activated) (struct xpc_partition *part); | ||
208 | void (*xpc_IPI_send_local_reactivate) (int from_nasid); | ||
209 | void (*xpc_IPI_send_disengage) (struct xpc_partition *part); | ||
210 | |||
211 | void (*xpc_IPI_send_closerequest) (struct xpc_channel *ch, | ||
212 | unsigned long *irq_flags); | ||
213 | void (*xpc_IPI_send_closereply) (struct xpc_channel *ch, | ||
214 | unsigned long *irq_flags); | ||
215 | void (*xpc_IPI_send_openrequest) (struct xpc_channel *ch, | ||
216 | unsigned long *irq_flags); | ||
217 | void (*xpc_IPI_send_openreply) (struct xpc_channel *ch, | ||
218 | unsigned long *irq_flags); | ||
219 | |||
220 | enum xp_retval (*xpc_allocate_msg) (struct xpc_channel *ch, u32 flags, | ||
221 | struct xpc_msg **address_of_msg); | ||
222 | |||
223 | enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, struct xpc_msg *msg, | ||
224 | u8 notify_type, xpc_notify_func func, | ||
225 | void *key); | ||
226 | void (*xpc_received_msg) (struct xpc_channel *ch, struct xpc_msg *msg); | ||
185 | 227 | ||
186 | /* | 228 | /* |
187 | * Timer function to enforce the timelimit on the partition disengage request. | 229 | * Timer function to enforce the timelimit on the partition disengage request. |
@@ -218,7 +260,7 @@ xpc_act_IRQ_handler(int irq, void *dev_id) | |||
218 | static void | 260 | static void |
219 | xpc_hb_beater(unsigned long dummy) | 261 | xpc_hb_beater(unsigned long dummy) |
220 | { | 262 | { |
221 | xpc_vars->heartbeat++; | 263 | xpc_increment_heartbeat(); |
222 | 264 | ||
223 | if (time_after_eq(jiffies, xpc_hb_check_timeout)) | 265 | if (time_after_eq(jiffies, xpc_hb_check_timeout)) |
224 | wake_up_interruptible(&xpc_act_IRQ_wq); | 266 | wake_up_interruptible(&xpc_act_IRQ_wq); |
@@ -227,6 +269,22 @@ xpc_hb_beater(unsigned long dummy) | |||
227 | add_timer(&xpc_hb_timer); | 269 | add_timer(&xpc_hb_timer); |
228 | } | 270 | } |
229 | 271 | ||
272 | static void | ||
273 | xpc_start_hb_beater(void) | ||
274 | { | ||
275 | xpc_heartbeat_init(); | ||
276 | init_timer(&xpc_hb_timer); | ||
277 | xpc_hb_timer.function = xpc_hb_beater; | ||
278 | xpc_hb_beater(0); | ||
279 | } | ||
280 | |||
281 | static void | ||
282 | xpc_stop_hb_beater(void) | ||
283 | { | ||
284 | del_timer_sync(&xpc_hb_timer); | ||
285 | xpc_heartbeat_exit(); | ||
286 | } | ||
287 | |||
230 | /* | 288 | /* |
231 | * This thread is responsible for nearly all of the partition | 289 | * This thread is responsible for nearly all of the partition |
232 | * activation/deactivation. | 290 | * activation/deactivation. |
@@ -244,7 +302,7 @@ xpc_hb_checker(void *ignore) | |||
244 | 302 | ||
245 | /* set our heartbeating to other partitions into motion */ | 303 | /* set our heartbeating to other partitions into motion */ |
246 | xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); | 304 | xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); |
247 | xpc_hb_beater(0); | 305 | xpc_start_hb_beater(); |
248 | 306 | ||
249 | while (!xpc_exiting) { | 307 | while (!xpc_exiting) { |
250 | 308 | ||
@@ -274,11 +332,8 @@ xpc_hb_checker(void *ignore) | |||
274 | dev_dbg(xpc_part, "found an IRQ to process; will be " | 332 | dev_dbg(xpc_part, "found an IRQ to process; will be " |
275 | "resetting xpc_hb_check_timeout\n"); | 333 | "resetting xpc_hb_check_timeout\n"); |
276 | 334 | ||
277 | last_IRQ_count += xpc_identify_act_IRQ_sender(); | 335 | xpc_process_act_IRQ_rcvd(new_IRQ_count - |
278 | if (last_IRQ_count < new_IRQ_count) { | 336 | last_IRQ_count); |
279 | /* retry once to help avoid missing AMO */ | ||
280 | (void)xpc_identify_act_IRQ_sender(); | ||
281 | } | ||
282 | last_IRQ_count = new_IRQ_count; | 337 | last_IRQ_count = new_IRQ_count; |
283 | 338 | ||
284 | xpc_hb_check_timeout = jiffies + | 339 | xpc_hb_check_timeout = jiffies + |
@@ -294,6 +349,8 @@ xpc_hb_checker(void *ignore) | |||
294 | xpc_exiting)); | 349 | xpc_exiting)); |
295 | } | 350 | } |
296 | 351 | ||
352 | xpc_stop_hb_beater(); | ||
353 | |||
297 | dev_dbg(xpc_part, "heartbeat checker is exiting\n"); | 354 | dev_dbg(xpc_part, "heartbeat checker is exiting\n"); |
298 | 355 | ||
299 | /* mark this thread as having exited */ | 356 | /* mark this thread as having exited */ |
@@ -401,31 +458,7 @@ xpc_activating(void *__partid) | |||
401 | 458 | ||
402 | dev_dbg(xpc_part, "activating partition %d\n", partid); | 459 | dev_dbg(xpc_part, "activating partition %d\n", partid); |
403 | 460 | ||
404 | /* | 461 | xpc_allow_hb(partid); |
405 | * Register the remote partition's AMOs with SAL so it can handle | ||
406 | * and cleanup errors within that address range should the remote | ||
407 | * partition go down. We don't unregister this range because it is | ||
408 | * difficult to tell when outstanding writes to the remote partition | ||
409 | * are finished and thus when it is safe to unregister. This should | ||
410 | * not result in wasted space in the SAL xp_addr_region table because | ||
411 | * we should get the same page for remote_amos_page_pa after module | ||
412 | * reloads and system reboots. | ||
413 | */ | ||
414 | if (sn_register_xp_addr_region(part->remote_amos_page_pa, | ||
415 | PAGE_SIZE, 1) < 0) { | ||
416 | dev_warn(xpc_part, "xpc_activating(%d) failed to register " | ||
417 | "xp_addr region\n", partid); | ||
418 | |||
419 | spin_lock_irqsave(&part->act_lock, irq_flags); | ||
420 | part->act_state = XPC_P_INACTIVE; | ||
421 | XPC_SET_REASON(part, xpPhysAddrRegFailed, __LINE__); | ||
422 | spin_unlock_irqrestore(&part->act_lock, irq_flags); | ||
423 | part->remote_rp_pa = 0; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | xpc_allow_hb(partid, xpc_vars); | ||
428 | xpc_IPI_send_activated(part); | ||
429 | 462 | ||
430 | if (xpc_setup_infrastructure(part) == xpSuccess) { | 463 | if (xpc_setup_infrastructure(part) == xpSuccess) { |
431 | (void)xpc_part_ref(part); /* this will always succeed */ | 464 | (void)xpc_part_ref(part); /* this will always succeed */ |
@@ -440,12 +473,12 @@ xpc_activating(void *__partid) | |||
440 | xpc_teardown_infrastructure(part); | 473 | xpc_teardown_infrastructure(part); |
441 | } | 474 | } |
442 | 475 | ||
443 | xpc_disallow_hb(partid, xpc_vars); | 476 | xpc_disallow_hb(partid); |
444 | xpc_mark_partition_inactive(part); | 477 | xpc_mark_partition_inactive(part); |
445 | 478 | ||
446 | if (part->reason == xpReactivating) { | 479 | if (part->reason == xpReactivating) { |
447 | /* interrupting ourselves results in activating partition */ | 480 | /* interrupting ourselves results in activating partition */ |
448 | xpc_IPI_send_reactivate(part); | 481 | xpc_IPI_send_local_reactivate(part->reactivate_nasid); |
449 | } | 482 | } |
450 | 483 | ||
451 | return 0; | 484 | return 0; |
@@ -478,6 +511,32 @@ xpc_activate_partition(struct xpc_partition *part) | |||
478 | } | 511 | } |
479 | 512 | ||
480 | /* | 513 | /* |
514 | * Check to see if there is any channel activity to/from the specified | ||
515 | * partition. | ||
516 | */ | ||
517 | static void | ||
518 | xpc_check_for_channel_activity(struct xpc_partition *part) | ||
519 | { | ||
520 | u64 IPI_amo; | ||
521 | unsigned long irq_flags; | ||
522 | |||
523 | /* this needs to be uncommented, but I'm thinking this function and the */ | ||
524 | /* ones that call it need to be moved into xpc_sn2.c... */ | ||
525 | IPI_amo = 0; /* = xpc_IPI_receive(part->local_IPI_amo_va); */ | ||
526 | if (IPI_amo == 0) | ||
527 | return; | ||
528 | |||
529 | spin_lock_irqsave(&part->IPI_lock, irq_flags); | ||
530 | part->local_IPI_amo |= IPI_amo; | ||
531 | spin_unlock_irqrestore(&part->IPI_lock, irq_flags); | ||
532 | |||
533 | dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n", | ||
534 | XPC_PARTID(part), IPI_amo); | ||
535 | |||
536 | xpc_wakeup_channel_mgr(part); | ||
537 | } | ||
538 | |||
539 | /* | ||
481 | * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified | 540 | * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified |
482 | * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more | 541 | * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more |
483 | * than one partition, we use an AMO_t structure per partition to indicate | 542 | * than one partition, we use an AMO_t structure per partition to indicate |
@@ -902,14 +961,11 @@ xpc_do_exit(enum xp_retval reason) | |||
902 | } while (1); | 961 | } while (1); |
903 | 962 | ||
904 | DBUG_ON(xpc_partition_engaged(-1UL)); | 963 | DBUG_ON(xpc_partition_engaged(-1UL)); |
964 | DBUG_ON(xpc_any_hbs_allowed() != 0); | ||
905 | 965 | ||
906 | /* indicate to others that our reserved page is uninitialized */ | 966 | /* indicate to others that our reserved page is uninitialized */ |
907 | xpc_rsvd_page->stamp = ZERO_STAMP; | 967 | xpc_rsvd_page->stamp = ZERO_STAMP; |
908 | 968 | ||
909 | /* now it's time to eliminate our heartbeat */ | ||
910 | del_timer_sync(&xpc_hb_timer); | ||
911 | DBUG_ON(xpc_vars->heartbeating_to_mask != 0); | ||
912 | |||
913 | if (reason == xpUnloading) { | 969 | if (reason == xpUnloading) { |
914 | (void)unregister_die_notifier(&xpc_die_notifier); | 970 | (void)unregister_die_notifier(&xpc_die_notifier); |
915 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); | 971 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); |
@@ -968,7 +1024,7 @@ xpc_die_disengage(void) | |||
968 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | 1024 | /* keep xpc_hb_checker thread from doing anything (just in case) */ |
969 | xpc_exiting = 1; | 1025 | xpc_exiting = 1; |
970 | 1026 | ||
971 | xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */ | 1027 | xpc_disallow_all_hbs(); /*indicate we're deactivated */ |
972 | 1028 | ||
973 | for (partid = 0; partid < xp_max_npartitions; partid++) { | 1029 | for (partid = 0; partid < xp_max_npartitions; partid++) { |
974 | part = &xpc_partitions[partid]; | 1030 | part = &xpc_partitions[partid]; |
@@ -1054,8 +1110,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
1054 | /* fall through */ | 1110 | /* fall through */ |
1055 | case DIE_MCA_MONARCH_ENTER: | 1111 | case DIE_MCA_MONARCH_ENTER: |
1056 | case DIE_INIT_MONARCH_ENTER: | 1112 | case DIE_INIT_MONARCH_ENTER: |
1057 | xpc_vars->heartbeat++; | 1113 | xpc_offline_heartbeat(); |
1058 | xpc_vars->heartbeat_offline = 1; | ||
1059 | break; | 1114 | break; |
1060 | 1115 | ||
1061 | case DIE_KDEBUG_LEAVE: | 1116 | case DIE_KDEBUG_LEAVE: |
@@ -1066,8 +1121,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
1066 | /* fall through */ | 1121 | /* fall through */ |
1067 | case DIE_MCA_MONARCH_LEAVE: | 1122 | case DIE_MCA_MONARCH_LEAVE: |
1068 | case DIE_INIT_MONARCH_LEAVE: | 1123 | case DIE_INIT_MONARCH_LEAVE: |
1069 | xpc_vars->heartbeat++; | 1124 | xpc_online_heartbeat(); |
1070 | xpc_vars->heartbeat_offline = 0; | ||
1071 | break; | 1125 | break; |
1072 | } | 1126 | } |
1073 | 1127 | ||
@@ -1202,9 +1256,6 @@ xpc_init(void) | |||
1202 | if (ret != 0) | 1256 | if (ret != 0) |
1203 | dev_warn(xpc_part, "can't register die notifier\n"); | 1257 | dev_warn(xpc_part, "can't register die notifier\n"); |
1204 | 1258 | ||
1205 | init_timer(&xpc_hb_timer); | ||
1206 | xpc_hb_timer.function = xpc_hb_beater; | ||
1207 | |||
1208 | /* | 1259 | /* |
1209 | * The real work-horse behind xpc. This processes incoming | 1260 | * The real work-horse behind xpc. This processes incoming |
1210 | * interrupts and monitors remote heartbeats. | 1261 | * interrupts and monitors remote heartbeats. |
@@ -1246,7 +1297,6 @@ out_4: | |||
1246 | /* indicate to others that our reserved page is uninitialized */ | 1297 | /* indicate to others that our reserved page is uninitialized */ |
1247 | xpc_rsvd_page->stamp = ZERO_STAMP; | 1298 | xpc_rsvd_page->stamp = ZERO_STAMP; |
1248 | 1299 | ||
1249 | del_timer_sync(&xpc_hb_timer); | ||
1250 | (void)unregister_die_notifier(&xpc_die_notifier); | 1300 | (void)unregister_die_notifier(&xpc_die_notifier); |
1251 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); | 1301 | (void)unregister_reboot_notifier(&xpc_reboot_notifier); |
1252 | out_3: | 1302 | out_3: |