* sm8250/lineage-20:
alarmtimer: Make alarmtimer platform device child of RTC device
Revert "timers: Rename del_timer_sync() to timer_delete_sync()"
Revert "geneve: make sure to pull inner header in geneve_rx()"
Linux 4.19.312
amdkfd: use calloc instead of kzalloc to avoid integer overflow
initramfs: fix populate_initrd_image() section mismatch
ip_gre: do not report erspan version on GRE interface
erspan: Check IFLA_GRE_ERSPAN_VER is set.
VMCI: Fix possible memcpy() run-time warning in vmci_datagram_invoke_guest_handler()
Bluetooth: btintel: Fixe build regression
x86/mm/pat: fix VM_PAT handling in COW mappings
virtio: reenable config if freezing device failed
drm/vkms: call drm_atomic_helper_shutdown before drm_dev_put()
tty: n_gsm: require CAP_NET_ADMIN to attach N_GSM0710 ldisc
fbmon: prevent division by zero in fb_videomode_from_videomode()
fbdev: viafb: fix typo in hw_bitblt_1 and hw_bitblt_2
usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
tools: iio: replace seekdir() in iio_generic_buffer
ktest: force $buildonly = 1 for 'make_warnings_file' test type
Input: allocate keycode for Display refresh rate toggle
block: prevent division by zero in blk_rq_stat_sum()
SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned int
drm/amd/display: Fix nanosec stat overflow
media: sta2x11: fix irq handler cast
isofs: handle CDs with bad root inode but good Joliet root directory
scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc()
sysv: don't call sb_bread() with pointers_lock held
Input: synaptics-rmi4 - fail probing if memory allocation for "phys" fails
Bluetooth: btintel: Fix null ptr deref in btintel_read_version
btrfs: send: handle path ref underflow in header iterate_inode_ref()
btrfs: export: handle invalid inode or root reference in btrfs_get_parent()
btrfs: handle chunk tree lookup error in btrfs_relocate_sys_chunks()
tools/power x86_energy_perf_policy: Fix file leak in get_pkg_num()
arm64: dts: rockchip: fix rk3399 hdmi ports node
VMCI: Fix memcpy() run-time warning in dg_dispatch_as_host()
wifi: ath9k: fix LNA selection in ath_ant_try_scan()
ALSA: hda/realtek: Update Panasonic CF-SZ6 quirk to support headset with microphone
ata: sata_mv: Fix PCI device ID table declaration compilation warning
ata: sata_sx4: fix pdc20621_get_from_dimm() on 64-bit
ASoC: ops: Fix wraparound for mask in snd_soc_get_volsw
erspan: make sure erspan_base_hdr is present in skb->head
erspan: Add type I version 0 support.
init: open /initrd.image with O_LARGEFILE
initramfs: switch initramfs unpacking to struct file based APIs
fs: add a vfs_fchmod helper
fs: add a vfs_fchown helper
initramfs: factor out a helper to populate the initrd image
staging: vc04_services: fix information leak in create_component()
staging: vc04_services: changen strncpy() to strscpy_pad()
staging: mmal-vchiq: Fix client_component for 64 bit kernel
staging: mmal-vchiq: Allocate and free components as required
staging: mmal-vchiq: Avoid use of bool in structures
i40e: fix vf may be used uninitialized in this function warning
ipv6: Fix infinite recursion in fib6_dump_done().
selftests: reuseaddr_conflict: add missing new line at the end of the output
net: stmmac: fix rx queue priority assignment
net/sched: act_skbmod: prevent kernel-infoleak
netfilter: nf_tables: Fix potential data-race in __nft_flowtable_type_get()
mm, vmscan: prevent infinite loop for costly GFP_NOIO | __GFP_RETRY_MAYFAIL allocations
Revert "x86/mm/ident_map: Use gbpages only where full GB page should be mapped."
net/rds: fix possible cp null dereference
netfilter: nf_tables: disallow timeout for anonymous sets
Bluetooth: Fix TOCTOU in HCI debugfs implementation
Bluetooth: hci_event: set the conn encrypted before conn establishes
r8169: fix issue caused by buggy BIOS on certain boards with RTL8168d
tcp: properly terminate timers for kernel sockets
mptcp: add sk_stop_timer_sync helper
nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet
USB: core: Fix deadlock in usb_deauthorize_interface()
scsi: lpfc: Correct size for wqe for memset()
x86/cpu: Enable STIBP on AMD if Automatic IBRS is enabled
scsi: qla2xxx: Fix command flush on cable pull
usb: udc: remove warning when queue disabled ep
usb: dwc2: gadget: LPM flow fix
usb: dwc2: host: Fix ISOC flow in DDMA mode
usb: dwc2: host: Fix hibernation flow
usb: dwc2: host: Fix remote wakeup from hibernation
loop: loop_set_status_from_info() check before assignment
loop: Check for overflow while configuring loop
loop: Factor out configuring loop from status
powerpc: xor_vmx: Add '-mhard-float' to CFLAGS
efivarfs: Request at most 512 bytes for variable names
perf/core: Fix reentry problem in perf_output_read_group()
loop: properly observe rotational flag of underlying device
loop: Refactor loop_set_status() size calculation
loop: Factor out setting loop device size
loop: Remove sector_t truncation checks
loop: Call loop_config_discard() only after new config is applied
Revert "loop: Check for overflow while configuring loop"
btrfs: allocate btrfs_ioctl_defrag_range_args on stack
printk: Update @console_may_schedule in console_trylock_spinning()
fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion
ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs
usb: cdc-wdm: close race between read and workqueue
exec: Fix NOMMU linux_binprm::exec in transfer_args_to_stack()
wifi: mac80211: check/clear fast rx for non-4addr sta VLAN changes
mm/migrate: set swap entry values of THP tail pages properly.
mm/memory-failure: fix an incorrect use of tail pages
vt: fix memory overlapping when deleting chars in the buffer
vt: fix unicode buffer corruption when deleting characters
tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
usb: port: Don't try to peer unused USB ports based on location
usb: gadget: ncm: Fix handling of zero block length packets
USB: usb-storage: Prevent divide-by-0 error in isd200_ata_command
ALSA: hda/realtek - Fix headset Mic no show at resume back for Lenovo ALC897 platform
xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
netfilter: nf_tables: reject constant set with timeout
netfilter: nf_tables: disallow anonymous set with timeout flag
comedi: comedi_test: Prevent timers rescheduling during deletion
ahci: asm1064: asm1166: don't limit reported ports
ahci: asm1064: correct count of reported ports
x86/CPU/AMD: Update the Zenbleed microcode revisions
nilfs2: prevent kernel bug at submit_bh_wbc()
nilfs2: use a more common logging style
nilfs2: fix failure to detect DAT corruption in btree and direct mappings
memtest: use {READ,WRITE}_ONCE in memory scanning
drm/vc4: hdmi: do not return negative values from .get_modes()
drm/imx/ipuv3: do not return negative values from .get_modes()
s390/zcrypt: fix reference counting on zcrypt card objects
soc: fsl: qbman: Use raw spinlock for cgr_lock
soc: fsl: qbman: Add CGR update function
soc: fsl: qbman: Add helper for sanity checking cgr ops
soc: fsl: qbman: Always disable interrupts when taking cgr_lock
vfio/platform: Disable virqfds on cleanup
kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
speakup: Fix 8bit characters from direct synth
slimbus: core: Remove usage of the deprecated ida_simple_xx() API
ext4: fix corruption during on-line resize
hwmon: (amc6821) add of_match table
mmc: core: Fix switch on gp3 partition
dm-raid: fix lockdep waring in "pers->hot_add_disk"
Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d""
PCI/PM: Drain runtime-idle callbacks before driver removal
PCI: Drop pci_device_remove() test of pci_dev->driver
fuse: don't unhash root
mmc: tmio: avoid concurrent runs of mmc_request_done()
PM: sleep: wakeirq: fix wake irq warning in system suspend
USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
USB: serial: option: add MeiG Smart SLM320 product
USB: serial: cp210x: add ID for MGP Instruments PDS100
USB: serial: add device ID for VeriFone adapter
USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB
powerpc/fsl: Fix mfpmr build errors with newer binutils
clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
PM: suspend: Set mem_sleep_current during kernel command line setup
parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit builds
parisc: Fix csum_ipv6_magic on 64-bit systems
parisc: Fix csum_ipv6_magic on 32-bit systems
parisc: Fix ip_fast_csum
parisc: Do not hardcode registers in checksum functions
ubi: correct the calculation of fastmap size
ubi: Check for too small LEB size in VTBL code
ubifs: Set page uptodate in the correct place
fat: fix uninitialized field in nostale filehandles
crypto: qat - resolve race condition during AER recovery
crypto: qat - fix double free during reset
sparc: vDSO: fix return value of __setup handler
sparc64: NMI watchdog: fix return value of __setup handler
KVM: Always flush async #PF workqueue when vCPU is being destroyed
media: xc4000: Fix atomicity violation in xc4000_get_frequency
arm: dts: marvell: Fix maxium->maxim typo in brownstone dts
ARM: dts: mmp2-brownstone: Don't redeclare phandle references
smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
timers: Rename del_timer_sync() to timer_delete_sync()
timers: Use del_timer_sync() even on UP
timers: Update kernel-doc for various functions
timers: Prepare support for PREEMPT_RT
timer/trace: Improve timer tracing
timer/trace: Replace deprecated vsprintf pointer extension %pf by %ps
x86/bugs: Use sysfs_emit()
x86/cpu: Support AMD Automatic IBRS
Documentation/hw-vuln: Update spectre doc
Linux 4.19.311
crypto: af_alg - Work around empty control messages without MSG_MORE
crypto: af_alg - Fix regression on empty requests
spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
net/bnx2x: Prevent access to a freed page in page_pool
hsr: Handle failures in module init
rds: introduce acquire/release ordering in acquire/release_in_xmit()
hsr: Fix uninit-value access in hsr_get_node()
net: hsr: fix placement of logical operator in a multi-line statement
usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
staging: greybus: fix get_channel_from_mode() failure path
serial: 8250_exar: Don't remove GPIO device on suspend
rtc: mt6397: select IRQ_DOMAIN instead of depending on it
kconfig: fix infinite loop when expanding a macro at the end of file
tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
serial: max310x: fix syntax error in IRQ error message
clk: qcom: gdsc: Add support to update GDSC transition delay
NFS: Fix an off by one in root_nfs_cat()
net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
scsi: csiostor: Avoid function pointer casts
ALSA: usb-audio: Stop parsing channels bits when all channels are found.
sparc32: Fix section mismatch in leon_pci_grpci
backlight: lp8788: Fully initialize backlight_properties during probe
backlight: lm3639: Fully initialize backlight_properties during probe
backlight: da9052: Fully initialize backlight_properties during probe
backlight: lm3630a: Don't set bl->props.brightness in get_brightness
backlight: lm3630a: Initialize backlight_properties on init
powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
media: go7007: fix a memleak in go7007_load_encoder
media: dvb-frontends: avoid stack overflow warnings with clang
media: pvrusb2: fix uaf in pvr2_context_set_notify
drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
crypto: arm/sha - fix function cast warnings
crypto: arm - Rename functions to avoid conflict with crypto/sha256.h
mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
drm/tegra: put drm_gem_object ref on error in tegra_fb_create
clk: hisilicon: hi3519: Release the correct number of gates in hi3519_clk_unregister()
PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
firmware: qcom: scm: Add WLAN VMID for Qualcomm SCM interface
media: pvrusb2: fix pvr2_stream_callback casts
media: go7007: add check of return value of go7007_read_addr()
ALSA: seq: fix function cast warnings
drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
quota: Fix rcu annotations of inode dquot pointers
quota: Fix potential NULL pointer dereference
quota: simplify drop_dquot_ref()
quota: check time limit when back out space/inode change
fs/quota: erase unused but set variable warning
quota: code cleanup for __dquot_alloc_space()
clk: qcom: reset: Ensure write completion on reset de/assertion
clk: qcom: reset: Commonize the de/assert functions
clk: qcom: reset: support resetting multiple bits
clk: qcom: reset: Allow specifying custom reset delay
media: edia: dvbdev: fix a use-after-free
media: dvb-core: Fix use-after-free due to race at dvb_register_device()
media: dvbdev: fix error logic at dvb_register_device()
media: dvbdev: Fix memleak in dvb_register_device
media: media/dvb: Use kmemdup rather than duplicating its implementation
media: dvbdev: remove double-unlock
media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
media: v4l2-tpg: fix some memleaks in tpg_alloc
media: em28xx: annotate unchecked call to media_device_register()
ABI: sysfs-bus-pci-devices-aer_stats uses an invalid tag
perf evsel: Fix duplicate initialization of data->id in evsel__parse_sample()
media: tc358743: register v4l2 async device only after successful setup
drm/rockchip: lvds: do not print scary message when probing defer
drm/rockchip: lvds: do not overwrite error code
drm: Don't treat 0 as -1 in drm_fixp2int_ceil
drm/rockchip: inno_hdmi: Fix video timing
drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path of tegra_dsi_probe()
drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
drm/tegra: dsi: Make use of the helper function dev_err_probe()
gpu: host1x: mipi: Update tegra_mipi_request() to be node based
drm/tegra: dsi: Add missing check for of_find_device_by_node
dm: call the resume method on internal suspend
dm raid: fix false positive for requeue needed during reshape
nfp: flower: handle acti_netdevs allocation failure
net/x25: fix incorrect parameter validation in the x25_getsockopt() function
net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt() function
tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
ipv6: fib6_rules: flush route cache when rule is changed
bpf: Fix stackmap overflow check on 32-bit arches
bpf: Fix hashtab overflow check on 32-bit arches
sr9800: Add check for usbnet_get_endpoints
Bluetooth: hci_core: Fix possible buffer overflow
Bluetooth: Remove superfluous call to hci_conn_check_pending()
igb: Fix missing time sync events
igb: move PEROUT and EXTTS isr logic to separate functions
mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove function
SUNRPC: fix some memleaks in gssx_dec_option_array
x86, relocs: Ignore relocations in .notes section
ACPI: scan: Fix device check notification handling
ARM: dts: arm: realview: Fix development chip ROM compatible value
wifi: brcmsmac: avoid function pointer casts
iommu/amd: Mark interrupt as managed
bus: tegra-aconnect: Update dependency to ARCH_TEGRA
ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
sock_diag: annotate data-races around sock_diag_handlers[family]
wifi: mwifiex: debugfs: Drop unnecessary error check for debugfs_create_dir()
wifi: b43: Disable QoS for bcm4331
wifi: b43: Stop correct queue in DMA worker when QoS is disabled
b43: main: Fix use true/false for bool type
wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
b43: dma: Fix use true/false for bool type variable
wifi: ath10k: fix NULL pointer dereference in ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
timekeeping: Fix cross-timestamp interpolation for non-x86
timekeeping: Fix cross-timestamp interpolation corner case decision
timekeeping: Fix cross-timestamp interpolation on counter wrap
aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
md: Don't clear MD_CLOSING when the raid is about to stop
md: implement ->set_read_only to hook into BLKROSET processing
block: add a new set_read_only method
md: switch to ->check_events for media change notifications
fs/select: rework stack allocation hack for clang
do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
crypto: algif_aead - Only wake up when ctx->more is zero
crypto: af_alg - make some functions static
crypto: algif_aead - fix uninitialized ctx->init
ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
Input: gpio_keys_polled - suppress deferred probe error for gpio
ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
firewire: core: use long bus reset on gap count error
Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
dm-verity, dm-crypt: align "struct bvec_iter" correctly
block: sed-opal: handle empty atoms when parsing response
net/iucv: fix the allocation size of iucv_path_table array
MIPS: Clear Cause.BD in instruction_pointer_set
x86/xen: Add some null pointer checking to smp.c
ASoC: rt5645: Make LattePanda board DMI match more precise
Linux 4.19.310
selftests/vm: fix map_hugetlb length used for testing read and write
selftests/vm: fix display of page size in map_hugetlb
getrusage: use sig->stats_lock rather than lock_task_sighand()
getrusage: use __for_each_thread()
getrusage: move thread_group_cputime_adjusted() outside of lock_task_sighand()
getrusage: add the "signal_struct *sig" local variable
y2038: rusage: use __kernel_old_timeval
hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
hv_netvsc: use netif_is_bond_master() instead of open code
hv_netvsc: Make netvsc/VF binding check both MAC and serial number
Input: i8042 - fix strange behavior of touchpad on Clevo NS70PU
um: allow not setting extra rpaths in the linux binary
selftests: mm: fix map_hugetlb failure on 64K page size systems
tools/selftest/vm: allow choosing mem size and page size in map_hugetlb
btrfs: ref-verify: free ref cache before clearing mount opt
netrom: Fix data-races around sysctl_net_busy_read
netrom: Fix a data-race around sysctl_netrom_link_fails_count
netrom: Fix a data-race around sysctl_netrom_routing_control
netrom: Fix a data-race around sysctl_netrom_transport_no_activity_timeout
netrom: Fix a data-race around sysctl_netrom_transport_requested_window_size
netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
netrom: Fix a data-race around sysctl_netrom_transport_acknowledge_delay
netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
netrom: Fix a data-race around sysctl_netrom_transport_timeout
netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
netrom: Fix a data-race around sysctl_netrom_obsolescence_count_initialiser
netrom: Fix a data-race around sysctl_netrom_default_path_quality
netfilter: nf_conntrack_h323: Add protection for bmp length out of range
net/rds: fix WARNING in rds_conn_connect_if_down
net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
geneve: make sure to pull inner header in geneve_rx()
net: move definition of pcpu_lstats to header file
net: lan78xx: fix runtime PM count underflow on link stop
lan78xx: Fix race conditions in suspend/resume handling
lan78xx: Fix partial packet errors on suspend/resume
lan78xx: Add missing return code checks
lan78xx: Fix white space and style issues
net: usb: lan78xx: Remove lots of set but unused 'ret' variables
Linux 4.19.309
gpio: 74x164: Enable output pins after registers are reset
cachefiles: fix memory leak in cachefiles_add_cache()
mmc: core: Fix eMMC initialization with 1-bit bus connection
btrfs: dev-replace: properly validate device names
wifi: nl80211: reject iftype change with mesh ID change
gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
ALSA: Drop leftover snd-rtctimer stuff from Makefile
power: supply: bq27xxx-i2c: Do not free non existing IRQ
efi/capsule-loader: fix incorrect allocation size
Bluetooth: Enforce validation on max value of connection interval
Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
Bluetooth: Avoid potential use-after-free in hci_error_reset
net: usb: dm9601: fix wrong return value in dm9601_mdio_read
lan78xx: enable auto speed configuration for LAN7850 if no EEPROM is detected
tun: Fix xdp_rxq_info's queue_index when detaching
netlink: Fix kernel-infoleak-after-free in __skb_datagram_iter
Linux 4.19.308
scripts/bpf: Fix xdp_md forward declaration typo
fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio
KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
PCI/MSI: Prevent MSI hardware interrupt number truncation
s390: use the correct count for __iowrite64_copy()
packet: move from strlcpy with unused retval to strscpy
ipv6: sr: fix possible use-after-free and null-ptr-deref
nouveau: fix function cast warnings
scsi: jazz_esp: Only build if SCSI core is builtin
bpf, scripts: Correct GPL license name
scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
RDMA/srpt: fix function pointer cast warnings
RDMA/srpt: Make debug output more detailed
RDMA/ulp: Use dev_name instead of ibdev->name
RDMA/srpt: Support specifying the srpt_service_guid parameter
RDMA/bnxt_re: Return error for SRQ resize
IB/hfi1: Fix a memleak in init_credit_return
usb: roles: don't get/set_role() when usb_role_switch is unregistered
usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
ARM: ep93xx: Add terminator to gpiod_lookup_table
l2tp: pass correct message length to ip6_append_data
gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
dm-crypt: don't modify the data when using authenticated encryption
mm: memcontrol: switch to rcu protection in drain_all_stock()
IB/hfi1: Fix sdma.h tx->num_descs off-by-one error
pmdomain: renesas: r8a77980-sysc: CR7 must be always on
s390/qeth: Fix potential loss of L3-IP@ in case of network issues
virtio-blk: Ensure no requests in virtqueues before deleting vqs.
firewire: core: send bus reset promptly on gap count error
hwmon: (coretemp) Enlarge per package core count limit
regulator: pwm-regulator: Add validity checks in continuous .get_voltage
ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal()
ext4: avoid allocating blocks from corrupted group in ext4_mb_try_best_found()
ahci: asm1166: correct count of reported ports
fbdev: sis: Error out if pixclock equals zero
fbdev: savage: Error out if pixclock equals zero
wifi: mac80211: fix race condition on enabling fast-xmit
wifi: cfg80211: fix missing interfaces when dumping
dmaengine: shdma: increase size of 'dev_id'
scsi: target: core: Add TMF to tmr_list handling
sched/rt: Disallow writing invalid values to sched_rt_period_us
sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset
sched/rt: Fix sysctl_sched_rr_timeslice intial value
userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
nilfs2: replace WARN_ONs for invalid DAT metadata block requests
memcg: add refcnt for pcpu stock to avoid UAF problem in drain_all_stock()
net: stmmac: fix notifier registration
stmmac: no need to check return value of debugfs_create functions
net/sched: Retire dsmark qdisc
net/sched: Retire ATM qdisc
net/sched: Retire CBQ qdisc
Linux 4.19.307
netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
lsm: new security_file_ioctl_compat() hook
nilfs2: fix potential bug in end_buffer_async_write
sched/membarrier: reduce the ability to hammer on sys_membarrier
Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"
pmdomain: core: Move the unused cleanup to a _sync initcall
irqchip/irq-brcmstb-l2: Add write memory barrier before exit
nfp: use correct macro for LengthSelect in BAR config
nilfs2: fix hang in nilfs_lookup_dirty_data_buffers()
nilfs2: fix data corruption in dsync block recovery for small block sizes
ALSA: hda/conexant: Add quirk for SWS JS201D
x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
x86/Kconfig: Transmeta Crusoe is CPU family 5, not 6
serial: max310x: improve crystal stable clock detection
serial: max310x: set default value when reading clock ready bit
ring-buffer: Clean ring_buffer_poll_wait() error return
staging: iio: ad5933: fix type mismatch regression
ext4: fix double-free of blocks due to wrong extents moved_len
binder: signal epoll threads of self-work
xen-netback: properly sync TX responses
nfc: nci: free rx_data_reassembly skb on NCI device cleanup
firewire: core: correct documentation of fw_csr_string() kernel API
scsi: Revert "scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock"
usb: f_mass_storage: forbid async queue when shutdown happen
USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
HID: wacom: Do not register input devices until after hid_hw_start
HID: wacom: generic: Avoid reporting a serial of '0' to userspace
mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again
tracing/trigger: Fix to return error if failed to alloc snapshot
i40e: Fix waiting for queues of all VSIs to be disabled
MIPS: Add 'memory' clobber to csum_ipv6_magic() inline assembler
net: sysfs: Fix /sys/class/net/<iface> path for statistics
Documentation: net-sysfs: describe missing statistics
ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work()
spi: ppc4xx: Drop write-only variable
btrfs: send: return EOPNOTSUPP on unknown flags
btrfs: forbid creating subvol qgroups
hrtimer: Report offline hrtimer enqueue
vhost: use kzalloc() instead of kmalloc() followed by memset()
Input: atkbd - skip ATKBD_CMD_SETLEDS when skipping ATKBD_CMD_GETID
USB: serial: cp210x: add ID for IMST iM871A-USB
USB: serial: option: add Fibocom FM101-GL variant
USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
net/af_iucv: clean up a try_then_request_module()
netfilter: nft_compat: restrict match/target protocol to u16
netfilter: nft_compat: reject unused compat flag
ppp_async: limit MRU to 64K
tipc: Check the bearer type before calling tipc_udp_nl_bearer_add()
rxrpc: Fix response to PING RESPONSE ACKs to a dead call
inet: read sk->sk_family once in inet_recv_error()
hwmon: (coretemp) Fix bogus core_id to attr name mapping
hwmon: (coretemp) Fix out-of-bounds memory access
hwmon: (aspeed-pwm-tacho) mutex for tach reading
atm: idt77252: fix a memleak in open_card_ubr0
phy: ti: phy-omap-usb2: Fix NULL pointer dereference for SRP
dmaengine: fix is_slave_direction() return false when DMA_DEV_TO_DEV
bonding: remove print in bond_verify_device_path
HID: apple: Add 2021 magic keyboard FN key mapping
HID: apple: Swap the Fn and Left Control keys on Apple keyboards
HID: apple: Add support for the 2021 Magic Keyboard
net: sysfs: Fix /sys/class/net/<iface> path
af_unix: fix lockdep positive in sk_diag_dump_icons()
net: ipv4: fix a memleak in ip_setup_cork
netfilter: nf_log: replace BUG_ON by WARN_ON_ONCE when putting logger
llc: call sock_orphan() at release time
ipv6: Ensure natural alignment of const ipv6 loopback and router addresses
ixgbe: Fix an error handling path in ixgbe_read_iosf_sb_reg_x550()
ixgbe: Refactor overtemp event handling
ixgbe: Refactor returning internal error codes
ixgbe: Remove non-inclusive language
net: remove unneeded break
scsi: isci: Fix an error code problem in isci_io_request_build()
wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
drm/amdgpu: Release 'adev->pm.fw' before return in 'amdgpu_device_need_post()'
ceph: fix deadlock or deadcode of misusing dget()
blk-mq: fix IO hang from sbitmap wakeup race
virtio_net: Fix "‘%d’ directive writing between 1 and 11 bytes into a region of size 10" warnings
libsubcmd: Fix memory leak in uniq()
usb: hub: Replace hardcoded quirk value with BIT() macro
PCI: Only override AMD USB controller if required
mfd: ti_am335x_tscadc: Fix TI SoC dependencies
um: net: Fix return type of uml_net_start_xmit()
um: Don't use vfprintf() for os_info()
um: Fix naming clash between UML and scheduler
leds: trigger: panic: Don't register panic notifier if creating the trigger failed
drm/amdgpu: Drop 'fence' check in 'to_amdgpu_amdkfd_fence()'
drm/amdgpu: Let KFD sync with VM fences
clk: mmp: pxa168: Fix memory leak in pxa168_clk_init()
clk: hi3620: Fix memory leak in hi3620_mmc_clk_init()
drm/msm/dpu: Ratelimit framedone timeout msgs
media: ddbridge: fix an error code problem in ddb_probe
IB/ipoib: Fix mcast list locking
drm/exynos: Call drm_atomic_helper_shutdown() at shutdown/unbind time
ALSA: hda: Intel: add HDA_ARL PCI ID support
PCI: add INTEL_HDA_ARL to pci_ids.h
media: rockchip: rga: fix swizzling for RGB formats
media: stk1160: Fixed high volume of stk1160_dbg messages
drm/mipi-dsi: Fix detach call without attach
drm/framebuffer: Fix use of uninitialized variable
drm/drm_file: fix use of uninitialized variable
RDMA/IPoIB: Fix error code return in ipoib_mcast_join
fast_dput(): handle underflows gracefully
ASoC: doc: Fix undefined SND_SOC_DAPM_NOPM argument
f2fs: fix to check return value of f2fs_reserve_new_block()
wifi: cfg80211: free beacon_ies when overridden from hidden BSS
wifi: rtlwifi: rtl8723{be,ae}: using calculate_bit_shift()
wifi: rtl8xxxu: Add additional USB IDs for RTL8192EU devices
md: Whenassemble the array, consult the superblock of the freshest device
ARM: dts: imx23/28: Fix the DMA controller node name
ARM: dts: imx23-sansa: Use preferred i2c-gpios properties
ARM: dts: imx27-apf27dev: Fix LED name
ARM: dts: imx1: Fix sram node
ARM: dts: imx27: Fix sram node
ARM: dts: imx: Use flash@0,0 pattern
ARM: dts: imx25/27-eukrea: Fix RTC node name
ARM: dts: rockchip: fix rk3036 hdmi ports node
scsi: libfc: Fix up timeout error in fc_fcp_rec_error()
scsi: libfc: Don't schedule abort twice
bpf: Add map and need_defer parameters to .map_fd_put_ptr()
wifi: ath9k: Fix potential array-index-out-of-bounds read in ath9k_htc_txstatus()
ARM: dts: imx7s: Fix nand-controller #size-cells
ARM: dts: imx7s: Fix lcdif compatible
bonding: return -ENOMEM instead of BUG in alb_upper_dev_walk
PCI: Add no PM reset quirk for NVIDIA Spectrum devices
scsi: lpfc: Fix possible file string name overflow when updating firmware
ext4: avoid online resizing failures due to oversized flex bg
ext4: remove unnecessary check from alloc_flex_gd()
ext4: unify the type of flexbg_size to unsigned int
ext4: fix inconsistent between segment fstrim and full fstrim
SUNRPC: Fix a suspicious RCU usage warning
KVM: s390: fix setting of fpc register
s390/ptrace: handle setting of fpc register correctly
jfs: fix array-index-out-of-bounds in diNewExt
rxrpc_find_service_conn_rcu: fix the usage of read_seqbegin_or_lock()
afs: fix the usage of read_seqbegin_or_lock() in afs_find_server*()
crypto: stm32/crc32 - fix parsing list of devices
pstore/ram: Fix crash when setting number of cpus to an odd number
jfs: fix uaf in jfs_evict_inode
jfs: fix array-index-out-of-bounds in dbAdjTree
jfs: fix slab-out-of-bounds Read in dtSearch
UBSAN: array-index-out-of-bounds in dtSplitRoot
FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
ACPI: extlog: fix NULL pointer dereference check
PNP: ACPI: fix fortify warning
ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
audit: Send netlink ACK before setting connection in auditd_set
powerpc/lib: Validate size for vector operations
powerpc/mm: Fix build failures due to arch_reserved_kernel_pages()
powerpc: Fix build error due to is_valid_bugaddr()
powerpc/mm: Fix null-pointer dereference in pgtable_cache_add
net/sched: cbs: Fix not adding cbs instance to list
x86/entry/ia32: Ensure s32 is sign extended to s64
tick/sched: Preserve number of idle sleeps across CPU hotplug events
mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan
gpio: eic-sprd: Clear interrupt after set the interrupt type
drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume
drm/bridge: nxp-ptn3460: simplify some error checking
drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking
drm: Don't unref the same fb many times by mistake due to deadlock handling
gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04
netfilter: nf_tables: reject QUEUE/DROP verdict parameters
btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args
btrfs: don't warn if discard range is not aligned to sector
net: fec: fix the unhandled context fault from smmu
fjes: fix memleaks in fjes_hw_setup
netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
net/mlx5e: fix a double-free in arfs_create_groups
net/mlx5: Use kfree(ft->g) in arfs_create_groups()
netlink: fix potential sleeping issue in mqueue_flush_file
Change-Id: I02289cff0df473bdd2ad4a8d064c76ce05e20597
947 lines
24 KiB
C
947 lines
24 KiB
C
/*
|
|
* Alarmtimer interface
|
|
*
|
|
* This interface provides a timer which is similarto hrtimers,
|
|
* but triggers a RTC alarm if the box is suspend.
|
|
*
|
|
* This interface is influenced by the Android RTC Alarm timer
|
|
* interface.
|
|
*
|
|
* Copyright (C) 2010 IBM Corperation
|
|
*
|
|
* Author: John Stultz <john.stultz@linaro.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/time.h>
|
|
#include <linux/hrtimer.h>
|
|
#include <linux/timerqueue.h>
|
|
#include <linux/rtc.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <linux/sched/debug.h>
|
|
#include <linux/alarmtimer.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/posix-timers.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/freezer.h>
|
|
#include <linux/compat.h>
|
|
#include <linux/module.h>
|
|
|
|
#include "posix-timers.h"
|
|
|
|
#define CREATE_TRACE_POINTS
|
|
#include <trace/events/alarmtimer.h>
|
|
|
|
/**
|
|
* struct alarm_base - Alarm timer bases
|
|
* @lock: Lock for syncrhonized access to the base
|
|
* @timerqueue: Timerqueue head managing the list of events
|
|
* @gettime: Function to read the time correlating to the base
|
|
* @base_clockid: clockid for the base
|
|
*/
|
|
static struct alarm_base {
|
|
spinlock_t lock;
|
|
struct timerqueue_head timerqueue;
|
|
ktime_t (*gettime)(void);
|
|
clockid_t base_clockid;
|
|
} alarm_bases[ALARM_NUMTYPE];
|
|
|
|
#if defined(CONFIG_POSIX_TIMERS) || defined(CONFIG_RTC_CLASS)
|
|
/* freezer information to handle clock_nanosleep triggered wakeups */
|
|
static enum alarmtimer_type freezer_alarmtype;
|
|
static ktime_t freezer_expires;
|
|
static ktime_t freezer_delta;
|
|
static DEFINE_SPINLOCK(freezer_delta_lock);
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTC_CLASS
|
|
static struct wakeup_source *ws;
|
|
|
|
/* rtc timer and device for setting alarm wakeups at suspend */
|
|
static struct rtc_timer rtctimer;
|
|
static struct rtc_device *rtcdev;
|
|
static int alarm_debug = 0;
|
|
static DEFINE_SPINLOCK(rtcdev_lock);
|
|
|
|
/**
|
|
* alarmtimer_get_rtcdev - Return selected rtcdevice
|
|
*
|
|
* This function returns the rtc device to use for wakealarms.
|
|
* If one has not already been chosen, it checks to see if a
|
|
* functional rtc device is available.
|
|
*/
|
|
struct rtc_device *alarmtimer_get_rtcdev(void)
|
|
{
|
|
unsigned long flags;
|
|
struct rtc_device *ret;
|
|
|
|
spin_lock_irqsave(&rtcdev_lock, flags);
|
|
ret = rtcdev;
|
|
spin_unlock_irqrestore(&rtcdev_lock, flags);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarmtimer_get_rtcdev);
|
|
|
|
static int alarmtimer_rtc_add_device(struct device *dev,
|
|
struct class_interface *class_intf)
|
|
{
|
|
unsigned long flags;
|
|
struct rtc_device *rtc = to_rtc_device(dev);
|
|
struct wakeup_source *__ws;
|
|
struct platform_device *pdev;
|
|
int ret = 0;
|
|
|
|
if (rtcdev)
|
|
return -EBUSY;
|
|
|
|
if (!rtc->ops->set_alarm)
|
|
return -1;
|
|
if (!device_may_wakeup(rtc->dev.parent))
|
|
return -1;
|
|
|
|
__ws = wakeup_source_register(dev, "alarmtimer");
|
|
pdev = platform_device_register_data(dev, "alarmtimer",
|
|
PLATFORM_DEVID_AUTO, NULL, 0);
|
|
|
|
spin_lock_irqsave(&rtcdev_lock, flags);
|
|
if (__ws && !IS_ERR(pdev) && !rtcdev) {
|
|
if (!try_module_get(rtc->owner)) {
|
|
ret = -1;
|
|
goto unlock;
|
|
}
|
|
|
|
rtcdev = rtc;
|
|
/* hold a reference so it doesn't go away */
|
|
get_device(dev);
|
|
ws = __ws;
|
|
__ws = NULL;
|
|
pdev = NULL;
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
unlock:
|
|
spin_unlock_irqrestore(&rtcdev_lock, flags);
|
|
|
|
platform_device_unregister(pdev);
|
|
wakeup_source_unregister(__ws);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline void alarmtimer_rtc_timer_init(void)
|
|
{
|
|
rtc_timer_init(&rtctimer, NULL, NULL);
|
|
}
|
|
|
|
static struct class_interface alarmtimer_rtc_interface = {
|
|
.add_dev = &alarmtimer_rtc_add_device,
|
|
};
|
|
|
|
static int alarmtimer_rtc_interface_setup(void)
|
|
{
|
|
alarmtimer_rtc_interface.class = rtc_class;
|
|
return class_interface_register(&alarmtimer_rtc_interface);
|
|
}
|
|
static void alarmtimer_rtc_interface_remove(void)
|
|
{
|
|
class_interface_unregister(&alarmtimer_rtc_interface);
|
|
}
|
|
#else
|
|
struct rtc_device *alarmtimer_get_rtcdev(void)
|
|
{
|
|
return NULL;
|
|
}
|
|
#define rtcdev (NULL)
|
|
static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
|
|
static inline void alarmtimer_rtc_interface_remove(void) { }
|
|
static inline void alarmtimer_rtc_timer_init(void) { }
|
|
#endif
|
|
|
|
/**
|
|
* alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue
|
|
* @base: pointer to the base where the timer is being run
|
|
* @alarm: pointer to alarm being enqueued.
|
|
*
|
|
* Adds alarm to a alarm_base timerqueue
|
|
*
|
|
* Must hold base->lock when calling.
|
|
*/
|
|
static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
|
|
{
|
|
if (alarm->state & ALARMTIMER_STATE_ENQUEUED)
|
|
timerqueue_del(&base->timerqueue, &alarm->node);
|
|
|
|
timerqueue_add(&base->timerqueue, &alarm->node);
|
|
alarm->state |= ALARMTIMER_STATE_ENQUEUED;
|
|
}
|
|
|
|
/**
|
|
* alarmtimer_dequeue - Removes an alarm timer from an alarm_base timerqueue
|
|
* @base: pointer to the base where the timer is running
|
|
* @alarm: pointer to alarm being removed
|
|
*
|
|
* Removes alarm to a alarm_base timerqueue
|
|
*
|
|
* Must hold base->lock when calling.
|
|
*/
|
|
static void alarmtimer_dequeue(struct alarm_base *base, struct alarm *alarm)
|
|
{
|
|
if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
|
|
return;
|
|
|
|
timerqueue_del(&base->timerqueue, &alarm->node);
|
|
alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
|
|
}
|
|
|
|
|
|
/**
|
|
* alarmtimer_fired - Handles alarm hrtimer being fired.
|
|
* @timer: pointer to hrtimer being run
|
|
*
|
|
* When a alarm timer fires, this runs through the timerqueue to
|
|
* see which alarms expired, and runs those. If there are more alarm
|
|
* timers queued for the future, we set the hrtimer to fire when
|
|
* when the next future alarm timer expires.
|
|
*/
|
|
static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
|
|
{
|
|
struct alarm *alarm = container_of(timer, struct alarm, timer);
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
unsigned long flags;
|
|
int ret = HRTIMER_NORESTART;
|
|
int restart = ALARMTIMER_NORESTART;
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
alarmtimer_dequeue(base, alarm);
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
|
|
if(alarm_debug & 0x1){
|
|
pr_info("%s: type=%d, func=%pf, exp:%llu\n", __func__,
|
|
alarm->type, alarm->function, ktime_to_ms(alarm->node.expires));
|
|
alarm_debug &= 0xFE;
|
|
}
|
|
|
|
if (alarm->function)
|
|
restart = alarm->function(alarm, base->gettime());
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
if (restart != ALARMTIMER_NORESTART) {
|
|
hrtimer_set_expires(&alarm->timer, alarm->node.expires);
|
|
alarmtimer_enqueue(base, alarm);
|
|
ret = HRTIMER_RESTART;
|
|
}
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
|
|
trace_alarmtimer_fired(alarm, base->gettime());
|
|
return ret;
|
|
|
|
}
|
|
|
|
ktime_t alarm_expires_remaining(const struct alarm *alarm)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
return ktime_sub(alarm->node.expires, base->gettime());
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_expires_remaining);
|
|
|
|
#ifdef CONFIG_RTC_CLASS
|
|
/**
|
|
* alarmtimer_suspend - Suspend time callback
|
|
* @dev: unused
|
|
* @state: unused
|
|
*
|
|
* When we are going into suspend, we look through the bases
|
|
* to see which is the soonest timer to expire. We then
|
|
* set an rtc timer to fire that far into the future, which
|
|
* will wake us from suspend.
|
|
*/
|
|
static int alarmtimer_suspend(struct device *dev)
|
|
{
|
|
ktime_t min, now, expires;
|
|
int i, ret, type;
|
|
struct rtc_device *rtc;
|
|
unsigned long flags;
|
|
struct rtc_time tm;
|
|
struct alarm* min_timer = NULL;
|
|
|
|
spin_lock_irqsave(&freezer_delta_lock, flags);
|
|
min = freezer_delta;
|
|
expires = freezer_expires;
|
|
type = freezer_alarmtype;
|
|
freezer_delta = 0;
|
|
spin_unlock_irqrestore(&freezer_delta_lock, flags);
|
|
|
|
rtc = alarmtimer_get_rtcdev();
|
|
/* If we have no rtcdev, just return */
|
|
if (!rtc)
|
|
return 0;
|
|
|
|
/* Find the soonest timer to expire*/
|
|
for (i = 0; i < ALARM_NUMTYPE; i++) {
|
|
struct alarm_base *base = &alarm_bases[i];
|
|
struct timerqueue_node *next;
|
|
ktime_t delta;
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
next = timerqueue_getnext(&base->timerqueue);
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
if (!next)
|
|
continue;
|
|
delta = ktime_sub(next->expires, base->gettime());
|
|
if (!min || (delta < min)) {
|
|
min_timer = container_of(next, struct alarm, node);
|
|
expires = next->expires;
|
|
min = delta;
|
|
type = i;
|
|
}
|
|
}
|
|
if (min == 0)
|
|
return 0;
|
|
|
|
if (min_timer){
|
|
pr_info("%s: [%p]type=%d, func=%pf, exp:%llu\n", __func__,
|
|
min_timer, min_timer->type, min_timer->function,
|
|
ktime_to_ms(min_timer->node.expires));
|
|
min_timer = NULL;
|
|
}
|
|
alarm_debug = 0x1;
|
|
|
|
if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
|
|
__pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
|
|
return -EBUSY;
|
|
}
|
|
|
|
trace_alarmtimer_suspend(expires, type);
|
|
|
|
/* Setup an rtc timer to fire that far in the future */
|
|
rtc_timer_cancel(rtc, &rtctimer);
|
|
rtc_read_time(rtc, &tm);
|
|
now = rtc_tm_to_ktime(tm);
|
|
now = ktime_add(now, min);
|
|
|
|
/* Set alarm, if in the past reject suspend briefly to handle */
|
|
ret = rtc_timer_start(rtc, &rtctimer, now, 0);
|
|
if (ret < 0)
|
|
__pm_wakeup_event(ws, MSEC_PER_SEC);
|
|
return ret;
|
|
}
|
|
|
|
static int alarmtimer_resume(struct device *dev)
|
|
{
|
|
struct rtc_device *rtc;
|
|
|
|
rtc = alarmtimer_get_rtcdev();
|
|
if (rtc)
|
|
rtc_timer_cancel(rtc, &rtctimer);
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
static int alarmtimer_suspend(struct device *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int alarmtimer_resume(struct device *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
__alarm_init(struct alarm *alarm, enum alarmtimer_type type,
|
|
enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
|
|
{
|
|
timerqueue_init(&alarm->node);
|
|
alarm->timer.function = alarmtimer_fired;
|
|
alarm->function = function;
|
|
alarm->type = type;
|
|
alarm->state = ALARMTIMER_STATE_INACTIVE;
|
|
}
|
|
|
|
/**
|
|
* alarm_init - Initialize an alarm structure
|
|
* @alarm: ptr to alarm to be initialized
|
|
* @type: the type of the alarm
|
|
* @function: callback that is run when the alarm fires
|
|
*/
|
|
void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
|
|
enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
|
|
{
|
|
hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
|
|
HRTIMER_MODE_ABS);
|
|
__alarm_init(alarm, type, function);
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_init);
|
|
|
|
/**
|
|
* alarm_start - Sets an absolute alarm to fire
|
|
* @alarm: ptr to alarm to set
|
|
* @start: time to run the alarm
|
|
*/
|
|
void alarm_start(struct alarm *alarm, ktime_t start)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
alarm->node.expires = start;
|
|
alarmtimer_enqueue(base, alarm);
|
|
hrtimer_start(&alarm->timer, alarm->node.expires, HRTIMER_MODE_ABS);
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
|
|
trace_alarmtimer_start(alarm, base->gettime());
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_start);
|
|
|
|
/**
|
|
* alarm_start_relative - Sets a relative alarm to fire
|
|
* @alarm: ptr to alarm to set
|
|
* @start: time relative to now to run the alarm
|
|
*/
|
|
void alarm_start_relative(struct alarm *alarm, ktime_t start)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
|
|
start = ktime_add_safe(start, base->gettime());
|
|
alarm_start(alarm, start);
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_start_relative);
|
|
|
|
void alarm_restart(struct alarm *alarm)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
hrtimer_set_expires(&alarm->timer, alarm->node.expires);
|
|
hrtimer_restart(&alarm->timer);
|
|
alarmtimer_enqueue(base, alarm);
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_restart);
|
|
|
|
/**
|
|
* alarm_try_to_cancel - Tries to cancel an alarm timer
|
|
* @alarm: ptr to alarm to be canceled
|
|
*
|
|
* Returns 1 if the timer was canceled, 0 if it was not running,
|
|
* and -1 if the callback was running
|
|
*/
|
|
int alarm_try_to_cancel(struct alarm *alarm)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
unsigned long flags;
|
|
int ret;
|
|
|
|
spin_lock_irqsave(&base->lock, flags);
|
|
ret = hrtimer_try_to_cancel(&alarm->timer);
|
|
if (ret >= 0)
|
|
alarmtimer_dequeue(base, alarm);
|
|
spin_unlock_irqrestore(&base->lock, flags);
|
|
|
|
trace_alarmtimer_cancel(alarm, base->gettime());
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_try_to_cancel);
|
|
|
|
|
|
/**
|
|
* alarm_cancel - Spins trying to cancel an alarm timer until it is done
|
|
* @alarm: ptr to alarm to be canceled
|
|
*
|
|
* Returns 1 if the timer was canceled, 0 if it was not active.
|
|
*/
|
|
int alarm_cancel(struct alarm *alarm)
|
|
{
|
|
for (;;) {
|
|
int ret = alarm_try_to_cancel(alarm);
|
|
if (ret >= 0)
|
|
return ret;
|
|
cpu_relax();
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_cancel);
|
|
|
|
|
|
u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
|
|
{
|
|
u64 overrun = 1;
|
|
ktime_t delta;
|
|
|
|
delta = ktime_sub(now, alarm->node.expires);
|
|
|
|
if (delta < 0)
|
|
return 0;
|
|
|
|
if (unlikely(delta >= interval)) {
|
|
s64 incr = ktime_to_ns(interval);
|
|
|
|
overrun = ktime_divns(delta, incr);
|
|
|
|
alarm->node.expires = ktime_add_ns(alarm->node.expires,
|
|
incr*overrun);
|
|
|
|
if (alarm->node.expires > now)
|
|
return overrun;
|
|
/*
|
|
* This (and the ktime_add() below) is the
|
|
* correction for exact:
|
|
*/
|
|
overrun++;
|
|
}
|
|
|
|
alarm->node.expires = ktime_add_safe(alarm->node.expires, interval);
|
|
return overrun;
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_forward);
|
|
|
|
static u64 __alarm_forward_now(struct alarm *alarm, ktime_t interval, bool throttle)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
ktime_t now = base->gettime();
|
|
|
|
if (IS_ENABLED(CONFIG_HIGH_RES_TIMERS) && throttle) {
|
|
/*
|
|
* Same issue as with posix_timer_fn(). Timers which are
|
|
* periodic but the signal is ignored can starve the system
|
|
* with a very small interval. The real fix which was
|
|
* promised in the context of posix_timer_fn() never
|
|
* materialized, but someone should really work on it.
|
|
*
|
|
* To prevent DOS fake @now to be 1 jiffie out which keeps
|
|
* the overrun accounting correct but creates an
|
|
* inconsistency vs. timer_gettime(2).
|
|
*/
|
|
ktime_t kj = NSEC_PER_SEC / HZ;
|
|
|
|
if (interval < kj)
|
|
now = ktime_add(now, kj);
|
|
}
|
|
|
|
return alarm_forward(alarm, now, interval);
|
|
}
|
|
|
|
u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
|
|
{
|
|
return __alarm_forward_now(alarm, interval, false);
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_forward_now);
|
|
|
|
#ifdef CONFIG_POSIX_TIMERS
|
|
|
|
static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
|
|
{
|
|
struct alarm_base *base;
|
|
unsigned long flags;
|
|
ktime_t delta;
|
|
|
|
switch(type) {
|
|
case ALARM_REALTIME:
|
|
base = &alarm_bases[ALARM_REALTIME];
|
|
type = ALARM_REALTIME_FREEZER;
|
|
break;
|
|
case ALARM_BOOTTIME:
|
|
base = &alarm_bases[ALARM_BOOTTIME];
|
|
type = ALARM_BOOTTIME_FREEZER;
|
|
break;
|
|
default:
|
|
WARN_ONCE(1, "Invalid alarm type: %d\n", type);
|
|
return;
|
|
}
|
|
|
|
delta = ktime_sub(absexp, base->gettime());
|
|
|
|
spin_lock_irqsave(&freezer_delta_lock, flags);
|
|
if (!freezer_delta || (delta < freezer_delta)) {
|
|
freezer_delta = delta;
|
|
freezer_expires = absexp;
|
|
freezer_alarmtype = type;
|
|
}
|
|
spin_unlock_irqrestore(&freezer_delta_lock, flags);
|
|
}
|
|
|
|
/**
|
|
* clock2alarm - helper that converts from clockid to alarmtypes
|
|
* @clockid: clockid.
|
|
*/
|
|
static enum alarmtimer_type clock2alarm(clockid_t clockid)
|
|
{
|
|
if (clockid == CLOCK_REALTIME_ALARM)
|
|
return ALARM_REALTIME;
|
|
if (clockid == CLOCK_BOOTTIME_ALARM)
|
|
return ALARM_BOOTTIME;
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* alarm_handle_timer - Callback for posix timers
|
|
* @alarm: alarm that fired
|
|
*
|
|
* Posix timer callback for expired alarm timers.
|
|
*/
|
|
static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
|
|
ktime_t now)
|
|
{
|
|
struct k_itimer *ptr = container_of(alarm, struct k_itimer,
|
|
it.alarm.alarmtimer);
|
|
enum alarmtimer_restart result = ALARMTIMER_NORESTART;
|
|
unsigned long flags;
|
|
int si_private = 0;
|
|
|
|
spin_lock_irqsave(&ptr->it_lock, flags);
|
|
|
|
ptr->it_active = 0;
|
|
if (ptr->it_interval)
|
|
si_private = ++ptr->it_requeue_pending;
|
|
|
|
if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
|
|
/*
|
|
* Handle ignored signals and rearm the timer. This will go
|
|
* away once we handle ignored signals proper. Ensure that
|
|
* small intervals cannot starve the system.
|
|
*/
|
|
ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true);
|
|
++ptr->it_requeue_pending;
|
|
ptr->it_active = 1;
|
|
result = ALARMTIMER_RESTART;
|
|
}
|
|
spin_unlock_irqrestore(&ptr->it_lock, flags);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_rearm - Posix timer callback for rearming timer
|
|
* @timr: Pointer to the posixtimer data struct
|
|
*/
|
|
static void alarm_timer_rearm(struct k_itimer *timr)
|
|
{
|
|
struct alarm *alarm = &timr->it.alarm.alarmtimer;
|
|
|
|
timr->it_overrun += alarm_forward_now(alarm, timr->it_interval);
|
|
alarm_start(alarm, alarm->node.expires);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_forward - Posix timer callback for forwarding timer
|
|
* @timr: Pointer to the posixtimer data struct
|
|
* @now: Current time to forward the timer against
|
|
*/
|
|
static s64 alarm_timer_forward(struct k_itimer *timr, ktime_t now)
|
|
{
|
|
struct alarm *alarm = &timr->it.alarm.alarmtimer;
|
|
|
|
return alarm_forward(alarm, timr->it_interval, now);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_remaining - Posix timer callback to retrieve remaining time
|
|
* @timr: Pointer to the posixtimer data struct
|
|
* @now: Current time to calculate against
|
|
*/
|
|
static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now)
|
|
{
|
|
struct alarm *alarm = &timr->it.alarm.alarmtimer;
|
|
|
|
return ktime_sub(alarm->node.expires, now);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_try_to_cancel - Posix timer callback to cancel a timer
|
|
* @timr: Pointer to the posixtimer data struct
|
|
*/
|
|
static int alarm_timer_try_to_cancel(struct k_itimer *timr)
|
|
{
|
|
return alarm_try_to_cancel(&timr->it.alarm.alarmtimer);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_arm - Posix timer callback to arm a timer
|
|
* @timr: Pointer to the posixtimer data struct
|
|
* @expires: The new expiry time
|
|
* @absolute: Expiry value is absolute time
|
|
* @sigev_none: Posix timer does not deliver signals
|
|
*/
|
|
static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires,
|
|
bool absolute, bool sigev_none)
|
|
{
|
|
struct alarm *alarm = &timr->it.alarm.alarmtimer;
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
|
|
if (!absolute)
|
|
expires = ktime_add_safe(expires, base->gettime());
|
|
if (sigev_none)
|
|
alarm->node.expires = expires;
|
|
else
|
|
alarm_start(&timr->it.alarm.alarmtimer, expires);
|
|
}
|
|
|
|
/**
|
|
* alarm_clock_getres - posix getres interface
|
|
* @which_clock: clockid
|
|
* @tp: timespec to fill
|
|
*
|
|
* Returns the granularity of underlying alarm base clock
|
|
*/
|
|
static int alarm_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
|
|
{
|
|
if (!alarmtimer_get_rtcdev())
|
|
return -EINVAL;
|
|
|
|
tp->tv_sec = 0;
|
|
tp->tv_nsec = hrtimer_resolution;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* alarm_clock_get - posix clock_get interface
|
|
* @which_clock: clockid
|
|
* @tp: timespec to fill.
|
|
*
|
|
* Provides the underlying alarm base time.
|
|
*/
|
|
static int alarm_clock_get(clockid_t which_clock, struct timespec64 *tp)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
|
|
|
|
if (!alarmtimer_get_rtcdev())
|
|
return -EINVAL;
|
|
|
|
*tp = ktime_to_timespec64(base->gettime());
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_create - posix timer_create interface
|
|
* @new_timer: k_itimer pointer to manage
|
|
*
|
|
* Initializes the k_itimer structure.
|
|
*/
|
|
static int alarm_timer_create(struct k_itimer *new_timer)
|
|
{
|
|
enum alarmtimer_type type;
|
|
|
|
if (!alarmtimer_get_rtcdev())
|
|
return -EOPNOTSUPP;
|
|
|
|
if (!capable(CAP_WAKE_ALARM))
|
|
return -EPERM;
|
|
|
|
type = clock2alarm(new_timer->it_clock);
|
|
alarm_init(&new_timer->it.alarm.alarmtimer, type, alarm_handle_timer);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
|
|
* @alarm: ptr to alarm that fired
|
|
*
|
|
* Wakes up the task that set the alarmtimer
|
|
*/
|
|
static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
|
|
ktime_t now)
|
|
{
|
|
struct task_struct *task = (struct task_struct *)alarm->data;
|
|
|
|
alarm->data = NULL;
|
|
if (task)
|
|
wake_up_process(task);
|
|
return ALARMTIMER_NORESTART;
|
|
}
|
|
|
|
/**
|
|
* alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation
|
|
* @alarm: ptr to alarmtimer
|
|
* @absexp: absolute expiration time
|
|
*
|
|
* Sets the alarm timer and sleeps until it is fired or interrupted.
|
|
*/
|
|
static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
|
|
enum alarmtimer_type type)
|
|
{
|
|
struct restart_block *restart;
|
|
alarm->data = (void *)current;
|
|
do {
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
alarm_start(alarm, absexp);
|
|
if (likely(alarm->data))
|
|
schedule();
|
|
|
|
alarm_cancel(alarm);
|
|
} while (alarm->data && !signal_pending(current));
|
|
|
|
__set_current_state(TASK_RUNNING);
|
|
|
|
destroy_hrtimer_on_stack(&alarm->timer);
|
|
|
|
if (!alarm->data)
|
|
return 0;
|
|
|
|
if (freezing(current))
|
|
alarmtimer_freezerset(absexp, type);
|
|
restart = ¤t->restart_block;
|
|
if (restart->nanosleep.type != TT_NONE) {
|
|
struct timespec64 rmt;
|
|
ktime_t rem;
|
|
|
|
rem = ktime_sub(absexp, alarm_bases[type].gettime());
|
|
|
|
if (rem <= 0)
|
|
return 0;
|
|
rmt = ktime_to_timespec64(rem);
|
|
|
|
return nanosleep_copyout(restart, &rmt);
|
|
}
|
|
return -ERESTART_RESTARTBLOCK;
|
|
}
|
|
|
|
static void
|
|
alarm_init_on_stack(struct alarm *alarm, enum alarmtimer_type type,
|
|
enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
|
|
{
|
|
hrtimer_init_on_stack(&alarm->timer, alarm_bases[type].base_clockid,
|
|
HRTIMER_MODE_ABS);
|
|
__alarm_init(alarm, type, function);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
|
|
* @restart: ptr to restart block
|
|
*
|
|
* Handles restarted clock_nanosleep calls
|
|
*/
|
|
static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
|
|
{
|
|
enum alarmtimer_type type = restart->nanosleep.clockid;
|
|
ktime_t exp = restart->nanosleep.expires;
|
|
struct alarm alarm;
|
|
|
|
alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
|
|
|
|
return alarmtimer_do_nsleep(&alarm, exp, type);
|
|
}
|
|
|
|
/**
|
|
* alarm_timer_nsleep - alarmtimer nanosleep
|
|
* @which_clock: clockid
|
|
* @flags: determins abstime or relative
|
|
* @tsreq: requested sleep time (abs or rel)
|
|
* @rmtp: remaining sleep time saved
|
|
*
|
|
* Handles clock_nanosleep calls against _ALARM clockids
|
|
*/
|
|
static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
|
|
const struct timespec64 *tsreq)
|
|
{
|
|
enum alarmtimer_type type = clock2alarm(which_clock);
|
|
struct restart_block *restart = ¤t->restart_block;
|
|
struct alarm alarm;
|
|
ktime_t exp;
|
|
int ret = 0;
|
|
|
|
if (!alarmtimer_get_rtcdev())
|
|
return -EOPNOTSUPP;
|
|
|
|
if (flags & ~TIMER_ABSTIME)
|
|
return -EINVAL;
|
|
|
|
if (!capable(CAP_WAKE_ALARM))
|
|
return -EPERM;
|
|
|
|
alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
|
|
|
|
exp = timespec64_to_ktime(*tsreq);
|
|
/* Convert (if necessary) to absolute time */
|
|
if (flags != TIMER_ABSTIME) {
|
|
ktime_t now = alarm_bases[type].gettime();
|
|
|
|
exp = ktime_add_safe(now, exp);
|
|
}
|
|
|
|
ret = alarmtimer_do_nsleep(&alarm, exp, type);
|
|
if (ret != -ERESTART_RESTARTBLOCK)
|
|
return ret;
|
|
|
|
/* abs timers don't set remaining time or restart */
|
|
if (flags == TIMER_ABSTIME)
|
|
return -ERESTARTNOHAND;
|
|
|
|
restart->nanosleep.clockid = type;
|
|
restart->nanosleep.expires = exp;
|
|
set_restart_fn(restart, alarm_timer_nsleep_restart);
|
|
return ret;
|
|
}
|
|
|
|
const struct k_clock alarm_clock = {
|
|
.clock_getres = alarm_clock_getres,
|
|
.clock_get = alarm_clock_get,
|
|
.timer_create = alarm_timer_create,
|
|
.timer_set = common_timer_set,
|
|
.timer_del = common_timer_del,
|
|
.timer_get = common_timer_get,
|
|
.timer_arm = alarm_timer_arm,
|
|
.timer_rearm = alarm_timer_rearm,
|
|
.timer_forward = alarm_timer_forward,
|
|
.timer_remaining = alarm_timer_remaining,
|
|
.timer_try_to_cancel = alarm_timer_try_to_cancel,
|
|
.nsleep = alarm_timer_nsleep,
|
|
};
|
|
#endif /* CONFIG_POSIX_TIMERS */
|
|
|
|
|
|
/* Suspend hook structures */
|
|
static const struct dev_pm_ops alarmtimer_pm_ops = {
|
|
.suspend = alarmtimer_suspend,
|
|
.resume = alarmtimer_resume,
|
|
};
|
|
|
|
static struct platform_driver alarmtimer_driver = {
|
|
.driver = {
|
|
.name = "alarmtimer",
|
|
.pm = &alarmtimer_pm_ops,
|
|
}
|
|
};
|
|
|
|
/**
|
|
* alarmtimer_init - Initialize alarm timer code
|
|
*
|
|
* This function initializes the alarm bases and registers
|
|
* the posix clock ids.
|
|
*/
|
|
static int __init alarmtimer_init(void)
|
|
{
|
|
int error;
|
|
int i;
|
|
|
|
alarmtimer_rtc_timer_init();
|
|
|
|
/* Initialize alarm bases */
|
|
alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
|
|
alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real;
|
|
alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME;
|
|
alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime;
|
|
for (i = 0; i < ALARM_NUMTYPE; i++) {
|
|
timerqueue_init_head(&alarm_bases[i].timerqueue);
|
|
spin_lock_init(&alarm_bases[i].lock);
|
|
}
|
|
|
|
error = alarmtimer_rtc_interface_setup();
|
|
if (error)
|
|
return error;
|
|
|
|
error = platform_driver_register(&alarmtimer_driver);
|
|
if (error)
|
|
goto out_if;
|
|
|
|
return 0;
|
|
out_if:
|
|
alarmtimer_rtc_interface_remove();
|
|
return error;
|
|
}
|
|
device_initcall(alarmtimer_init);
|