clockevents.c revision fe79a9ba11962a603fb6af68fcb476e64031e46c
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) && 7597b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner (!ismax || evt->mult <= (1U << 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) { 149d1748302f70be7469809809283fe164156a34231Martin Schwidefsky printk(KERN_WARNING "CE: Reprogramming failure. Giving up\n"); 150d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event.tv64 = KTIME_MAX; 151d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return -ETIME; 152d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 153d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 154d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->min_delta_ns < 5000) 155d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns = 5000; 156d1748302f70be7469809809283fe164156a34231Martin Schwidefsky else 157d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns += dev->min_delta_ns >> 1; 158d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 159d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->min_delta_ns > MIN_DELTA_LIMIT) 160d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->min_delta_ns = MIN_DELTA_LIMIT; 161d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 162d1748302f70be7469809809283fe164156a34231Martin Schwidefsky printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n", 163d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->name ? dev->name : "?", 164d1748302f70be7469809809283fe164156a34231Martin Schwidefsky (unsigned long long) dev->min_delta_ns); 165d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 166d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 167d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 168d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/** 169d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * clockevents_program_min_delta - Set clock event device to the minimum delay. 170d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 171d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * 172d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * Returns 0 on success, -ETIME when the retry loop failed. 173d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 174d1748302f70be7469809809283fe164156a34231Martin Schwidefskystatic int clockevents_program_min_delta(struct clock_event_device *dev) 175d1748302f70be7469809809283fe164156a34231Martin Schwidefsky{ 176d1748302f70be7469809809283fe164156a34231Martin Schwidefsky unsigned long long clc; 177d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int64_t delta; 178d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int i; 179d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 180d1748302f70be7469809809283fe164156a34231Martin Schwidefsky for (i = 0;;) { 181d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = dev->min_delta_ns; 182d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event = ktime_add_ns(ktime_get(), delta); 183d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 184d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 185d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 186d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 187d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->retries++; 188d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 189d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->set_next_event((unsigned long) clc, dev) == 0) 190d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 191d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 192d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (++i > 2) { 193d1748302f70be7469809809283fe164156a34231Martin Schwidefsky /* 194d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * We tried 3 times to program the device with the 195d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * given min_delta_ns. Try to increase the minimum 196d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * delta, if that fails as well get out of here. 197d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 198d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (clockevents_increase_min_delta(dev)) 199d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return -ETIME; 200d1748302f70be7469809809283fe164156a34231Martin Schwidefsky i = 0; 201d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 202d1748302f70be7469809809283fe164156a34231Martin Schwidefsky } 203d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 204d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 205d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#else /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */ 206d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 207d1748302f70be7469809809283fe164156a34231Martin Schwidefsky/** 208d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * clockevents_program_min_delta - Set clock event device to the minimum delay. 209d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 210d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * 211d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * Returns 0 on success, -ETIME when the retry loop failed. 212d1748302f70be7469809809283fe164156a34231Martin Schwidefsky */ 213d1748302f70be7469809809283fe164156a34231Martin Schwidefskystatic int clockevents_program_min_delta(struct clock_event_device *dev) 214d1748302f70be7469809809283fe164156a34231Martin Schwidefsky{ 215d1748302f70be7469809809283fe164156a34231Martin Schwidefsky unsigned long long clc; 216d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int64_t delta; 217d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 218d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = dev->min_delta_ns; 219d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->next_event = ktime_add_ns(ktime_get(), delta); 220d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 221d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 222d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return 0; 223d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 224d1748302f70be7469809809283fe164156a34231Martin Schwidefsky dev->retries++; 225d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 226d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return dev->set_next_event((unsigned long) clc, dev); 227d1748302f70be7469809809283fe164156a34231Martin Schwidefsky} 228d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 229d1748302f70be7469809809283fe164156a34231Martin Schwidefsky#endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */ 230d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 2312344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner/** 232d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_program_event - Reprogram the clock event device. 233d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @dev: device to program 234d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @expires: absolute expiry time (monotonic clock) 235d1748302f70be7469809809283fe164156a34231Martin Schwidefsky * @force: program minimum delay if expires can not be set 236d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 237d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Returns 0 on success, -ETIME when the event is in the past. 238d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 239d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerint clockevents_program_event(struct clock_event_device *dev, ktime_t expires, 240d1748302f70be7469809809283fe164156a34231Martin Schwidefsky bool force) 241d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 242d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner unsigned long long clc; 243d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner int64_t delta; 244d1748302f70be7469809809283fe164156a34231Martin Schwidefsky int rc; 245d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 246167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner if (unlikely(expires.tv64 < 0)) { 247167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner WARN_ON_ONCE(1); 248167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner return -ETIME; 249167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner } 250167b1de3ee4e50d65a2bd0a2667c9cd48faf54f3Thomas Gleixner 251d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev->next_event = expires; 252d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 253d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN) 254d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner return 0; 255d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 25665516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky /* Shortcut for clockevent devices that can deal with ktime. */ 25765516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky if (dev->features & CLOCK_EVT_FEAT_KTIME) 25865516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky return dev->set_next_ktime(expires, dev); 25965516f8a7c2028381f0dae4c16ddb621c96158ccMartin Schwidefsky 260d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = ktime_to_ns(ktime_sub(expires, ktime_get())); 261d1748302f70be7469809809283fe164156a34231Martin Schwidefsky if (delta <= 0) 262d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return force ? clockevents_program_min_delta(dev) : -ETIME; 263d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 264d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = min(delta, (int64_t) dev->max_delta_ns); 265d1748302f70be7469809809283fe164156a34231Martin Schwidefsky delta = max(delta, (int64_t) dev->min_delta_ns); 266d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 267d1748302f70be7469809809283fe164156a34231Martin Schwidefsky clc = ((unsigned long long) delta * dev->mult) >> dev->shift; 268d1748302f70be7469809809283fe164156a34231Martin Schwidefsky rc = dev->set_next_event((unsigned long) clc, dev); 269d1748302f70be7469809809283fe164156a34231Martin Schwidefsky 270d1748302f70be7469809809283fe164156a34231Martin Schwidefsky return (rc && force) ? clockevents_program_min_delta(dev) : rc; 271d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 272d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 273d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* 2743eb056764dd806bbe84eb604e45e7470feeaafd8Li Zefan * Called after a notify add to make devices available which were 275d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released from the notifier call. 276d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 277d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnerstatic void clockevents_notify_released(void) 278d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 279d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device *dev; 280d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 281d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner while (!list_empty(&clockevents_released)) { 282d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner dev = list_entry(clockevents_released.next, 283d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device, list); 284d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_del(&dev->list); 285d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&dev->list, &clockevent_devices); 2867172a286ced0c1f4f239a0fa09db54ed37d3ead2Thomas Gleixner tick_check_new_device(dev); 287d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 288d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 289d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 29003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 29103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Try to install a replacement clock event device 29203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 29303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int clockevents_replace(struct clock_event_device *ced) 29403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 29503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct clock_event_device *dev, *newdev = NULL; 29603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 29703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_for_each_entry(dev, &clockevent_devices, list) { 29803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (dev == ced || dev->mode != CLOCK_EVT_MODE_UNUSED) 29903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!tick_check_replacement(newdev, dev)) 30203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!try_module_get(dev->owner)) 30503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner continue; 30603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 30703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (newdev) 30803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner module_put(newdev->owner); 30903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner newdev = dev; 31003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 31103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (newdev) { 31203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner tick_install_replacement(newdev); 31303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_del_init(&ced->list); 31403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 31503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return newdev ? 0 : -EBUSY; 31603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 31703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 31803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 31903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Called with clockevents_mutex and clockevents_lock held 32003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 32103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int __clockevents_try_unbind(struct clock_event_device *ced, int cpu) 32203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 32303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner /* Fast track. Device is unused */ 32403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ced->mode == CLOCK_EVT_MODE_UNUSED) { 32503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_del_init(&ced->list); 32603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return 0; 32703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 32803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 32903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ced == per_cpu(tick_cpu_device, cpu).evtdev ? -EAGAIN : -EBUSY; 33003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 33103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 33203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 33303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * SMP function call to unbind a device 33403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 33503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic void __clockevents_unbind(void *arg) 33603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 33703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct ce_unbind *cu = arg; 33803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner int res; 33903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 34003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_lock(&clockevents_lock); 34103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner res = __clockevents_try_unbind(cu->ce, smp_processor_id()); 34203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (res == -EAGAIN) 34303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner res = clockevents_replace(cu->ce); 34403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner cu->res = res; 34503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_unlock(&clockevents_lock); 34603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 34703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 34803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 34903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Issues smp function call to unbind a per cpu device. Called with 35003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * clockevents_mutex held. 35103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 35203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic int clockevents_unbind(struct clock_event_device *ced, int cpu) 35303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 35403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct ce_unbind cu = { .ce = ced, .res = -ENODEV }; 35503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 35603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner smp_call_function_single(cpu, __clockevents_unbind, &cu, 1); 35703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return cu.res; 35803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 35903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 36003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* 36103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * Unbind a clockevents device. 36203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 36303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerint clockevents_unbind_device(struct clock_event_device *ced, int cpu) 36403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 36503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner int ret; 36603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 36703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_lock(&clockevents_mutex); 36803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = clockevents_unbind(ced, cpu); 36903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_unlock(&clockevents_mutex); 37003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret; 37103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 37203e13cf5ee60584fe0c831682c67212effb7fca4Thomas GleixnerEXPORT_SYMBOL_GPL(clockevents_unbind); 37303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 374d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 375d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_register_device - register a clock event device 376d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @dev: device to register 377d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 378d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_register_device(struct clock_event_device *dev) 379d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 380f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha unsigned long flags; 381f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha 382d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); 3831b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner if (!dev->cpumask) { 3841b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner WARN_ON(num_possible_cpus() > 1); 3851b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner dev->cpumask = cpumask_of(smp_processor_id()); 3861b054b67d3bfc6dca9f634c104780f3f24ff3eecThomas Gleixner } 387320ab2b0b1e08e3805a3e1084a2f0eb1938d5d67Rusty Russell 388b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_lock_irqsave(&clockevents_lock, flags); 389d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 390d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&dev->list, &clockevent_devices); 3917172a286ced0c1f4f239a0fa09db54ed37d3ead2Thomas Gleixner tick_check_new_device(dev); 392d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner clockevents_notify_released(); 393d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 394b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_unlock_irqrestore(&clockevents_lock, flags); 395d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 396c81fc2c331b8514ad112054cd2d87e6ec132286bMagnus DammEXPORT_SYMBOL_GPL(clockevents_register_device); 397d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 398e5400321a6f15ce0fe77c8455954f213ef7dcc54Magnus Dammvoid clockevents_config(struct clock_event_device *dev, u32 freq) 39957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{ 400c0e299b1a91cbdb21ae08e382a4176200398bc36Thomas Gleixner u64 sec; 40157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 40257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) 40357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner return; 40457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 40557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner /* 40657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * Calculate the maximum number of seconds we can sleep. Limit 40757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * to 10 minutes for hardware which can program more than 40857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * 32bit ticks so we still get reasonable conversion values. 40957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner */ 41057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = dev->max_delta_ticks; 41157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner do_div(sec, freq); 41257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner if (!sec) 41357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = 1; 41457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner else if (sec > 600 && dev->max_delta_ticks > UINT_MAX) 41557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner sec = 600; 41657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 41757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_calc_mult_shift(dev, freq, sec); 41897b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false); 41997b9410643475d6557d2517c2aff9fd2221141a9Thomas Gleixner dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true); 42057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner} 42157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 42257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner/** 42357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * clockevents_config_and_register - Configure and register a clock event device 42457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @dev: device to register 42557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @freq: The clock frequency 42657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @min_delta: The minimum clock ticks to program in oneshot mode 42757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * @max_delta: The maximum clock ticks to program in oneshot mode 42857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * 42957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner * min/max_delta can be 0 for devices which do not support oneshot mode. 43057f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner */ 43157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixnervoid clockevents_config_and_register(struct clock_event_device *dev, 43257f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner u32 freq, unsigned long min_delta, 43357f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner unsigned long max_delta) 43457f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner{ 43557f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner dev->min_delta_ticks = min_delta; 43657f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner dev->max_delta_ticks = max_delta; 43757f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_config(dev, freq); 43857f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner clockevents_register_device(dev); 43957f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner} 440c35ef95c273c06471818f9245a05ac5a6e3ffa34Shawn GuoEXPORT_SYMBOL_GPL(clockevents_config_and_register); 44157f0fcbe1dea8a36c9d1673086326059991c5f81Thomas Gleixner 442627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixnerint __clockevents_update_freq(struct clock_event_device *dev, u32 freq) 443627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner{ 444627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner clockevents_config(dev, freq); 445627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 446fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann if (dev->mode == CLOCK_EVT_MODE_ONESHOT) 447fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann return clockevents_program_event(dev, dev->next_event, false); 448fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann 449fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann if (dev->mode == CLOCK_EVT_MODE_PERIODIC) 450fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev); 451627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 452fe79a9ba11962a603fb6af68fcb476e64031e46cSoren Brinkmann return 0; 453627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner} 454627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner 45580b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner/** 45680b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * clockevents_update_freq - Update frequency and reprogram a clock event device. 45780b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @dev: device to modify 45880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * @freq: new device frequency 45980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * 46080b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * Reconfigure and reprogram a clock event device in oneshot 46180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner * mode. Must be called on the cpu for which the device delivers per 462627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * cpu timer events. If called for the broadcast device the core takes 463627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * care of serialization. 464627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * 465627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner * Returns 0 on success, -ETIME when the event is in the past. 46680b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner */ 46780b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixnerint clockevents_update_freq(struct clock_event_device *dev, u32 freq) 46880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner{ 469627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner unsigned long flags; 470627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner int ret; 47180b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner 472627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner local_irq_save(flags); 473627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner ret = tick_broadcast_update_freq(dev, freq); 474627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner if (ret == -ENODEV) 475627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner ret = __clockevents_update_freq(dev, freq); 476627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner local_irq_restore(flags); 477627ee7947e2e83ba565c31c5c9373d6e364b1ecdThomas Gleixner return ret; 47880b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner} 47980b816b736cfa5b9582279127099b20a479ab7d9Thomas Gleixner 480d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/* 481d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Noop handler when we shut down an event device 482d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 4837c1e76897492d92b6a1c2d6892494d39ded9680cVenkatesh Pallipadivoid clockevents_handle_noop(struct clock_event_device *dev) 484d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 485d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 486d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 487d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 488d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_exchange_device - release and request clock devices 489d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @old: device to release (can be NULL) 490d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * @new: device to request (can be NULL) 491d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * 492d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Called from the notifier chain. clockevents_lock is held already 493d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 494d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_exchange_device(struct clock_event_device *old, 495d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner struct clock_event_device *new) 496d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 497d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner unsigned long flags; 498d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 499d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner local_irq_save(flags); 500d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner /* 501d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Caller releases a clock event device. We queue it into the 502d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released list and do a notify add later. 503d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 504d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (old) { 505ccf33d6880f39a35158fff66db13000ae4943facThomas Gleixner module_put(old->owner); 506d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); 507d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_del(&old->list); 508d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner list_add(&old->list, &clockevents_released); 509d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 510d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 511d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner if (new) { 512d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); 5132344abbcbdb82140050e8be29d3d55e4f6fe860bThomas Gleixner clockevents_shutdown(new); 514d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 515d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner local_irq_restore(flags); 516d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 517d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 518adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki/** 519adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki * clockevents_suspend - suspend clock devices 520adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki */ 521adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysockivoid clockevents_suspend(void) 522adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki{ 523adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki struct clock_event_device *dev; 524adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 525adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki list_for_each_entry_reverse(dev, &clockevent_devices, list) 526adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki if (dev->suspend) 527adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki dev->suspend(dev); 528adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki} 529adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 530adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki/** 531adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki * clockevents_resume - resume clock devices 532adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki */ 533adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysockivoid clockevents_resume(void) 534adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki{ 535adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki struct clock_event_device *dev; 536adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 537adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki list_for_each_entry(dev, &clockevent_devices, list) 538adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki if (dev->resume) 539adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki dev->resume(dev); 540adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki} 541adc78e6b9946a4b22e22403d961f3b03c469e5d3Rafael J. Wysocki 542de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#ifdef CONFIG_GENERIC_CLOCKEVENTS 543d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner/** 544d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * clockevents_notify - notification about relevant events 545d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 546d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixnervoid clockevents_notify(unsigned long reason, void *arg) 547d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner{ 548bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner struct clock_event_device *dev, *tmp; 549f833bab87fca5c3ce13778421b1365845843b976Suresh Siddha unsigned long flags; 550bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner int cpu; 5510b858e6ff9a38b987a83d22e6f2a2f621c80608dLi Zefan 552b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_lock_irqsave(&clockevents_lock, flags); 553d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner 554d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner switch (reason) { 5558c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_ON: 5568c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_OFF: 5578c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: 5588c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_broadcast_on_off(reason, arg); 5598c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5608c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5618c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: 5628c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: 5638c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_broadcast_oneshot_control(reason); 5648c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5658c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5668c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_CPU_DYING: 5678c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_handover_do_timer(arg); 5688c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5698c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5708c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_SUSPEND: 5718c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_suspend(); 5728c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_suspend_broadcast(); 5738c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5748c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 5758c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner case CLOCK_EVT_NOTIFY_RESUME: 5768c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_resume(); 5778c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner break; 5788c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner 579d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner case CLOCK_EVT_NOTIFY_CPU_DEAD: 5808c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown_broadcast_oneshot(arg); 5818c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown_broadcast(arg); 5828c53daf63f56791ed47fc585206ef3049489612fThomas Gleixner tick_shutdown(arg); 583d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner /* 584d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * Unregister the clock event devices which were 585d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner * released from the users in the notify chain. 586d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner */ 587bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_for_each_entry_safe(dev, tmp, &clockevents_released, list) 588bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_del(&dev->list); 589bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner /* 590bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner * Now check whether the CPU has left unused per cpu devices 591bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner */ 592bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner cpu = *((int *)arg); 593bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { 594bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner if (cpumask_test_cpu(cpu, dev->cpumask) && 595ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng cpumask_weight(dev->cpumask) == 1 && 596ea9d8e3f45404d411c00ae67b45cc35c58265bb7Xiaotian Feng !tick_is_broadcast_device(dev)) { 597bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); 598bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner list_del(&dev->list); 599bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner } 600bb6eddf7676e1c1f3e637aa93c5224488d99036fThomas Gleixner } 601d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner break; 602d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner default: 603d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner break; 604d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner } 605b5f91da0a6973bb6f9ff3b91b0e92c0773a458f3Thomas Gleixner raw_spin_unlock_irqrestore(&clockevents_lock, flags); 606d316c57ff6bfad9557462b9100f25c6260d2b774Thomas Gleixner} 607d316c57ff6bfad9557462b9100f25c6260d2b774Thomas GleixnerEXPORT_SYMBOL_GPL(clockevents_notify); 608501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 609501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#ifdef CONFIG_SYSFS 610501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstruct bus_type clockevents_subsys = { 611501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .name = "clockevents", 612501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .dev_name = "clockevent", 613501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner}; 614501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 615501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic DEFINE_PER_CPU(struct device, tick_percpu_dev); 616501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev); 617501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 618501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic ssize_t sysfs_show_current_tick_dev(struct device *dev, 619501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct device_attribute *attr, 620501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner char *buf) 621501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 622501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct tick_device *td; 623501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner ssize_t count = 0; 624501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 625501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner raw_spin_lock_irq(&clockevents_lock); 626501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner td = tick_get_tick_dev(dev); 627501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (td && td->evtdev) 628501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner count = snprintf(buf, PAGE_SIZE, "%s\n", td->evtdev->name); 629501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner raw_spin_unlock_irq(&clockevents_lock); 630501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return count; 631501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 632501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic DEVICE_ATTR(current_device, 0444, sysfs_show_current_tick_dev, NULL); 633501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 63403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner/* We don't support the abomination of removable broadcast devices */ 63503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic ssize_t sysfs_unbind_tick_dev(struct device *dev, 63603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct device_attribute *attr, 63703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner const char *buf, size_t count) 63803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner{ 63903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner char name[CS_NAME_LEN]; 640891292a767c2453af0e5be9465e95b06b4b29ebePatrick Palka ssize_t ret = sysfs_get_uname(buf, name, count); 64103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner struct clock_event_device *ce; 64203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 64303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ret < 0) 64403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret; 64503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 64603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = -ENODEV; 64703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_lock(&clockevents_mutex); 64803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_lock_irq(&clockevents_lock); 64903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner list_for_each_entry(ce, &clockevent_devices, list) { 65003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!strcmp(ce->name, name)) { 65103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = __clockevents_try_unbind(ce, dev->id); 65203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner break; 65303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 65403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner } 65503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner raw_spin_unlock_irq(&clockevents_lock); 65603e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner /* 65703e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner * We hold clockevents_mutex, so ce can't go away 65803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner */ 65903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (ret == -EAGAIN) 66003e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner ret = clockevents_unbind(ce, dev->id); 66103e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner mutex_unlock(&clockevents_mutex); 66203e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner return ret ? ret : count; 66303e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner} 66403e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixnerstatic DEVICE_ATTR(unbind_device, 0200, NULL, sysfs_unbind_tick_dev); 66503e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner 666501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 667501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct device tick_bc_dev = { 668501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .init_name = "broadcast", 669501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .id = 0, 670501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner .bus = &clockevents_subsys, 671501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner}; 672501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 673501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev) 674501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 675501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return dev == &tick_bc_dev ? tick_get_broadcast_device() : 676501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner &per_cpu(tick_cpu_device, dev->id); 677501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 678501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 679501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic __init int tick_broadcast_init_sysfs(void) 680501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 681501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err = device_register(&tick_bc_dev); 682501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 683501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 684501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_create_file(&tick_bc_dev, &dev_attr_current_device); 685501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 686501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 687501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#else 688501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic struct tick_device *tick_get_tick_dev(struct device *dev) 689501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 690501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return &per_cpu(tick_cpu_device, dev->id); 691501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 692501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic inline int tick_broadcast_init_sysfs(void) { return 0; } 693de68d9b173ee657115dd0e584c2365b7954253a5Thomas Gleixner#endif 694501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 695501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic int __init tick_init_sysfs(void) 696501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 697501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int cpu; 698501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 699501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner for_each_possible_cpu(cpu) { 700501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner struct device *dev = &per_cpu(tick_percpu_dev, cpu); 701501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err; 702501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 703501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner dev->id = cpu; 704501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner dev->bus = &clockevents_subsys; 705501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_register(dev); 706501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 707501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = device_create_file(dev, &dev_attr_current_device); 70803e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner if (!err) 70903e13cf5ee60584fe0c831682c67212effb7fca4Thomas Gleixner err = device_create_file(dev, &dev_attr_unbind_device); 710501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (err) 711501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 712501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner } 713501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return tick_broadcast_init_sysfs(); 714501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 715501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 716501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerstatic int __init clockevents_init_sysfs(void) 717501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner{ 718501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner int err = subsys_system_register(&clockevents_subsys, NULL); 719501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 720501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner if (!err) 721501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner err = tick_init_sysfs(); 722501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner return err; 723501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner} 724501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixnerdevice_initcall(clockevents_init_sysfs); 725501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#endif /* SYSFS */ 726501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner 727501f867064e95f9a6f540e60705be0937280e7ecThomas Gleixner#endif /* GENERIC_CLOCK_EVENTS */ 728