1d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* 2d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * linux/kernel/time/clockevents.c 3d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 4d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * This file contains functions which manage clock event devices. 5d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 6d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> 7d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar 8d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner 9d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 10d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * This code is licenced under the GPL version 2. For details see 11d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * kernel-base/COPYING. 12d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 13d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 14d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/clockchips.h> 15d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/hrtimer.h> 16d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/init.h> 17d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/module.h> 18d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner#include <linux/smp.h> 19501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#include <linux/device.h> 20d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 218e1a928a2ed7e8d5cad97c8e985294b4caedd168H Hartley Sweeten#include "tick-internal.h" 228e1a928a2ed7e8d5cad97c8e985294b4caedd168H Hartley Sweeten 23d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* The registered clock event devices */ 24d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic LIST_HEAD(clockevent_devices); 25d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic LIST_HEAD(clockevents_released); 26d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* Protection for the above */ 27b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixnerstatic DEFINE_RAW_SPINLOCK(clockevents_lock); 2803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* Protection for unbind operations */ 2903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic DEFINE_MUTEX(clockevents_mutex); 3003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 3103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstruct ce_unbind { 3203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct clock_event_device *ce; 3303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner int res; 3403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner}; 35d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 3697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixnerstatic u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt, 3797b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner bool ismax) 38d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 3997813f2fe77804a4464564c75ba8d8826377feeaJon Hunter u64 clc = (u64) latch << evt->shift; 4097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner u64 rnd; 41d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 4245fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar if (unlikely(!evt->mult)) { 4345fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar evt->mult = 1; 4445fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar WARN_ON(1); 4545fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar } 4697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner rnd = (u64) evt->mult - 1; 4797b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner 4897b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner /* 4997b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * Upper bound sanity check. If the backwards conversion is 5097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * not equal latch, we know that the above shift overflowed. 5197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner */ 5297b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner if ((clc >> evt->shift) != (u64)latch) 5397b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner clc = ~0ULL; 5497b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner 5597b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner /* 5697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * Scaled math oddities: 5797b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * 5897b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * For mult <= (1 << shift) we can safely add mult - 1 to 5997b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * prevent integer rounding loss. So the backwards conversion 6097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * from nsec to device ticks will be correct. 6197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * 6297b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * For mult > (1 << shift), i.e. device frequency is > 1GHz we 6397b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * need to be careful. Adding mult - 1 will result in a value 6497b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * which when converted back to device ticks can be larger 6597b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * than latch by up to (mult - 1) >> shift. For the min_delta 6697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * calculation we still want to apply this in order to stay 6797b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * above the minimum device ticks limit. For the upper limit 6897b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * we would end up with a latch value larger than the upper 6997b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * limit of the device, so we omit the add to stay below the 7097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * device upper boundary. 7197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * 7297b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * Also omit the add if it would overflow the u64 boundary. 7397b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner */ 7497b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner if ((~0ULL - clc > rnd) && 7510632008b9e18b76cbff0ffc69c15e948aa548e0Thomas Gleixner (!ismax || evt->mult <= (1ULL << evt->shift))) 7697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner clc += rnd; 7745fe4fe19120a22f7339f5bb110447170c25fca9Ingo Molnar 78d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner do_div(clc, evt->mult); 79d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 8097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner /* Deltas less than 1usec are pointless noise */ 8197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner return clc > 1000 ? clc : 1000; 8297b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner} 8397b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner 8497b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner/** 8597b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds 8697b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * @latch: value to convert 8797b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * @evt: pointer to clock event device descriptor 8897b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * 8997b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner * Math helper, returns latch value converted to nanoseconds (bound checked) 9097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner */ 9197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixneru64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) 9297b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner{ 9397b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner return cev_delta2ns(latch, evt, false); 94d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 95c81fc2c331b8514ad112054cd2d87e6ec132286bMagnus DammEXPORT_SYMBOL_GPL(clockevent_delta2ns); 96d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 97d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 98d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_set_mode - set the operating mode of a clock event device 99d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @dev: device to modify 100d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @mode: new mode 101d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 102d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Must be called with interrupts disabled ! 103d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 104d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_set_mode(struct clock_event_device *dev, 105d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner enum clock_event_mode mode) 106d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 107d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (dev->mode != mode) { 108d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev->set_mode(mode, dev); 109d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev->mode = mode; 1102d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm 1112d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm /* 1122d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm * A nsec2cyc multiplicator of 0 is invalid and we'd crash 1132d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm * on it, so fix it up and emit a warning: 1142d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm */ 1152d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm if (mode == CLOCK_EVT_MODE_ONESHOT) { 1162d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm if (unlikely(!dev->mult)) { 1172d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm dev->mult = 1; 1182d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm WARN_ON(1); 1192d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm } 1202d68259db26ad57fd9643f1c69b5181ec9836ca9Magnus Damm } 121d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 122d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 123d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 124d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 1252344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner * clockevents_shutdown - shutdown the device and clear next_event 1262344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner * @dev: device to shutdown 1272344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner */ 1282344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixnervoid clockevents_shutdown(struct clock_event_device *dev) 1292344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner{ 1302344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); 1312344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner dev->next_event.tv64 = KTIME_MAX; 1322344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner} 1332344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner 134d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST 135d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 136d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/* Limit min_delta to a jiffie */ 137d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ) 138d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 139d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/** 140d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * clockevents_increase_min_delta - raise minimum delta of a clock event device 141d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to increase the minimum delta 142d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * 143d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * Returns 0 on success, -ETIME when the minimum delta reached the limit. 144d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 145d1748302f70be7469809809283fe164156a34231Martin Schwidefskystatic int clockevents_increase_min_delta(struct clock_event_device *dev) 146d1748302f70be7469809809283fe164156a34231Martin Schwidefsky{ 147d1748302f70be7469809809283fe164156a34231Martin Schwidefsky /* Nothing to do if we already reached the limit */ 148d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->min_delta_ns >= MIN_DELTA_LIMIT) { 149504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara printk_deferred(KERN_WARNING 150504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara "CE: Reprogramming failure. Giving up\n"); 151d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event.tv64 = KTIME_MAX; 152d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return -ETIME; 153d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 154d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 155d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->min_delta_ns < 5000) 156d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns = 5000; 157d1748302f70be7469809809283fe164156a34231Martin Schwidefsky else 158d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns += dev->min_delta_ns >> 1; 159d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 160d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->min_delta_ns > MIN_DELTA_LIMIT) 161d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns = MIN_DELTA_LIMIT; 162d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 163504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara printk_deferred(KERN_WARNING 164504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara "CE: %s increased min_delta_ns to %llu nsec\n", 165504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara dev->name ? dev->name : "?", 166504d58745c9ca28d33572e2d8a9990b43e06075dJan Kara (unsigned long long) dev->min_delta_ns); 167d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 168d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 169d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 170d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/** 171d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * clockevents_program_min_delta - Set clock event device to the minimum delay. 172d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 173d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * 174d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * Returns 0 on success, -ETIME when the retry loop failed. 175d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 176d1748302f70be7469809809283fe164156a34231Martin Schwidefskystatic int clockevents_program_min_delta(struct clock_event_device *dev) 177d1748302f70be7469809809283fe164156a34231Martin Schwidefsky{ 178d1748302f70be7469809809283fe164156a34231Martin Schwidefsky unsigned long long clc; 179d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int64_t delta; 180d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int i; 181d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 182d1748302f70be7469809809283fe164156a34231Martin Schwidefsky for (i = 0;;) { 183d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = dev->min_delta_ns; 184d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event = ktime_add_ns(ktime_get(), delta); 185d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 186d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 187d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 188d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 189d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->retries++; 190d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 191d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->set_next_event((unsigned long) clc, dev) == 0) 192d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 193d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 194d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (++i > 2) { 195d1748302f70be7469809809283fe164156a34231Martin Schwidefsky /* 196d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * We tried 3 times to program the device with the 197d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * given min_delta_ns. Try to increase the minimum 198d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * delta, if that fails as well get out of here. 199d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 200d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (clockevents_increase_min_delta(dev)) 201d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return -ETIME; 202d1748302f70be7469809809283fe164156a34231Martin Schwidefsky i = 0; 203d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 204d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 205d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 206d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 207d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#else /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */ 208d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 209d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/** 210d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * clockevents_program_min_delta - Set clock event device to the minimum delay. 211d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 212d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * 213d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * Returns 0 on success, -ETIME when the retry loop failed. 214d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 215d1748302f70be7469809809283fe164156a34231Martin Schwidefskystatic int clockevents_program_min_delta(struct clock_event_device *dev) 216d1748302f70be7469809809283fe164156a34231Martin Schwidefsky{ 217d1748302f70be7469809809283fe164156a34231Martin Schwidefsky unsigned long long clc; 218d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int64_t delta; 219d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 220d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = dev->min_delta_ns; 221d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event = ktime_add_ns(ktime_get(), delta); 222d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 223d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 224d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 225d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 226d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->retries++; 227d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 228d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return dev->set_next_event((unsigned long) clc, dev); 229d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 230d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 231d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */ 232d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 2332344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner/** 234d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_program_event - Reprogram the clock event device. 235d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 236d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @expires: absolute expiry time (monotonic clock) 237d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @force: program minimum delay if expires can not be set 238d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 239d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Returns 0 on success, -ETIME when the event is in the past. 240d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 241d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerint clockevents_program_event(struct clock_event_device *dev, ktime_t expires, 242d1748302f70be7469809809283fe164156a34231Martin Schwidefsky bool force) 243d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 244d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner unsigned long long clc; 245d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner int64_t delta; 246d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int rc; 247d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 248167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner if (unlikely(expires.tv64 < 0)) { 249167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner WARN_ON_ONCE(1); 250167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner return -ETIME; 251167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner } 252167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner 253d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev->next_event = expires; 254d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 255d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 256d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner return 0; 257d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 25865516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky /* Shortcut for clockevent devices that can deal with ktime. */ 25965516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky if (dev->features & CLOCK_EVT_FEAT_KTIME) 26065516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky return dev->set_next_ktime(expires, dev); 26165516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky 262d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = ktime_to_ns(ktime_sub(expires, ktime_get())); 263d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (delta <= 0) 264d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return force ? clockevents_program_min_delta(dev) : -ETIME; 265d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 266d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = min(delta, (int64_t) dev->max_delta_ns); 267d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = max(delta, (int64_t) dev->min_delta_ns); 268d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 269d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 270d1748302f70be7469809809283fe164156a34231Martin Schwidefsky rc = dev->set_next_event((unsigned long) clc, dev); 271d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 272d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return (rc && force) ? clockevents_program_min_delta(dev) : rc; 273d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 274d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 275d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* 2763eb056764dd806bbe84eb604e45e7470feeaafd8Li Zefan * Called after a notify add to make devices available which were 277d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released from the notifier call. 278d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 279d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic void clockevents_notify_released(void) 280d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 281d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device *dev; 282d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 283d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner while (!list_empty(&clockevents_released)) { 284d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev = list_entry(clockevents_released.next, 285d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device, list); 286d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_del(&dev->list); 287d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&dev->list, &clockevent_devices); 2887172a286ced0c1f4f239a0fa09db54ed37d3ead2Thomas Gleixner tick_check_new_device(dev); 289d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 290d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 291d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 29203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 29303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Try to install a replacement clock event device 29403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 29503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int clockevents_replace(struct clock_event_device *ced) 29603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 29703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct clock_event_device *dev, *newdev = NULL; 29803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 29903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_for_each_entry(dev, &clockevent_devices, list) { 30003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (dev == ced || dev->mode != CLOCK_EVT_MODE_UNUSED) 30103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!tick_check_replacement(newdev, dev)) 30403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!try_module_get(dev->owner)) 30703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (newdev) 31003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner module_put(newdev->owner); 31103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner newdev = dev; 31203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 31303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (newdev) { 31403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner tick_install_replacement(newdev); 31503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_del_init(&ced->list); 31603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 31703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return newdev ? 0 : -EBUSY; 31803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 31903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 32003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 32103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Called with clockevents_mutex and clockevents_lock held 32203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 32303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int __clockevents_try_unbind(struct clock_event_device *ced, int cpu) 32403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 32503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner /* Fast track. Device is unused */ 32603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ced->mode == CLOCK_EVT_MODE_UNUSED) { 32703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_del_init(&ced->list); 32803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return 0; 32903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 33003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 33103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ced == per_cpu(tick_cpu_device, cpu).evtdev ? -EAGAIN : -EBUSY; 33203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 33303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 33403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 33503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * SMP function call to unbind a device 33603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 33703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic void __clockevents_unbind(void *arg) 33803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 33903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct ce_unbind *cu = arg; 34003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner int res; 34103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 34203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_lock(&clockevents_lock); 34303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner res = __clockevents_try_unbind(cu->ce, smp_processor_id()); 34403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (res == -EAGAIN) 34503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner res = clockevents_replace(cu->ce); 34603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner cu->res = res; 34703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_unlock(&clockevents_lock); 34803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 34903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 35003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 35103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Issues smp function call to unbind a per cpu device. Called with 35203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * clockevents_mutex held. 35303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 35403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int clockevents_unbind(struct clock_event_device *ced, int cpu) 35503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 35603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct ce_unbind cu = { .ce = ced, .res = -ENODEV }; 35703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 35803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner smp_call_function_single(cpu, __clockevents_unbind, &cu, 1); 35903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return cu.res; 36003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 36103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 36203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 36303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Unbind a clockevents device. 36403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 36503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerint clockevents_unbind_device(struct clock_event_device *ced, int cpu) 36603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 36703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner int ret; 36803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 36903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_lock(&clockevents_mutex); 37003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = clockevents_unbind(ced, cpu); 37103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_unlock(&clockevents_mutex); 37203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret; 37303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 37403e13cf5ee60584fe0c831682c67212effb7fca4Thomas GleixnerEXPORT_SYMBOL_GPL(clockevents_unbind); 37503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 376d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 377d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_register_device - register a clock event device 378d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @dev: device to register 379d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 380d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_register_device(struct clock_event_device *dev) 381d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 382f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha unsigned long flags; 383f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha 384d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); 3851b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner if (!dev->cpumask) { 3861b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner WARN_ON(num_possible_cpus() > 1); 3871b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner dev->cpumask = cpumask_of(smp_processor_id()); 3881b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner } 389320ab2b0b1e08e3805a3e1084a2f0eb1938d5d67Rusty Russell 390b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_lock_irqsave(&clockevents_lock, flags); 391d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 392d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&dev->list, &clockevent_devices); 3937172a286ced0c1f4f239a0fa09db54ed37d3ead2Thomas Gleixner tick_check_new_device(dev); 394d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner clockevents_notify_released(); 395d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 396b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_unlock_irqrestore(&clockevents_lock, flags); 397d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 398c81fc2c331b8514ad112054cd2d87e6ec132286bMagnus DammEXPORT_SYMBOL_GPL(clockevents_register_device); 399d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 400e5400321a6f15ce0fe77c8455954f213ef7dcc54Magnus Dammvoid clockevents_config(struct clock_event_device *dev, u32 freq) 40157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{ 402c0e299b1a91cbdb21ae08e382a4176200398bc36Thomas Gleixner u64 sec; 40357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 40457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) 40557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner return; 40657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 40757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner /* 40857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * Calculate the maximum number of seconds we can sleep. Limit 40957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * to 10 minutes for hardware which can program more than 41057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * 32bit ticks so we still get reasonable conversion values. 41157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner */ 41257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = dev->max_delta_ticks; 41357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner do_div(sec, freq); 41457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner if (!sec) 41557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = 1; 41657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner else if (sec > 600 && dev->max_delta_ticks > UINT_MAX) 41757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = 600; 41857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 41957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_calc_mult_shift(dev, freq, sec); 42097b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false); 42197b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true); 42257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner} 42357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 42457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner/** 42557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * clockevents_config_and_register - Configure and register a clock event device 42657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @dev: device to register 42757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @freq: The clock frequency 42857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @min_delta: The minimum clock ticks to program in oneshot mode 42957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @max_delta: The maximum clock ticks to program in oneshot mode 43057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * 43157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * min/max_delta can be 0 for devices which do not support oneshot mode. 43257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner */ 43357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixnervoid clockevents_config_and_register(struct clock_event_device *dev, 43457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner u32 freq, unsigned long min_delta, 43557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner unsigned long max_delta) 43657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{ 43757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner dev->min_delta_ticks = min_delta; 43857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner dev->max_delta_ticks = max_delta; 43957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_config(dev, freq); 44057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_register_device(dev); 44157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner} 442c35ef95c273c06471818f9245a05ac5a6e3ffa34Shawn GuoEXPORT_SYMBOL_GPL(clockevents_config_and_register); 44357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 444627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixnerint __clockevents_update_freq(struct clock_event_device *dev, u32 freq) 445627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner{ 446627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner clockevents_config(dev, freq); 447627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 448fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann if (dev->mode == CLOCK_EVT_MODE_ONESHOT) 449fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann return clockevents_program_event(dev, dev->next_event, false); 450fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann 451fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann if (dev->mode == CLOCK_EVT_MODE_PERIODIC) 452fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev); 453627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 454fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann return 0; 455627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner} 456627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 45780b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner/** 45880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * clockevents_update_freq - Update frequency and reprogram a clock event device. 45980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @dev: device to modify 46080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @freq: new device frequency 46180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * 46280b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * Reconfigure and reprogram a clock event device in oneshot 46380b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * mode. Must be called on the cpu for which the device delivers per 464627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * cpu timer events. If called for the broadcast device the core takes 465627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * care of serialization. 466627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * 467627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * Returns 0 on success, -ETIME when the event is in the past. 46880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner */ 46980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixnerint clockevents_update_freq(struct clock_event_device *dev, u32 freq) 47080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner{ 471627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner unsigned long flags; 472627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner int ret; 47380b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner 474627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner local_irq_save(flags); 475627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner ret = tick_broadcast_update_freq(dev, freq); 476627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner if (ret == -ENODEV) 477627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner ret = __clockevents_update_freq(dev, freq); 478627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner local_irq_restore(flags); 479627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner return ret; 48080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner} 48180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner 482d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* 483d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Noop handler when we shut down an event device 484d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 4857c1e76897492d92b6a1c2d6892494d39ded9680cVenkatesh Pallipadivoid clockevents_handle_noop(struct clock_event_device *dev) 486d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 487d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 488d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 489d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 490d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_exchange_device - release and request clock devices 491d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @old: device to release (can be NULL) 492d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @new: device to request (can be NULL) 493d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 494d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Called from the notifier chain. clockevents_lock is held already 495d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 496d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_exchange_device(struct clock_event_device *old, 497d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device *new) 498d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 499d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner unsigned long flags; 500d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 501d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner local_irq_save(flags); 502d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner /* 503d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Caller releases a clock event device. We queue it into the 504d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released list and do a notify add later. 505d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 506d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (old) { 507ccf33d6880f39a35158fff66db13000ae4943facThomas Gleixner module_put(old->owner); 508d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); 509d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_del(&old->list); 510d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&old->list, &clockevents_released); 511d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 512d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 513d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (new) { 514d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); 5152344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner clockevents_shutdown(new); 516d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 517d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner local_irq_restore(flags); 518d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 519d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 520adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki/** 521adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki * clockevents_suspend - suspend clock devices 522adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki */ 523adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysockivoid clockevents_suspend(void) 524adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki{ 525adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki struct clock_event_device *dev; 526adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 527adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki list_for_each_entry_reverse(dev, &clockevent_devices, list) 528adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki if (dev->suspend) 529adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki dev->suspend(dev); 530adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki} 531adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 532adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki/** 533adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki * clockevents_resume - resume clock devices 534adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki */ 535adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysockivoid clockevents_resume(void) 536adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki{ 537adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki struct clock_event_device *dev; 538adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 539adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki list_for_each_entry(dev, &clockevent_devices, list) 540adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki if (dev->resume) 541adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki dev->resume(dev); 542adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki} 543adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 544de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#ifdef CONFIG_GENERIC_CLOCKEVENTS 545d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 546d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_notify - notification about relevant events 547da7e6f45c34d39186b72328bacc4dd86bff60e0aPreeti U Murthy * Returns 0 on success, any other value on error 548d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 549da7e6f45c34d39186b72328bacc4dd86bff60e0aPreeti U Murthyint clockevents_notify(unsigned long reason, void *arg) 550d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 551bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner struct clock_event_device *dev, *tmp; 552f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha unsigned long flags; 553da7e6f45c34d39186b72328bacc4dd86bff60e0aPreeti U Murthy int cpu, ret = 0; 5540b858e6ff9a38b987a83d22e6f2a2f621c80608dLi Zefan 555b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_lock_irqsave(&clockevents_lock, flags); 556d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 557d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner switch (reason) { 5588c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_ON: 5598c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_OFF: 5608c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: 5618c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_broadcast_on_off(reason, arg); 5628c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5638c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5648c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: 5658c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: 566da7e6f45c34d39186b72328bacc4dd86bff60e0aPreeti U Murthy ret = tick_broadcast_oneshot_control(reason); 5678c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5688c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5698c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_CPU_DYING: 5708c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_handover_do_timer(arg); 5718c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5728c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5738c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_SUSPEND: 5748c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_suspend(); 5758c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_suspend_broadcast(); 5768c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5778c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5788c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_RESUME: 5798c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_resume(); 5808c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5818c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 582d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner case CLOCK_EVT_NOTIFY_CPU_DEAD: 5838c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown_broadcast_oneshot(arg); 5848c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown_broadcast(arg); 5858c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown(arg); 586d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner /* 587d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Unregister the clock event devices which were 588d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released from the users in the notify chain. 589d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 590bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_for_each_entry_safe(dev, tmp, &clockevents_released, list) 591bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_del(&dev->list); 592bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner /* 593bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner * Now check whether the CPU has left unused per cpu devices 594bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner */ 595bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner cpu = *((int *)arg); 596bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { 597bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner if (cpumask_test_cpu(cpu, dev->cpumask) && 598ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng cpumask_weight(dev->cpumask) == 1 && 599ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng !tick_is_broadcast_device(dev)) { 600bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); 601bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_del(&dev->list); 602bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner } 603bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner } 604d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner break; 605d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner default: 606d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner break; 607d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 608b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_unlock_irqrestore(&clockevents_lock, flags); 609da7e6f45c34d39186b72328bacc4dd86bff60e0aPreeti U Murthy return ret; 610d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 611d316c57ff6bfad9557462b9100f25c6260d2b774Thomas GleixnerEXPORT_SYMBOL_GPL(clockevents_notify); 612501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 613501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#ifdef CONFIG_SYSFS 614501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstruct bus_type clockevents_subsys = { 615501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .name = "clockevents", 616501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .dev_name = "clockevent", 617501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner}; 618501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 619501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic DEFINE_PER_CPU(struct device, tick_percpu_dev); 620501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev); 621501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 622501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic ssize_t sysfs_show_current_tick_dev(struct device *dev, 623501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct device_attribute *attr, 624501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner char *buf) 625501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 626501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct tick_device *td; 627501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner ssize_t count = 0; 628501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 629501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner raw_spin_lock_irq(&clockevents_lock); 630501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner td = tick_get_tick_dev(dev); 631501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (td && td->evtdev) 632501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner count = snprintf(buf, PAGE_SIZE, "%s\n", td->evtdev->name); 633501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner raw_spin_unlock_irq(&clockevents_lock); 634501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return count; 635501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 636501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic DEVICE_ATTR(current_device, 0444, sysfs_show_current_tick_dev, NULL); 637501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 63803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* We don't support the abomination of removable broadcast devices */ 63903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic ssize_t sysfs_unbind_tick_dev(struct device *dev, 64003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct device_attribute *attr, 64103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner const char *buf, size_t count) 64203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 64303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner char name[CS_NAME_LEN]; 644891292a767c2453af0e5be9465e95b06b4b29ebePatrick Palka ssize_t ret = sysfs_get_uname(buf, name, count); 64503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct clock_event_device *ce; 64603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 64703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ret < 0) 64803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret; 64903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 65003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = -ENODEV; 65103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_lock(&clockevents_mutex); 65203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_lock_irq(&clockevents_lock); 65303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_for_each_entry(ce, &clockevent_devices, list) { 65403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!strcmp(ce->name, name)) { 65503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = __clockevents_try_unbind(ce, dev->id); 65603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner break; 65703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 65803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 65903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_unlock_irq(&clockevents_lock); 66003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner /* 66103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * We hold clockevents_mutex, so ce can't go away 66203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 66303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ret == -EAGAIN) 66403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = clockevents_unbind(ce, dev->id); 66503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_unlock(&clockevents_mutex); 66603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret ? ret : count; 66703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 66803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic DEVICE_ATTR(unbind_device, 0200, NULL, sysfs_unbind_tick_dev); 66903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 670501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 671501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct device tick_bc_dev = { 672501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .init_name = "broadcast", 673501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .id = 0, 674501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .bus = &clockevents_subsys, 675501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner}; 676501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 677501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev) 678501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 679501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return dev == &tick_bc_dev ? tick_get_broadcast_device() : 680501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner &per_cpu(tick_cpu_device, dev->id); 681501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 682501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 683501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic __init int tick_broadcast_init_sysfs(void) 684501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 685501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err = device_register(&tick_bc_dev); 686501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 687501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 688501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_create_file(&tick_bc_dev, &dev_attr_current_device); 689501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 690501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 691501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#else 692501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev) 693501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 694501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return &per_cpu(tick_cpu_device, dev->id); 695501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 696501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic inline int tick_broadcast_init_sysfs(void) { return 0; } 697de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#endif 698501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 699501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic int __init tick_init_sysfs(void) 700501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 701501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int cpu; 702501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 703501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner for_each_possible_cpu(cpu) { 704501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct device *dev = &per_cpu(tick_percpu_dev, cpu); 705501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err; 706501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 707501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner dev->id = cpu; 708501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner dev->bus = &clockevents_subsys; 709501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_register(dev); 710501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 711501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_create_file(dev, &dev_attr_current_device); 71203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!err) 71303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner err = device_create_file(dev, &dev_attr_unbind_device); 714501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (err) 715501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 716501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner } 717501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return tick_broadcast_init_sysfs(); 718501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 719501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 720501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic int __init clockevents_init_sysfs(void) 721501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 722501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err = subsys_system_register(&clockevents_subsys, NULL); 723501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 724501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 725501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = tick_init_sysfs(); 726501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 727501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 728501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerdevice_initcall(clockevents_init_sysfs); 729501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#endif /* SYSFS */ 730501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 731501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#endif /* GENERIC_CLOCK_EVENTS */ 732