| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0  | 
|---|
| 1 | 2 |  /* | 
|---|
| 2 |  | - * linux/kernel/time/tick-broadcast.c  | 
|---|
| 3 |  | - *  | 
|---|
| 4 | 3 |   * This file contains functions which emulate a local clock-event | 
|---|
| 5 | 4 |   * device via a broadcast event source. | 
|---|
| 6 | 5 |   * | 
|---|
| 7 | 6 |   * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> | 
|---|
| 8 | 7 |   * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar | 
|---|
| 9 | 8 |   * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner | 
|---|
| 10 |  | - *  | 
|---|
| 11 |  | - * This code is licenced under the GPL version 2. For details see  | 
|---|
| 12 |  | - * kernel-base/COPYING.  | 
|---|
| 13 | 9 |   */ | 
|---|
| 14 | 10 |  #include <linux/cpu.h> | 
|---|
| 15 | 11 |  #include <linux/err.h> | 
|---|
| .. | .. | 
|---|
| 37 | 33 |  static __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(tick_broadcast_lock); | 
|---|
| 38 | 34 |   | 
|---|
| 39 | 35 |  #ifdef CONFIG_TICK_ONESHOT | 
|---|
 | 36 | +static DEFINE_PER_CPU(struct clock_event_device *, tick_oneshot_wakeup_device);  | 
|---|
 | 37 | +  | 
|---|
| 40 | 38 |  static void tick_broadcast_setup_oneshot(struct clock_event_device *bc); | 
|---|
| 41 | 39 |  static void tick_broadcast_clear_oneshot(int cpu); | 
|---|
| 42 | 40 |  static void tick_resume_broadcast_oneshot(struct clock_event_device *bc); | 
|---|
 | 41 | +# ifdef CONFIG_HOTPLUG_CPU  | 
|---|
 | 42 | +static void tick_broadcast_oneshot_offline(unsigned int cpu);  | 
|---|
 | 43 | +# endif  | 
|---|
| 43 | 44 |  #else | 
|---|
| 44 | 45 |  static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); } | 
|---|
| 45 | 46 |  static inline void tick_broadcast_clear_oneshot(int cpu) { } | 
|---|
| 46 | 47 |  static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { } | 
|---|
 | 48 | +# ifdef CONFIG_HOTPLUG_CPU  | 
|---|
 | 49 | +static inline void tick_broadcast_oneshot_offline(unsigned int cpu) { }  | 
|---|
 | 50 | +# endif  | 
|---|
| 47 | 51 |  #endif | 
|---|
| 48 | 52 |   | 
|---|
| 49 | 53 |  /* | 
|---|
| .. | .. | 
|---|
| 57 | 61 |  struct cpumask *tick_get_broadcast_mask(void) | 
|---|
| 58 | 62 |  { | 
|---|
| 59 | 63 |  	return tick_broadcast_mask; | 
|---|
 | 64 | +}  | 
|---|
 | 65 | +  | 
|---|
 | 66 | +static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu);  | 
|---|
 | 67 | +  | 
|---|
 | 68 | +const struct clock_event_device *tick_get_wakeup_device(int cpu)  | 
|---|
 | 69 | +{  | 
|---|
 | 70 | +	return tick_get_oneshot_wakeup_device(cpu);  | 
|---|
| 60 | 71 |  } | 
|---|
| 61 | 72 |   | 
|---|
| 62 | 73 |  /* | 
|---|
| .. | .. | 
|---|
| 86 | 97 |  	return !curdev || newdev->rating > curdev->rating; | 
|---|
| 87 | 98 |  } | 
|---|
| 88 | 99 |   | 
|---|
 | 100 | +#ifdef CONFIG_TICK_ONESHOT  | 
|---|
 | 101 | +static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu)  | 
|---|
 | 102 | +{  | 
|---|
 | 103 | +	return per_cpu(tick_oneshot_wakeup_device, cpu);  | 
|---|
 | 104 | +}  | 
|---|
 | 105 | +  | 
|---|
 | 106 | +static void tick_oneshot_wakeup_handler(struct clock_event_device *wd)  | 
|---|
 | 107 | +{  | 
|---|
 | 108 | +	/*  | 
|---|
 | 109 | +	 * If we woke up early and the tick was reprogrammed in the  | 
|---|
 | 110 | +	 * meantime then this may be spurious but harmless.  | 
|---|
 | 111 | +	 */  | 
|---|
 | 112 | +	tick_receive_broadcast();  | 
|---|
 | 113 | +}  | 
|---|
 | 114 | +  | 
|---|
 | 115 | +static bool tick_set_oneshot_wakeup_device(struct clock_event_device *newdev,  | 
|---|
 | 116 | +					   int cpu)  | 
|---|
 | 117 | +{  | 
|---|
 | 118 | +	struct clock_event_device *curdev = tick_get_oneshot_wakeup_device(cpu);  | 
|---|
 | 119 | +  | 
|---|
 | 120 | +	if (!newdev)  | 
|---|
 | 121 | +		goto set_device;  | 
|---|
 | 122 | +  | 
|---|
 | 123 | +	if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) ||  | 
|---|
 | 124 | +	    (newdev->features & CLOCK_EVT_FEAT_C3STOP))  | 
|---|
 | 125 | +		 return false;  | 
|---|
 | 126 | +  | 
|---|
 | 127 | +	if (!(newdev->features & CLOCK_EVT_FEAT_PERCPU) ||  | 
|---|
 | 128 | +	    !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))  | 
|---|
 | 129 | +		return false;  | 
|---|
 | 130 | +  | 
|---|
 | 131 | +	if (!cpumask_equal(newdev->cpumask, cpumask_of(cpu)))  | 
|---|
 | 132 | +		return false;  | 
|---|
 | 133 | +  | 
|---|
 | 134 | +	if (curdev && newdev->rating <= curdev->rating)  | 
|---|
 | 135 | +		return false;  | 
|---|
 | 136 | +  | 
|---|
 | 137 | +	if (!try_module_get(newdev->owner))  | 
|---|
 | 138 | +		return false;  | 
|---|
 | 139 | +  | 
|---|
 | 140 | +	newdev->event_handler = tick_oneshot_wakeup_handler;  | 
|---|
 | 141 | +set_device:  | 
|---|
 | 142 | +	clockevents_exchange_device(curdev, newdev);  | 
|---|
 | 143 | +	per_cpu(tick_oneshot_wakeup_device, cpu) = newdev;  | 
|---|
 | 144 | +	return true;  | 
|---|
 | 145 | +}  | 
|---|
 | 146 | +#else  | 
|---|
 | 147 | +static struct clock_event_device *tick_get_oneshot_wakeup_device(int cpu)  | 
|---|
 | 148 | +{  | 
|---|
 | 149 | +	return NULL;  | 
|---|
 | 150 | +}  | 
|---|
 | 151 | +  | 
|---|
 | 152 | +static bool tick_set_oneshot_wakeup_device(struct clock_event_device *newdev,  | 
|---|
 | 153 | +					   int cpu)  | 
|---|
 | 154 | +{  | 
|---|
 | 155 | +	return false;  | 
|---|
 | 156 | +}  | 
|---|
 | 157 | +#endif  | 
|---|
 | 158 | +  | 
|---|
| 89 | 159 |  /* | 
|---|
| 90 | 160 |   * Conditionally install/replace broadcast device | 
|---|
| 91 | 161 |   */ | 
|---|
| 92 |  | -void tick_install_broadcast_device(struct clock_event_device *dev)  | 
|---|
 | 162 | +void tick_install_broadcast_device(struct clock_event_device *dev, int cpu)  | 
|---|
| 93 | 163 |  { | 
|---|
| 94 | 164 |  	struct clock_event_device *cur = tick_broadcast_device.evtdev; | 
|---|
 | 165 | +  | 
|---|
 | 166 | +	if (tick_set_oneshot_wakeup_device(dev, cpu))  | 
|---|
 | 167 | +		return;  | 
|---|
| 95 | 168 |   | 
|---|
| 96 | 169 |  	if (!tick_check_broadcast_device(cur, dev)) | 
|---|
| 97 | 170 |  		return; | 
|---|
| .. | .. | 
|---|
| 105 | 178 |  	tick_broadcast_device.evtdev = dev; | 
|---|
| 106 | 179 |  	if (!cpumask_empty(tick_broadcast_mask)) | 
|---|
| 107 | 180 |  		tick_broadcast_start_periodic(dev); | 
|---|
 | 181 | +  | 
|---|
 | 182 | +	if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))  | 
|---|
 | 183 | +		return;  | 
|---|
 | 184 | +  | 
|---|
 | 185 | +	/*  | 
|---|
 | 186 | +	 * If the system already runs in oneshot mode, switch the newly  | 
|---|
 | 187 | +	 * registered broadcast device to oneshot mode explicitly.  | 
|---|
 | 188 | +	 */  | 
|---|
 | 189 | +	if (tick_broadcast_oneshot_active()) {  | 
|---|
 | 190 | +		tick_broadcast_switch_to_oneshot();  | 
|---|
 | 191 | +		return;  | 
|---|
 | 192 | +	}  | 
|---|
 | 193 | +  | 
|---|
| 108 | 194 |  	/* | 
|---|
| 109 | 195 |  	 * Inform all cpus about this. We might be in a situation | 
|---|
| 110 | 196 |  	 * where we did not switch to oneshot mode because the per cpu | 
|---|
| .. | .. | 
|---|
| 113 | 199 |  	 * notification the systems stays stuck in periodic mode | 
|---|
| 114 | 200 |  	 * forever. | 
|---|
| 115 | 201 |  	 */ | 
|---|
| 116 |  | -	if (dev->features & CLOCK_EVT_FEAT_ONESHOT)  | 
|---|
| 117 |  | -		tick_clock_notify();  | 
|---|
 | 202 | +	tick_clock_notify();  | 
|---|
| 118 | 203 |  } | 
|---|
| 119 | 204 |   | 
|---|
| 120 | 205 |  /* | 
|---|
| .. | .. | 
|---|
| 239 | 324 |  	return ret; | 
|---|
| 240 | 325 |  } | 
|---|
| 241 | 326 |   | 
|---|
| 242 |  | -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST  | 
|---|
| 243 | 327 |  int tick_receive_broadcast(void) | 
|---|
| 244 | 328 |  { | 
|---|
| 245 | 329 |  	struct tick_device *td = this_cpu_ptr(&tick_cpu_device); | 
|---|
| .. | .. | 
|---|
| 254 | 338 |  	evt->event_handler(evt); | 
|---|
| 255 | 339 |  	return 0; | 
|---|
| 256 | 340 |  } | 
|---|
| 257 |  | -#endif  | 
|---|
| 258 | 341 |   | 
|---|
| 259 | 342 |  /* | 
|---|
| 260 | 343 |   * Broadcast the event to the cpus, which are set in the mask (mangled). | 
|---|
| .. | .. | 
|---|
| 379 | 462 |  	switch (mode) { | 
|---|
| 380 | 463 |  	case TICK_BROADCAST_FORCE: | 
|---|
| 381 | 464 |  		tick_broadcast_forced = 1; | 
|---|
 | 465 | +		fallthrough;  | 
|---|
| 382 | 466 |  	case TICK_BROADCAST_ON: | 
|---|
| 383 | 467 |  		cpumask_set_cpu(cpu, tick_broadcast_on); | 
|---|
| 384 | 468 |  		if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { | 
|---|
| .. | .. | 
|---|
| 400 | 484 |  		if (tick_broadcast_forced) | 
|---|
| 401 | 485 |  			break; | 
|---|
| 402 | 486 |  		cpumask_clear_cpu(cpu, tick_broadcast_on); | 
|---|
| 403 |  | -		if (!tick_device_is_functional(dev))  | 
|---|
| 404 |  | -			break;  | 
|---|
| 405 | 487 |  		if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_mask)) { | 
|---|
| 406 | 488 |  			if (tick_broadcast_device.mode == | 
|---|
| 407 | 489 |  			    TICKDEV_MODE_PERIODIC) | 
|---|
| .. | .. | 
|---|
| 438 | 520 |  } | 
|---|
| 439 | 521 |   | 
|---|
| 440 | 522 |  #ifdef CONFIG_HOTPLUG_CPU | 
|---|
| 441 |  | -/*  | 
|---|
| 442 |  | - * Remove a CPU from broadcasting  | 
|---|
| 443 |  | - */  | 
|---|
| 444 |  | -void tick_shutdown_broadcast(unsigned int cpu)  | 
|---|
 | 523 | +static void tick_shutdown_broadcast(void)  | 
|---|
| 445 | 524 |  { | 
|---|
| 446 |  | -	struct clock_event_device *bc;  | 
|---|
| 447 |  | -	unsigned long flags;  | 
|---|
| 448 |  | -  | 
|---|
| 449 |  | -	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);  | 
|---|
| 450 |  | -  | 
|---|
| 451 |  | -	bc = tick_broadcast_device.evtdev;  | 
|---|
| 452 |  | -	cpumask_clear_cpu(cpu, tick_broadcast_mask);  | 
|---|
| 453 |  | -	cpumask_clear_cpu(cpu, tick_broadcast_on);  | 
|---|
 | 525 | +	struct clock_event_device *bc = tick_broadcast_device.evtdev;  | 
|---|
| 454 | 526 |   | 
|---|
| 455 | 527 |  	if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { | 
|---|
| 456 | 528 |  		if (bc && cpumask_empty(tick_broadcast_mask)) | 
|---|
| 457 | 529 |  			clockevents_shutdown(bc); | 
|---|
| 458 | 530 |  	} | 
|---|
| 459 |  | -  | 
|---|
| 460 |  | -	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);  | 
|---|
| 461 | 531 |  } | 
|---|
 | 532 | +  | 
|---|
 | 533 | +/*  | 
|---|
 | 534 | + * Remove a CPU from broadcasting  | 
|---|
 | 535 | + */  | 
|---|
 | 536 | +void tick_broadcast_offline(unsigned int cpu)  | 
|---|
 | 537 | +{  | 
|---|
 | 538 | +	raw_spin_lock(&tick_broadcast_lock);  | 
|---|
 | 539 | +	cpumask_clear_cpu(cpu, tick_broadcast_mask);  | 
|---|
 | 540 | +	cpumask_clear_cpu(cpu, tick_broadcast_on);  | 
|---|
 | 541 | +	tick_broadcast_oneshot_offline(cpu);  | 
|---|
 | 542 | +	tick_shutdown_broadcast();  | 
|---|
 | 543 | +	raw_spin_unlock(&tick_broadcast_lock);  | 
|---|
 | 544 | +}  | 
|---|
 | 545 | +  | 
|---|
| 462 | 546 |  #endif | 
|---|
| 463 | 547 |   | 
|---|
| 464 | 548 |  void tick_suspend_broadcast(void) | 
|---|
| .. | .. | 
|---|
| 704 | 788 |  	clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); | 
|---|
| 705 | 789 |  } | 
|---|
| 706 | 790 |   | 
|---|
| 707 |  | -int __tick_broadcast_oneshot_control(enum tick_broadcast_state state)  | 
|---|
 | 791 | +static int ___tick_broadcast_oneshot_control(enum tick_broadcast_state state,  | 
|---|
 | 792 | +					     struct tick_device *td,  | 
|---|
 | 793 | +					     int cpu)  | 
|---|
| 708 | 794 |  { | 
|---|
| 709 |  | -	struct clock_event_device *bc, *dev;  | 
|---|
| 710 |  | -	int cpu, ret = 0;  | 
|---|
 | 795 | +	struct clock_event_device *bc, *dev = td->evtdev;  | 
|---|
 | 796 | +	int ret = 0;  | 
|---|
| 711 | 797 |  	ktime_t now; | 
|---|
| 712 |  | -  | 
|---|
| 713 |  | -	/*  | 
|---|
| 714 |  | -	 * If there is no broadcast device, tell the caller not to go  | 
|---|
| 715 |  | -	 * into deep idle.  | 
|---|
| 716 |  | -	 */  | 
|---|
| 717 |  | -	if (!tick_broadcast_device.evtdev)  | 
|---|
| 718 |  | -		return -EBUSY;  | 
|---|
| 719 |  | -  | 
|---|
| 720 |  | -	dev = this_cpu_ptr(&tick_cpu_device)->evtdev;  | 
|---|
| 721 | 798 |   | 
|---|
| 722 | 799 |  	raw_spin_lock(&tick_broadcast_lock); | 
|---|
| 723 | 800 |  	bc = tick_broadcast_device.evtdev; | 
|---|
| 724 |  | -	cpu = smp_processor_id();  | 
|---|
| 725 | 801 |   | 
|---|
| 726 | 802 |  	if (state == TICK_BROADCAST_ENTER) { | 
|---|
| 727 | 803 |  		/* | 
|---|
| .. | .. | 
|---|
| 806 | 882 |  			 * either the CPU handling the broadcast | 
|---|
| 807 | 883 |  			 * interrupt or we got woken by something else. | 
|---|
| 808 | 884 |  			 * | 
|---|
| 809 |  | -			 * We are not longer in the broadcast mask, so  | 
|---|
 | 885 | +			 * We are no longer in the broadcast mask, so  | 
|---|
| 810 | 886 |  			 * if the cpu local expiry time is already | 
|---|
| 811 | 887 |  			 * reached, we would reprogram the cpu local | 
|---|
| 812 | 888 |  			 * timer with an already expired event. | 
|---|
| 813 | 889 |  			 * | 
|---|
| 814 | 890 |  			 * This can lead to a ping-pong when we return | 
|---|
| 815 |  | -			 * to idle and therefor rearm the broadcast  | 
|---|
 | 891 | +			 * to idle and therefore rearm the broadcast  | 
|---|
| 816 | 892 |  			 * timer before the cpu local timer was able | 
|---|
| 817 | 893 |  			 * to fire. This happens because the forced | 
|---|
| 818 | 894 |  			 * reprogramming makes sure that the event | 
|---|
| .. | .. | 
|---|
| 848 | 924 |  out: | 
|---|
| 849 | 925 |  	raw_spin_unlock(&tick_broadcast_lock); | 
|---|
| 850 | 926 |  	return ret; | 
|---|
 | 927 | +}  | 
|---|
 | 928 | +  | 
|---|
 | 929 | +static int tick_oneshot_wakeup_control(enum tick_broadcast_state state,  | 
|---|
 | 930 | +				       struct tick_device *td,  | 
|---|
 | 931 | +				       int cpu)  | 
|---|
 | 932 | +{  | 
|---|
 | 933 | +	struct clock_event_device *dev, *wd;  | 
|---|
 | 934 | +  | 
|---|
 | 935 | +	dev = td->evtdev;  | 
|---|
 | 936 | +	if (td->mode != TICKDEV_MODE_ONESHOT)  | 
|---|
 | 937 | +		return -EINVAL;  | 
|---|
 | 938 | +  | 
|---|
 | 939 | +	wd = tick_get_oneshot_wakeup_device(cpu);  | 
|---|
 | 940 | +	if (!wd)  | 
|---|
 | 941 | +		return -ENODEV;  | 
|---|
 | 942 | +  | 
|---|
 | 943 | +	switch (state) {  | 
|---|
 | 944 | +	case TICK_BROADCAST_ENTER:  | 
|---|
 | 945 | +		clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);  | 
|---|
 | 946 | +		clockevents_switch_state(wd, CLOCK_EVT_STATE_ONESHOT);  | 
|---|
 | 947 | +		clockevents_program_event(wd, dev->next_event, 1);  | 
|---|
 | 948 | +		break;  | 
|---|
 | 949 | +	case TICK_BROADCAST_EXIT:  | 
|---|
 | 950 | +		/* We may have transitioned to oneshot mode while idle */  | 
|---|
 | 951 | +		if (clockevent_get_state(wd) != CLOCK_EVT_STATE_ONESHOT)  | 
|---|
 | 952 | +			return -ENODEV;  | 
|---|
 | 953 | +	}  | 
|---|
 | 954 | +  | 
|---|
 | 955 | +	return 0;  | 
|---|
 | 956 | +}  | 
|---|
 | 957 | +  | 
|---|
 | 958 | +int __tick_broadcast_oneshot_control(enum tick_broadcast_state state)  | 
|---|
 | 959 | +{  | 
|---|
 | 960 | +	struct tick_device *td = this_cpu_ptr(&tick_cpu_device);  | 
|---|
 | 961 | +	int cpu = smp_processor_id();  | 
|---|
 | 962 | +  | 
|---|
 | 963 | +	if (!tick_oneshot_wakeup_control(state, td, cpu))  | 
|---|
 | 964 | +		return 0;  | 
|---|
 | 965 | +  | 
|---|
 | 966 | +	if (tick_broadcast_device.evtdev)  | 
|---|
 | 967 | +		return ___tick_broadcast_oneshot_control(state, td, cpu);  | 
|---|
 | 968 | +  | 
|---|
 | 969 | +	/*  | 
|---|
 | 970 | +	 * If there is no broadcast or wakeup device, tell the caller not  | 
|---|
 | 971 | +	 * to go into deep idle.  | 
|---|
 | 972 | +	 */  | 
|---|
 | 973 | +	return -EBUSY;  | 
|---|
| 851 | 974 |  } | 
|---|
| 852 | 975 |   | 
|---|
| 853 | 976 |  /* | 
|---|
| .. | .. | 
|---|
| 955 | 1078 |  } | 
|---|
| 956 | 1079 |   | 
|---|
| 957 | 1080 |  /* | 
|---|
| 958 |  | - * Remove a dead CPU from broadcasting  | 
|---|
 | 1081 | + * Remove a dying CPU from broadcasting  | 
|---|
| 959 | 1082 |   */ | 
|---|
| 960 |  | -void tick_shutdown_broadcast_oneshot(unsigned int cpu)  | 
|---|
 | 1083 | +static void tick_broadcast_oneshot_offline(unsigned int cpu)  | 
|---|
| 961 | 1084 |  { | 
|---|
| 962 |  | -	unsigned long flags;  | 
|---|
| 963 |  | -  | 
|---|
| 964 |  | -	raw_spin_lock_irqsave(&tick_broadcast_lock, flags);  | 
|---|
 | 1085 | +	if (tick_get_oneshot_wakeup_device(cpu))  | 
|---|
 | 1086 | +		tick_set_oneshot_wakeup_device(NULL, cpu);  | 
|---|
| 965 | 1087 |   | 
|---|
| 966 | 1088 |  	/* | 
|---|
| 967 | 1089 |  	 * Clear the broadcast masks for the dead cpu, but do not stop | 
|---|
| .. | .. | 
|---|
| 970 | 1092 |  	cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); | 
|---|
| 971 | 1093 |  	cpumask_clear_cpu(cpu, tick_broadcast_pending_mask); | 
|---|
| 972 | 1094 |  	cpumask_clear_cpu(cpu, tick_broadcast_force_mask); | 
|---|
| 973 |  | -  | 
|---|
| 974 |  | -	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);  | 
|---|
| 975 | 1095 |  } | 
|---|
| 976 | 1096 |  #endif | 
|---|
| 977 | 1097 |   | 
|---|