Commit 0a1d4434 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'timers-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "Updates for timers, timekeeping and drivers:

  Core:

   - The timer_shutdown[_sync]() infrastructure:

     Tearing down timers can be tedious when there are circular
     dependencies to other things which need to be torn down. A prime
     example is timer and workqueue where the timer schedules work and
     the work arms the timer.

     What needs to prevented is that pending work which is drained via
     destroy_workqueue() does not rearm the previously shutdown timer.
     Nothing in that shutdown sequence relies on the timer being
     functional.

     The conclusion was that the semantics of timer_shutdown_sync()
     should be:
	- timer is not enqueued
    	- timer callback is not running
    	- timer cannot be rearmed

     Preventing the rearming of shutdown timers is done by discarding
     rearm attempts silently.

     A warning for the case that a rearm attempt of a shutdown timer is
     detected would not be really helpful because it's entirely unclear
     how it should be acted upon. The only way to address such a case is
     to add 'if (in_shutdown)' conditionals all over the place. This is
     error prone and in most cases of teardown not required all.

   - The real fix for the bluetooth HCI teardown based on
     timer_shutdown_sync().

     A larger scale conversion to timer_shutdown_sync() is work in
     progress.

   - Consolidation of VDSO time namespace helper functions

   - Small fixes for timer and timerqueue

  Drivers:

   - Prevent integer overflow on the XGene-1 TVAL register which causes
     an never ending interrupt storm.

   - The usual set of new device tree bindings

   - Small fixes and improvements all over the place"

* tag 'timers-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits)
  dt-bindings: timer: renesas,cmt: Add r8a779g0 CMT support
  dt-bindings: timer: renesas,tmu: Add r8a779g0 support
  clocksource/drivers/arm_arch_timer: Use kstrtobool() instead of strtobool()
  clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in dmtimer_systimer_init_clock()
  clocksource/drivers/timer-ti-dm: Clear settings on probe and free
  clocksource/drivers/timer-ti-dm: Make timer_get_irq static
  clocksource/drivers/timer-ti-dm: Fix warning for omap_timer_match
  clocksource/drivers/arm_arch_timer: Fix XGene-1 TVAL register math error
  clocksource/drivers/timer-npcm7xx: Enable timer 1 clock before use
  dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks
  dt-bindings: timer: rockchip: Add rockchip,rk3128-timer
  clockevents: Repair kernel-doc for clockevent_delta2ns()
  clocksource/drivers/ingenic-ost: Define pm functions properly in platform_driver struct
  clocksource/drivers/sh_cmt: Access registers according to spec
  vdso/timens: Refactor copy-pasted find_timens_vvar_page() helper into one copy
  Bluetooth: hci_qca: Fix the teardown problem for real
  timers: Update the documentation to reflect on the new timer_shutdown() API
  timers: Provide timer_shutdown[_sync]()
  timers: Add shutdown mechanism to the internal functions
  timers: Split [try_to_]del_timer[_sync]() to prepare for shutdown mode
  ...
parents 79ad8912 18a20784
......@@ -1858,7 +1858,7 @@ unloaded. After a given module has been unloaded, any attempt to call
one of its functions results in a segmentation fault. The module-unload
functions must therefore cancel any delayed calls to loadable-module
functions, for example, any outstanding mod_timer() must be dealt
with via del_timer_sync() or similar.
with via timer_shutdown_sync() or similar.
Unfortunately, there is no way to cancel an RCU callback; once you
invoke call_rcu(), the callback function is eventually going to be
......
......@@ -191,7 +191,7 @@ Here is a sample module which implements a basic per cpu counter using
static void __exit test_exit(void)
{
del_timer_sync(&test_timer);
timer_shutdown_sync(&test_timer);
}
module_init(test_init);
......
......@@ -25,7 +25,13 @@ properties:
- description: The timer interrupt of timer 0
clocks:
maxItems: 1
items:
- description: The reference clock for timer 0
- description: The reference clock for timer 1
- description: The reference clock for timer 2
- description: The reference clock for timer 3
- description: The reference clock for timer 4
minItems: 1
required:
- compatible
......
......@@ -102,12 +102,14 @@ properties:
- enum:
- renesas,r8a779a0-cmt0 # 32-bit CMT0 on R-Car V3U
- renesas,r8a779f0-cmt0 # 32-bit CMT0 on R-Car S4-8
- renesas,r8a779g0-cmt0 # 32-bit CMT0 on R-Car V4H
- const: renesas,rcar-gen4-cmt0 # 32-bit CMT0 on R-Car Gen4
- items:
- enum:
- renesas,r8a779a0-cmt1 # 48-bit CMT on R-Car V3U
- renesas,r8a779f0-cmt1 # 48-bit CMT on R-Car S4-8
- renesas,r8a779g0-cmt1 # 48-bit CMT on R-Car V4H
- const: renesas,rcar-gen4-cmt1 # 48-bit CMT on R-Car Gen4
reg:
......
......@@ -38,6 +38,7 @@ properties:
- renesas,tmu-r8a77995 # R-Car D3
- renesas,tmu-r8a779a0 # R-Car V3U
- renesas,tmu-r8a779f0 # R-Car S4-8
- renesas,tmu-r8a779g0 # R-Car V4H
- const: renesas,tmu
reg:
......
......@@ -18,6 +18,7 @@ properties:
- enum:
- rockchip,rv1108-timer
- rockchip,rk3036-timer
- rockchip,rk3128-timer
- rockchip,rk3188-timer
- rockchip,rk3228-timer
- rockchip,rk3229-timer
......
......@@ -967,7 +967,7 @@ you might do the following::
while (list) {
struct foo *next = list->next;
del_timer(&list->timer);
timer_delete(&list->timer);
kfree(list);
list = next;
}
......@@ -981,7 +981,7 @@ the lock after we spin_unlock_bh(), and then try to free
the element (which has already been freed!).
This can be avoided by checking the result of
del_timer(): if it returns 1, the timer has been deleted.
timer_delete(): if it returns 1, the timer has been deleted.
If 0, it means (in this case) that it is currently running, so we can
do::
......@@ -990,7 +990,7 @@ do::
while (list) {
struct foo *next = list->next;
if (!del_timer(&list->timer)) {
if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */
spin_unlock_bh(&list_lock);
goto retry;
......@@ -1005,9 +1005,12 @@ do::
Another common problem is deleting timers which restart themselves (by
calling add_timer() at the end of their timer function).
Because this is a fairly common case which is prone to races, you should
use del_timer_sync() (``include/linux/timer.h``) to
handle this case. It returns the number of times the timer had to be
deleted before we finally stopped it from adding itself back in.
use timer_delete_sync() (``include/linux/timer.h``) to handle this case.
Before freeing a timer, timer_shutdown() or timer_shutdown_sync() should be
called which will keep it from being rearmed. Any subsequent attempt to
rearm the timer will be silently ignored by the core code.
Locking Speed
=============
......@@ -1335,7 +1338,7 @@ lock.
- kfree()
- add_timer() and del_timer()
- add_timer() and timer_delete()
Mutex API reference
===================
......
......@@ -118,7 +118,7 @@ existing timer wheel code, as it is mature and well suited. Sharing code
was not really a win, due to the different data structures. Also, the
hrtimer functions now have clearer behavior and clearer names - such as
hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
equivalent to del_timer() and del_timer_sync()] - so there's no direct
equivalent to timer_delete() and timer_delete_sync()] - so there's no direct
1:1 mapping between them on the algorithmic level, and thus no real
potential for code sharing either.
......
......@@ -990,7 +990,7 @@ potreste fare come segue::
while (list) {
struct foo *next = list->next;
del_timer(&list->timer);
timer_delete(&list->timer);
kfree(list);
list = next;
}
......@@ -1003,7 +1003,7 @@ e prenderà il *lock* solo dopo spin_unlock_bh(), e cercherà
di eliminare il suo oggetto (che però è già stato eliminato).
Questo può essere evitato controllando il valore di ritorno di
del_timer(): se ritorna 1, il temporizzatore è stato già
timer_delete(): se ritorna 1, il temporizzatore è stato già
rimosso. Se 0, significa (in questo caso) che il temporizzatore è in
esecuzione, quindi possiamo fare come segue::
......@@ -1012,7 +1012,7 @@ esecuzione, quindi possiamo fare come segue::
while (list) {
struct foo *next = list->next;
if (!del_timer(&list->timer)) {
if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */
spin_unlock_bh(&list_lock);
goto retry;
......@@ -1026,10 +1026,8 @@ esecuzione, quindi possiamo fare come segue::
Un altro problema è l'eliminazione dei temporizzatori che si riavviano
da soli (chiamando add_timer() alla fine della loro esecuzione).
Dato che questo è un problema abbastanza comune con una propensione
alle corse critiche, dovreste usare del_timer_sync()
(``include/linux/timer.h``) per gestire questo caso. Questa ritorna il
numero di volte che il temporizzatore è stato interrotto prima che
fosse in grado di fermarlo senza che si riavviasse.
alle corse critiche, dovreste usare timer_delete_sync()
(``include/linux/timer.h``) per gestire questo caso.
Velocità della sincronizzazione
===============================
......@@ -1374,7 +1372,7 @@ contesto, o trattenendo un qualsiasi *lock*.
- kfree()
- add_timer() e del_timer()
- add_timer() e timer_delete()
Riferimento per l'API dei Mutex
===============================
......
......@@ -185,7 +185,7 @@ UP之间没有不同的行为,在你的架构的 ``local.h`` 中包括 ``asm-g
static void __exit test_exit(void)
{
del_timer_sync(&test_timer);
timer_shutdown_sync(&test_timer);
}
module_init(test_init);
......
......@@ -90,7 +90,7 @@ static void __init spear_clocksource_init(void)
200, 16, clocksource_mmio_readw_up);
}
static inline void timer_shutdown(struct clock_event_device *evt)
static inline void spear_timer_shutdown(struct clock_event_device *evt)
{
u16 val = readw(gpt_base + CR(CLKEVT));
......@@ -101,7 +101,7 @@ static inline void timer_shutdown(struct clock_event_device *evt)
static int spear_shutdown(struct clock_event_device *evt)
{
timer_shutdown(evt);
spear_timer_shutdown(evt);
return 0;
}
......@@ -111,7 +111,7 @@ static int spear_set_oneshot(struct clock_event_device *evt)
u16 val;
/* stop the timer */
timer_shutdown(evt);
spear_timer_shutdown(evt);
val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT;
......@@ -126,7 +126,7 @@ static int spear_set_periodic(struct clock_event_device *evt)
u16 val;
/* stop the timer */
timer_shutdown(evt);
spear_timer_shutdown(evt);
period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16;
......
......@@ -151,28 +151,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops.
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
#else
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
......@@ -129,28 +129,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0;
}
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops.
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
#else
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
......@@ -137,28 +137,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops.
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
#else
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
......@@ -44,21 +44,6 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page);
}
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops().
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
/*
* The VVAR page layout depends on whether a task belongs to the root or
* non-root time namespace. Whenever a task changes its namespace, the VVAR
......@@ -84,11 +69,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
#else
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
......@@ -98,24 +98,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
}
#ifdef CONFIG_TIME_NS
static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops().
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
/*
* The vvar page layout depends on whether a task belongs to the root or
* non-root time namespace. Whenever a task changes its namespace, the VVAR
......@@ -140,11 +122,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0;
}
#else
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
......@@ -696,9 +696,15 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq);
skb_queue_purge(&qca->rx_memdump_q);
/*
* Shut the timers down so they can't be rearmed when
* destroy_workqueue() drains pending work which in turn might try
* to arm a timer. After shutdown rearm attempts are silently
* ignored by the timer core code.
*/
timer_shutdown_sync(&qca->tx_idle_timer);
timer_shutdown_sync(&qca->wake_retrans_timer);
destroy_workqueue(qca->workqueue);
del_timer_sync(&qca->tx_idle_timer);
del_timer_sync(&qca->wake_retrans_timer);
qca->hu = NULL;
kfree_skb(qca->rx_skb);
......
......@@ -155,7 +155,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
out:
if (!priv->response_length) {
*off = 0;
del_singleshot_timer_sync(&priv->user_read_timer);
del_timer_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work);
}
mutex_unlock(&priv->buffer_mutex);
......@@ -262,7 +262,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)
void tpm_common_release(struct file *file, struct file_priv *priv)
{
flush_work(&priv->async_work);
del_singleshot_timer_sync(&priv->user_read_timer);
del_timer_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work);
file->private_data = NULL;
priv->response_length = 0;
......
......@@ -18,6 +18,7 @@
#include <linux/clocksource.h>
#include <linux/clocksource_ids.h>
#include <linux/interrupt.h>
#include <linux/kstrtox.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/io.h>
......@@ -97,7 +98,7 @@ static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EV
static int __init early_evtstrm_cfg(char *buf)
{
return strtobool(buf, &evtstrm_enable);
return kstrtobool(buf, &evtstrm_enable);
}
early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
......@@ -687,8 +688,8 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
}
static __always_inline int timer_shutdown(const int access,
struct clock_event_device *clk)
static __always_inline int arch_timer_shutdown(const int access,
struct clock_event_device *clk)
{
unsigned long ctrl;
......@@ -701,22 +702,22 @@ static __always_inline int timer_shutdown(const int access,
static int arch_timer_shutdown_virt(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
return arch_timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
}
static int arch_timer_shutdown_phys(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
return arch_timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
}
static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
return arch_timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
}
static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
{
return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
return arch_timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
}
static __always_inline void set_next_event(const int access, unsigned long evt,
......
......@@ -141,7 +141,7 @@ static int __init ingenic_ost_probe(struct platform_device *pdev)
return 0;
}
static int __maybe_unused ingenic_ost_suspend(struct device *dev)
static int ingenic_ost_suspend(struct device *dev)
{
struct ingenic_ost *ost = dev_get_drvdata(dev);
......@@ -150,14 +150,14 @@ static int __maybe_unused ingenic_ost_suspend(struct device *dev)
return 0;
}
static int __maybe_unused ingenic_ost_resume(struct device *dev)
static int ingenic_ost_resume(struct device *dev)
{
struct ingenic_ost *ost = dev_get_drvdata(dev);
return clk_enable(ost->clk);
}
static const struct dev_pm_ops __maybe_unused ingenic_ost_pm_ops = {
static const struct dev_pm_ops ingenic_ost_pm_ops = {
/* _noirq: We want the OST clock to be gated last / ungated first */
.suspend_noirq = ingenic_ost_suspend,
.resume_noirq = ingenic_ost_resume,
......@@ -181,9 +181,7 @@ static const struct of_device_id ingenic_ost_of_match[] = {
static struct platform_driver ingenic_ost_driver = {
.driver = {
.name = "ingenic-ost",
#ifdef CONFIG_PM_SUSPEND
.pm = &ingenic_ost_pm_ops,
#endif
.pm = pm_sleep_ptr(&ingenic_ost_pm_ops),
.of_match_table = ingenic_ost_of_match,
},
};
......
......@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
......@@ -116,6 +117,7 @@ struct sh_cmt_device {
void __iomem *mapbase;
struct clk *clk;
unsigned long rate;
unsigned int reg_delay;
raw_spinlock_t lock; /* Protect the shared start/stop register */
......@@ -247,10 +249,17 @@ static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
{
if (ch->iostart)
ch->cmt->info->write_control(ch->iostart, 0, value);
else
ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
u32 old_value = sh_cmt_read_cmstr(ch);
if (value != old_value) {
if (ch->iostart) {
ch->cmt->info->write_control(ch->iostart, 0, value);
udelay(ch->cmt->reg_delay);
} else {
ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
udelay(ch->cmt->reg_delay);
}
}
}
static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
......@@ -260,7 +269,12 @@ static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value)
{
ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
u32 old_value = sh_cmt_read_cmcsr(ch);
if (value != old_value) {
ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
udelay(ch->cmt->reg_delay);
}
}
static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
......@@ -268,14 +282,33 @@ static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
}
static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
{
/* Tests showed that we need to wait 3 clocks here */
unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2);
u32 reg;
if (ch->cmt->info->model > SH_CMT_16BIT) {
int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg,
!(reg & SH_CMT32_CMCSR_WRFLG),
1, cmcnt_delay, false, ch);
if (ret < 0)
return ret;
}
ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
udelay(cmcnt_delay);
return 0;
}
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value)
{
ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR);
if (value != old_value) {
ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
udelay(ch->cmt->reg_delay);
}
}
static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped)
......@@ -319,7 +352,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
static int sh_cmt_enable(struct sh_cmt_channel *ch)
{
int k, ret;
int ret;
dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
......@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch)
}
sh_cmt_write_cmcor(ch, 0xffffffff);
sh_cmt_write_cmcnt(ch, 0);
/*
* According to the sh73a0 user's manual, as CMCNT can be operated
* only by the RCLK (Pseudo 32 kHz), there's one restriction on
* modifying CMCNT register; two RCLK cycles are necessary before
* this register is either read or any modification of the value
* it holds is reflected in the LSI's actual operation.
*
* While at it, we're supposed to clear out the CMCNT as of this
* moment, so make sure it's processed properly here. This will
* take RCLKx2 at maximum.
*/
for (k = 0; k < 100; k++) {
if (!sh_cmt_read_cmcnt(ch))
break;
udelay(1);
}
ret = sh_cmt_write_cmcnt(ch, 0);
if (sh_cmt_read_cmcnt(ch)) {
if (ret || sh_cmt_read_cmcnt(ch)) {
dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
ch->index);
ret = -ETIMEDOUT;
......@@ -995,8 +1011,8 @@ MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
{
unsigned int mask;
unsigned int i;
unsigned int mask, i;
unsigned long rate;
int ret;
cmt->pdev = pdev;
......@@ -1032,10 +1048,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
if (ret < 0)
goto err_clk_unprepare;
if (cmt->info->width == 16)
cmt->rate = clk_get_rate(cmt->clk) / 512;
else
cmt->rate = clk_get_rate(cmt->clk) / 8;
rate = clk_get_rate(cmt->clk);
if (!rate) {
ret = -EINVAL;
goto err_clk_disable;
}
/* We shall wait 2 input clks after register writes */
if (cmt->info->model >= SH_CMT_48BIT)
cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate);
cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8);
/* Map the memory resource(s). */
ret = sh_cmt_map_memory(cmt);
......
......@@ -188,6 +188,7 @@ static void __init npcm7xx_clocksource_init(void)
static int __init npcm7xx_timer_init(struct device_node *np)
{
struct clk *clk;
int ret;
ret = timer_of_init(np, &npcm7xx_to);
......@@ -199,6 +200,15 @@ static int __init npcm7xx_timer_init(struct device_node *np)
npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
(NPCM7XX_Tx_MIN_PRESCALE + 1);
/* Enable the clock for timer1, if it exists */
clk = of_clk_get(np, 1);
if (clk) {
if (!IS_ERR(clk))
clk_prepare_enable(clk);
else
pr_warn("%pOF: Failed to get clock for timer1: %pe", np, clk);
}
npcm7xx_clocksource_init();
npcm7xx_clockevents_init();
......
......@@ -155,14 +155,14 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static inline void timer_shutdown(struct clock_event_device *evt)
static inline void evt_timer_shutdown(struct clock_event_device *evt)
{
writel(0, common_clkevt->ctrl);
}
static int sp804_shutdown(struct clock_event_device *evt)
{
timer_shutdown(evt);
evt_timer_shutdown(evt);
return 0;
}
......@@ -171,7 +171,7 @@ static int sp804_set_periodic(struct clock_event_device *evt)
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
timer_shutdown(evt);
evt_timer_shutdown(evt);
writel(common_clkevt->reload, common_clkevt->load);
writel(ctrl, common_clkevt->ctrl);
return 0;
......
......@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
return error;
r = clk_get_rate(clock);
if (!r)
if (!r) {
clk_disable_unprepare(clock);
return -ENODEV;
}
if (is_ick)
t->ick = clock;
......
......@@ -633,6 +633,8 @@ static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *n
static int omap_dm_timer_free(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
struct device *dev;
int rc;
timer = to_dmtimer(cookie);
if (unlikely(!timer))
......@@ -640,10 +642,21 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie)
WARN_ON(!timer->reserved);
timer->reserved = 0;
dev = &timer->pdev->dev;
rc = pm_runtime_resume_and_get(dev);
if (rc)
return rc;
/* Clear timer configuration */
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
pm_runtime_put_sync(dev);
return 0;
}
int omap_dm_timer_get_irq(struct omap_dm_timer *cookie)
static int omap_dm_timer_get_irq(struct omap_dm_timer *cookie)
{
struct dmtimer *timer = to_dmtimer(cookie);
if (timer)
......@@ -1135,6 +1148,10 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
goto err_disable;
}
__omap_dm_timer_init_regs(timer);
/* Clear timer configuration */
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
pm_runtime_put(dev);
}
......@@ -1258,7 +1275,7 @@ static struct platform_driver omap_dm_timer_driver = {
.remove = omap_dm_timer_remove,
.driver = {
.name = "omap_timer",
.of_match_table = of_match_ptr(omap_timer_match),
.of_match_table = omap_timer_match,
.pm = &omap_dm_timer_pm_ops,
},
};
......
......@@ -1116,8 +1116,8 @@ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw,
if (ctlx == get_active_ctlx(hw)) {
spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
del_singleshot_timer_sync(&hw->reqtimer);
del_singleshot_timer_sync(&hw->resptimer);
del_timer_sync(&hw->reqtimer);
del_timer_sync(&hw->resptimer);
hw->req_timer_done = 1;
hw->resp_timer_done = 1;
usb_kill_urb(&hw->ctlx_urb);
......
......@@ -170,9 +170,9 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
*/
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
del_singleshot_timer_sync(&hw->throttle);
del_singleshot_timer_sync(&hw->reqtimer);
del_singleshot_timer_sync(&hw->resptimer);
del_timer_sync(&hw->throttle);
del_timer_sync(&hw->reqtimer);
del_timer_sync(&hw->resptimer);
/* Unlink all the URBs. This "removes the wheels"
* from the entire CTLX handling mechanism.
......
......@@ -62,8 +62,6 @@
struct omap_dm_timer {
};
int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
/*
......
......@@ -45,6 +45,7 @@ struct time_namespace *copy_time_ns(unsigned long flags,
void free_time_ns(struct time_namespace *ns);
void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
struct vdso_data *arch_get_vdso_data(void *vvar_page);
struct page *find_timens_vvar_page(struct vm_area_struct *vma);
static inline void put_time_ns(struct time_namespace *ns)
{
......@@ -141,6 +142,11 @@ static inline void timens_on_fork(struct nsproxy *nsproxy,
return;
}
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
static inline void timens_add_monotonic(struct timespec64 *ts) { }
static inline void timens_add_boottime(struct timespec64 *ts) { }
......
......@@ -169,7 +169,6 @@ static inline int timer_pending(const struct timer_list * timer)
}
extern void add_timer_on(struct timer_list *timer, int cpu);
extern int del_timer(struct timer_list * timer);
extern int mod_timer(struct timer_list *timer, unsigned long expires);
extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
extern int timer_reduce(struct timer_list *timer, unsigned long expires);
......@@ -183,14 +182,36 @@ extern int timer_reduce(struct timer_list *timer, unsigned long expires);
extern void add_timer(struct timer_list *timer);
extern int try_to_del_timer_sync(struct timer_list *timer);
extern int timer_delete_sync(struct timer_list *timer);
extern int timer_delete(struct timer_list *timer);
extern int timer_shutdown_sync(struct timer_list *timer);
extern int timer_shutdown(struct timer_list *timer);
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT)
extern int del_timer_sync(struct timer_list *timer);
#else
# define del_timer_sync(t) del_timer(t)
#endif
/**
* del_timer_sync - Delete a pending timer and wait for a running callback
* @timer: The timer to be deleted
*
* See timer_delete_sync() for detailed explanation.
*
* Do not use in new code. Use timer_delete_sync() instead.
*/
static inline int del_timer_sync(struct timer_list *timer)
{
return timer_delete_sync(timer);
}
#define del_singleshot_timer_sync(t) del_timer_sync(t)
/**
* del_timer - Delete a pending timer
* @timer: The timer to be deleted
*
* See timer_delete() for detailed explanation.
*
* Do not use in new code. Use timer_delete() instead.
*/
static inline int del_timer(struct timer_list *timer)
{
return timer_delete(timer);
}
extern void init_timers(void);
struct hrtimer;
......
......@@ -35,7 +35,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
{
struct rb_node *leftmost = rb_first_cached(&head->rb_root);
return rb_entry(leftmost, struct timerqueue_node, node);
return rb_entry_safe(leftmost, struct timerqueue_node, node);
}
static inline void timerqueue_init(struct timerqueue_node *node)
......
......@@ -76,7 +76,7 @@ static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
}
/**
* clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
* clockevent_delta2ns - Convert a latch value (device ticks) to nanoseconds
* @latch: value to convert
* @evt: pointer to clock event device descriptor
*
......
......@@ -192,6 +192,24 @@ static void timens_setup_vdso_data(struct vdso_data *vdata,
offset[CLOCK_BOOTTIME_ALARM] = boottime;
}
struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
if (likely(vma->vm_mm == current->mm))
return current->nsproxy->time_ns->vvar_page;
/*
* VM_PFNMAP | VM_IO protect .fault() handler from being called
* through interfaces like /proc/$pid/mem or
* process_vm_{readv,writev}() as long as there's no .access()
* in special_mapping_vmops().
* For more details check_vma_flags() and __access_remote_vm()
*/
WARN(1, "vvar_page accessed remotely");
return NULL;
}
/*
* Protects possibly multiple offsets writers racing each other
* and tasks entering the namespace.
......
This diff is collapsed.
......@@ -1164,7 +1164,7 @@ xprt_request_enqueue_receive(struct rpc_task *task)
spin_unlock(&xprt->queue_lock);
/* Turn off autodisconnect */
del_singleshot_timer_sync(&xprt->timer);
del_timer_sync(&xprt->timer);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment