These AFS patches need the timer_reduce() patch from timers/core.
Signed-off-by: David Howells <dhowells@redhat.com>
F: include/linux/altera_jtaguart.h
AMAZON ETHERNET DRIVERS
-M: Netanel Belgazal <netanel@annapurnalabs.com>
-R: Saeed Bishara <saeed@annapurnalabs.com>
-R: Zorik Machulsky <zorik@annapurnalabs.com>
+M: Netanel Belgazal <netanel@amazon.com>
+R: Saeed Bishara <saeedb@amazon.com>
+R: Zorik Machulsky <zorik@amazon.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/ena.txt
F: drivers/staging/android/
ANDROID GOLDFISH RTC DRIVER
-M: Miodrag Dinic <miodrag.dinic@imgtec.com>
+M: Miodrag Dinic <miodrag.dinic@mips.com>
S: Supported
F: Documentation/devicetree/bindings/rtc/google,goldfish-rtc.txt
F: drivers/rtc/rtc-goldfish.c
S: Supported
F: arch/x86/net/bpf_jit*
F: Documentation/networking/filter.txt
+F: Documentation/bpf/
F: include/linux/bpf*
F: include/linux/filter.h
F: include/uapi/linux/bpf*
F: net/sched/act_bpf.c
F: net/sched/cls_bpf.c
F: samples/bpf/
-F: tools/net/bpf*
+F: tools/bpf/
F: tools/testing/selftests/bpf/
BROADCOM B44 10/100 ETHERNET DRIVER
F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
BROADCOM GENET ETHERNET DRIVER
+M: Doug Berger <opendmb@gmail.com>
M: Florian Fainelli <f.fainelli@gmail.com>
L: netdev@vger.kernel.org
S: Supported
CA8210 IEEE-802.15.4 RADIO DRIVER
M: Harry Morris <h.morris@cascoda.com>
-M: linuxdev@cascoda.com
L: linux-wpan@vger.kernel.org
W: https://github.com/Cascoda/ca8210-linux.git
S: Maintained
F: drivers/auxdisplay/cfag12864bfb.c
F: include/linux/cfag12864b.h
-CFG80211 and NL80211
+802.11 (including CFG80211/NL80211)
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
S: Maintained
+F: net/wireless/
F: include/uapi/linux/nl80211.h
+F: include/linux/ieee80211.h
+F: include/net/wext.h
F: include/net/cfg80211.h
-F: net/wireless/*
-X: net/wireless/wext*
+F: include/net/iw_handler.h
+F: include/net/ieee80211_radiotap.h
+F: Documentation/driver-api/80211/cfg80211.rst
+F: Documentation/networking/regulatory.txt
CHAR and MISC DRIVERS
M: Arnd Bergmann <arnd@arndb.de>
CISCO VIC ETHERNET NIC DRIVER
M: Christian Benvenuti <benve@cisco.com>
M: Govindarajulu Varadarajan <_govind@gmx.com>
-M: Neel Patel <neepatel@cisco.com>
+M: Parvi Kaustubhi <pkaustub@cisco.com>
S: Supported
F: drivers/net/ethernet/cisco/enic/
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
S: Supported
- F: drivers/clocksource
+ F: drivers/clocksource/
+ F: Documentation/devicetree/bindings/timer/
CMPC ACPI DRIVER
M: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
F: drivers/iommu/exynos-iommu.c
EZchip NPS platform support
-M: Noam Camus <noamc@ezchip.com>
+M: Elad Kanfi <eladkan@mellanox.com>
+M: Vineet Gupta <vgupta@synopsys.com>
S: Supported
F: arch/arc/plat-eznps
F: arch/arc/boot/dts/eznps.dts
L: linux-fsdevel@vger.kernel.org
S: Maintained
F: include/linux/fcntl.h
-F: include/linux/fs.h
F: include/uapi/linux/fcntl.h
-F: include/uapi/linux/fs.h
F: fs/fcntl.c
F: fs/locks.c
L: linux-fsdevel@vger.kernel.org
S: Maintained
F: fs/*
+F: include/linux/fs.h
+F: include/uapi/linux/fs.h
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: Riku Voipio <riku.voipio@iki.fi>
F: Documentation/networking/ieee802154.txt
IFE PROTOCOL
-M: Yotam Gigi <yotamg@mellanox.com>
+M: Yotam Gigi <yotam.gi@gmail.com>
M: Jamal Hadi Salim <jhs@mojatatu.com>
F: net/ife
F: include/net/ife.h
F: drivers/usb/atm/ueagle-atm.c
IMGTEC ASCII LCD DRIVER
-M: Paul Burton <paul.burton@imgtec.com>
+M: Paul Burton <paul.burton@mips.com>
S: Maintained
F: Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
F: drivers/auxdisplay/img-ascii-lcd.c
IMGTEC IR DECODER DRIVER
-M: James Hogan <james.hogan@imgtec.com>
+M: James Hogan <jhogan@kernel.org>
S: Maintained
F: drivers/media/rc/img-ir/
F: arch/arm64/kvm/
KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
-M: James Hogan <james.hogan@imgtec.com>
+M: James Hogan <jhogan@kernel.org>
L: linux-mips@linux-mips.org
S: Supported
F: arch/mips/include/uapi/asm/kvm*
F: arch/mips/kvm/
KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc)
-M: Alexander Graf <agraf@suse.com>
+M: Paul Mackerras <paulus@ozlabs.org>
L: kvm-ppc@vger.kernel.org
W: http://www.linux-kvm.org/
T: git git://github.com/agraf/linux-2.6.git
F: Documentation/scsi/53c700.txt
F: drivers/scsi/53c700*
+LEAKING_ADDRESSES
+M: Tobin C. Harding <me@tobin.cc>
+S: Maintained
+F: scripts/leaking_addresses.pl
+
LED SUBSYSTEM
M: Richard Purdie <rpurdie@rpsys.net>
M: Jacek Anaszewski <jacek.anaszewski@gmail.com>
F: include/net/mac80211.h
F: net/mac80211/
F: drivers/net/wireless/mac80211_hwsim.[ch]
+F: Documentation/networking/mac80211_hwsim/README
MAILBOX API
M: Jassi Brar <jassisinghbrar@gmail.com>
S: Orphan
F: drivers/net/wireless/marvell/libertas/
+MARVELL MACCHIATOBIN SUPPORT
+M: Russell King <rmk@armlinux.org.uk>
+L: linux-arm-kernel@lists.infradead.org
+S: Maintained
+F: arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
+
MARVELL MV643XX ETHERNET DRIVER
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: netdev@vger.kernel.org
F: drivers/net/ethernet/mellanox/mlxsw/
MELLANOX FIRMWARE FLASH LIBRARY (mlxfw)
-M: Yotam Gigi <yotamg@mellanox.com>
+M: mlxsw@mellanox.com
L: netdev@vger.kernel.org
S: Supported
W: http://www.mellanox.com
T: git git://linuxtv.org/media_tree.git
METAG ARCHITECTURE
-M: James Hogan <james.hogan@imgtec.com>
+M: James Hogan <jhogan@kernel.org>
L: linux-metag@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git
S: Odd Fixes
F: arch/mips/
MIPS BOSTON DEVELOPMENT BOARD
-M: Paul Burton <paul.burton@imgtec.com>
+M: Paul Burton <paul.burton@mips.com>
L: linux-mips@linux-mips.org
S: Maintained
F: Documentation/devicetree/bindings/clock/img,boston-clock.txt
F: include/dt-bindings/clock/boston-clock.h
MIPS GENERIC PLATFORM
-M: Paul Burton <paul.burton@imgtec.com>
+M: Paul Burton <paul.burton@mips.com>
L: linux-mips@linux-mips.org
S: Supported
F: arch/mips/generic/
F: drivers/*/*/*loongson1*
MIPS RINT INSTRUCTION EMULATION
-M: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
+M: Aleksandar Markovic <aleksandar.markovic@mips.com>
L: linux-mips@linux-mips.org
S: Supported
F: arch/mips/math-emu/sp_rint.c
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <b-liu@ti.com>
L: linux-usb@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/musb/
M: Josef Bacik <jbacik@fb.com>
S: Maintained
L: linux-block@vger.kernel.org
-L: nbd-general@lists.sourceforge.net
+L: nbd@other.debian.org
F: Documentation/blockdev/nbd.txt
F: drivers/block/nbd.c
F: include/uapi/linux/nbd.h
S: Maintained
F: net/dsa/
F: include/net/dsa.h
+F: include/linux/dsa/
F: drivers/net/dsa/
NETWORKING [GENERAL]
F: include/uapi/linux/net.h
F: include/uapi/linux/netdevice.h
F: include/uapi/linux/net_namespace.h
-F: tools/net/
F: tools/testing/selftests/net/
+F: lib/net_utils.c
F: lib/random32.c
NETWORKING [IPSEC]
PARAVIRT_OPS INTERFACE
M: Juergen Gross <jgross@suse.com>
-M: Chris Wright <chrisw@sous-sol.org>
M: Alok Kataria <akataria@vmware.com>
M: Rusty Russell <rusty@rustcorp.com.au>
L: virtualization@lists.linux-foundation.org
PCI DRIVER FOR MICROSEMI SWITCHTEC
M: Kurt Schwemmer <kurt.schwemmer@microsemi.com>
-M: Stephen Bates <stephen.bates@microsemi.com>
M: Logan Gunthorpe <logang@deltatee.com>
L: linux-pci@vger.kernel.org
S: Maintained
PCI ENDPOINT SUBSYSTEM
M: Kishon Vijay Abraham I <kishon@ti.com>
+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
L: linux-pci@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/pci-endpoint.git
S: Supported
F: arch/x86/pci/
F: arch/x86/kernel/quirks.c
+PCI NATIVE HOST BRIDGE AND ENDPOINT DRIVERS
+M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+L: linux-pci@vger.kernel.org
+Q: http://patchwork.ozlabs.org/project/linux-pci/list/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
+S: Supported
+F: drivers/pci/host/
+F: drivers/pci/dwc/
+
PCIE DRIVER FOR AXIS ARTPEC
M: Niklas Cassel <niklas.cassel@axis.com>
M: Jesper Nilsson <jesper.nilsson@axis.com>
PCIE DRIVER FOR HISILICON
M: Zhou Wang <wangzhou1@hisilicon.com>
-M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
M: Ingo Molnar <mingo@redhat.com>
M: Arnaldo Carvalho de Melo <acme@kernel.org>
R: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+R: Jiri Olsa <jolsa@redhat.com>
+R: Namhyung Kim <namhyung@kernel.org>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
S: Supported
F: drivers/pinctrl/spear/
PISTACHIO SOC SUPPORT
-M: James Hartley <james.hartley@imgtec.com>
-M: Ionela Voinescu <ionela.voinescu@imgtec.com>
+M: James Hartley <james.hartley@sondrel.com>
L: linux-mips@linux-mips.org
-S: Maintained
+S: Odd Fixes
F: arch/mips/pistachio/
F: arch/mips/include/asm/mach-pistachio/
F: arch/mips/boot/dts/img/pistachio*
F: drivers/block/ps3vram.c
PSAMPLE PACKET SAMPLING SUPPORT:
-M: Yotam Gigi <yotamg@mellanox.com>
+M: Yotam Gigi <yotam.gi@gmail.com>
S: Maintained
F: net/psample
F: include/net/psample.h
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
S: Maintained
F: Documentation/rfkill.txt
+F: Documentation/ABI/stable/sysfs-class-rfkill
F: net/rfkill/
RHASHTABLE
SYNOPSYS HSDK RESET CONTROLLER DRIVER
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
S: Supported
-F: drivers/reset/reset-hsdk-v1.c
-F: include/dt-bindings/reset/snps,hsdk-v1-reset.h
-F: Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt
+F: drivers/reset/reset-hsdk.c
+F: include/dt-bindings/reset/snps,hsdk-reset.h
+F: Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt
SYSTEM CONFIGURATION (SYSCON)
M: Lee Jones <lee.jones@linaro.org>
M: Yehezkel Bernat <yehezkel.bernat@intel.com>
S: Maintained
F: drivers/thunderbolt/
+F: include/linux/thunderbolt.h
+
+THUNDERBOLT NETWORK DRIVER
+M: Michael Jamet <michael.jamet@intel.com>
+M: Mika Westerberg <mika.westerberg@linux.intel.com>
+M: Yehezkel Bernat <yehezkel.bernat@intel.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/thunderbolt.c
THUNDERX GPIO DRIVER
M: David Daney <david.daney@cavium.com>
TPM DEVICE DRIVER
M: Peter Huewe <peterhuewe@gmx.de>
-M: Marcel Selhorst <tpmdd@selhorst.net>
M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
R: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
-W: http://tpmdd.sourceforge.net
-L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
-Q: https://patchwork.kernel.org/project/tpmdd-devel/list/
+L: linux-integrity@vger.kernel.org
+Q: https://patchwork.kernel.org/project/linux-integrity/list/
T: git git://git.infradead.org/users/jjs/linux-tpmdd.git
S: Maintained
F: drivers/char/tpm/
-TPM IBM_VTPM DEVICE DRIVER
-M: Ashley Lai <ashleydlai@gmail.com>
-W: http://tpmdd.sourceforge.net
-L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
-S: Maintained
-F: drivers/char/tpm/tpm_ibmvtpm*
-
TRACING
M: Steven Rostedt <rostedt@goodmis.org>
M: Ingo Molnar <mingo@redhat.com>
F: include/linux/virtio_vsock.h
F: include/uapi/linux/virtio_vsock.h
F: include/uapi/linux/vsockmon.h
+F: include/uapi/linux/vm_sockets_diag.h
+F: net/vmw_vsock/diag.c
F: net/vmw_vsock/af_vsock_tap.c
F: net/vmw_vsock/virtio_transport_common.c
F: net/vmw_vsock/virtio_transport.c
F: drivers/net/vsockmon.c
F: drivers/vhost/vsock.c
F: drivers/vhost/vsock.h
+F: tools/testing/vsock/
VIRTIO CONSOLE DRIVER
M: Amit Shah <amit@kernel.org>
S: Supported
W: http://wireless.kernel.org/en/users/Drivers/wil6210
F: drivers/net/wireless/ath/wil6210/
-F: include/uapi/linux/wil6210_uapi.h
WIMAX STACK
M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+// SPDX-License-Identifier: GPL-2.0
/*
* DSM-G600 board-setup
*
#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
static void dsmg600_power_handler(unsigned long data);
- static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
+ static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler);
static void dsmg600_power_handler(unsigned long data)
{
+// SPDX-License-Identifier: GPL-2.0
/*
* arch/arm/mach-ixp4xx/nas100d-setup.c
*
#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
static void nas100d_power_handler(unsigned long data);
- static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
+ static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler);
static void nas100d_power_handler(unsigned long data)
{
+// SPDX-License-Identifier: GPL-2.0
/*
* Mac bong noise generator. Note - we ought to put a boingy noise
* here 8)
/*
* our timer to start/continue/stop the bell
*/
- static DEFINE_TIMER(mac_sound_timer, mac_nosound, 0, 0);
+ static DEFINE_TIMER(mac_sound_timer, mac_nosound);
/*
* Sort of initialize the sound chip (called from mac_mksound on the first
+// SPDX-License-Identifier: GPL-2.0
/*
* Watchdog support on powerpc systems.
*
add_timer_on(t, cpu);
}
- static void wd_timer_fn(unsigned long data)
+ static void wd_timer_fn(struct timer_list *t)
{
- struct timer_list *t = this_cpu_ptr(&wd_timer);
int cpu = smp_processor_id();
watchdog_timer_interrupt(cpu);
per_cpu(wd_timer_tb, cpu) = get_tb();
- setup_pinned_timer(t, wd_timer_fn, 0);
+ timer_setup(t, wd_timer_fn, TIMER_PINNED);
wd_timer_reset(cpu, t);
}
if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
return 0;
- if (watchdog_suspended)
- return 0;
-
if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
return 0;
wd_timer_period_ms = watchdog_thresh * 1000 * 2 / 5;
}
-void watchdog_nmi_reconfigure(void)
+void watchdog_nmi_stop(void)
{
int cpu;
- watchdog_calc_timeouts();
-
for_each_cpu(cpu, &wd_cpus_enabled)
stop_wd_on_cpu(cpu);
+}
+void watchdog_nmi_start(void)
+{
+ int cpu;
+
+ watchdog_calc_timeouts();
for_each_cpu_and(cpu, cpu_online_mask, &watchdog_cpumask)
start_wd_on_cpu(cpu);
}
/*
- * This runs after lockup_detector_init() which sets up watchdog_cpumask.
+ * Invoked from core watchdog init.
*/
-static int __init powerpc_watchdog_init(void)
+int __init watchdog_nmi_probe(void)
{
int err;
- watchdog_calc_timeouts();
-
- err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/watchdog:online",
- start_wd_on_cpu, stop_wd_on_cpu);
- if (err < 0)
+ err = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "powerpc/watchdog:online",
+ start_wd_on_cpu, stop_wd_on_cpu);
+ if (err < 0) {
pr_warn("Watchdog could not be initialized");
-
+ return err;
+ }
return 0;
}
-arch_initcall(powerpc_watchdog_init);
static void handle_backtrace_ipi(struct pt_regs *regs)
{
int arch_update_cpu_topology(void)
{
- lockdep_assert_cpus_held();
return numa_update_cpu_topology(true);
}
schedule_work(&topology_work);
}
- static void topology_timer_fn(unsigned long ignored)
+ static void topology_timer_fn(struct timer_list *unused)
{
if (prrn_enabled && cpumask_weight(&cpu_associativity_changes_mask))
topology_schedule_update();
reset_topology_timer();
}
}
- static struct timer_list topology_timer =
- TIMER_INITIALIZER(topology_timer_fn, 0, 0);
+ static struct timer_list topology_timer;
static void reset_topology_timer(void)
{
- topology_timer.data = 0;
- topology_timer.expires = jiffies + 60 * HZ;
- mod_timer(&topology_timer, topology_timer.expires);
+ mod_timer(&topology_timer, jiffies + 60 * HZ);
}
#ifdef CONFIG_SMP
prrn_enabled = 0;
vphn_enabled = 1;
setup_cpu_associativity_change_counters();
- init_timer_deferrable(&topology_timer);
+ timer_setup(&topology_timer, topology_timer_fn,
+ TIMER_DEFERRABLE);
reset_topology_timer();
}
}
static void idt77105_restart_timer_func(unsigned long);
- static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func, 0, 0);
- static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func, 0, 0);
+ static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func);
+ static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func);
static int start_timer = 1;
static struct idt77105_priv *idt77105_all = NULL;
if (start_timer) {
start_timer = 0;
- setup_timer(&stats_timer, idt77105_stats_timer_func, 0UL);
stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD;
add_timer(&stats_timer);
- setup_timer(&restart_timer, idt77105_restart_timer_func, 0UL);
restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD;
add_timer(&restart_timer);
}
static struct atm_dev *_ia_dev[8];
static int iadev_count;
static void ia_led_timer(unsigned long arg);
- static DEFINE_TIMER(ia_timer, ia_led_timer, 0, 0);
+ static DEFINE_TIMER(ia_timer, ia_led_timer);
static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
{
- static const struct ia_reg suni_ds3_init [] = {
+ static const struct ia_reg suni_ds3_init[] = {
{ SUNI_DS3_FRM_INTR_ENBL, 0x17 },
{ SUNI_DS3_FRM_CFG, 0x01 },
{ SUNI_DS3_TRAN_CFG, 0x01 },
static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
{
- static const struct ia_reg suni_e3_init [] = {
+ static const struct ia_reg suni_e3_init[] = {
{ SUNI_E3_FRM_FRAM_OPTIONS, 0x04 },
{ SUNI_E3_FRM_MAINT_OPTIONS, 0x20 },
{ SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d },
static void ia_suni_pm7345_init(struct iadev_priv *iadev)
{
- static const struct ia_reg suni_init [] = {
+ static const struct ia_reg suni_init[] = {
/* Enable RSOP loss of signal interrupt. */
{ SUNI_INTR_ENBL, 0x28 },
/* Clear error counters. */
/*
* Copyright (C) 2016 Imagination Technologies
- * Author: Paul Burton <paul.burton@imgtec.com>
+ * Author: Paul Burton <paul.burton@mips.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Scroll the current message along the LCD by one character, rearming the
* timer if required.
*/
- static void img_ascii_lcd_scroll(unsigned long arg)
+ static void img_ascii_lcd_scroll(struct timer_list *t)
{
- struct img_ascii_lcd_ctx *ctx = (struct img_ascii_lcd_ctx *)arg;
+ struct img_ascii_lcd_ctx *ctx = from_timer(ctx, t, timer);
unsigned int i, ch = ctx->scroll_pos;
unsigned int num_chars = ctx->cfg->num_chars;
ctx->scroll_pos = 0;
/* update the LCD */
- img_ascii_lcd_scroll((unsigned long)ctx);
+ img_ascii_lcd_scroll(&ctx->timer);
return 0;
}
ctx->scroll_rate = HZ / 2;
/* initialise a timer for scrolling the message */
- init_timer(&ctx->timer);
- ctx->timer.function = img_ascii_lcd_scroll;
- ctx->timer.data = (unsigned long)ctx;
+ timer_setup(&ctx->timer, img_ascii_lcd_scroll, 0);
platform_set_drvdata(pdev, ctx);
+// SPDX-License-Identifier: GPL-2.0
/*
* Faraday Technology FTTMR010 timer driver
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
fttmr010->base = of_iomap(np, 0);
if (!fttmr010->base) {
- pr_err("Can't remap registers");
+ pr_err("Can't remap registers\n");
ret = -ENXIO;
goto out_free;
}
/* IRQ for timer 1 */
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0) {
- pr_err("Can't parse IRQ");
+ pr_err("Can't parse IRQ\n");
ret = -EINVAL;
goto out_unmap;
}
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __TIMER_OF_H__
#define __TIMER_OF_H__
extern int __init timer_of_init(struct device_node *np,
struct timer_of *to);
+
+ extern void timer_of_exit(struct timer_of *to);
+
#endif
/* The crypto framework makes it hard to avoid this global. */
static struct device *artpec6_crypto_dev;
-static struct dentry *dbgfs_root;
-
#ifdef CONFIG_FAULT_INJECTION
static DECLARE_FAULT_ATTR(artpec6_crypto_fail_status_read);
static DECLARE_FAULT_ATTR(artpec6_crypto_fail_dma_array_full);
del_timer(&ac->timer);
}
- static void artpec6_crypto_timeout(unsigned long data)
+ static void artpec6_crypto_timeout(struct timer_list *t)
{
- struct artpec6_crypto *ac = (struct artpec6_crypto *) data;
+ struct artpec6_crypto *ac = from_timer(ac, t, timer);
dev_info_ratelimited(artpec6_crypto_dev, "timeout\n");
char *desc;
};
+static struct dentry *dbgfs_root;
+
static void artpec6_crypto_init_debugfs(void)
{
dbgfs_root = debugfs_create_dir("artpec6_crypto", NULL);
spin_lock_init(&ac->queue_lock);
INIT_LIST_HEAD(&ac->queue);
INIT_LIST_HEAD(&ac->pending);
- setup_timer(&ac->timer, artpec6_crypto_timeout, (unsigned long) ac);
+ timer_setup(&ac->timer, artpec6_crypto_timeout, 0);
ac->base = base;
spin_lock_init(&hwif->lock);
- setup_timer(&hwif->timer, &ide_timer_expiry, (unsigned long)hwif);
+ timer_setup(&hwif->timer, ide_timer_expiry, 0);
init_completion(&hwif->gendev_rel_comp);
if (hwif_init(hwif) == 0) {
printk(KERN_INFO "%s: failed to initialize IDE "
"interface\n", hwif->name);
+ device_unregister(hwif->portdev);
device_unregister(&hwif->gendev);
ide_disable_port(hwif);
continue;
+// SPDX-License-Identifier: GPL-2.0
/*
* e100net.c: A network driver for the ETRAX 100LX network controller.
*
static unsigned int network_tr_ctrl_shadow = 0;
/* Network speed indication. */
- static DEFINE_TIMER(speed_timer, NULL, 0, 0);
- static DEFINE_TIMER(clear_led_timer, NULL, 0, 0);
+ static DEFINE_TIMER(speed_timer, NULL);
+ static DEFINE_TIMER(clear_led_timer, NULL);
static int current_speed; /* Speed read from transceiver */
static int current_speed_selection; /* Speed selected by user */
static unsigned long led_next_time;
static int rx_queue_len;
/* Duplex */
- static DEFINE_TIMER(duplex_timer, NULL, 0, 0);
+ static DEFINE_TIMER(duplex_timer, NULL);
static int full_duplex;
static enum duplex current_duplex;
static struct yam_mcs *yam_data;
- static DEFINE_TIMER(yam_timer, NULL, 0, 0);
+ static DEFINE_TIMER(yam_timer, NULL);
/* --------------------------------------------------------------------- */
yam_start_tx(dev, yp);
}
-static void yam_dotimer(unsigned long dummy)
+static void yam_dotimer(struct timer_list *unused)
{
int i;
}
- yam_timer.function = yam_dotimer;
+ timer_setup(&yam_timer, yam_dotimer, 0);
yam_timer.expires = jiffies + HZ / 100;
add_timer(&yam_timer);
+// SPDX-License-Identifier: GPL-2.0
#include <linux/mm.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
mod_timer(t, round_jiffies(iv));
}
- static void cec_timer_fn(unsigned long data)
+ static void cec_timer_fn(struct timer_list *unused)
{
- struct ce_array *ca = (struct ce_array *)data;
-
- do_spring_cleaning(ca);
+ do_spring_cleaning(&ce_arr);
cec_mod_timer(&cec_timer, timer_interval);
}
if (create_debugfs_nodes())
return;
- setup_timer(&cec_timer, cec_timer_fn, (unsigned long)&ce_arr);
+ timer_setup(&cec_timer, cec_timer_fn, 0);
cec_mod_timer(&cec_timer, CEC_TIMER_DEFAULT_INTERVAL);
pr_info("Correctable Errors collector initialized.\n");
if (*str == '=')
str++;
- if (!strncmp(str, "cec_disable", 7))
+ if (!strcmp(str, "cec_disable"))
ce_arr.disabled = 1;
else
return 0;
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* tape device driver for 3480/3490E/3590 tapes.
*
int options; /* options for execution. */
int retries; /* retry counter for error recovery. */
int rescnt; /* residual count from devstat. */
+ struct timer_list timer; /* timer for std_assign_timeout(). */
/* Callback for delivering final status. */
void (*callback)(struct tape_request *, void *);
+// SPDX-License-Identifier: GPL-2.0
/*
* standard tape device functions for ibm tapes.
*
* tape_std_assign
*/
static void
- tape_std_assign_timeout(unsigned long data)
+ tape_std_assign_timeout(struct timer_list *t)
{
- struct tape_request * request;
- struct tape_device * device;
+ struct tape_request * request = from_timer(request, t, timer);
+ struct tape_device * device = request->device;
int rc;
- request = (struct tape_request *) data;
- device = request->device;
BUG_ON(!device);
DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
* to another host (actually this shouldn't happen but it does).
* So we set up a timeout for this call.
*/
- init_timer_on_stack(&timeout);
- timeout.function = tape_std_assign_timeout;
- timeout.data = (unsigned long) request;
- timeout.expires = jiffies + 2 * HZ;
- add_timer(&timeout);
+ timer_setup(&request->timer, tape_std_assign_timeout, 0);
+ mod_timer(&timeout, jiffies + 2 * HZ);
rc = tape_do_io_interruptible(device, request);
- del_timer_sync(&timeout);
- destroy_timer_on_stack(&timeout);
+ del_timer_sync(&request->timer);
if (rc != 0) {
DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
+/* SPDX-License-Identifier: GPL-2.0 */
/*lcs.h*/
#include <linux/interrupt.h>
void (*callback)(struct lcs_card *, struct lcs_cmd *);
wait_queue_head_t wait_q;
struct lcs_card *card;
+ struct timer_list timer;
int received;
int rc;
};
if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
reason = FAILURE_SESSION_IN_RECOVERY;
- sc->result = DID_REQUEUE;
+ sc->result = DID_REQUEUE << 16;
goto fault;
}
}
EXPORT_SYMBOL_GPL(iscsi_target_alloc);
- static void iscsi_tmf_timedout(unsigned long data)
+ static void iscsi_tmf_timedout(struct timer_list *t)
{
- struct iscsi_conn *conn = (struct iscsi_conn *)data;
+ struct iscsi_conn *conn = from_timer(conn, t, tmf_timer);
struct iscsi_session *session = conn->session;
spin_lock(&session->frwd_lock);
}
conn->tmfcmd_pdus_cnt++;
conn->tmf_timer.expires = timeout * HZ + jiffies;
- conn->tmf_timer.function = iscsi_tmf_timedout;
- conn->tmf_timer.data = (unsigned long)conn;
add_timer(&conn->tmf_timer);
ISCSI_DBG_EH(session, "tmf set timeout\n");
}
EXPORT_SYMBOL_GPL(iscsi_eh_cmd_timed_out);
- static void iscsi_check_transport_timeouts(unsigned long data)
+ static void iscsi_check_transport_timeouts(struct timer_list *t)
{
- struct iscsi_conn *conn = (struct iscsi_conn *)data;
+ struct iscsi_conn *conn = from_timer(conn, t, transport_timer);
struct iscsi_session *session = conn->session;
unsigned long recv_timeout, next_timeout = 0, last_recv;
/**
* iscsi_session_teardown - destroy session, host, and cls_session
* @cls_session: iscsi session
- *
- * The driver must have called iscsi_remove_session before
- * calling this.
*/
void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
{
iscsi_pool_free(&session->cmdpool);
+ iscsi_remove_session(cls_session);
+
kfree(session->password);
kfree(session->password_in);
kfree(session->username);
kfree(session->portal_type);
kfree(session->discovery_parent_type);
- iscsi_destroy_session(cls_session);
+ iscsi_free_session(cls_session);
+
iscsi_host_dec_session_cnt(shost);
module_put(owner);
}
conn->exp_statsn = 0;
conn->tmf_state = TMF_INITIAL;
- init_timer(&conn->transport_timer);
- conn->transport_timer.data = (unsigned long)conn;
- conn->transport_timer.function = iscsi_check_transport_timeouts;
+ timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0);
INIT_LIST_HEAD(&conn->mgmtqueue);
INIT_LIST_HEAD(&conn->cmdqueue);
goto login_task_data_alloc_fail;
conn->login_task->data = conn->data = data;
- init_timer(&conn->tmf_timer);
+ timer_setup(&conn->tmf_timer, iscsi_tmf_timedout, 0);
init_waitqueue_head(&conn->ehwait);
return cls_conn;
*/
__inline__ void
- qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval)
+ qla2x00_start_timer(scsi_qla_host_t *vha, unsigned long interval)
{
- init_timer(&vha->timer);
+ timer_setup(&vha->timer, qla2x00_timer, 0);
vha->timer.expires = jiffies + interval * HZ;
- vha->timer.data = (unsigned long)vha;
- vha->timer.function = (void (*)(unsigned long))func;
add_timer(&vha->timer);
vha->timer_active = 1;
}
host->max_cmd_len, host->max_channel, host->max_lun,
host->transportt, sht->vendor_id);
+ INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
+
/* Set up the irqs */
ret = qla2x00_request_irqs(ha, rsp);
if (ret)
ql_log(ql_log_fatal, base_vha, 0x00ed,
"Failed to start DPC thread.\n");
ret = PTR_ERR(ha->dpc_thread);
+ ha->dpc_thread = NULL;
goto probe_failed;
}
ql_dbg(ql_dbg_init, base_vha, 0x00ee,
*/
qla2xxx_wake_dpc(base_vha);
- INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
INIT_WORK(&ha->board_disable, qla2x00_disable_board_on_pci_error);
if (IS_QLA8031(ha) || IS_MCTP_CAPABLE(ha)) {
base_vha->host->irq = ha->pdev->irq;
/* Initialized the timer */
- qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL);
+ qla2x00_start_timer(base_vha, WATCH_INTERVAL);
ql_dbg(ql_dbg_init, base_vha, 0x00ef,
"Started qla2x00_timer with "
"interval=%d.\n", WATCH_INTERVAL);
* Context: Interrupt
***************************************************************************/
void
- qla2x00_timer(scsi_qla_host_t *vha)
+ qla2x00_timer(struct timer_list *t)
{
+ scsi_qla_host_t *vha = from_timer(vha, t, timer);
unsigned long cpu_flags = 0;
int start_dpc = 0;
int index;
+// SPDX-License-Identifier: GPL-2.0
#include "wilc_wfi_cfgoperations.h"
#include "host_interface.h"
#include <linux/errno.h>
last_scanned_shadow[i].time_scan = jiffies;
}
- static void remove_network_from_shadow(unsigned long arg)
+ static void remove_network_from_shadow(unsigned long unused)
{
unsigned long now = jiffies;
int i, j;
}
if (last_scanned_cnt != 0) {
- hAgingTimer.data = arg;
mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
}
}
int i;
if (last_scanned_cnt == 0) {
- hAgingTimer.data = (unsigned long)user_void;
mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
state = -1;
} else {
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ISCSI_TARGET_ERL0_H
#define ISCSI_TARGET_ERL0_H
extern int iscsit_check_pre_dataout(struct iscsi_cmd *, unsigned char *);
extern int iscsit_check_post_dataout(struct iscsi_cmd *, unsigned char *, u8);
extern void iscsit_start_time2retain_handler(struct iscsi_session *);
+ extern void iscsit_handle_time2retain_timeout(struct timer_list *t);
extern int iscsit_stop_time2retain_timer(struct iscsi_session *);
extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ISCSI_TARGET_ERL1_H
#define ISCSI_TARGET_ERL1_H
extern int iscsit_execute_cmd(struct iscsi_cmd *, int);
extern int iscsit_handle_ooo_cmdsn(struct iscsi_session *, struct iscsi_cmd *, u32);
extern void iscsit_remove_ooo_cmdsn(struct iscsi_session *, struct iscsi_ooo_cmdsn *);
+ extern void iscsit_handle_dataout_timeout(struct timer_list *t);
extern void iscsit_mod_dataout_timer(struct iscsi_cmd *);
extern void iscsit_start_dataout_timer(struct iscsi_cmd *, struct iscsi_conn *);
extern void iscsit_stop_dataout_timer(struct iscsi_cmd *);
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ISCSI_TARGET_LOGIN_H
#define ISCSI_TARGET_LOGIN_H
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
bool, bool);
extern int iscsi_target_login_thread(void *);
+ extern void iscsi_handle_login_thread_timeout(struct timer_list *t);
#endif /*** ISCSI_TARGET_LOGIN_H ***/
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef ISCSI_TARGET_UTIL_H
#define ISCSI_TARGET_UTIL_H
extern void iscsit_check_conn_usage_count(struct iscsi_conn *);
extern void iscsit_dec_conn_usage_count(struct iscsi_conn *);
extern void iscsit_inc_conn_usage_count(struct iscsi_conn *);
+ extern void iscsit_handle_nopin_response_timeout(struct timer_list *t);
extern void iscsit_mod_nopin_response_timer(struct iscsi_conn *);
extern void iscsit_start_nopin_response_timer(struct iscsi_conn *);
extern void iscsit_stop_nopin_response_timer(struct iscsi_conn *);
+ extern void iscsit_handle_nopin_timeout(struct timer_list *t);
extern void __iscsit_start_nopin_timer(struct iscsi_conn *);
extern void iscsit_start_nopin_timer(struct iscsi_conn *);
extern void iscsit_stop_nopin_timer(struct iscsi_conn *);
return tmp;
}
- if (in) {
+ if (in)
dev->in_pipe = usb_rcvbulkpipe(udev,
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ if (out)
dev->out_pipe = usb_sndbulkpipe(udev,
out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
- }
+
if (iso_in) {
dev->iso_in = &iso_in->desc;
dev->in_iso_pipe = usb_rcvisocpipe(udev,
return sg;
}
- static void sg_timeout(unsigned long _req)
+ struct sg_timeout {
+ struct timer_list timer;
+ struct usb_sg_request *req;
+ };
+
+ static void sg_timeout(struct timer_list *t)
{
- struct usb_sg_request *req = (struct usb_sg_request *) _req;
+ struct sg_timeout *timeout = from_timer(timeout, t, timer);
- usb_sg_cancel(req);
+ usb_sg_cancel(timeout->req);
}
static int perform_sglist(
{
struct usb_device *udev = testdev_to_usbdev(tdev);
int retval = 0;
- struct timer_list sg_timer;
+ struct sg_timeout timeout = {
+ .req = req,
+ };
- setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req);
+ timer_setup_on_stack(&timeout.timer, sg_timeout, 0);
while (retval == 0 && iterations-- > 0) {
retval = usb_sg_init(req, udev, pipe,
if (retval)
break;
- mod_timer(&sg_timer, jiffies +
+ mod_timer(&timeout.timer, jiffies +
msecs_to_jiffies(SIMPLE_IO_TIMEOUT));
usb_sg_wait(req);
- if (!del_timer_sync(&sg_timer))
+ if (!del_timer_sync(&timeout.timer))
retval = -ETIMEDOUT;
else
retval = req->status;
+ destroy_timer_on_stack(&timeout.timer);
/* FIXME check resulting data pattern */
int status = 0;
struct urb *urbs[param->sglen];
+ if (!param->sglen || param->iterations > UINT_MAX / param->sglen)
+ return -EINVAL;
+
memset(&context, 0, sizeof(context));
context.count = param->iterations * param->sglen;
context.dev = dev;
if (param->iterations <= 0)
return -EINVAL;
+ if (param->sglen > MAX_SGLEN)
+ return -EINVAL;
/*
* Just a bunch of test cases that every HCD is expected to handle.
*
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* ncp_fs_sb.h
*
extern void ncp_tcp_tx_proc(struct work_struct *work);
extern void ncpdgram_rcv_proc(struct work_struct *work);
extern void ncpdgram_timeout_proc(struct work_struct *work);
- extern void ncpdgram_timeout_call(unsigned long server);
+ extern void ncpdgram_timeout_call(struct timer_list *t);
extern void ncp_tcp_data_ready(struct sock* sk);
extern void ncp_tcp_write_space(struct sock* sk);
extern void ncp_tcp_error_report(struct sock* sk);
+// SPDX-License-Identifier: GPL-2.0
/*
* linux/fs/ncpfs/sock.c
*
schedule_work(&server->tx.tq);
}
- void ncpdgram_timeout_call(unsigned long v)
+ void ncpdgram_timeout_call(struct timer_list *t)
{
- struct ncp_server *server = (void*)v;
-
+ struct ncp_server *server = from_timer(server, t, timeout_tm);
+
schedule_work(&server->timeout_tq);
}
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IDE_H
#define _IDE_H
/*
extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
- extern void ide_timer_expiry(unsigned long);
+ extern void ide_timer_expiry(struct timer_list *t);
extern irqreturn_t ide_intr(int irq, void *dev_id);
extern void do_ide_request(struct request_queue *);
extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_KTHREAD_H
#define _LINUX_KTHREAD_H
/* Simple interface for creating and stopping kernel threads without mess. */
*/
struct kthread_work;
typedef void (*kthread_work_func_t)(struct kthread_work *work);
- void kthread_delayed_work_timer_fn(unsigned long __data);
+ void kthread_delayed_work_timer_fn(struct timer_list *t);
enum {
KTW_FREEZABLE = 1 << 0, /* freeze during suspend */
#define KTHREAD_DELAYED_WORK_INIT(dwork, fn) { \
.work = KTHREAD_WORK_INIT((dwork).work, (fn)), \
- .timer = __TIMER_INITIALIZER(kthread_delayed_work_timer_fn, \
- 0, (unsigned long)&(dwork), \
+ .timer = __TIMER_INITIALIZER((TIMER_FUNC_TYPE)kthread_delayed_work_timer_fn,\
+ (TIMER_DATA_TYPE)&(dwork.timer), \
TIMER_IRQSAFE), \
}
do { \
kthread_init_work(&(dwork)->work, (fn)); \
__setup_timer(&(dwork)->timer, \
- kthread_delayed_work_timer_fn, \
- (unsigned long)(dwork), \
+ (TIMER_FUNC_TYPE)kthread_delayed_work_timer_fn,\
+ (TIMER_DATA_TYPE)&(dwork)->timer, \
TIMER_IRQSAFE); \
} while (0)
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Generic RTC interface.
* This version contains the part of the user interface to the Real Time Clock
/* Some hardware can't support UIE mode */
int uie_unsupported;
+ /* Number of nsec it takes to set the RTC clock. This influences when
+ * the set ops are called. An offset:
+ * - of 0.5 s will call RTC set for wall clock time 10.0 s at 9.5 s
+ * - of 1.5 s will call RTC set for wall clock time 10.0 s at 8.5 s
+ * - of -0.5 s will call RTC set for wall clock time 10.0 s at 10.5 s
+ */
+ long set_offset_nsec;
+
bool registered;
struct nvmem_config *nvmem_config;
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
- extern int rtc_set_ntp_time(struct timespec64 now);
+ extern int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec);
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
extern int rtc_read_alarm(struct rtc_device *rtc,
struct rtc_wkalrm *alrm);
return (!(year % 4) && (year % 100)) || !(year % 400);
}
+ /* Determine if we can call to driver to set the time. Drivers can only be
+ * called to set a second aligned time value, and the field set_offset_nsec
+ * specifies how far away from the second aligned time to call the driver.
+ *
+ * This also computes 'to_set' which is the time we are trying to set, and has
+ * a zero in tv_nsecs, such that:
+ * to_set - set_delay_nsec == now +/- FUZZ
+ *
+ */
+ static inline bool rtc_tv_nsec_ok(s64 set_offset_nsec,
+ struct timespec64 *to_set,
+ const struct timespec64 *now)
+ {
+ /* Allowed error in tv_nsec, arbitarily set to 5 jiffies in ns. */
+ const unsigned long TIME_SET_NSEC_FUZZ = TICK_NSEC * 5;
+ struct timespec64 delay = {.tv_sec = 0,
+ .tv_nsec = set_offset_nsec};
+
+ *to_set = timespec64_add(*now, delay);
+
+ if (to_set->tv_nsec < TIME_SET_NSEC_FUZZ) {
+ to_set->tv_nsec = 0;
+ return true;
+ }
+
+ if (to_set->tv_nsec > NSEC_PER_SEC - TIME_SET_NSEC_FUZZ) {
+ to_set->tv_sec++;
+ to_set->tv_nsec = 0;
+ return true;
+ }
+ return false;
+ }
+
#define rtc_register_device(device) \
__rtc_register_device(THIS_MODULE, device)
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TIME_H
#define _LINUX_TIME_H
int put_itimerspec64(const struct itimerspec64 *it,
struct itimerspec __user *uit);
- #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
-
- static inline int timespec_equal(const struct timespec *a,
- const struct timespec *b)
- {
- return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
- }
-
- /*
- * lhs < rhs: return <0
- * lhs == rhs: return 0
- * lhs > rhs: return >0
- */
- static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
- {
- if (lhs->tv_sec < rhs->tv_sec)
- return -1;
- if (lhs->tv_sec > rhs->tv_sec)
- return 1;
- return lhs->tv_nsec - rhs->tv_nsec;
- }
-
- static inline int timeval_compare(const struct timeval *lhs, const struct timeval *rhs)
- {
- if (lhs->tv_sec < rhs->tv_sec)
- return -1;
- if (lhs->tv_sec > rhs->tv_sec)
- return 1;
- return lhs->tv_usec - rhs->tv_usec;
- }
-
extern time64_t mktime64(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
- /**
- * Deprecated. Use mktime64().
- */
- static inline unsigned long mktime(const unsigned int year,
- const unsigned int mon, const unsigned int day,
- const unsigned int hour, const unsigned int min,
- const unsigned int sec)
- {
- return mktime64(year, mon, day, hour, min, sec);
- }
-
- extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);
-
- /*
- * timespec_add_safe assumes both values are positive and checks
- * for overflow. It will return TIME_T_MAX if the reutrn would be
- * smaller then either of the arguments.
- */
- extern struct timespec timespec_add_safe(const struct timespec lhs,
- const struct timespec rhs);
-
-
- static inline struct timespec timespec_add(struct timespec lhs,
- struct timespec rhs)
- {
- struct timespec ts_delta;
- set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec,
- lhs.tv_nsec + rhs.tv_nsec);
- return ts_delta;
- }
-
- /*
- * sub = lhs - rhs, in normalized form
- */
- static inline struct timespec timespec_sub(struct timespec lhs,
- struct timespec rhs)
- {
- struct timespec ts_delta;
- set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec,
- lhs.tv_nsec - rhs.tv_nsec);
- return ts_delta;
- }
-
- /*
- * Returns true if the timespec is norm, false if denorm:
- */
- static inline bool timespec_valid(const struct timespec *ts)
- {
- /* Dates before 1970 are bogus */
- if (ts->tv_sec < 0)
- return false;
- /* Can't have more nanoseconds then a second */
- if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
- return false;
- return true;
- }
-
- static inline bool timespec_valid_strict(const struct timespec *ts)
- {
- if (!timespec_valid(ts))
- return false;
- /* Disallow values that could overflow ktime_t */
- if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
- return false;
- return true;
- }
-
- static inline bool timeval_valid(const struct timeval *tv)
- {
- /* Dates before 1970 are bogus */
- if (tv->tv_sec < 0)
- return false;
-
- /* Can't have more microseconds then a second */
- if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
- return false;
-
- return true;
- }
-
- extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
-
- /*
- * Validates if a timespec/timeval used to inject a time offset is valid.
- * Offsets can be postive or negative. The value of the timeval/timespec
- * is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must
- * always be non-negative.
- */
- static inline bool timeval_inject_offset_valid(const struct timeval *tv)
- {
- /* We don't check the tv_sec as it can be positive or negative */
-
- /* Can't have more microseconds then a second */
- if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
- return false;
- return true;
- }
-
- static inline bool timespec_inject_offset_valid(const struct timespec *ts)
- {
- /* We don't check the tv_sec as it can be positive or negative */
-
- /* Can't have more nanoseconds then a second */
- if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
- return false;
- return true;
- }
-
/* Some architectures do not supply their own clocksource.
* This is mainly the case in architectures that get their
* inter-tick times by reading the counter on their interval
void time64_to_tm(time64_t totalsecs, int offset, struct tm *result);
- /**
- * time_to_tm - converts the calendar time to local broken-down time
- *
- * @totalsecs the number of seconds elapsed since 00:00:00 on January 1, 1970,
- * Coordinated Universal Time (UTC).
- * @offset offset seconds adding to totalsecs.
- * @result pointer to struct tm variable to receive broken-down time
- */
- static inline void time_to_tm(time_t totalsecs, int offset, struct tm *result)
- {
- time64_to_tm(totalsecs, offset, result);
- }
-
- /**
- * timespec_to_ns - Convert timespec to nanoseconds
- * @ts: pointer to the timespec variable to be converted
- *
- * Returns the scalar nanosecond representation of the timespec
- * parameter.
- */
- static inline s64 timespec_to_ns(const struct timespec *ts)
- {
- return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
- }
-
- /**
- * timeval_to_ns - Convert timeval to nanoseconds
- * @ts: pointer to the timeval variable to be converted
- *
- * Returns the scalar nanosecond representation of the timeval
- * parameter.
- */
- static inline s64 timeval_to_ns(const struct timeval *tv)
- {
- return ((s64) tv->tv_sec * NSEC_PER_SEC) +
- tv->tv_usec * NSEC_PER_USEC;
- }
-
- /**
- * ns_to_timespec - Convert nanoseconds to timespec
- * @nsec: the nanoseconds value to be converted
- *
- * Returns the timespec representation of the nsec parameter.
- */
- extern struct timespec ns_to_timespec(const s64 nsec);
-
- /**
- * ns_to_timeval - Convert nanoseconds to timeval
- * @nsec: the nanoseconds value to be converted
- *
- * Returns the timeval representation of the nsec parameter.
- */
- extern struct timeval ns_to_timeval(const s64 nsec);
-
- /**
- * timespec_add_ns - Adds nanoseconds to a timespec
- * @a: pointer to timespec to be incremented
- * @ns: unsigned nanoseconds value to be added
- *
- * This must always be inlined because its used from the x86-64 vdso,
- * which cannot call other kernel functions.
- */
- static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
- {
- a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
- a->tv_nsec = ns;
- }
+ # include <linux/time32.h>
static inline bool itimerspec64_valid(const struct itimerspec64 *its)
{
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TIME64_H
#define _LINUX_TIME64_H
typedef __s64 time64_t;
typedef __u64 timeu64_t;
- /*
- * This wants to go into uapi/linux/time.h once we agreed about the
- * userspace interfaces.
- */
#if __BITS_PER_LONG == 64
+ /* this trick allows us to optimize out timespec64_to_timespec */
# define timespec64 timespec
#define itimerspec64 itimerspec
#else
#define KTIME_MAX ((s64)~((u64)1 << 63))
#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
- #if __BITS_PER_LONG == 64
-
- static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
- {
- return ts64;
- }
-
- static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
- {
- return ts;
- }
-
- static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64)
- {
- return *its64;
- }
-
- static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its)
- {
- return *its;
- }
-
- # define timespec64_equal timespec_equal
- # define timespec64_compare timespec_compare
- # define set_normalized_timespec64 set_normalized_timespec
- # define timespec64_add timespec_add
- # define timespec64_sub timespec_sub
- # define timespec64_valid timespec_valid
- # define timespec64_valid_strict timespec_valid_strict
- # define timespec64_to_ns timespec_to_ns
- # define ns_to_timespec64 ns_to_timespec
- # define timespec64_add_ns timespec_add_ns
-
- #else
-
- static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
- {
- struct timespec ret;
-
- ret.tv_sec = (time_t)ts64.tv_sec;
- ret.tv_nsec = ts64.tv_nsec;
- return ret;
- }
-
- static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
- {
- struct timespec64 ret;
-
- ret.tv_sec = ts.tv_sec;
- ret.tv_nsec = ts.tv_nsec;
- return ret;
- }
-
- static inline struct itimerspec itimerspec64_to_itimerspec(struct itimerspec64 *its64)
- {
- struct itimerspec ret;
-
- ret.it_interval = timespec64_to_timespec(its64->it_interval);
- ret.it_value = timespec64_to_timespec(its64->it_value);
- return ret;
- }
-
- static inline struct itimerspec64 itimerspec_to_itimerspec64(struct itimerspec *its)
- {
- struct itimerspec64 ret;
-
- ret.it_interval = timespec_to_timespec64(its->it_interval);
- ret.it_value = timespec_to_timespec64(its->it_value);
- return ret;
- }
-
static inline int timespec64_equal(const struct timespec64 *a,
const struct timespec64 *b)
{
a->tv_nsec = ns;
}
- #endif
-
/*
* timespec64_add_safe assumes both values are positive and checks for
* overflow. It will return TIME64_MAX in case of overflow.
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* You SHOULD NOT be including this unless you're vsyscall
* handling code or timekeeping internal code!
/**
* struct tk_read_base - base structure for timekeeping readout
* @clock: Current clocksource used for timekeeping.
- * @read: Read function of @clock
* @mask: Bitmask for two's complement subtraction of non 64bit clocks
* @cycle_last: @clock cycle value at last update
* @mult: (NTP adjusted) multiplier for scaled math conversion
* @shift: Shift value for scaled math conversion
* @xtime_nsec: Shifted (fractional) nano seconds offset for readout
* @base: ktime_t (nanoseconds) base time for readout
+ * @base_real: Nanoseconds base value for clock REALTIME readout
*
* This struct has size 56 byte on 64 bit. Together with a seqcount it
* occupies a single 64byte cache line.
*
* The struct is separate from struct timekeeper as it is also used
* for a fast NMI safe accessors.
+ *
+ * @base_real is for the fast NMI safe accessor to allow reading clock
+ * realtime from any context.
*/
struct tk_read_base {
struct clocksource *clock;
u32 shift;
u64 xtime_nsec;
ktime_t base;
+ u64 base_real;
};
/**
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TIMEKEEPING_H
#define _LINUX_TIMEKEEPING_H
/*
* Get and set timeofday
*/
- extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday64(const struct timespec64 *ts);
extern int do_sys_settimeofday64(const struct timespec64 *tv,
const struct timezone *tz);
/*
* Kernel time accessors
*/
- unsigned long get_seconds(void);
struct timespec64 current_kernel_time64(void);
- /* does not take xtime_lock */
- struct timespec __current_kernel_time(void);
-
- static inline struct timespec current_kernel_time(void)
- {
- struct timespec64 now = current_kernel_time64();
-
- return timespec64_to_timespec(now);
- }
/*
- * timespec based interfaces
+ * timespec64 based interfaces
*/
struct timespec64 get_monotonic_coarse64(void);
extern void getrawmonotonic64(struct timespec64 *ts);
extern void getnstimeofday64(struct timespec64 *tv);
extern void getboottime64(struct timespec64 *ts);
- #if BITS_PER_LONG == 64
- /**
- * Deprecated. Use do_settimeofday64().
- */
- static inline int do_settimeofday(const struct timespec *ts)
- {
- return do_settimeofday64(ts);
- }
-
- static inline int __getnstimeofday(struct timespec *ts)
- {
- return __getnstimeofday64(ts);
- }
-
- static inline void getnstimeofday(struct timespec *ts)
- {
- getnstimeofday64(ts);
- }
-
- static inline void ktime_get_ts(struct timespec *ts)
- {
- ktime_get_ts64(ts);
- }
-
- static inline void ktime_get_real_ts(struct timespec *ts)
- {
- getnstimeofday64(ts);
- }
-
- static inline void getrawmonotonic(struct timespec *ts)
- {
- getrawmonotonic64(ts);
- }
-
- static inline struct timespec get_monotonic_coarse(void)
- {
- return get_monotonic_coarse64();
- }
-
- static inline void getboottime(struct timespec *ts)
- {
- return getboottime64(ts);
- }
- #else
- /**
- * Deprecated. Use do_settimeofday64().
- */
- static inline int do_settimeofday(const struct timespec *ts)
- {
- struct timespec64 ts64;
-
- ts64 = timespec_to_timespec64(*ts);
- return do_settimeofday64(&ts64);
- }
-
- static inline int __getnstimeofday(struct timespec *ts)
- {
- struct timespec64 ts64;
- int ret = __getnstimeofday64(&ts64);
-
- *ts = timespec64_to_timespec(ts64);
- return ret;
- }
-
- static inline void getnstimeofday(struct timespec *ts)
- {
- struct timespec64 ts64;
-
- getnstimeofday64(&ts64);
- *ts = timespec64_to_timespec(ts64);
- }
-
- static inline void ktime_get_ts(struct timespec *ts)
- {
- struct timespec64 ts64;
-
- ktime_get_ts64(&ts64);
- *ts = timespec64_to_timespec(ts64);
- }
-
- static inline void ktime_get_real_ts(struct timespec *ts)
- {
- struct timespec64 ts64;
-
- getnstimeofday64(&ts64);
- *ts = timespec64_to_timespec(ts64);
- }
-
- static inline void getrawmonotonic(struct timespec *ts)
- {
- struct timespec64 ts64;
-
- getrawmonotonic64(&ts64);
- *ts = timespec64_to_timespec(ts64);
- }
-
- static inline struct timespec get_monotonic_coarse(void)
- {
- return timespec64_to_timespec(get_monotonic_coarse64());
- }
-
- static inline void getboottime(struct timespec *ts)
- {
- struct timespec64 ts64;
-
- getboottime64(&ts64);
- *ts = timespec64_to_timespec(ts64);
- }
- #endif
-
#define ktime_get_real_ts64(ts) getnstimeofday64(ts)
/*
extern u64 ktime_get_mono_fast_ns(void);
extern u64 ktime_get_raw_fast_ns(void);
extern u64 ktime_get_boot_fast_ns(void);
+ extern u64 ktime_get_real_fast_ns(void);
/*
- * Timespec interfaces utilizing the ktime based ones
+ * timespec64 interfaces utilizing the ktime based ones
*/
- static inline void get_monotonic_boottime(struct timespec *ts)
- {
- *ts = ktime_to_timespec(ktime_get_boottime());
- }
-
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_boottime());
}
- static inline void timekeeping_clocktai(struct timespec *ts)
- {
- *ts = ktime_to_timespec(ktime_get_clocktai());
- }
-
static inline void timekeeping_clocktai64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_clocktai());
*/
extern int persistent_clock_is_local;
- extern void read_persistent_clock(struct timespec *ts);
extern void read_persistent_clock64(struct timespec64 *ts);
extern void read_boot_clock64(struct timespec64 *ts);
- extern int update_persistent_clock(struct timespec now);
extern int update_persistent_clock64(struct timespec64 now);
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_TIMER_H
#define _LINUX_TIMER_H
#define TIMER_TRACE_FLAGMASK (TIMER_MIGRATING | TIMER_DEFERRABLE | TIMER_PINNED | TIMER_IRQSAFE)
- #define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \
+ #define TIMER_DATA_TYPE unsigned long
+ #define TIMER_FUNC_TYPE void (*)(TIMER_DATA_TYPE)
+
+ #define __TIMER_INITIALIZER(_function, _data, _flags) { \
.entry = { .next = TIMER_ENTRY_STATIC }, \
.function = (_function), \
- .expires = (_expires), \
.data = (_data), \
.flags = (_flags), \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__FILE__ ":" __stringify(__LINE__)) \
}
- #define TIMER_INITIALIZER(_function, _expires, _data) \
- __TIMER_INITIALIZER((_function), (_expires), (_data), 0)
-
- #define TIMER_PINNED_INITIALIZER(_function, _expires, _data) \
- __TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_PINNED)
-
- #define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) \
- __TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_DEFERRABLE)
-
- #define TIMER_PINNED_DEFERRED_INITIALIZER(_function, _expires, _data) \
- __TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_DEFERRABLE | TIMER_PINNED)
-
- #define DEFINE_TIMER(_name, _function, _expires, _data) \
+ #define DEFINE_TIMER(_name, _function) \
struct timer_list _name = \
- TIMER_INITIALIZER(_function, _expires, _data)
+ __TIMER_INITIALIZER((TIMER_FUNC_TYPE)_function, 0, 0)
void init_timer_key(struct timer_list *timer, unsigned int flags,
const char *name, struct lock_class_key *key);
#define init_timer(timer) \
__init_timer((timer), 0)
- #define init_timer_pinned(timer) \
- __init_timer((timer), TIMER_PINNED)
- #define init_timer_deferrable(timer) \
- __init_timer((timer), TIMER_DEFERRABLE)
- #define init_timer_pinned_deferrable(timer) \
- __init_timer((timer), TIMER_DEFERRABLE | TIMER_PINNED)
- #define init_timer_on_stack(timer) \
- __init_timer_on_stack((timer), 0)
#define __setup_timer(_timer, _fn, _data, _flags) \
do { \
#define setup_pinned_deferrable_timer_on_stack(timer, fn, data) \
__setup_timer_on_stack((timer), (fn), (data), TIMER_DEFERRABLE | TIMER_PINNED)
- #define TIMER_DATA_TYPE unsigned long
- #define TIMER_FUNC_TYPE void (*)(TIMER_DATA_TYPE)
-
+ #ifndef CONFIG_LOCKDEP
static inline void timer_setup(struct timer_list *timer,
void (*callback)(struct timer_list *),
unsigned int flags)
(TIMER_DATA_TYPE)timer, flags);
}
+ static inline void timer_setup_on_stack(struct timer_list *timer,
+ void (*callback)(struct timer_list *),
+ unsigned int flags)
+ {
+ __setup_timer_on_stack(timer, (TIMER_FUNC_TYPE)callback,
+ (TIMER_DATA_TYPE)timer, flags);
+ }
+ #else
+ /*
+ * Under LOCKDEP, the timer lock_class_key (set up in __init_timer) needs
+ * to be tied to the caller's context, so an inline (above) won't work. We
+ * do want to keep the inline for argument type checking, though.
+ */
+ # define timer_setup(timer, callback, flags) \
+ __setup_timer((timer), (TIMER_FUNC_TYPE)(callback), \
+ (TIMER_DATA_TYPE)(timer), (flags))
+ # define timer_setup_on_stack(timer, callback, flags) \
+ __setup_timer_on_stack((timer), \
+ (TIMER_FUNC_TYPE)(callback), \
+ (TIMER_DATA_TYPE)(timer), (flags))
+ #endif
+
#define from_timer(var, callback_timer, timer_fieldname) \
container_of(callback_timer, typeof(*var), timer_fieldname)
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);
/*
* The jiffies value which is added to now, when there is no timer
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* workqueue.h --- work queue handling for Linux.
*/
struct work_struct;
typedef void (*work_func_t)(struct work_struct *work);
- void delayed_work_timer_fn(unsigned long __data);
+ void delayed_work_timer_fn(struct timer_list *t);
/*
* The first word is the work queue pointer and the flags rolled into
#define __DELAYED_WORK_INITIALIZER(n, f, tflags) { \
.work = __WORK_INITIALIZER((n).work, (f)), \
- .timer = __TIMER_INITIALIZER(delayed_work_timer_fn, \
- 0, (unsigned long)&(n), \
+ .timer = __TIMER_INITIALIZER((TIMER_FUNC_TYPE)delayed_work_timer_fn,\
+ (TIMER_DATA_TYPE)&(n.timer), \
(tflags) | TIMER_IRQSAFE), \
}
#define __INIT_DELAYED_WORK(_work, _func, _tflags) \
do { \
INIT_WORK(&(_work)->work, (_func)); \
- __setup_timer(&(_work)->timer, delayed_work_timer_fn, \
- (unsigned long)(_work), \
+ __setup_timer(&(_work)->timer, \
+ (TIMER_FUNC_TYPE)delayed_work_timer_fn, \
+ (TIMER_DATA_TYPE)&(_work)->timer, \
(_tflags) | TIMER_IRQSAFE); \
} while (0)
do { \
INIT_WORK_ONSTACK(&(_work)->work, (_func)); \
__setup_timer_on_stack(&(_work)->timer, \
- delayed_work_timer_fn, \
- (unsigned long)(_work), \
+ (TIMER_FUNC_TYPE)delayed_work_timer_fn,\
+ (TIMER_DATA_TYPE)&(_work)->timer,\
(_tflags) | TIMER_IRQSAFE); \
} while (0)
+// SPDX-License-Identifier: GPL-2.0
/*
* linux/kernel/irq/spurious.c
*
#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
static void poll_spurious_irqs(unsigned long dummy);
- static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0);
+ static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs);
static int irq_poll_cpu;
static atomic_t irq_poll_active;
+// SPDX-License-Identifier: GPL-2.0
/*
* NTP state machine interfaces and logic.
*
return leap;
}
+ static void sync_hw_clock(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(sync_work, sync_hw_clock);
+
+ static void sched_sync_hw_clock(struct timespec64 now,
+ unsigned long target_nsec, bool fail)
+
+ {
+ struct timespec64 next;
+
+ getnstimeofday64(&next);
+ if (!fail)
+ next.tv_sec = 659;
+ else {
+ /*
+ * Try again as soon as possible. Delaying long periods
+ * decreases the accuracy of the work queue timer. Due to this
+ * the algorithm is very likely to require a short-sleep retry
+ * after the above long sleep to synchronize ts_nsec.
+ */
+ next.tv_sec = 0;
+ }
+
+ /* Compute the needed delay that will get to tv_nsec == target_nsec */
+ next.tv_nsec = target_nsec - next.tv_nsec;
+ if (next.tv_nsec <= 0)
+ next.tv_nsec += NSEC_PER_SEC;
+ if (next.tv_nsec >= NSEC_PER_SEC) {
+ next.tv_sec++;
+ next.tv_nsec -= NSEC_PER_SEC;
+ }
+
+ queue_delayed_work(system_power_efficient_wq, &sync_work,
+ timespec64_to_jiffies(&next));
+ }
+
+ static void sync_rtc_clock(void)
+ {
+ unsigned long target_nsec;
+ struct timespec64 adjust, now;
+ int rc;
+
+ if (!IS_ENABLED(CONFIG_RTC_SYSTOHC))
+ return;
+
+ getnstimeofday64(&now);
+
+ adjust = now;
+ if (persistent_clock_is_local)
+ adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
+
+ /*
+ * The current RTC in use will provide the target_nsec it wants to be
+ * called at, and does rtc_tv_nsec_ok internally.
+ */
+ rc = rtc_set_ntp_time(adjust, &target_nsec);
+ if (rc == -ENODEV)
+ return;
+
+ sched_sync_hw_clock(now, target_nsec, rc);
+ }
+
#ifdef CONFIG_GENERIC_CMOS_UPDATE
int __weak update_persistent_clock(struct timespec now)
{
}
#endif
- #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
- static void sync_cmos_clock(struct work_struct *work);
-
- static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
-
- static void sync_cmos_clock(struct work_struct *work)
+ static bool sync_cmos_clock(void)
{
+ static bool no_cmos;
struct timespec64 now;
- struct timespec64 next;
- int fail = 1;
+ struct timespec64 adjust;
+ int rc = -EPROTO;
+ long target_nsec = NSEC_PER_SEC / 2;
+
+ if (!IS_ENABLED(CONFIG_GENERIC_CMOS_UPDATE))
+ return false;
+
+ if (no_cmos)
+ return false;
/*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- * This code is run on a timer. If the clock is set, that timer
- * may not expire at the correct time. Thus, we adjust...
- * We want the clock to be within a couple of ticks from the target.
+ * Historically update_persistent_clock64() has followed x86
+ * semantics, which match the MC146818A/etc RTC. This RTC will store
+ * 'adjust' and then in .5s it will advance once second.
+ *
+ * Architectures are strongly encouraged to use rtclib and not
+ * implement this legacy API.
*/
- if (!ntp_synced()) {
- /*
- * Not synced, exit, do not restart a timer (if one is
- * running, let it run out).
- */
- return;
- }
-
getnstimeofday64(&now);
- if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
- struct timespec64 adjust = now;
-
- fail = -ENODEV;
+ if (rtc_tv_nsec_ok(-1 * target_nsec, &adjust, &now)) {
if (persistent_clock_is_local)
adjust.tv_sec -= (sys_tz.tz_minuteswest * 60);
- #ifdef CONFIG_GENERIC_CMOS_UPDATE
- fail = update_persistent_clock64(adjust);
- #endif
-
- #ifdef CONFIG_RTC_SYSTOHC
- if (fail == -ENODEV)
- fail = rtc_set_ntp_time(adjust);
- #endif
+ rc = update_persistent_clock64(adjust);
+ /*
+ * The machine does not support update_persistent_clock64 even
+ * though it defines CONFIG_GENERIC_CMOS_UPDATE.
+ */
+ if (rc == -ENODEV) {
+ no_cmos = true;
+ return false;
+ }
}
- next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
- if (next.tv_nsec <= 0)
- next.tv_nsec += NSEC_PER_SEC;
+ sched_sync_hw_clock(now, target_nsec, rc);
+ return true;
+ }
- if (!fail || fail == -ENODEV)
- next.tv_sec = 659;
- else
- next.tv_sec = 0;
+ /*
+ * If we have an externally synchronized Linux clock, then update RTC clock
+ * accordingly every ~11 minutes. Generally RTCs can only store second
+ * precision, but many RTCs will adjust the phase of their second tick to
+ * match the moment of update. This infrastructure arranges to call to the RTC
+ * set at the correct moment to phase synchronize the RTC second tick over
+ * with the kernel clock.
+ */
+ static void sync_hw_clock(struct work_struct *work)
+ {
+ if (!ntp_synced())
+ return;
- if (next.tv_nsec >= NSEC_PER_SEC) {
- next.tv_sec++;
- next.tv_nsec -= NSEC_PER_SEC;
- }
- queue_delayed_work(system_power_efficient_wq,
- &sync_cmos_work, timespec64_to_jiffies(&next));
+ if (sync_cmos_clock())
+ return;
+
+ sync_rtc_clock();
}
void ntp_notify_cmos_timer(void)
{
- queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
- }
-
- #else
- void ntp_notify_cmos_timer(void) { }
- #endif
+ if (!ntp_synced())
+ return;
+ if (IS_ENABLED(CONFIG_GENERIC_CMOS_UPDATE) ||
+ IS_ENABLED(CONFIG_RTC_SYSTOHC))
+ queue_delayed_work(system_power_efficient_wq, &sync_work, 0);
+ }
/*
* Propagate a new txc->status value into the NTP state:
}
-
- /**
- * ntp_validate_timex - Ensures the timex is ok for use in do_adjtimex
- */
- int ntp_validate_timex(struct timex *txc)
- {
- if (txc->modes & ADJ_ADJTIME) {
- /* singleshot must not be used with any other mode bits */
- if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
- return -EINVAL;
- if (!(txc->modes & ADJ_OFFSET_READONLY) &&
- !capable(CAP_SYS_TIME))
- return -EPERM;
- } else {
- /* In order to modify anything, you gotta be super-user! */
- if (txc->modes && !capable(CAP_SYS_TIME))
- return -EPERM;
- /*
- * if the quartz is off by more than 10% then
- * something is VERY wrong!
- */
- if (txc->modes & ADJ_TICK &&
- (txc->tick < 900000/USER_HZ ||
- txc->tick > 1100000/USER_HZ))
- return -EINVAL;
- }
-
- if (txc->modes & ADJ_SETOFFSET) {
- /* In order to inject time, you gotta be super-user! */
- if (!capable(CAP_SYS_TIME))
- return -EPERM;
-
- if (txc->modes & ADJ_NANO) {
- struct timespec ts;
-
- ts.tv_sec = txc->time.tv_sec;
- ts.tv_nsec = txc->time.tv_usec;
- if (!timespec_inject_offset_valid(&ts))
- return -EINVAL;
-
- } else {
- if (!timeval_inject_offset_valid(&txc->time))
- return -EINVAL;
- }
- }
-
- /*
- * Check for potential multiplication overflows that can
- * only happen on 64-bit systems:
- */
- if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) {
- if (LLONG_MIN / PPM_SCALE > txc->freq)
- return -EINVAL;
- if (LLONG_MAX / PPM_SCALE < txc->freq)
- return -EINVAL;
- }
-
- return 0;
- }
-
-
/*
* adjtimex mainly allows reading (and writing, if superuser) of
* kernel time-keeping variables. used by xntpd.
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_NTP_INTERNAL_H
#define _LINUX_NTP_INTERNAL_H
extern u64 ntp_tick_length(void);
extern ktime_t ntp_get_next_leap(void);
extern int second_overflow(time64_t secs);
- extern int ntp_validate_timex(struct timex *);
extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *);
extern void __hardpps(const struct timespec64 *, const struct timespec64 *);
#endif /* _LINUX_NTP_INTERNAL_H */
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _KERNEL_TIME_TIMEKEEPING_H
#define _KERNEL_TIME_TIMEKEEPING_H
/*
extern int timekeeping_valid_for_hres(void);
extern u64 timekeeping_max_deferment(void);
- extern int timekeeping_inject_offset(struct timespec *ts);
+ extern void timekeeping_warp_clock(void);
extern int timekeeping_suspend(void);
extern void timekeeping_resume(void);
* attach_mutex to avoid changing binding state while
* worker_attach_to_pool() is in progress.
*/
+ POOL_MANAGER_ACTIVE = 1 << 0, /* being managed */
POOL_DISASSOCIATED = 1 << 2, /* cpu can't serve workers */
/* worker flags */
/* L: hash of busy workers */
/* see manage_workers() for details on the two manager mutexes */
- struct mutex manager_arb; /* manager arbitration */
struct worker *manager; /* L: purely informational */
struct mutex attach_mutex; /* attach/detach exclusion */
struct list_head workers; /* A: attached workers */
static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list */
static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */
+static DECLARE_WAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go away */
static LIST_HEAD(workqueues); /* PR: list of all workqueues */
static bool workqueue_freezing; /* PL: have wqs started freezing? */
/* Do we have too many workers and should some go away? */
static bool too_many_workers(struct worker_pool *pool)
{
- bool managing = mutex_is_locked(&pool->manager_arb);
+ bool managing = pool->flags & POOL_MANAGER_ACTIVE;
int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
int nr_busy = pool->nr_workers - nr_idle;
}
EXPORT_SYMBOL(queue_work_on);
- void delayed_work_timer_fn(unsigned long __data)
+ void delayed_work_timer_fn(struct timer_list *t)
{
- struct delayed_work *dwork = (struct delayed_work *)__data;
+ struct delayed_work *dwork = from_timer(dwork, t, timer);
/* should have been called from irqsafe timer with irq already off */
__queue_work(dwork->cpu, dwork->wq, &dwork->work);
struct work_struct *work = &dwork->work;
WARN_ON_ONCE(!wq);
- WARN_ON_ONCE(timer->function != delayed_work_timer_fn ||
- timer->data != (unsigned long)dwork);
+ WARN_ON_ONCE(timer->function != (TIMER_FUNC_TYPE)delayed_work_timer_fn);
WARN_ON_ONCE(timer_pending(timer));
WARN_ON_ONCE(!list_empty(&work->entry));
wake_up_process(worker->task);
}
- static void idle_worker_timeout(unsigned long __pool)
+ static void idle_worker_timeout(struct timer_list *t)
{
- struct worker_pool *pool = (void *)__pool;
+ struct worker_pool *pool = from_timer(pool, t, idle_timer);
spin_lock_irq(&pool->lock);
}
}
- static void pool_mayday_timeout(unsigned long __pool)
+ static void pool_mayday_timeout(struct timer_list *t)
{
- struct worker_pool *pool = (void *)__pool;
+ struct worker_pool *pool = from_timer(pool, t, mayday_timer);
struct work_struct *work;
spin_lock_irq(&pool->lock);
{
struct worker_pool *pool = worker->pool;
- /*
- * Anyone who successfully grabs manager_arb wins the arbitration
- * and becomes the manager. mutex_trylock() on pool->manager_arb
- * failure while holding pool->lock reliably indicates that someone
- * else is managing the pool and the worker which failed trylock
- * can proceed to executing work items. This means that anyone
- * grabbing manager_arb is responsible for actually performing
- * manager duties. If manager_arb is grabbed and released without
- * actual management, the pool may stall indefinitely.
- */
- if (!mutex_trylock(&pool->manager_arb))
+ if (pool->flags & POOL_MANAGER_ACTIVE)
return false;
+
+ pool->flags |= POOL_MANAGER_ACTIVE;
pool->manager = worker;
maybe_create_worker(pool);
pool->manager = NULL;
- mutex_unlock(&pool->manager_arb);
+ pool->flags &= ~POOL_MANAGER_ACTIVE;
+ wake_up(&wq_manager_wait);
return true;
}
INIT_LIST_HEAD(&pool->idle_list);
hash_init(pool->busy_hash);
- setup_deferrable_timer(&pool->idle_timer, idle_worker_timeout,
- (unsigned long)pool);
+ timer_setup(&pool->idle_timer, idle_worker_timeout, TIMER_DEFERRABLE);
- setup_timer(&pool->mayday_timer, pool_mayday_timeout,
- (unsigned long)pool);
+ timer_setup(&pool->mayday_timer, pool_mayday_timeout, 0);
- mutex_init(&pool->manager_arb);
mutex_init(&pool->attach_mutex);
INIT_LIST_HEAD(&pool->workers);
hash_del(&pool->hash_node);
/*
- * Become the manager and destroy all workers. Grabbing
- * manager_arb prevents @pool's workers from blocking on
- * attach_mutex.
+ * Become the manager and destroy all workers. This prevents
+ * @pool's workers from blocking on attach_mutex. We're the last
+ * manager and @pool gets freed with the flag set.
*/
- mutex_lock(&pool->manager_arb);
-
spin_lock_irq(&pool->lock);
+ wait_event_lock_irq(wq_manager_wait,
+ !(pool->flags & POOL_MANAGER_ACTIVE), pool->lock);
+ pool->flags |= POOL_MANAGER_ACTIVE;
+
while ((worker = first_idle_worker(pool)))
destroy_worker(worker);
WARN_ON(pool->nr_workers || pool->nr_idle);
if (pool->detach_completion)
wait_for_completion(pool->detach_completion);
- mutex_unlock(&pool->manager_arb);
-
/* shut down the timers */
del_timer_sync(&pool->idle_timer);
del_timer_sync(&pool->mayday_timer);
*/
#ifdef CONFIG_WQ_WATCHDOG
- static void wq_watchdog_timer_fn(unsigned long data);
-
static unsigned long wq_watchdog_thresh = 30;
- static struct timer_list wq_watchdog_timer =
- TIMER_DEFERRED_INITIALIZER(wq_watchdog_timer_fn, 0, 0);
+ static struct timer_list wq_watchdog_timer;
static unsigned long wq_watchdog_touched = INITIAL_JIFFIES;
static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES;
per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
}
- static void wq_watchdog_timer_fn(unsigned long data)
+ static void wq_watchdog_timer_fn(struct timer_list *unused)
{
unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
bool lockup_detected = false;
static void wq_watchdog_init(void)
{
+ timer_setup(&wq_watchdog_timer, wq_watchdog_timer_fn, TIMER_DEFERRABLE);
wq_watchdog_set_thresh(wq_watchdog_thresh);
}
+// SPDX-License-Identifier: GPL-2.0
/*
* This is a maximally equidistributed combined Tausworthe generator
* based on code from GNU Scientific Library 1.5 (30 Jun 2004)
static void __prandom_timer(unsigned long dontcare);
- static DEFINE_TIMER(seed_timer, __prandom_timer, 0, 0);
+ static DEFINE_TIMER(seed_timer, __prandom_timer);
static void __prandom_timer(unsigned long dontcare)
{
static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
unsigned long event, void *dev);
static void mpc_timer_refresh(void);
-static void mpc_cache_check(unsigned long checking_time);
+static void mpc_cache_check(struct timer_list *unused);
static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
0xaa, 0xaa, 0x03,
struct mpoa_client *mpcs = NULL; /* FIXME */
static struct atm_mpoa_qos *qos_head = NULL;
- static DEFINE_TIMER(mpc_timer, NULL, 0, 0);
+ static DEFINE_TIMER(mpc_timer, NULL);
static struct mpoa_client *find_mpc_by_itfnum(int itf)
int err;
if (mpcs == NULL) {
- init_timer(&mpc_timer);
mpc_timer_refresh();
/* This lets us now how our LECs are doing */
msg_to_mpoad(msg, mpc);
}
+static unsigned long checking_time;
+
static void mpc_timer_refresh(void)
{
mpc_timer.expires = jiffies + (MPC_P2 * HZ);
- mpc_timer.data = mpc_timer.expires;
- mpc_timer.function = mpc_cache_check;
+ checking_time = mpc_timer.expires;
+ mpc_timer.function = (TIMER_FUNC_TYPE)mpc_cache_check;
add_timer(&mpc_timer);
}
-static void mpc_cache_check(unsigned long checking_time)
+static void mpc_cache_check(struct timer_list *unused)
{
struct mpoa_client *mpc = mpcs;
static unsigned long previous_resolving_check_time;
static unsigned int dn_rt_hash_mask;
static struct timer_list dn_route_timer;
- static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush, 0, 0);
+ static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush);
int decnet_dst_gc_interval = 2;
static struct dst_ops dn_dst_ops = {
dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
- dst_use(&rth->dst, now);
+ dst_hold_and_use(&rth->dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
dst_release_immediate(&rt->dst);
rcu_assign_pointer(rt->dst.dn_next, dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
- dst_use(&rt->dst, now);
+ dst_hold_and_use(&rt->dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
*rp = rt;
return 0;
(flp->flowidn_mark == rt->fld.flowidn_mark) &&
dn_is_output_route(rt) &&
(rt->fld.flowidn_oif == flp->flowidn_oif)) {
- dst_use(&rt->dst, jiffies);
+ dst_hold_and_use(&rt->dst, jiffies);
rcu_read_unlock_bh();
*pprt = &rt->dst;
return 0;
(rt->fld.flowidn_oif == 0) &&
(rt->fld.flowidn_mark == skb->mark) &&
(rt->fld.flowidn_iif == cb->iif)) {
- dst_use(&rt->dst, jiffies);
+ dst_hold_and_use(&rt->dst, jiffies);
rcu_read_unlock();
skb_dst_set(skb, (struct dst_entry *)rt);
return 0;
static struct ip6_flowlabel __rcu *fl_ht[FL_HASH_MASK+1];
static void ip6_fl_gc(unsigned long dummy);
- static DEFINE_TIMER(ip6_fl_gc_timer, ip6_fl_gc, 0, 0);
+ static DEFINE_TIMER(ip6_fl_gc_timer, ip6_fl_gc);
/* FL hash table lock: it protects only of GC */
}
opt_space->dst1opt = fopt->dst1opt;
opt_space->opt_flen = fopt->opt_flen;
+ opt_space->tot_len = fopt->tot_len;
return opt_space;
}
EXPORT_SYMBOL_GPL(fl6_merge_options);
spin_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
- static void ip_vs_conn_expire(unsigned long data);
+ static void ip_vs_conn_expire(struct timer_list *t);
/*
* Returns hash value for IPVS connection entry
hlist_add_head_rcu(&cp->c_list, &ip_vs_conn_tab[hash]);
ret = 1;
} else {
- pr_err("%s(): request for already hashed, called from %pF\n",
+ pr_err("%s(): request for already hashed, called from %pS\n",
__func__, __builtin_return_address(0));
ret = 0;
}
static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp)
{
__ip_vs_conn_put(cp);
- ip_vs_conn_expire((unsigned long)cp);
+ ip_vs_conn_expire(&cp->timer);
}
/*
kmem_cache_free(ip_vs_conn_cachep, cp);
}
- static void ip_vs_conn_expire(unsigned long data)
+ static void ip_vs_conn_expire(struct timer_list *t)
{
- struct ip_vs_conn *cp = (struct ip_vs_conn *)data;
+ struct ip_vs_conn *cp = from_timer(cp, t, timer);
struct netns_ipvs *ipvs = cp->ipvs;
/*
}
INIT_HLIST_NODE(&cp->c_list);
- setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
+ timer_setup(&cp->timer, ip_vs_conn_expire, 0);
cp->ipvs = ipvs;
cp->af = p->af;
cp->daf = dest_af;
unsigned int hash;
if (svc->flags & IP_VS_SVC_F_HASHED) {
- pr_err("%s(): request for already hashed, called from %pF\n",
+ pr_err("%s(): request for already hashed, called from %pS\n",
__func__, __builtin_return_address(0));
return 0;
}
static int ip_vs_svc_unhash(struct ip_vs_service *svc)
{
if (!(svc->flags & IP_VS_SVC_F_HASHED)) {
- pr_err("%s(): request for unhash flagged, called from %pF\n",
+ pr_err("%s(): request for unhash flagged, called from %pS\n",
__func__, __builtin_return_address(0));
return 0;
}
return 0;
}
- static void ip_vs_dest_trash_expire(unsigned long data)
+ static void ip_vs_dest_trash_expire(struct timer_list *t)
{
- struct netns_ipvs *ipvs = (struct netns_ipvs *)data;
+ struct netns_ipvs *ipvs = from_timer(ipvs, t, dest_trash_timer);
struct ip_vs_dest *dest, *next;
unsigned long now = jiffies;
seq_puts(seq,
" -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n");
} else {
+ struct net *net = seq_file_net(seq);
+ struct netns_ipvs *ipvs = net_ipvs(net);
const struct ip_vs_service *svc = v;
const struct ip_vs_iter *iter = seq->private;
const struct ip_vs_dest *dest;
struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler);
char *sched_name = sched ? sched->name : "none";
+ if (svc->ipvs != ipvs)
+ return 0;
if (iter->table == ip_vs_svc_table) {
#ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6)
INIT_LIST_HEAD(&ipvs->dest_trash);
spin_lock_init(&ipvs->dest_trash_lock);
- setup_timer(&ipvs->dest_trash_timer, ip_vs_dest_trash_expire,
- (unsigned long) ipvs);
+ timer_setup(&ipvs->dest_trash_timer, ip_vs_dest_trash_expire, 0);
atomic_set(&ipvs->ftpsvc_counter, 0);
atomic_set(&ipvs->nullsvc_counter, 0);
atomic_set(&ipvs->conn_out_counter, 0);
* Reaper for links from keyrings to dead keys.
*/
static void key_gc_timer_func(unsigned long);
- static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
+ static DEFINE_TIMER(key_gc_timer, key_gc_timer_func);
static time_t key_gc_next_run = LONG_MAX;
static struct key_type *key_gc_dead_keytype;
while (!list_empty(keys)) {
struct key *key =
list_entry(keys->next, struct key, graveyard_link);
+ short state = key->state;
+
list_del(&key->graveyard_link);
kdebug("- %u", key->serial);
key_check(key);
/* Throw away the key data if the key is instantiated */
- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
- !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
- key->type->destroy)
+ if (state == KEY_IS_POSITIVE && key->type->destroy)
key->type->destroy(key);
security_key_free(key);
}
atomic_dec(&key->user->nkeys);
- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
+ if (state != KEY_IS_UNINSTANTIATED)
atomic_dec(&key->user->nikeys);
key_user_put(key->user);