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 ...@@ -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 one of its functions results in a segmentation fault. The module-unload
functions must therefore cancel any delayed calls to loadable-module functions must therefore cancel any delayed calls to loadable-module
functions, for example, any outstanding mod_timer() must be dealt 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 Unfortunately, there is no way to cancel an RCU callback; once you
invoke call_rcu(), the callback function is eventually going to be 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 ...@@ -191,7 +191,7 @@ Here is a sample module which implements a basic per cpu counter using
static void __exit test_exit(void) static void __exit test_exit(void)
{ {
del_timer_sync(&test_timer); timer_shutdown_sync(&test_timer);
} }
module_init(test_init); module_init(test_init);
......
...@@ -25,7 +25,13 @@ properties: ...@@ -25,7 +25,13 @@ properties:
- description: The timer interrupt of timer 0 - description: The timer interrupt of timer 0
clocks: 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: required:
- compatible - compatible
......
...@@ -102,12 +102,14 @@ properties: ...@@ -102,12 +102,14 @@ properties:
- enum: - enum:
- renesas,r8a779a0-cmt0 # 32-bit CMT0 on R-Car V3U - renesas,r8a779a0-cmt0 # 32-bit CMT0 on R-Car V3U
- renesas,r8a779f0-cmt0 # 32-bit CMT0 on R-Car S4-8 - 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 - const: renesas,rcar-gen4-cmt0 # 32-bit CMT0 on R-Car Gen4
- items: - items:
- enum: - enum:
- renesas,r8a779a0-cmt1 # 48-bit CMT on R-Car V3U - renesas,r8a779a0-cmt1 # 48-bit CMT on R-Car V3U
- renesas,r8a779f0-cmt1 # 48-bit CMT on R-Car S4-8 - 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 - const: renesas,rcar-gen4-cmt1 # 48-bit CMT on R-Car Gen4
reg: reg:
......
...@@ -38,6 +38,7 @@ properties: ...@@ -38,6 +38,7 @@ properties:
- renesas,tmu-r8a77995 # R-Car D3 - renesas,tmu-r8a77995 # R-Car D3
- renesas,tmu-r8a779a0 # R-Car V3U - renesas,tmu-r8a779a0 # R-Car V3U
- renesas,tmu-r8a779f0 # R-Car S4-8 - renesas,tmu-r8a779f0 # R-Car S4-8
- renesas,tmu-r8a779g0 # R-Car V4H
- const: renesas,tmu - const: renesas,tmu
reg: reg:
......
...@@ -18,6 +18,7 @@ properties: ...@@ -18,6 +18,7 @@ properties:
- enum: - enum:
- rockchip,rv1108-timer - rockchip,rv1108-timer
- rockchip,rk3036-timer - rockchip,rk3036-timer
- rockchip,rk3128-timer
- rockchip,rk3188-timer - rockchip,rk3188-timer
- rockchip,rk3228-timer - rockchip,rk3228-timer
- rockchip,rk3229-timer - rockchip,rk3229-timer
......
...@@ -967,7 +967,7 @@ you might do the following:: ...@@ -967,7 +967,7 @@ you might do the following::
while (list) { while (list) {
struct foo *next = list->next; struct foo *next = list->next;
del_timer(&list->timer); timer_delete(&list->timer);
kfree(list); kfree(list);
list = next; list = next;
} }
...@@ -981,7 +981,7 @@ the lock after we spin_unlock_bh(), and then try to free ...@@ -981,7 +981,7 @@ the lock after we spin_unlock_bh(), and then try to free
the element (which has already been freed!). the element (which has already been freed!).
This can be avoided by checking the result of 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 If 0, it means (in this case) that it is currently running, so we can
do:: do::
...@@ -990,7 +990,7 @@ do:: ...@@ -990,7 +990,7 @@ do::
while (list) { while (list) {
struct foo *next = list->next; struct foo *next = list->next;
if (!del_timer(&list->timer)) { if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */ /* Give timer a chance to delete this */
spin_unlock_bh(&list_lock); spin_unlock_bh(&list_lock);
goto retry; goto retry;
...@@ -1005,9 +1005,12 @@ do:: ...@@ -1005,9 +1005,12 @@ do::
Another common problem is deleting timers which restart themselves (by Another common problem is deleting timers which restart themselves (by
calling add_timer() at the end of their timer function). calling add_timer() at the end of their timer function).
Because this is a fairly common case which is prone to races, you should Because this is a fairly common case which is prone to races, you should
use del_timer_sync() (``include/linux/timer.h``) to use timer_delete_sync() (``include/linux/timer.h``) to handle this case.
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. 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 Locking Speed
============= =============
...@@ -1335,7 +1338,7 @@ lock. ...@@ -1335,7 +1338,7 @@ lock.
- kfree() - kfree()
- add_timer() and del_timer() - add_timer() and timer_delete()
Mutex API reference Mutex API reference
=================== ===================
......
...@@ -118,7 +118,7 @@ existing timer wheel code, as it is mature and well suited. Sharing code ...@@ -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 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 functions now have clearer behavior and clearer names - such as
hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly 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 1:1 mapping between them on the algorithmic level, and thus no real
potential for code sharing either. potential for code sharing either.
......
...@@ -990,7 +990,7 @@ potreste fare come segue:: ...@@ -990,7 +990,7 @@ potreste fare come segue::
while (list) { while (list) {
struct foo *next = list->next; struct foo *next = list->next;
del_timer(&list->timer); timer_delete(&list->timer);
kfree(list); kfree(list);
list = next; list = next;
} }
...@@ -1003,7 +1003,7 @@ e prenderà il *lock* solo dopo spin_unlock_bh(), e cercherà ...@@ -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). di eliminare il suo oggetto (che però è già stato eliminato).
Questo può essere evitato controllando il valore di ritorno di 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 rimosso. Se 0, significa (in questo caso) che il temporizzatore è in
esecuzione, quindi possiamo fare come segue:: esecuzione, quindi possiamo fare come segue::
...@@ -1012,7 +1012,7 @@ esecuzione, quindi possiamo fare come segue:: ...@@ -1012,7 +1012,7 @@ esecuzione, quindi possiamo fare come segue::
while (list) { while (list) {
struct foo *next = list->next; struct foo *next = list->next;
if (!del_timer(&list->timer)) { if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */ /* Give timer a chance to delete this */
spin_unlock_bh(&list_lock); spin_unlock_bh(&list_lock);
goto retry; goto retry;
...@@ -1026,10 +1026,8 @@ esecuzione, quindi possiamo fare come segue:: ...@@ -1026,10 +1026,8 @@ esecuzione, quindi possiamo fare come segue::
Un altro problema è l'eliminazione dei temporizzatori che si riavviano Un altro problema è l'eliminazione dei temporizzatori che si riavviano
da soli (chiamando add_timer() alla fine della loro esecuzione). da soli (chiamando add_timer() alla fine della loro esecuzione).
Dato che questo è un problema abbastanza comune con una propensione Dato che questo è un problema abbastanza comune con una propensione
alle corse critiche, dovreste usare del_timer_sync() alle corse critiche, dovreste usare timer_delete_sync()
(``include/linux/timer.h``) per gestire questo caso. Questa ritorna il (``include/linux/timer.h``) per gestire questo caso.
numero di volte che il temporizzatore è stato interrotto prima che
fosse in grado di fermarlo senza che si riavviasse.
Velocità della sincronizzazione Velocità della sincronizzazione
=============================== ===============================
...@@ -1374,7 +1372,7 @@ contesto, o trattenendo un qualsiasi *lock*. ...@@ -1374,7 +1372,7 @@ contesto, o trattenendo un qualsiasi *lock*.
- kfree() - kfree()
- add_timer() e del_timer() - add_timer() e timer_delete()
Riferimento per l'API dei Mutex Riferimento per l'API dei Mutex
=============================== ===============================
......
...@@ -185,7 +185,7 @@ UP之间没有不同的行为,在你的架构的 ``local.h`` 中包括 ``asm-g ...@@ -185,7 +185,7 @@ UP之间没有不同的行为,在你的架构的 ``local.h`` 中包括 ``asm-g
static void __exit test_exit(void) static void __exit test_exit(void)
{ {
del_timer_sync(&test_timer); timer_shutdown_sync(&test_timer);
} }
module_init(test_init); module_init(test_init);
......
...@@ -90,7 +90,7 @@ static void __init spear_clocksource_init(void) ...@@ -90,7 +90,7 @@ static void __init spear_clocksource_init(void)
200, 16, clocksource_mmio_readw_up); 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)); u16 val = readw(gpt_base + CR(CLKEVT));
...@@ -101,7 +101,7 @@ static inline void timer_shutdown(struct clock_event_device *evt) ...@@ -101,7 +101,7 @@ static inline void timer_shutdown(struct clock_event_device *evt)
static int spear_shutdown(struct clock_event_device *evt) static int spear_shutdown(struct clock_event_device *evt)
{ {
timer_shutdown(evt); spear_timer_shutdown(evt);
return 0; return 0;
} }
...@@ -111,7 +111,7 @@ static int spear_set_oneshot(struct clock_event_device *evt) ...@@ -111,7 +111,7 @@ static int spear_set_oneshot(struct clock_event_device *evt)
u16 val; u16 val;
/* stop the timer */ /* stop the timer */
timer_shutdown(evt); spear_timer_shutdown(evt);
val = readw(gpt_base + CR(CLKEVT)); val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT; val |= CTRL_ONE_SHOT;
...@@ -126,7 +126,7 @@ static int spear_set_periodic(struct clock_event_device *evt) ...@@ -126,7 +126,7 @@ static int spear_set_periodic(struct clock_event_device *evt)
u16 val; u16 val;
/* stop the timer */ /* stop the timer */
timer_shutdown(evt); spear_timer_shutdown(evt);
period = clk_get_rate(gpt_clk) / HZ; period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16; period >>= CTRL_PRESCALER16;
......
...@@ -151,28 +151,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) ...@@ -151,28 +151,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm); mmap_read_unlock(mm);
return 0; 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 #endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 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) ...@@ -129,28 +129,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0; 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 #endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 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) ...@@ -137,28 +137,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm); mmap_read_unlock(mm);
return 0; 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 #endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 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) ...@@ -44,21 +44,6 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(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 * 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 * 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) ...@@ -84,11 +69,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm); mmap_read_unlock(mm);
return 0; return 0;
} }
#else
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif #endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, 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, ...@@ -98,24 +98,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
} }
#ifdef CONFIG_TIME_NS #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 * 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 * 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) ...@@ -140,11 +122,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0; return 0;
} }
#else
static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
{
return NULL;
}
#endif #endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
......
...@@ -696,9 +696,15 @@ static int qca_close(struct hci_uart *hu) ...@@ -696,9 +696,15 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(&qca->tx_wait_q); skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq); skb_queue_purge(&qca->txq);
skb_queue_purge(&qca->rx_memdump_q); 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); destroy_workqueue(qca->workqueue);
del_timer_sync(&qca->tx_idle_timer);
del_timer_sync(&qca->wake_retrans_timer);
qca->hu = NULL; qca->hu = NULL;
kfree_skb(qca->rx_skb); kfree_skb(qca->rx_skb);
......
...@@ -155,7 +155,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf, ...@@ -155,7 +155,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
out: out:
if (!priv->response_length) { if (!priv->response_length) {
*off = 0; *off = 0;
del_singleshot_timer_sync(&priv->user_read_timer); del_timer_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work); flush_work(&priv->timeout_work);
} }
mutex_unlock(&priv->buffer_mutex); mutex_unlock(&priv->buffer_mutex);
...@@ -262,7 +262,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait) ...@@ -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) void tpm_common_release(struct file *file, struct file_priv *priv)
{ {
flush_work(&priv->async_work); 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); flush_work(&priv->timeout_work);
file->private_data = NULL; file->private_data = NULL;
priv->response_length = 0; priv->response_length = 0;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/clocksource_ids.h> #include <linux/clocksource_ids.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kstrtox.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -97,7 +98,7 @@ static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EV ...@@ -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) 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); 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) ...@@ -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); return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
} }
static __always_inline int timer_shutdown(const int access, static __always_inline int arch_timer_shutdown(const int access,
struct clock_event_device *clk) struct clock_event_device *clk)
{ {
unsigned long ctrl; unsigned long ctrl;
...@@ -701,22 +702,22 @@ static __always_inline int timer_shutdown(const int access, ...@@ -701,22 +702,22 @@ static __always_inline int timer_shutdown(const int access,
static int arch_timer_shutdown_virt(struct clock_event_device *clk) 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) 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) 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) 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, 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) ...@@ -141,7 +141,7 @@ static int __init ingenic_ost_probe(struct platform_device *pdev)
return 0; 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); struct ingenic_ost *ost = dev_get_drvdata(dev);
...@@ -150,14 +150,14 @@ static int __maybe_unused ingenic_ost_suspend(struct device *dev) ...@@ -150,14 +150,14 @@ static int __maybe_unused ingenic_ost_suspend(struct device *dev)
return 0; 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); struct ingenic_ost *ost = dev_get_drvdata(dev);
return clk_enable(ost->clk); 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 */ /* _noirq: We want the OST clock to be gated last / ungated first */
.suspend_noirq = ingenic_ost_suspend, .suspend_noirq = ingenic_ost_suspend,
.resume_noirq = ingenic_ost_resume, .resume_noirq = ingenic_ost_resume,
...@@ -181,9 +181,7 @@ static const struct of_device_id ingenic_ost_of_match[] = { ...@@ -181,9 +181,7 @@ static const struct of_device_id ingenic_ost_of_match[] = {
static struct platform_driver ingenic_ost_driver = { static struct platform_driver ingenic_ost_driver = {
.driver = { .driver = {
.name = "ingenic-ost", .name = "ingenic-ost",
#ifdef CONFIG_PM_SUSPEND .pm = pm_sleep_ptr(&ingenic_ost_pm_ops),
.pm = &ingenic_ost_pm_ops,
#endif
.of_match_table = ingenic_ost_of_match, .of_match_table = ingenic_ost_of_match,
}, },
}; };
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -116,6 +117,7 @@ struct sh_cmt_device { ...@@ -116,6 +117,7 @@ struct sh_cmt_device {
void __iomem *mapbase; void __iomem *mapbase;
struct clk *clk; struct clk *clk;
unsigned long rate; unsigned long rate;
unsigned int reg_delay;
raw_spinlock_t lock; /* Protect the shared start/stop register */ 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) ...@@ -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) static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
{ {
if (ch->iostart) u32 old_value = sh_cmt_read_cmstr(ch);
ch->cmt->info->write_control(ch->iostart, 0, value);
else if (value != old_value) {
ch->cmt->info->write_control(ch->cmt->mapbase, 0, 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) 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) ...@@ -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) 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) 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) ...@@ -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); 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); 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) 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) 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) ...@@ -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) static int sh_cmt_enable(struct sh_cmt_channel *ch)
{ {
int k, ret; int ret;
dev_pm_syscore_device(&ch->cmt->pdev->dev, true); dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
...@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) ...@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch)
} }
sh_cmt_write_cmcor(ch, 0xffffffff); sh_cmt_write_cmcor(ch, 0xffffffff);
sh_cmt_write_cmcnt(ch, 0); ret = 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);
}
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", dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
ch->index); ch->index);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
...@@ -995,8 +1011,8 @@ MODULE_DEVICE_TABLE(of, sh_cmt_of_table); ...@@ -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) static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
{ {
unsigned int mask; unsigned int mask, i;
unsigned int i; unsigned long rate;
int ret; int ret;
cmt->pdev = pdev; cmt->pdev = pdev;
...@@ -1032,10 +1048,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) ...@@ -1032,10 +1048,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto err_clk_unprepare; goto err_clk_unprepare;
if (cmt->info->width == 16) rate = clk_get_rate(cmt->clk);
cmt->rate = clk_get_rate(cmt->clk) / 512; if (!rate) {
else ret = -EINVAL;
cmt->rate = clk_get_rate(cmt->clk) / 8; 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). */ /* Map the memory resource(s). */
ret = sh_cmt_map_memory(cmt); ret = sh_cmt_map_memory(cmt);
......
...@@ -188,6 +188,7 @@ static void __init npcm7xx_clocksource_init(void) ...@@ -188,6 +188,7 @@ static void __init npcm7xx_clocksource_init(void)
static int __init npcm7xx_timer_init(struct device_node *np) static int __init npcm7xx_timer_init(struct device_node *np)
{ {
struct clk *clk;
int ret; int ret;
ret = timer_of_init(np, &npcm7xx_to); ret = timer_of_init(np, &npcm7xx_to);
...@@ -199,6 +200,15 @@ static int __init npcm7xx_timer_init(struct device_node *np) ...@@ -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_to.of_clk.rate = npcm7xx_to.of_clk.rate /
(NPCM7XX_Tx_MIN_PRESCALE + 1); (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_clocksource_init();
npcm7xx_clockevents_init(); npcm7xx_clockevents_init();
......
...@@ -155,14 +155,14 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) ...@@ -155,14 +155,14 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; 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); writel(0, common_clkevt->ctrl);
} }
static int sp804_shutdown(struct clock_event_device *evt) static int sp804_shutdown(struct clock_event_device *evt)
{ {
timer_shutdown(evt); evt_timer_shutdown(evt);
return 0; return 0;
} }
...@@ -171,7 +171,7 @@ static int sp804_set_periodic(struct clock_event_device *evt) ...@@ -171,7 +171,7 @@ static int sp804_set_periodic(struct clock_event_device *evt)
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
timer_shutdown(evt); evt_timer_shutdown(evt);
writel(common_clkevt->reload, common_clkevt->load); writel(common_clkevt->reload, common_clkevt->load);
writel(ctrl, common_clkevt->ctrl); writel(ctrl, common_clkevt->ctrl);
return 0; return 0;
......
...@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, ...@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
return error; return error;
r = clk_get_rate(clock); r = clk_get_rate(clock);
if (!r) if (!r) {
clk_disable_unprepare(clock);
return -ENODEV; return -ENODEV;
}
if (is_ick) if (is_ick)
t->ick = clock; t->ick = clock;
......
...@@ -633,6 +633,8 @@ static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *n ...@@ -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) static int omap_dm_timer_free(struct omap_dm_timer *cookie)
{ {
struct dmtimer *timer; struct dmtimer *timer;
struct device *dev;
int rc;
timer = to_dmtimer(cookie); timer = to_dmtimer(cookie);
if (unlikely(!timer)) if (unlikely(!timer))
...@@ -640,10 +642,21 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie) ...@@ -640,10 +642,21 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie)
WARN_ON(!timer->reserved); WARN_ON(!timer->reserved);
timer->reserved = 0; 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; 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); struct dmtimer *timer = to_dmtimer(cookie);
if (timer) if (timer)
...@@ -1135,6 +1148,10 @@ static int omap_dm_timer_probe(struct platform_device *pdev) ...@@ -1135,6 +1148,10 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
goto err_disable; goto err_disable;
} }
__omap_dm_timer_init_regs(timer); __omap_dm_timer_init_regs(timer);
/* Clear timer configuration */
dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
pm_runtime_put(dev); pm_runtime_put(dev);
} }
...@@ -1258,7 +1275,7 @@ static struct platform_driver omap_dm_timer_driver = { ...@@ -1258,7 +1275,7 @@ static struct platform_driver omap_dm_timer_driver = {
.remove = omap_dm_timer_remove, .remove = omap_dm_timer_remove,
.driver = { .driver = {
.name = "omap_timer", .name = "omap_timer",
.of_match_table = of_match_ptr(omap_timer_match), .of_match_table = omap_timer_match,
.pm = &omap_dm_timer_pm_ops, .pm = &omap_dm_timer_pm_ops,
}, },
}; };
......
...@@ -1116,8 +1116,8 @@ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw, ...@@ -1116,8 +1116,8 @@ static int hfa384x_usbctlx_complete_sync(struct hfa384x *hw,
if (ctlx == get_active_ctlx(hw)) { if (ctlx == get_active_ctlx(hw)) {
spin_unlock_irqrestore(&hw->ctlxq.lock, flags); spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
del_singleshot_timer_sync(&hw->reqtimer); del_timer_sync(&hw->reqtimer);
del_singleshot_timer_sync(&hw->resptimer); del_timer_sync(&hw->resptimer);
hw->req_timer_done = 1; hw->req_timer_done = 1;
hw->resp_timer_done = 1; hw->resp_timer_done = 1;
usb_kill_urb(&hw->ctlx_urb); usb_kill_urb(&hw->ctlx_urb);
......
...@@ -170,9 +170,9 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) ...@@ -170,9 +170,9 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface)
*/ */
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
del_singleshot_timer_sync(&hw->throttle); del_timer_sync(&hw->throttle);
del_singleshot_timer_sync(&hw->reqtimer); del_timer_sync(&hw->reqtimer);
del_singleshot_timer_sync(&hw->resptimer); del_timer_sync(&hw->resptimer);
/* Unlink all the URBs. This "removes the wheels" /* Unlink all the URBs. This "removes the wheels"
* from the entire CTLX handling mechanism. * from the entire CTLX handling mechanism.
......
...@@ -62,8 +62,6 @@ ...@@ -62,8 +62,6 @@
struct omap_dm_timer { struct omap_dm_timer {
}; };
int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
/* /*
......
...@@ -45,6 +45,7 @@ struct time_namespace *copy_time_ns(unsigned long flags, ...@@ -45,6 +45,7 @@ struct time_namespace *copy_time_ns(unsigned long flags,
void free_time_ns(struct time_namespace *ns); void free_time_ns(struct time_namespace *ns);
void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk); void timens_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);
struct vdso_data *arch_get_vdso_data(void *vvar_page); 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) static inline void put_time_ns(struct time_namespace *ns)
{ {
...@@ -141,6 +142,11 @@ static inline void timens_on_fork(struct nsproxy *nsproxy, ...@@ -141,6 +142,11 @@ static inline void timens_on_fork(struct nsproxy *nsproxy,
return; 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_monotonic(struct timespec64 *ts) { }
static inline void timens_add_boottime(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) ...@@ -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 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(struct timer_list *timer, unsigned long expires);
extern int mod_timer_pending(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); 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); ...@@ -183,14 +182,36 @@ extern int timer_reduce(struct timer_list *timer, unsigned long expires);
extern void add_timer(struct timer_list *timer); extern void add_timer(struct timer_list *timer);
extern int try_to_del_timer_sync(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); * del_timer_sync - Delete a pending timer and wait for a running callback
#else * @timer: The timer to be deleted
# define del_timer_sync(t) del_timer(t) *
#endif * 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); extern void init_timers(void);
struct hrtimer; struct hrtimer;
......
...@@ -35,7 +35,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) ...@@ -35,7 +35,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
{ {
struct rb_node *leftmost = rb_first_cached(&head->rb_root); 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) 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, ...@@ -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 * @latch: value to convert
* @evt: pointer to clock event device descriptor * @evt: pointer to clock event device descriptor
* *
......
...@@ -192,6 +192,24 @@ static void timens_setup_vdso_data(struct vdso_data *vdata, ...@@ -192,6 +192,24 @@ static void timens_setup_vdso_data(struct vdso_data *vdata,
offset[CLOCK_BOOTTIME_ALARM] = boottime; 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 * Protects possibly multiple offsets writers racing each other
* and tasks entering the namespace. * and tasks entering the namespace.
......
This diff is collapsed.
...@@ -1164,7 +1164,7 @@ xprt_request_enqueue_receive(struct rpc_task *task) ...@@ -1164,7 +1164,7 @@ xprt_request_enqueue_receive(struct rpc_task *task)
spin_unlock(&xprt->queue_lock); spin_unlock(&xprt->queue_lock);
/* Turn off autodisconnect */ /* Turn off autodisconnect */
del_singleshot_timer_sync(&xprt->timer); del_timer_sync(&xprt->timer);
return 0; 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