hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
kernel/kernel/time/clockevents.c
....@@ -97,6 +97,7 @@
9797 /* Transition with new state-specific callbacks */
9898 switch (state) {
9999 case CLOCK_EVT_STATE_DETACHED:
100
+ case CLOCK_EVT_STATE_RESERVED:
100101 /* The clockevent device is getting replaced. Shut it down. */
101102
102103 case CLOCK_EVT_STATE_SHUTDOWN:
....@@ -437,6 +438,69 @@
437438 }
438439 EXPORT_SYMBOL_GPL(clockevents_unbind_device);
439440
441
+#ifdef CONFIG_IRQ_PIPELINE
442
+
443
+/**
444
+ * clockevents_register_proxy - register a proxy device on the current CPU
445
+ * @dev: proxy to register
446
+ */
447
+int clockevents_register_proxy(struct clock_proxy_device *dev)
448
+{
449
+ struct clock_event_device *proxy_dev, *real_dev;
450
+ unsigned long flags;
451
+ u32 freq;
452
+ int ret;
453
+
454
+ raw_spin_lock_irqsave(&clockevents_lock, flags);
455
+
456
+ ret = tick_setup_proxy(dev);
457
+ if (ret) {
458
+ raw_spin_unlock_irqrestore(&clockevents_lock, flags);
459
+ return ret;
460
+ }
461
+
462
+ proxy_dev = &dev->proxy_device;
463
+ clockevent_set_state(proxy_dev, CLOCK_EVT_STATE_DETACHED);
464
+
465
+ list_add(&proxy_dev->list, &clockevent_devices);
466
+ tick_check_new_device(proxy_dev);
467
+ clockevents_notify_released();
468
+
469
+ raw_spin_unlock_irqrestore(&clockevents_lock, flags);
470
+
471
+ real_dev = dev->real_device;
472
+ freq = (1000000000ULL * real_dev->mult) >> real_dev->shift;
473
+ printk(KERN_INFO "CPU%d: proxy tick device registered (%u.%02uMHz)\n",
474
+ smp_processor_id(), freq / 1000000, (freq / 10000) % 100);
475
+
476
+ return ret;
477
+}
478
+
479
+void clockevents_unregister_proxy(struct clock_proxy_device *dev)
480
+{
481
+ unsigned long flags;
482
+ int ret;
483
+
484
+ clockevents_register_device(dev->real_device);
485
+ clockevents_switch_state(dev->real_device, CLOCK_EVT_STATE_DETACHED);
486
+
487
+ /*
488
+ * Pop the proxy device, do not give it back to the
489
+ * framework.
490
+ */
491
+ raw_spin_lock_irqsave(&clockevents_lock, flags);
492
+ ret = clockevents_replace(&dev->proxy_device);
493
+ raw_spin_unlock_irqrestore(&clockevents_lock, flags);
494
+
495
+ if (WARN_ON(ret))
496
+ return;
497
+
498
+ printk(KERN_INFO "CPU%d: proxy tick device unregistered\n",
499
+ smp_processor_id());
500
+}
501
+
502
+#endif
503
+
440504 /**
441505 * clockevents_register_device - register a clock event device
442506 * @dev: device to register
....@@ -575,9 +639,18 @@
575639 */
576640 if (old) {
577641 module_put(old->owner);
578
- clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED);
642
+ /*
643
+ * Do not move the device backing a proxy tick device
644
+ * to the release list, keep it around but mark it as
645
+ * reserved.
646
+ */
579647 list_del(&old->list);
580
- list_add(&old->list, &clockevents_released);
648
+ if (tick_check_is_proxy(new)) {
649
+ clockevents_switch_state(old, CLOCK_EVT_STATE_RESERVED);
650
+ } else {
651
+ clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED);
652
+ list_add(&old->list, &clockevents_released);
653
+ }
581654 }
582655
583656 if (new) {