* 4.9/tmp-8dd0f52: Linux 4.9.72 sparc32: Export vac_cache_size to fix build error bpf: fix incorrect sign extension in check_alu_op() bpf: reject out-of-bounds stack pointer calculation bpf: fix branch pruning logic bpf: adjust insn_aux_data when patching insns Revert "Bluetooth: btusb: driver to enable the usb-wakeup feature" platform/x86: asus-wireless: send an EV_SYN/SYN_REPORT between state changes MIPS: math-emu: Fix final emulation phase for certain instructions thermal/drivers/hisi: Fix multiple alarm interrupts firing thermal/drivers/hisi: Simplify the temperature/step computation thermal/drivers/hisi: Fix kernel panic on alarm interrupt thermal/drivers/hisi: Fix missing interrupt enablement thermal: hisilicon: Handle return value of clk_prepare_enable cpuidle: fix broadcast control when broadcast can not be entered rtc: set the alarm to the next expiring timer tcp: fix under-evaluated ssthresh in TCP Vegas clk: sunxi-ng: sun6i: Rename HDMI DDC clock to avoid name collision staging: greybus: light: Release memory obtained by kasprintf net: ipv6: send NS for DAD when link operationally up fm10k: ensure we process SM mbx when processing VF mbx vfio/pci: Virtualize Maximum Payload Size scsi: lpfc: PLOGI failures during NPIV testing scsi: lpfc: Fix secure firmware updates fm10k: fix mis-ordered parameters in declaration for .ndo_set_vf_bw ASoC: img-parallel-out: Add pm_runtime_get/put to set_fmt callback tracing: Exclude 'generic fields' from histograms PCI/AER: Report non-fatal errors only to the affected endpoint IB/rxe: check for allocation failure on elem ixgbe: fix use of uninitialized padding igb: check memory allocation failure PM / OPP: Move error message to debug level PCI: Create SR-IOV virtfn/physfn links before attaching driver scsi: mpt3sas: Fix IO error occurs on pulling out a drive from RAID1 volume created on two SATA drive scsi: cxgb4i: fix Tx skb leak PCI: Avoid bus reset if bridge itself is broken net: phy: at803x: Change error to EINVAL for invalid MAC kvm, mm: account kvm related kmem slabs to kmemcg rtc: pl031: make interrupt optional crypto: crypto4xx - increase context and scatter ring buffer elements backlight: pwm_bl: Fix overflow condition bnxt_en: Fix NULL pointer dereference in reopen failure path cpuidle: powernv: Pass correct drv->cpumask for registration ARM: dma-mapping: disallow dma_get_sgtable() for non-kernel managed memory Btrfs: fix an integer overflow check netfilter: nfnetlink_queue: fix secctx memory leak xhci: plat: Register shutdown for xhci_plat net: moxa: fix TX overrun memory leak isdn: kcapi: avoid uninitialized data virtio_balloon: prevent uninitialized variable use virtio-balloon: use actual number of stats for stats queue buffers KVM: pci-assign: do not map smm memory slot pages in vt-d page tables net: ipconfig: fix ic_close_devs() use-after-free cpufreq: Fix creation of symbolic links to policy directories ARM: dts: am335x-evmsk: adjust mmc2 param to allow suspend netfilter: nf_nat_snmp: Fix panic when snmp_trap_helper fails to register netfilter: nfnl_cthelper: fix a race when walk the nf_ct_helper_hash table irda: vlsi_ir: fix check for DMA mapping errors RDMA/iser: Fix possible mr leak on device removal event i40e: Do not enable NAPI on q_vectors that have no rings IB/rxe: increment msn only when completing a request IB/rxe: double free on error net: Do not allow negative values for busy_read and busy_poll sysctl interfaces nbd: set queue timeout properly infiniband: Fix alignment of mmap cookies to support VIPT caching IB/core: Protect against self-requeue of a cq work item i40iw: Receive netdev events post INET_NOTIFIER state bna: avoid writing uninitialized data into hw registers s390/qeth: no ETH header for outbound AF_IUCV s390/qeth: size calculation outbound buffers r8152: prevent the driver from transmitting packets with carrier off ASoC: STI: Fix reader substream pointer set HID: xinmo: fix for out of range for THT 2P arcade controller. hwmon: (asus_atk0110) fix uninitialized data access ARM: dts: ti: fix PCI bus dtc warnings KVM: VMX: Fix enable VPID conditions KVM: x86: correct async page present tracepoint kvm: vmx: Flush TLB when the APIC-access address changes scsi: lpfc: Fix PT2PT PRLI reject pinctrl: st: add irq_request/release_resources callbacks inet: frag: release spinlock before calling icmp_send() tipc: fix nametbl deadlock at tipc_nametbl_unsubscribe r8152: fix the rx early size of RTL8153 iommu/exynos: Workaround FLPD cache flush issues for SYSMMU v5 netfilter: nfnl_cthelper: Fix memory leak netfilter: nfnl_cthelper: fix runtime expectation policy updates usb: gadget: udc: remove pointer dereference after free usb: gadget: f_uvc: Sanity check wMaxPacketSize for SuperSpeed hwmon: (max31790) Set correct PWM value net: qmi_wwan: Add USB IDs for MDM6600 modem on Motorola Droid 4 sctp: out_qlen should be updated when pruning unsent queue bna: integer overflow bug in debugfs sch_dsmark: fix invalid skb_cow() usage vsock: cancel packets when failing to connect vhost-vsock: add pkt cancel capability vsock: track pkt owner vsock crypto: deadlock between crypto_alg_sem/rtnl_mutex/genl_mutex r8152: fix the list rx_done may be used without initialization cpuidle: Validate cpu_dev in cpuidle_add_sysfs() nvme-loop: handle cpu unplug when re-establishing the controller arm: kprobes: Align stack to 8-bytes in test code arm: kprobes: Fix the return address of multiple kretprobes HID: corsair: Add driver Scimitar Pro RGB gaming mouse 1b1c:1b3e support to hid-corsair HID: corsair: support for K65-K70 Rapidfire and Scimitar Pro RGB kvm: fix usage of uninit spinlock in avic_vm_destroy() ALSA: hda - add support for docking station for HP 840 G3 ALSA: hda - add support for docking station for HP 820 G2 arm64: Initialise high_memory global variable earlier cxl: Check if vphb exists before iterating over AFU devices Linux 4.9.71 ath9k: fix tx99 potential info leak icmp: don't fail on fragment reassembly time exceeded IB/ipoib: Grab rtnl lock on heavy flush when calling ndo_open/stop RDMA/cma: Avoid triggering undefined behavior macvlan: Only deliver one copy of the frame to the macvlan interface udf: Avoid overflow when session starts at large offset scsi: bfa: integer overflow in debugfs scsi: sd: change allow_restart to bool in sysfs interface scsi: sd: change manage_start_stop to bool in sysfs interface rtl8188eu: Fix a possible sleep-in-atomic bug in rtw_disassoc_cmd rtl8188eu: Fix a possible sleep-in-atomic bug in rtw_createbss_cmd vt6655: Fix a possible sleep-in-atomic bug in vt6655_suspend IB/core: Fix calculation of maximum RoCE MTU scsi: scsi_devinfo: Add REPORTLUN2 to EMC SYMMETRIX blacklist entry raid5: Set R5_Expanded on parity devices as well as data. pinctrl: adi2: Fix Kconfig build problem usb: musb: da8xx: fix babble condition handling tty fix oops when rmmod 8250 soc: mediatek: pwrap: fix compiler errors powerpc/perf/hv-24x7: Fix incorrect comparison in memord scsi: hpsa: destroy sas transport properties before scsi_host scsi: hpsa: cleanup sas_phy structures in sysfs when unloading PCI: Detach driver before procfs & sysfs teardown on device remove RDMA/cxgb4: Declare stag as __be32 xfs: fix incorrect extent state in xfs_bmap_add_extent_unwritten_real xfs: fix log block underflow during recovery cycle verification l2tp: cleanup l2tp_tunnel_delete calls nvme: use kref_get_unless_zero in nvme_find_get_ns platform/x86: hp_accel: Add quirk for HP ProBook 440 G4 btrfs: tests: Fix a memory leak in error handling path in 'run_test()' arm64: prevent regressions in compressed kernel image size when upgrading to binutils 2.27 Ib/hfi1: Return actual operational VLs in port info query bcache: fix wrong cache_misses statistics bcache: explicitly destroy mutex while exiting GFS2: Take inode off order_write list when setting jdata flag scsi: scsi_debug: write_same: fix error report thermal/drivers/step_wise: Fix temperature regulation misbehavior ASoC: rsnd: rsnd_ssi_run_mods() needs to care ssi_parent_mod ppp: Destroy the mutex when cleanup clk: tegra: Fix cclk_lp divisor register clk: hi6220: mark clock cs_atb_syspll as critical clk: imx6: refine hdmi_isfr's parent to make HDMI work on i.MX6 SoCs w/o VPU clk: mediatek: add the option for determining PLL source clock mm: Handle 0 flags in _calc_vm_trans() macro crypto: tcrypt - fix buffer lengths in test_aead_speed() arm-ccn: perf: Prevent module unload while PMU is in use xfs: truncate pagecache before writeback in xfs_setattr_size() iommu/amd: Limit the IOVA page range to the specified addresses badblocks: fix wrong return value in badblocks_set if badblocks are disabled target/file: Do not return error for UNMAP if length is zero target:fix condition return in core_pr_dump_initiator_port() iscsi-target: fix memory leak in lio_target_tiqn_addtpg() target/iscsi: Fix a race condition in iscsit_add_reject_from_cmd() platform/x86: intel_punit_ipc: Fix resource ioremap warning powerpc/ipic: Fix status get and status clear powerpc/opal: Fix EBUSY bug in acquiring tokens netfilter: ipvs: Fix inappropriate output of procfs iommu/mediatek: Fix driver name PCI: Do not allocate more buses than available in parent powerpc/powernv/cpufreq: Fix the frequency read by /proc/cpuinfo PCI/PME: Handle invalid data when reading Root Status dmaengine: ti-dma-crossbar: Correct am335x/am43xx mux value type ASoC: Intel: Skylake: Fix uuid_module memory leak in failure case rtc: pcf8563: fix output clock rate video: fbdev: au1200fb: Return an error code if a memory allocation fails video: fbdev: au1200fb: Release some resources if a memory allocation fails video: udlfb: Fix read EDID timeout fbdev: controlfb: Add missing modes to fix out of bounds access sfc: don't warn on successful change of MAC HID: cp2112: fix broken gpio_direction_input callback Revert "x86/acpi: Set persistent cpuid <-> nodeid mapping when booting" target: fix race during implicit transition work flushes target: fix ALUA transition timeout handling target: Use system workqueue for ALUA transitions btrfs: add missing memset while reading compressed inline extents NFSv4.1 respect server's max size in CREATE_SESSION efi/esrt: Cleanup bad memory map log messages perf symbols: Fix symbols__fixup_end heuristic for corner cases tty: fix data race in tty_ldisc_ref_wait() tty: don't panic on OOM in tty_set_ldisc() rxrpc: Ignore BUSY packets on old calls net: mpls: Fix nexthop alive tracking on down events net/mlx4_core: Avoid delays during VF driver device shutdown nvmet-rdma: Fix a possible uninitialized variable dereference nvmet: confirm sq percpu has scheduled and switched to atomic nvme-loop: fix a possible use-after-free when destroying the admin queue afs: Fix abort on signal while waiting for call completion afs: Fix afs_kill_pages() afs: Fix page leak in afs_write_begin() afs: Populate and use client modification time afs: Better abort and net error handling afs: Invalid op ID should abort with RXGEN_OPCODE afs: Fix the maths in afs_fs_store_data() afs: Prevent callback expiry timer overflow afs: Migrate vlocation fields to 64-bit afs: Flush outstanding writes when an fd is closed afs: Deal with an empty callback array afs: Adjust mode bits processing afs: Populate group ID from vnode status afs: Fix missing put_page() drm/radeon: reinstate oland workaround for sclk mmc: mediatek: Fixed bug where clock frequency could be set wrong sched/deadline: Use deadline instead of period when calculating overflow sched/deadline: Throttle a constrained deadline task activated after the deadline sched/deadline: Make sure the replenishment timer fires in the next period sched/deadline: Add missing update_rq_clock() in dl_task_timer() iwlwifi: mvm: cleanup pending frames in DQA mode Drivers: hv: util: move waiting for release to hv_utils_transport itself drm/radeon/si: add dpm quirk for Oland fjes: Fix wrong netdevice feature flags scsi: hpsa: do not timeout reset operations scsi: hpsa: limit outstanding rescans scsi: hpsa: update check for logical volume status ASoC: rcar: clear DE bit only in PDMACHCR when it stops openrisc: fix issue handling 8 byte get_user calls intel_th: pci: Add Gemini Lake support drm: amd: remove broken include path qed: Fix interrupt flags on Rx LL2 qed: Fix mapping leak on LL2 rx flow qed: Align CIDs according to DORQ requirement mlxsw: reg: Fix SPVMLR max record count mlxsw: reg: Fix SPVM max record count net: Resend IGMP memberships upon peer notification. irqchip/mvebu-odmi: Select GENERIC_MSI_IRQ_DOMAIN dmaengine: Fix array index out of bounds warning in __get_unmap_pool() net: wimax/i2400m: fix NULL-deref at probe writeback: fix memory leak in wb_queue_work() blk-mq: Fix tagset reinit in the presence of cpu hot-unplug ASoC: rsnd: fix sound route path when using SRC6/SRC9 netfilter: bridge: honor frag_max_size when refragmenting drm/omap: fix dmabuf mmap for dma_alloc'ed buffers Input: i8042 - add TUXEDO BU1406 (N24_25BU) to the nomux list NFSD: fix nfsd_reset_versions for NFSv4. NFSD: fix nfsd_minorversion(.., NFSD_AVAIL) drm/amdgpu: fix parser init error path to avoid crash in parser fini iommu/io-pgtable-arm-v7s: Check for leaf entry before dereferencing it net/mlx5: Don't save PCI state when PCI error is detected net/mlx5: Fix create autogroup prev initializer rxrpc: Wake up the transmitter if Rx window size increases on the peer net: bcmgenet: Power up the internal PHY before probing the MII net: bcmgenet: synchronize irq0 status between the isr and task net: bcmgenet: power down internal phy if open or resume fails net: bcmgenet: reserved phy revisions must be checked first net: bcmgenet: correct MIB access of UniMAC RUNT counters net: bcmgenet: correct the RBUF_OVFL_CNT and RBUF_ERR_CNT MIB values bnxt_en: Ignore 0 value in autoneg supported speed from firmware. net: initialize msg.msg_flags in recvfrom userfaultfd: selftest: vm: allow to build in vm/ directory userfaultfd: shmem: __do_fault requires VM_FAULT_NOPAGE md-cluster: free md_cluster_info if node leave cluster usb: xhci-mtk: check hcc_params after adding primary hcd KVM: nVMX: do not warn when MSR bitmap address is not backed usb: phy: isp1301: Add OF device ID table mac80211: Fix addition of mesh configuration element ext4: fix crash when a directory's i_size is too small ext4: fix fdatasync(2) after fallocate(2) operation dmaengine: dmatest: move callback wait queue to thread context eeprom: at24: change nvmem stride to 1 sched/rt: Do not pull from current CPU if only one CPU to pull nfs: don't wait on commit in nfs_commit_inode() if there were no commit requests xhci: Don't add a virt_dev to the devs array before it's fully allocated Bluetooth: btusb: driver to enable the usb-wakeup feature usb: xhci: fix TDS for MTK xHCI1.1 ceph: drop negative child dentries before try pruning inode's alias usbip: fix stub_send_ret_submit() vulnerability to null transfer_buffer usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input usb: add helper to extract bits 12:11 of wMaxPacketSize usbip: fix stub_rx: get_pipe() to validate endpoint number USB: core: prevent malicious bNumInterfaces overflow USB: uas and storage: Add US_FL_BROKEN_FUA for another JMicron JMS567 ID tracing: Allocate mask_str buffer dynamically autofs: fix careless error in recent commit crypto: salsa20 - fix blkcipher_walk API usage crypto: hmac - require that the underlying hash algorithm is unkeyed crypto: rsa - fix buffer overread when stripping leading zeroes mfd: fsl-imx25: Clean up irq settings during removal Linux 4.9.70 RDMA/cxgb4: Annotate r2 and stag as __be32 md: free unused memory after bitmap resize audit: ensure that 'audit=1' actually enables audit for PID 1 ipvlan: fix ipv6 outbound device kbuild: do not call cc-option before KBUILD_CFLAGS initialization powerpc/64: Fix checksum folding in csum_tcpudp_nofold and ip_fast_csum_nofold KVM: arm/arm64: vgic-its: Preserve the revious read from the pending table fix kcm_clone() usb: gadget: ffs: Forbid usb_ep_alloc_request from sleeping s390: always save and restore all registers on context switch ipmi: Stop timers before cleaning up the module Fix handling of verdicts after NF_QUEUE tipc: call tipc_rcv() only if bearer is up in tipc_udp_recv() s390/qeth: fix thinko in IPv4 multicast address tracking s390/qeth: fix GSO throughput regression s390/qeth: build max size GSO skbs on L2 devices tcp/dccp: block bh before arming time_wait timer stmmac: reset last TSO segment size after device open net: remove hlist_nulls_add_tail_rcu() usbnet: fix alignment for frames with no ethernet header net/packet: fix a race in packet_bind() and packet_notifier() packet: fix crash in fanout_demux_rollover() sit: update frag_off info rds: Fix NULL pointer dereference in __rds_rdma_map tipc: fix memory leak in tipc_accept_from_sock() s390/qeth: fix early exit from error path net: qmi_wwan: add Quectel BG96 2c7c:0296 ANDROID: dma-buf/sw_sync: Rename active_list to link FROMLIST: android: binder: Fix null ptr dereference in debug msg FROMLIST: android: binder: Move buffer out of area shared with user space FROMLIST: android: binder: Add allocator selftest FROMLIST: android: binder: Refactor prev and next buffer into a helper function Linux 4.9.69 afs: Connect up the CB.ProbeUuid IB/mlx5: Assign send CQ and recv CQ of UMR QP IB/mlx4: Increase maximal message size under UD QP xfrm: Copy policy family in clone_policy jump_label: Invoke jump_label_test() via early_initcall() atm: horizon: Fix irq release error clk: uniphier: fix DAPLL2 clock rate of Pro5 bpf: fix lockdep splat sctp: use the right sk after waking up from wait_buf sleep sctp: do not free asoc when it is already dead in sctp_sendmsg zsmalloc: calling zs_map_object() from irq is a bug sparc64/mm: set fields in deferred pages block: wake up all tasks blocked in get_request() dt-bindings: usb: fix reg-property port-number range xfs: fix forgotten rcu read unlock when skipping inode reclaim sunrpc: Fix rpc_task_begin trace point NFS: Fix a typo in nfs_rename() dynamic-debug-howto: fix optional/omitted ending line number to be LARGE instead of 0 lib/genalloc.c: make the avail variable an atomic_long_t drivers/rapidio/devices/rio_mport_cdev.c: fix resource leak in error handling path in 'rio_dma_transfer()' route: update fnhe_expires for redirect when the fnhe exists route: also update fnhe_genid when updating a route cache gre6: use log_ecn_error module parameter in ip6_tnl_rcv() mac80211_hwsim: Fix memory leak in hwsim_new_radio_nl() x86/mpx/selftests: Fix up weird arrays coccinelle: fix parallel build with CHECK=scripts/coccicheck kbuild: pkg: use --transform option to prefix paths in tar EDAC, i5000, i5400: Fix definition of NRECMEMB register EDAC, i5000, i5400: Fix use of MTR_DRAM_WIDTH macro powerpc/powernv/ioda2: Gracefully fail if too many TCE levels requested drm/amd/amdgpu: fix console deadlock if late init failed axonram: Fix gendisk handling netfilter: don't track fragmented packets zram: set physical queue limits to avoid array out of bounds accesses blk-mq: initialize mq kobjects in blk_mq_init_allocated_queue() i2c: riic: fix restart condition crypto: s5p-sss - Fix completing crypto request in IRQ handler ipv6: reorder icmpv6_init() and ip6_mr_init() ibmvnic: Allocate number of rx/tx buffers agreed on by firmware ibmvnic: Fix overflowing firmware/hardware TX queue rds: tcp: Sequence teardown of listen and acceptor sockets to avoid races bnx2x: do not rollback VF MAC/VLAN filters we did not configure bnx2x: fix detection of VLAN filtering feature for VF bnx2x: fix possible overrun of VFPF multicast addresses array bnx2x: prevent crash when accessing PTP with interface down spi_ks8995: regs_size incorrect for some devices spi_ks8995: fix "BUG: key accdaa28 not in .data!" KVM: arm/arm64: VGIC: Fix command handling while ITS being disabled arm64: KVM: Survive unknown traps from guests arm: KVM: Survive unknown traps from guests KVM: nVMX: reset nested_run_pending if the vCPU is going to be reset irqchip/crossbar: Fix incorrect type of register size scsi: lpfc: Fix crash during Hardware error recovery on SLI3 adapters scsi: qla2xxx: Fix ql_dump_buffer workqueue: trigger WARN if queue_delayed_work() is called with NULL @wq libata: drop WARN from protocol error in ata_sff_qc_issue() kvm: nVMX: VMCLEAR should not cause the vCPU to shut down usb: gadget: udc: net2280: Fix tmp reusage in net2280 driver usb: gadget: pxa27x: Test for a valid argument pointer usb: dwc3: gadget: Fix system suspend/resume on TI platforms USB: gadgetfs: Fix a potential memory leak in 'dev_config()' usb: gadget: configs: plug memory leak HID: chicony: Add support for another ASUS Zen AiO keyboard gpio: altera: Use handle_level_irq when configured as a level_high ASoC: rcar: avoid SSI_MODEx settings for SSI8 ARM: OMAP2+: Release device node after it is no longer needed. ARM: OMAP2+: Fix device node reference counts powerpc/64: Fix checksum folding in csum_add() module: set __jump_table alignment to 8 lirc: fix dead lock between open and wakeup_filter powerpc: Fix compiling a BE kernel with a powerpc64le toolchain selftest/powerpc: Fix false failures for skipped tests powerpc/64: Invalidate process table caching after setting process table x86/hpet: Prevent might sleep splat on resume sched/fair: Make select_idle_cpu() more aggressive x86/platform/uv/BAU: Fix HUB errors by remove initial write to sw-ack register x86/selftests: Add clobbers for int80 on x86_64 ARM: OMAP2+: gpmc-onenand: propagate error on initialization failure vti6: Don't report path MTU below IPV6_MIN_MTU. ARM: 8657/1: uaccess: consistently check object sizes Revert "spi: SPI_FSL_DSPI should depend on HAS_DMA" Revert "drm/armada: Fix compile fail" mm: drop unused pmdp_huge_get_and_clear_notify() thp: fix MADV_DONTNEED vs. numa balancing race thp: reduce indentation level in change_huge_pmd() ARM: avoid faulting on qemu ARM: BUG if jumping to usermode address in kernel mode usb: f_fs: Force Reserved1=1 in OS_DESC_EXT_COMPAT crypto: talitos - fix ctr-aes-talitos crypto: talitos - fix use of sg_link_tbl_len crypto: talitos - fix AEAD for sha224 on non sha224 capable chips crypto: talitos - fix setkey to check key weakness crypto: talitos - fix memory corruption on SEC2 crypto: talitos - fix AEAD test failures bus: arm-ccn: fix module unloading Error: Removing state 147 which has instances left. bus: arm-ccn: Fix use of smp_processor_id() in preemptible context bus: arm-ccn: Check memory allocation failure bus: arm-cci: Fix use of smp_processor_id() in preemptible context arm64: fpsimd: Prevent registers leaking from dead tasks KVM: arm/arm64: vgic-its: Check result of allocation before use KVM: arm/arm64: vgic-irqfd: Fix MSI entry allocation KVM: arm/arm64: Fix broken GICH_ELRSR big endian conversion KVM: VMX: remove I/O port 0x80 bypass on Intel hosts arm: KVM: Fix VTTBR_BADDR_MASK BUG_ON off-by-one arm64: KVM: fix VTTBR_BADDR_MASK BUG_ON off-by-one media: dvb: i2c transfers over usb cannot be done from stack drm/exynos: gem: Drop NONCONTIG flag for buffers allocated without IOMMU kdb: Fix handling of kallsyms_symbol_next() return value brcmfmac: change driver unbind order of the sdio function devices powerpc/64s: Initialize ISAv3 MMU registers before setting partition table KVM: s390: Fix skey emulation permission check s390: fix compat system call table smp/hotplug: Move step CPUHP_AP_SMPCFD_DYING to the correct place iommu/vt-d: Fix scatterlist offset handling ALSA: usb-audio: Add check return value for usb_string() ALSA: usb-audio: Fix out-of-bound error ALSA: seq: Remove spurious WARN_ON() at timer check ALSA: pcm: prevent UAF in snd_pcm_info btrfs: fix missing error return in btrfs_drop_snapshot KVM: x86: fix APIC page invalidation x86/PCI: Make broadcom_postcore_init() check acpi_disabled X.509: fix comparisons of ->pkey_algo X.509: reject invalid BIT STRING for subjectPublicKey KEYS: add missing permission check for request_key() destination ASN.1: check for error from ASN1_OP_END__ACT actions ASN.1: fix out-of-bounds read when parsing indefinite length item efi/esrt: Use memunmap() instead of kfree() to free the remapping efi: Move some sysfs files to be read-only by root scsi: libsas: align sata_device's rps_resp on a cacheline scsi: use dma_get_cache_alignment() as minimum DMA alignment scsi: dma-mapping: always provide dma_get_cache_alignment isa: Prevent NULL dereference in isa_bus driver callbacks hv: kvp: Avoid reading past allocated blocks from KVP file virtio: release virtio index when fail to device_register can: usb_8dev: cancel urb on -EPIPE and -EPROTO can: esd_usb2: cancel urb on -EPIPE and -EPROTO can: ems_usb: cancel urb on -EPIPE and -EPROTO can: kvaser_usb: cancel urb on -EPIPE and -EPROTO can: kvaser_usb: ratelimit errors if incomplete messages are received can: kvaser_usb: Fix comparison bug in kvaser_usb_read_bulk_callback() can: kvaser_usb: free buf in error paths can: ti_hecc: Fix napi poll return value for repoll usb: gadget: udc: renesas_usb3: fix number of the pipes ANDROID: Revert "arm64: move ELF_ET_DYN_BASE to 4GB / 4MB" ANDROID: Revert "arm: move ELF_ET_DYN_BASE to 4MB" Linux 4.9.68 xen-netfront: avoid crashing on resume after a failure in talk_to_netback() usb: host: fix incorrect updating of offset USB: usbfs: Filter flags passed in from user space USB: devio: Prevent integer overflow in proc_do_submiturb() USB: Increase usbfs transfer limit USB: core: Add type-specific length check of BOS descriptors usb: xhci: fix panic in xhci_free_virt_devices_depth_first usb: hub: Cycle HUB power when initialization fails dma-buf: Update kerneldoc for sync_file_create dma-buf/sync_file: hold reference to fence when creating sync_file dma-buf/sw_sync: force signal all unsignaled fences on dying timeline dma-fence: Introduce drm_fence_set_error() helper dma-fence: Wrap querying the fence->status dma-fence: Clear fence->status during dma_fence_init() dma-buf/sw_sync: clean up list before signaling the fence dma-buf/sw_sync: move timeline_fence_ops around dma-buf/sw-sync: Use an rbtree to sort fences in the timeline dma-buf/sw-sync: Fix locking around sync_timeline lists dma-buf/sw-sync: sync_pt is private and of fixed size dma-buf/sw-sync: Reduce irqsave/irqrestore from known context dma-buf/sw-sync: Prevent user overflow on timeline advance dma-buf/sw-sync: Fix the is-signaled test to handle u32 wraparound dma-buf/dma-fence: Extract __dma_fence_is_later() net: fec: fix multicast filtering hardware setup xen-netback: vif counters from int/long to u64 cec: initiator should be the same as the destination for, poll xen-netfront: Improve error handling during initialization mm: avoid returning VM_FAULT_RETRY from ->page_mkwrite handlers vfio/spapr: Fix missing mutex unlock when creating a window be2net: fix initial MAC setting net: thunderx: avoid dereferencing xcv when NULL net: phy: micrel: KSZ8795 do not set SUPPORTED_[Asym_]Pause gtp: fix cross netns recv on gtp socket gtp: clear DF bit on GTP packet tx nvmet: cancel fatal error and flush async work before free controller i2c: i2c-cadence: Initialize configuration before probing devices tcp: correct memory barrier usage in tcp_check_space() dmaengine: pl330: fix double lock tipc: fix cleanup at module unload tipc: fix nametbl_lock soft lockup at module exit RDMA/qedr: Fix RDMA CM loopback RDMA/qedr: Return success when not changing QP state mac80211: don't try to sleep in rate_control_rate_init() drm/amdgpu: fix unload driver issue for virtual display x86/fpu: Set the xcomp_bv when we fake up a XSAVES area net: sctp: fix array overrun read on sctp_timer_tbl drm/exynos/decon5433: set STANDALONE_UPDATE_F on output enablement drm/amdgpu: fix bug set incorrect value to vce register qla2xxx: Fix wrong IOCB type assumption powerpc/mm: Fix memory hotplug BUG() on radix perf/x86/intel: Account interrupts for PEBS errors NFSv4: Fix client recovery when server reboots multiple times mac80211: prevent skb/txq mismatch KVM: arm/arm64: Fix occasional warning from the timer work function drm/exynos/decon5433: set STANDALONE_UPDATE_F also if planes are disabled drm/exynos/decon5433: update shadow registers iff there are active windows nfs: Don't take a reference on fl->fl_file for LOCK operation ravb: Remove Rx overflow log messages mac80211: calculate min channel width correctly mm: fix remote numa hits statistics net: qrtr: Mark 'buf' as little endian libfs: Modify mount_pseudo_xattr to be clear it is not a userspace mount net/appletalk: Fix kernel memory disclosure be2net: fix unicast list filling be2net: fix accesses to unicast list vti6: fix device register to report IFLA_INFO_KIND ARM: OMAP1: DMA: Correct the number of logical channels ARM: OMAP2+: Fix WL1283 Bluetooth Baud Rate net: systemport: Pad packet before inserting TSB net: systemport: Utilize skb_put_padto() libcxgb: fix error check for ip6_route_output() usb: gadget: f_fs: Fix ExtCompat descriptor validation dmaengine: stm32-dma: Fix null pointer dereference in stm32_dma_tx_status dmaengine: stm32-dma: Set correct args number for DMA request from DT l2tp: take remote address into account in l2tp_ip and l2tp_ip6 socket lookups net/mlx4_en: Fix type mismatch for 32-bit systems dax: Avoid page invalidation races and unnecessary radix tree traversals iio: adc: ti-ads1015: add 10% to conversion wait time tools include: Do not use poison with C++ kprobes/x86: Disable preemption in ftrace-based jprobes perf test attr: Fix ignored test case result usbip: tools: Install all headers needed for libusbip development sysrq : fix Show Regs call trace on ARM EDAC, sb_edac: Fix missing break in switch x86/entry: Use SYSCALL_DEFINE() macros for sys_modify_ldt() serial: 8250: Preserve DLD[7:4] for PORT_XR17V35X usb: phy: tahvo: fix error handling in tahvo_usb_probe() mmc: sdhci-msm: fix issue with power irq spi: spi-axi: fix potential use-after-free after deregistration spi: sh-msiof: Fix DMA transfer size check staging: rtl8188eu: avoid a null dereference on pmlmepriv serial: 8250_fintek: Fix rs485 disablement on invalid ioctl() m68k: fix ColdFire node shift size calculation staging: greybus: loopback: Fix iteration count on async path selftests/x86/ldt_get: Add a few additional tests for limits s390/pci: do not require AIS facility ima: fix hash algorithm initialization USB: serial: option: add Quectel BG96 id s390/runtime instrumentation: simplify task exit handling serial: 8250_pci: Add Amazon PCI serial device ID usb: quirks: Add no-lpm quirk for KY-688 USB 3.1 Type-C Hub uas: Always apply US_FL_NO_ATA_1X quirk to Seagate devices mm, oom_reaper: gather each vma to prevent leaking TLB entry Revert "crypto: caam - get rid of tasklet" drm/fsl-dcu: enable IRQ before drm_atomic_helper_resume() drm/fsl-dcu: avoid disabling pixel clock twice on suspend bcache: recover data from backing when data is clean bcache: only permit to recovery read error when cache device is clean Linux 4.9.67 drm/i915: Prevent zero length "index" write drm/i915: Don't try indexed reads to alternate slave addresses NFS: revalidate "." etc correctly on "open". Revert "x86/entry/64: Add missing irqflags tracing to native_load_gs_index()" drm/amd/pp: fix typecast error in powerplay. drm/ttm: once more fix ttm_buffer_object_transfer drm/hisilicon: Ensure LDI regs are properly configured. drm/panel: simple: Add missing panel_simple_unprepare() calls drm/radeon: fix atombios on big endian drm/amdgpu: Potential uninitialized variable in amdgpu_vm_update_directories() drm/amdgpu: potential uninitialized variable in amdgpu_vce_ring_parse_cs() Revert "drm/radeon: dont switch vt on suspend" nvme-pci: add quirk for delay before CHK RDY for WDC SN200 hwmon: (jc42) optionally try to disable the SMBUS timeout bcache: Fix building error on MIPS i2c: i801: Fix Failed to allocate irq -2147483648 error eeprom: at24: check at24_read/write arguments eeprom: at24: correctly set the size for at24mac402 eeprom: at24: fix reading from 24MAC402/24MAC602 mmc: core: prepend 0x to OCR entry in sysfs mmc: core: Do not leave the block driver in a suspended state KVM: lapic: Fixup LDR on load in x2apic KVM: lapic: Split out x2apic ldr calculation KVM: x86: inject exceptions produced by x86_decode_insn KVM: x86: Exit to user-mode on #UD intercept when emulator requires KVM: x86: pvclock: Handle first-time write to pvclock-page contains random junk ARM: OMAP2+: Fix WL1283 Bluetooth Baud Rate mfd: twl4030-power: Fix pmic for boards that need vmmc1 on reboot nfsd: fix panic in posix_unblock_lock called from nfs4_laundromat nfsd: Fix another OPEN stateid race nfsd: Fix stateid races between OPEN and CLOSE btrfs: clear space cache inode generation always mm/madvise.c: fix madvise() infinite loop under special circumstances mm, hugetlbfs: introduce ->split() to vm_operations_struct mm/cma: fix alloc_contig_range ret code/potential leak mm, thp: Do not make page table dirty unconditionally in touch_p[mu]d() ARM: dts: omap3: logicpd-torpedo-37xx-devkit: Fix MMC1 cd-gpio ARM: dts: LogicPD Torpedo: Fix camera pin mux Linux 4.9.66 xen: xenbus driver must not accept invalid transaction ids nvmet: fix KATO offset in Set Features cec: update log_addr[] before finishing configuration cec: CEC_MSG_GIVE_FEATURES should abort for CEC version < 2 cec: when canceling a message, don't overwrite old status info s390/kbuild: enable modversions for symbols exported from asm ASoC: wm_adsp: Don't overrun firmware file buffer when reading region data btrfs: return the actual error value from from btrfs_uuid_tree_iterate crypto: marvell - Copy IVDIG before launching partial DMA ahash requests ASoC: rsnd: don't double free kctrl netfilter: nf_tables: fix oob access netfilter: nft_queue: use raw_smp_processor_id() spi: SPI_FSL_DSPI should depend on HAS_DMA staging: iio: cdc: fix improper return value iio: light: fix improper return value adm80211: add checks for dma mapping errors mac80211: Suppress NEW_PEER_CANDIDATE event if no room mac80211: Remove invalid flag operations in mesh TSF synchronization drm/mediatek: don't use drm_put_dev clk: qcom: ipq4019: Add all the frequencies for apss cpu drm: Apply range restriction after color adjustment when allocation gpio: mockup: dynamically allocate memory for chip name ALSA: hda - Apply ALC269_FIXUP_NO_SHUTUP on HDA_FIXUP_ACT_PROBE ath10k: set CTS protection VDEV param only if VDEV is up bnxt_en: Set default completion ring for async events. pinctrl: sirf: atlas7: Add missing 'of_node_put()' ath10k: fix potential memory leak in ath10k_wmi_tlv_op_pull_fw_stats() ath10k: ignore configuring the incorrect board_id ath10k: fix incorrect txpower set by P2P_DEVICE interface mwifiex: sdio: fix use after free issue for save_adapter adm80211: return an error if adm8211_alloc_rings() fails rt2800: set minimum MPDU and PSDU lengths to sane values drm/armada: Fix compile fail net: 3com: typhoon: typhoon_init_one: fix incorrect return values net: 3com: typhoon: typhoon_init_one: make return values more specific net: Allow IP_MULTICAST_IF to set index to L3 slave fscrypt: use ENOTDIR when setting encryption policy on nondirectory fscrypt: use ENOKEY when file cannot be created w/o key dmaengine: zx: set DMA_CYCLIC cap_mask bit clk: sunxi-ng: fix PLL_CPUX adjusting on A33 clk: sunxi-ng: A31: Fix spdif clock register drm/sun4i: Fix a return value in case of error PCI: Apply _HPX settings only to relevant devices RDS: RDMA: fix the ib_map_mr_sg_zbva() argument RDS: RDMA: return appropriate error on rdma map failures RDS: make message size limit compliant with spec e1000e: Avoid receiver overrun interrupt bursts e1000e: Separate signaling for link check/link up e1000e: Fix return value test e1000e: Fix error path in link detection Revert "drm/i915: Do not rely on wm preservation for ILK watermarks" PM / OPP: Add missing of_node_put(np) net/9p: Switch to wait_event_killable() fscrypt: lock mutex before checking for bounce page pool sched/rt: Simplify the IPI based RT balancing logic media: v4l2-ctrl: Fix flags field on Control events cx231xx-cards: fix NULL-deref on missing association descriptor media: rc: check for integer overflow media: Don't do DMA on stack for firmware upload in the AS102 driver powerpc/signal: Properly handle return value from uprobe_deny_signal() parisc: Fix validity check of pointer size argument in new CAS implementation ixgbe: Fix skb list corruption on Power systems fm10k: Use smp_rmb rather than read_barrier_depends i40evf: Use smp_rmb rather than read_barrier_depends ixgbevf: Use smp_rmb rather than read_barrier_depends igbvf: Use smp_rmb rather than read_barrier_depends igb: Use smp_rmb rather than read_barrier_depends i40e: Use smp_rmb rather than read_barrier_depends NFC: fix device-allocation error return IB/srp: Avoid that a cable pull can trigger a kernel crash IB/srpt: Do not accept invalid initiator port names libnvdimm, namespace: make 'resource' attribute only readable by root libnvdimm, namespace: fix label initialization to use valid seq numbers libnvdimm, pfn: make 'resource' attribute only readable by root clk: ti: dra7-atl-clock: fix child-node lookups SUNRPC: Fix tracepoint storage issues with svc_recv and svc_rqst_status KVM: SVM: obey guest PAT KVM: nVMX: set IDTR and GDTR limits when loading L1 host state lockd: double unregister of inetaddr notifiers irqchip/gic-v3: Fix ppi-partitions lookup block: Fix a race between blk_cleanup_queue() and timeout handling p54: don't unregister leds when they are not initialized mtd: nand: mtk: fix infinite ECC decode IRQ issue mtd: nand: Fix writing mtdoops to nand flash. mtd: nand: omap2: Fix subpage write target: Fix QUEUE_FULL + SCSI task attribute handling iscsi-target: Fix non-immediate TMR reference leak fs/9p: Compare qid.path in v9fs_test_inode fix a page leak in vhost_scsi_iov_to_sgl() error recovery ALSA: hda/realtek - Fix ALC700 family no sound issue ALSA: hda: Fix too short HDMI/DP chmap reporting ALSA: timer: Remove kernel warning at compat ioctl error paths ALSA: usb-audio: Add sanity checks in v2 clock parsers ALSA: usb-audio: Fix potential out-of-bound access at parsing SU ALSA: usb-audio: Add sanity checks to FE parser ALSA: pcm: update tstamp only if audio_tstamp changed ext4: fix interaction between i_size, fallocate, and delalloc after a crash ata: fixes kernel crash while tracing ata_eh_link_autopsy event rtlwifi: fix uninitialized rtlhal->last_suspend_sec time rtlwifi: rtl8192ee: Fix memory leak when loading firmware nfsd: deal with revoked delegations appropriately NFS: Avoid RCU usage in tracepoints nfs: Fix ugly referral attributes NFS: Fix typo in nomigration mount option isofs: fix timestamps beyond 2027 bcache: check ca->alloc_thread initialized before wake up it libceph: don't WARN() if user tries to add invalid key eCryptfs: use after free in ecryptfs_release_messaging() nilfs2: fix race condition that causes file system corruption autofs: don't fail mount for transient error rt2x00usb: mark device removed when get ENOENT usb error MIPS: BCM47XX: Fix LED inversion for WRT54GSv1 MIPS: Fix an n32 core file generation regset support regression MIPS: dts: remove bogus bcm96358nb4ser.dtb from dtb-y entry MIPS: Fix odd fp register warnings with MIPS64r2 dm: fix race between dm_get_from_kobject() and __dm_destroy() MIPS: pci: Remove KERN_WARN instance inside the mt7620 driver dm: allocate struct mapped_device with kvzalloc dm bufio: fix integer overflow when limiting maximum cache size ALSA: hda: Add Raven PCI ID PCI: Set Cavium ACS capability quirk flags to assert RR/CR/SV/UF MIPS: ralink: Fix typo in mt7628 pinmux function MIPS: ralink: Fix MT7628 pinmux ARM: 8721/1: mm: dump: check hardware RO bit for LPAE ARM: 8722/1: mm: make STRICT_KERNEL_RWX effective for LPAE arm64: Implement arch-specific pte_access_permitted() x86/entry/64: Add missing irqflags tracing to native_load_gs_index() x86/decoder: Add new TEST instruction pattern lib/mpi: call cond_resched() from mpi_powm() loop sched: Make resched_cpu() unconditional vsock: use new wait API for vsock_stream_sendmsg() ipv6: only call ip6_route_dev_notify() once for NETDEV_UNREGISTER x86/mm: fix use-after-free of vma during userfaultfd fault ACPI / EC: Fix regression related to triggering source of EC event handling s390/disassembler: increase show_code buffer size s390/disassembler: add missing end marker for e7 table s390/runtime instrumention: fix possible memory corruption s390: fix transactional execution control register handling Conflicts: drivers/android/binder_alloc.c drivers/android/binder_alloc.h drivers/android/binder_alloc_selftest.c drivers/mmc/core/bus.c drivers/mmc/host/sdhci-msm.c drivers/thermal/step_wise.c kernel/cpu.c mm/oom_kill.c sound/usb/mixer.c Change-Id: Id01eb66cafc5970b460321e44ec8ffcfa76971a6 Signed-off-by: Kyle Yan <kyan@codeaurora.org>
1023 lines
25 KiB
C
1023 lines
25 KiB
C
/*
|
|
* RTC subsystem, interface functions
|
|
*
|
|
* Copyright (C) 2005 Tower Technologies
|
|
* Author: Alessandro Zummo <a.zummo@towertech.it>
|
|
*
|
|
* based on arch/arm/common/rtctime.c
|
|
*
|
|
* 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/rtc.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/module.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/workqueue.h>
|
|
|
|
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer);
|
|
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer);
|
|
|
|
static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
|
|
{
|
|
int err;
|
|
if (!rtc->ops)
|
|
err = -ENODEV;
|
|
else if (!rtc->ops->read_time)
|
|
err = -EINVAL;
|
|
else {
|
|
memset(tm, 0, sizeof(struct rtc_time));
|
|
err = rtc->ops->read_time(rtc->dev.parent, tm);
|
|
if (err < 0) {
|
|
dev_dbg(&rtc->dev, "read_time: fail to read: %d\n",
|
|
err);
|
|
return err;
|
|
}
|
|
|
|
err = rtc_valid_tm(tm);
|
|
if (err < 0)
|
|
dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n");
|
|
}
|
|
return err;
|
|
}
|
|
|
|
int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
|
|
{
|
|
int err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
err = __rtc_read_time(rtc, tm);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_read_time);
|
|
|
|
int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
|
|
{
|
|
int err;
|
|
|
|
err = rtc_valid_tm(tm);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
if (!rtc->ops)
|
|
err = -ENODEV;
|
|
else if (rtc->ops->set_time)
|
|
err = rtc->ops->set_time(rtc->dev.parent, tm);
|
|
else if (rtc->ops->set_mmss64) {
|
|
time64_t secs64 = rtc_tm_to_time64(tm);
|
|
|
|
err = rtc->ops->set_mmss64(rtc->dev.parent, secs64);
|
|
} else if (rtc->ops->set_mmss) {
|
|
time64_t secs64 = rtc_tm_to_time64(tm);
|
|
err = rtc->ops->set_mmss(rtc->dev.parent, secs64);
|
|
} else
|
|
err = -EINVAL;
|
|
|
|
pm_stay_awake(rtc->dev.parent);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
/* A timer might have just expired */
|
|
schedule_work(&rtc->irqwork);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_set_time);
|
|
|
|
static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
int err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
if (rtc->ops == NULL)
|
|
err = -ENODEV;
|
|
else if (!rtc->ops->read_alarm)
|
|
err = -EINVAL;
|
|
else {
|
|
alarm->enabled = 0;
|
|
alarm->pending = 0;
|
|
alarm->time.tm_sec = -1;
|
|
alarm->time.tm_min = -1;
|
|
alarm->time.tm_hour = -1;
|
|
alarm->time.tm_mday = -1;
|
|
alarm->time.tm_mon = -1;
|
|
alarm->time.tm_year = -1;
|
|
alarm->time.tm_wday = -1;
|
|
alarm->time.tm_yday = -1;
|
|
alarm->time.tm_isdst = -1;
|
|
err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
|
|
}
|
|
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return err;
|
|
}
|
|
|
|
int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
int err;
|
|
struct rtc_time before, now;
|
|
int first_time = 1;
|
|
time64_t t_now, t_alm;
|
|
enum { none, day, month, year } missing = none;
|
|
unsigned days;
|
|
|
|
/* The lower level RTC driver may return -1 in some fields,
|
|
* creating invalid alarm->time values, for reasons like:
|
|
*
|
|
* - The hardware may not be capable of filling them in;
|
|
* many alarms match only on time-of-day fields, not
|
|
* day/month/year calendar data.
|
|
*
|
|
* - Some hardware uses illegal values as "wildcard" match
|
|
* values, which non-Linux firmware (like a BIOS) may try
|
|
* to set up as e.g. "alarm 15 minutes after each hour".
|
|
* Linux uses only oneshot alarms.
|
|
*
|
|
* When we see that here, we deal with it by using values from
|
|
* a current RTC timestamp for any missing (-1) values. The
|
|
* RTC driver prevents "periodic alarm" modes.
|
|
*
|
|
* But this can be racey, because some fields of the RTC timestamp
|
|
* may have wrapped in the interval since we read the RTC alarm,
|
|
* which would lead to us inserting inconsistent values in place
|
|
* of the -1 fields.
|
|
*
|
|
* Reading the alarm and timestamp in the reverse sequence
|
|
* would have the same race condition, and not solve the issue.
|
|
*
|
|
* So, we must first read the RTC timestamp,
|
|
* then read the RTC alarm value,
|
|
* and then read a second RTC timestamp.
|
|
*
|
|
* If any fields of the second timestamp have changed
|
|
* when compared with the first timestamp, then we know
|
|
* our timestamp may be inconsistent with that used by
|
|
* the low-level rtc_read_alarm_internal() function.
|
|
*
|
|
* So, when the two timestamps disagree, we just loop and do
|
|
* the process again to get a fully consistent set of values.
|
|
*
|
|
* This could all instead be done in the lower level driver,
|
|
* but since more than one lower level RTC implementation needs it,
|
|
* then it's probably best best to do it here instead of there..
|
|
*/
|
|
|
|
/* Get the "before" timestamp */
|
|
err = rtc_read_time(rtc, &before);
|
|
if (err < 0)
|
|
return err;
|
|
do {
|
|
if (!first_time)
|
|
memcpy(&before, &now, sizeof(struct rtc_time));
|
|
first_time = 0;
|
|
|
|
/* get the RTC alarm values, which may be incomplete */
|
|
err = rtc_read_alarm_internal(rtc, alarm);
|
|
if (err)
|
|
return err;
|
|
|
|
/* full-function RTCs won't have such missing fields */
|
|
if (rtc_valid_tm(&alarm->time) == 0)
|
|
return 0;
|
|
|
|
/* get the "after" timestamp, to detect wrapped fields */
|
|
err = rtc_read_time(rtc, &now);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
/* note that tm_sec is a "don't care" value here: */
|
|
} while ( before.tm_min != now.tm_min
|
|
|| before.tm_hour != now.tm_hour
|
|
|| before.tm_mon != now.tm_mon
|
|
|| before.tm_year != now.tm_year);
|
|
|
|
/* Fill in the missing alarm fields using the timestamp; we
|
|
* know there's at least one since alarm->time is invalid.
|
|
*/
|
|
if (alarm->time.tm_sec == -1)
|
|
alarm->time.tm_sec = now.tm_sec;
|
|
if (alarm->time.tm_min == -1)
|
|
alarm->time.tm_min = now.tm_min;
|
|
if (alarm->time.tm_hour == -1)
|
|
alarm->time.tm_hour = now.tm_hour;
|
|
|
|
/* For simplicity, only support date rollover for now */
|
|
if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
|
|
alarm->time.tm_mday = now.tm_mday;
|
|
missing = day;
|
|
}
|
|
if ((unsigned)alarm->time.tm_mon >= 12) {
|
|
alarm->time.tm_mon = now.tm_mon;
|
|
if (missing == none)
|
|
missing = month;
|
|
}
|
|
if (alarm->time.tm_year == -1) {
|
|
alarm->time.tm_year = now.tm_year;
|
|
if (missing == none)
|
|
missing = year;
|
|
}
|
|
|
|
/* with luck, no rollover is needed */
|
|
t_now = rtc_tm_to_time64(&now);
|
|
t_alm = rtc_tm_to_time64(&alarm->time);
|
|
if (t_now < t_alm)
|
|
goto done;
|
|
|
|
switch (missing) {
|
|
|
|
/* 24 hour rollover ... if it's now 10am Monday, an alarm that
|
|
* that will trigger at 5am will do so at 5am Tuesday, which
|
|
* could also be in the next month or year. This is a common
|
|
* case, especially for PCs.
|
|
*/
|
|
case day:
|
|
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
|
|
t_alm += 24 * 60 * 60;
|
|
rtc_time64_to_tm(t_alm, &alarm->time);
|
|
break;
|
|
|
|
/* Month rollover ... if it's the 31th, an alarm on the 3rd will
|
|
* be next month. An alarm matching on the 30th, 29th, or 28th
|
|
* may end up in the month after that! Many newer PCs support
|
|
* this type of alarm.
|
|
*/
|
|
case month:
|
|
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
|
|
do {
|
|
if (alarm->time.tm_mon < 11)
|
|
alarm->time.tm_mon++;
|
|
else {
|
|
alarm->time.tm_mon = 0;
|
|
alarm->time.tm_year++;
|
|
}
|
|
days = rtc_month_days(alarm->time.tm_mon,
|
|
alarm->time.tm_year);
|
|
} while (days < alarm->time.tm_mday);
|
|
break;
|
|
|
|
/* Year rollover ... easy except for leap years! */
|
|
case year:
|
|
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
|
|
do {
|
|
alarm->time.tm_year++;
|
|
} while (!is_leap_year(alarm->time.tm_year + 1900)
|
|
&& rtc_valid_tm(&alarm->time) != 0);
|
|
break;
|
|
|
|
default:
|
|
dev_warn(&rtc->dev, "alarm rollover not handled\n");
|
|
}
|
|
|
|
done:
|
|
err = rtc_valid_tm(&alarm->time);
|
|
|
|
if (err) {
|
|
dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
|
|
alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
|
|
alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
|
|
alarm->time.tm_sec);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
int err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
if (rtc->ops == NULL)
|
|
err = -ENODEV;
|
|
else if (!rtc->ops->read_alarm)
|
|
err = -EINVAL;
|
|
else {
|
|
memset(alarm, 0, sizeof(struct rtc_wkalrm));
|
|
alarm->enabled = rtc->aie_timer.enabled;
|
|
alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires);
|
|
}
|
|
mutex_unlock(&rtc->ops_lock);
|
|
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_read_alarm);
|
|
|
|
static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
struct rtc_time tm;
|
|
time64_t now, scheduled;
|
|
int err;
|
|
|
|
err = rtc_valid_tm(&alarm->time);
|
|
if (err)
|
|
return err;
|
|
scheduled = rtc_tm_to_time64(&alarm->time);
|
|
|
|
/* Make sure we're not setting alarms in the past */
|
|
err = __rtc_read_time(rtc, &tm);
|
|
if (err)
|
|
return err;
|
|
now = rtc_tm_to_time64(&tm);
|
|
if (scheduled <= now)
|
|
return -ETIME;
|
|
/*
|
|
* XXX - We just checked to make sure the alarm time is not
|
|
* in the past, but there is still a race window where if
|
|
* the is alarm set for the next second and the second ticks
|
|
* over right here, before we set the alarm.
|
|
*/
|
|
|
|
if (!rtc->ops)
|
|
err = -ENODEV;
|
|
else if (!rtc->ops->set_alarm)
|
|
err = -EINVAL;
|
|
else
|
|
err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
|
|
|
|
return err;
|
|
}
|
|
|
|
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
int err;
|
|
|
|
err = rtc_valid_tm(&alarm->time);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
if (rtc->aie_timer.enabled)
|
|
rtc_timer_remove(rtc, &rtc->aie_timer);
|
|
|
|
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
|
|
rtc->aie_timer.period = ktime_set(0, 0);
|
|
if (alarm->enabled)
|
|
err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
|
|
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_set_alarm);
|
|
|
|
static void rtc_alarm_disable(struct rtc_device *rtc)
|
|
{
|
|
if (!rtc->ops || !rtc->ops->alarm_irq_enable)
|
|
return;
|
|
|
|
rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
|
|
}
|
|
|
|
/* Called once per device from rtc_device_register */
|
|
int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|
{
|
|
int err;
|
|
struct rtc_time now;
|
|
|
|
err = rtc_valid_tm(&alarm->time);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
err = rtc_read_time(rtc, &now);
|
|
if (err)
|
|
return err;
|
|
|
|
err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
|
|
rtc->aie_timer.period = ktime_set(0, 0);
|
|
|
|
/* Alarm has to be enabled & in the future for us to enqueue it */
|
|
if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
|
|
rtc->aie_timer.node.expires.tv64)) {
|
|
|
|
rtc->aie_timer.enabled = 1;
|
|
timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
|
|
} else if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 >=
|
|
rtc->aie_timer.node.expires.tv64)){
|
|
rtc_alarm_disable(rtc);
|
|
}
|
|
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
|
|
|
|
int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
|
|
{
|
|
int err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
if (rtc->aie_timer.enabled != enabled) {
|
|
if (enabled)
|
|
err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
|
|
else
|
|
rtc_timer_remove(rtc, &rtc->aie_timer);
|
|
}
|
|
|
|
if (err)
|
|
/* nothing */;
|
|
else if (!rtc->ops)
|
|
err = -ENODEV;
|
|
else if (!rtc->ops->alarm_irq_enable)
|
|
err = -EINVAL;
|
|
else
|
|
err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
|
|
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
|
|
|
|
int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
|
|
{
|
|
int err = mutex_lock_interruptible(&rtc->ops_lock);
|
|
if (err)
|
|
return err;
|
|
|
|
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
|
|
if (enabled == 0 && rtc->uie_irq_active) {
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return rtc_dev_update_irq_enable_emul(rtc, 0);
|
|
}
|
|
#endif
|
|
/* make sure we're changing state */
|
|
if (rtc->uie_rtctimer.enabled == enabled)
|
|
goto out;
|
|
|
|
if (rtc->uie_unsupported) {
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (enabled) {
|
|
struct rtc_time tm;
|
|
ktime_t now, onesec;
|
|
|
|
__rtc_read_time(rtc, &tm);
|
|
onesec = ktime_set(1, 0);
|
|
now = rtc_tm_to_ktime(tm);
|
|
rtc->uie_rtctimer.node.expires = ktime_add(now, onesec);
|
|
rtc->uie_rtctimer.period = ktime_set(1, 0);
|
|
err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer);
|
|
} else
|
|
rtc_timer_remove(rtc, &rtc->uie_rtctimer);
|
|
|
|
out:
|
|
mutex_unlock(&rtc->ops_lock);
|
|
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
|
|
/*
|
|
* Enable emulation if the driver did not provide
|
|
* the update_irq_enable function pointer or if returned
|
|
* -EINVAL to signal that it has been configured without
|
|
* interrupts or that are not available at the moment.
|
|
*/
|
|
if (err == -EINVAL)
|
|
err = rtc_dev_update_irq_enable_emul(rtc, enabled);
|
|
#endif
|
|
return err;
|
|
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
|
|
|
|
|
|
/**
|
|
* rtc_handle_legacy_irq - AIE, UIE and PIE event hook
|
|
* @rtc: pointer to the rtc device
|
|
*
|
|
* This function is called when an AIE, UIE or PIE mode interrupt
|
|
* has occurred (or been emulated).
|
|
*
|
|
* Triggers the registered irq_task function callback.
|
|
*/
|
|
void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
|
|
{
|
|
unsigned long flags;
|
|
|
|
/* mark one irq of the appropriate mode */
|
|
spin_lock_irqsave(&rtc->irq_lock, flags);
|
|
rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
|
|
spin_unlock_irqrestore(&rtc->irq_lock, flags);
|
|
|
|
/* call the task func */
|
|
spin_lock_irqsave(&rtc->irq_task_lock, flags);
|
|
if (rtc->irq_task)
|
|
rtc->irq_task->func(rtc->irq_task->private_data);
|
|
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
|
|
|
|
wake_up_interruptible(&rtc->irq_queue);
|
|
kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
|
|
}
|
|
|
|
|
|
/**
|
|
* rtc_aie_update_irq - AIE mode rtctimer hook
|
|
* @private: pointer to the rtc_device
|
|
*
|
|
* This functions is called when the aie_timer expires.
|
|
*/
|
|
void rtc_aie_update_irq(void *private)
|
|
{
|
|
struct rtc_device *rtc = (struct rtc_device *)private;
|
|
rtc_handle_legacy_irq(rtc, 1, RTC_AF);
|
|
}
|
|
|
|
|
|
/**
|
|
* rtc_uie_update_irq - UIE mode rtctimer hook
|
|
* @private: pointer to the rtc_device
|
|
*
|
|
* This functions is called when the uie_timer expires.
|
|
*/
|
|
void rtc_uie_update_irq(void *private)
|
|
{
|
|
struct rtc_device *rtc = (struct rtc_device *)private;
|
|
rtc_handle_legacy_irq(rtc, 1, RTC_UF);
|
|
}
|
|
|
|
|
|
/**
|
|
* rtc_pie_update_irq - PIE mode hrtimer hook
|
|
* @timer: pointer to the pie mode hrtimer
|
|
*
|
|
* This function is used to emulate PIE mode interrupts
|
|
* using an hrtimer. This function is called when the periodic
|
|
* hrtimer expires.
|
|
*/
|
|
enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
|
|
{
|
|
struct rtc_device *rtc;
|
|
ktime_t period;
|
|
int count;
|
|
rtc = container_of(timer, struct rtc_device, pie_timer);
|
|
|
|
period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
|
|
count = hrtimer_forward_now(timer, period);
|
|
|
|
rtc_handle_legacy_irq(rtc, count, RTC_PF);
|
|
|
|
return HRTIMER_RESTART;
|
|
}
|
|
|
|
/**
|
|
* rtc_update_irq - Triggered when a RTC interrupt occurs.
|
|
* @rtc: the rtc device
|
|
* @num: how many irqs are being reported (usually one)
|
|
* @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
|
|
* Context: any
|
|
*/
|
|
void rtc_update_irq(struct rtc_device *rtc,
|
|
unsigned long num, unsigned long events)
|
|
{
|
|
if (IS_ERR_OR_NULL(rtc))
|
|
return;
|
|
|
|
pm_stay_awake(rtc->dev.parent);
|
|
schedule_work(&rtc->irqwork);
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_update_irq);
|
|
|
|
static int __rtc_match(struct device *dev, const void *data)
|
|
{
|
|
const char *name = data;
|
|
|
|
if (strcmp(dev_name(dev), name) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
struct rtc_device *rtc_class_open(const char *name)
|
|
{
|
|
struct device *dev;
|
|
struct rtc_device *rtc = NULL;
|
|
|
|
dev = class_find_device(rtc_class, NULL, name, __rtc_match);
|
|
if (dev)
|
|
rtc = to_rtc_device(dev);
|
|
|
|
if (rtc) {
|
|
if (!try_module_get(rtc->owner)) {
|
|
put_device(dev);
|
|
rtc = NULL;
|
|
}
|
|
}
|
|
|
|
return rtc;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_class_open);
|
|
|
|
void rtc_class_close(struct rtc_device *rtc)
|
|
{
|
|
module_put(rtc->owner);
|
|
put_device(&rtc->dev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_class_close);
|
|
|
|
int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
|
|
{
|
|
int retval = -EBUSY;
|
|
|
|
if (task == NULL || task->func == NULL)
|
|
return -EINVAL;
|
|
|
|
/* Cannot register while the char dev is in use */
|
|
if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
|
|
return -EBUSY;
|
|
|
|
spin_lock_irq(&rtc->irq_task_lock);
|
|
if (rtc->irq_task == NULL) {
|
|
rtc->irq_task = task;
|
|
retval = 0;
|
|
}
|
|
spin_unlock_irq(&rtc->irq_task_lock);
|
|
|
|
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
|
|
|
|
return retval;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_irq_register);
|
|
|
|
void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
|
|
{
|
|
spin_lock_irq(&rtc->irq_task_lock);
|
|
if (rtc->irq_task == task)
|
|
rtc->irq_task = NULL;
|
|
spin_unlock_irq(&rtc->irq_task_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_irq_unregister);
|
|
|
|
static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
|
|
{
|
|
/*
|
|
* We always cancel the timer here first, because otherwise
|
|
* we could run into BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
|
|
* when we manage to start the timer before the callback
|
|
* returns HRTIMER_RESTART.
|
|
*
|
|
* We cannot use hrtimer_cancel() here as a running callback
|
|
* could be blocked on rtc->irq_task_lock and hrtimer_cancel()
|
|
* would spin forever.
|
|
*/
|
|
if (hrtimer_try_to_cancel(&rtc->pie_timer) < 0)
|
|
return -1;
|
|
|
|
if (enabled) {
|
|
ktime_t period = ktime_set(0, NSEC_PER_SEC / rtc->irq_freq);
|
|
|
|
hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
|
|
* @rtc: the rtc device
|
|
* @task: currently registered with rtc_irq_register()
|
|
* @enabled: true to enable periodic IRQs
|
|
* Context: any
|
|
*
|
|
* Note that rtc_irq_set_freq() should previously have been used to
|
|
* specify the desired frequency of periodic IRQ task->func() callbacks.
|
|
*/
|
|
int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
|
|
{
|
|
int err = 0;
|
|
unsigned long flags;
|
|
|
|
retry:
|
|
spin_lock_irqsave(&rtc->irq_task_lock, flags);
|
|
if (rtc->irq_task != NULL && task == NULL)
|
|
err = -EBUSY;
|
|
else if (rtc->irq_task != task)
|
|
err = -EACCES;
|
|
else {
|
|
if (rtc_update_hrtimer(rtc, enabled) < 0) {
|
|
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
|
|
cpu_relax();
|
|
goto retry;
|
|
}
|
|
rtc->pie_enabled = enabled;
|
|
}
|
|
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_irq_set_state);
|
|
|
|
/**
|
|
* rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
|
|
* @rtc: the rtc device
|
|
* @task: currently registered with rtc_irq_register()
|
|
* @freq: positive frequency with which task->func() will be called
|
|
* Context: any
|
|
*
|
|
* Note that rtc_irq_set_state() is used to enable or disable the
|
|
* periodic IRQs.
|
|
*/
|
|
int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
|
|
{
|
|
int err = 0;
|
|
unsigned long flags;
|
|
|
|
if (freq <= 0 || freq > RTC_MAX_FREQ)
|
|
return -EINVAL;
|
|
retry:
|
|
spin_lock_irqsave(&rtc->irq_task_lock, flags);
|
|
if (rtc->irq_task != NULL && task == NULL)
|
|
err = -EBUSY;
|
|
else if (rtc->irq_task != task)
|
|
err = -EACCES;
|
|
else {
|
|
rtc->irq_freq = freq;
|
|
if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
|
|
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
|
|
cpu_relax();
|
|
goto retry;
|
|
}
|
|
}
|
|
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
|
|
|
|
/**
|
|
* rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
|
|
* @rtc rtc device
|
|
* @timer timer being added.
|
|
*
|
|
* Enqueues a timer onto the rtc devices timerqueue and sets
|
|
* the next alarm event appropriately.
|
|
*
|
|
* Sets the enabled bit on the added timer.
|
|
*
|
|
* Must hold ops_lock for proper serialization of timerqueue
|
|
*/
|
|
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
|
|
{
|
|
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
|
|
struct rtc_time tm;
|
|
ktime_t now;
|
|
|
|
timer->enabled = 1;
|
|
__rtc_read_time(rtc, &tm);
|
|
now = rtc_tm_to_ktime(tm);
|
|
|
|
/* Skip over expired timers */
|
|
while (next) {
|
|
if (next->expires.tv64 >= now.tv64)
|
|
break;
|
|
next = timerqueue_iterate_next(next);
|
|
}
|
|
|
|
timerqueue_add(&rtc->timerqueue, &timer->node);
|
|
if (!next || ktime_before(timer->node.expires, next->expires)) {
|
|
struct rtc_wkalrm alarm;
|
|
int err;
|
|
alarm.time = rtc_ktime_to_tm(timer->node.expires);
|
|
alarm.enabled = 1;
|
|
err = __rtc_set_alarm(rtc, &alarm);
|
|
if (err == -ETIME) {
|
|
pm_stay_awake(rtc->dev.parent);
|
|
schedule_work(&rtc->irqwork);
|
|
} else if (err) {
|
|
timerqueue_del(&rtc->timerqueue, &timer->node);
|
|
timer->enabled = 0;
|
|
return err;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
|
|
* @rtc rtc device
|
|
* @timer timer being removed.
|
|
*
|
|
* Removes a timer onto the rtc devices timerqueue and sets
|
|
* the next alarm event appropriately.
|
|
*
|
|
* Clears the enabled bit on the removed timer.
|
|
*
|
|
* Must hold ops_lock for proper serialization of timerqueue
|
|
*/
|
|
static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
|
|
{
|
|
struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
|
|
timerqueue_del(&rtc->timerqueue, &timer->node);
|
|
timer->enabled = 0;
|
|
if (next == &timer->node) {
|
|
struct rtc_wkalrm alarm;
|
|
int err;
|
|
next = timerqueue_getnext(&rtc->timerqueue);
|
|
if (!next) {
|
|
rtc_alarm_disable(rtc);
|
|
return;
|
|
}
|
|
alarm.time = rtc_ktime_to_tm(next->expires);
|
|
alarm.enabled = 1;
|
|
err = __rtc_set_alarm(rtc, &alarm);
|
|
if (err == -ETIME) {
|
|
pm_stay_awake(rtc->dev.parent);
|
|
schedule_work(&rtc->irqwork);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* rtc_timer_do_work - Expires rtc timers
|
|
* @rtc rtc device
|
|
* @timer timer being removed.
|
|
*
|
|
* Expires rtc timers. Reprograms next alarm event if needed.
|
|
* Called via worktask.
|
|
*
|
|
* Serializes access to timerqueue via ops_lock mutex
|
|
*/
|
|
void rtc_timer_do_work(struct work_struct *work)
|
|
{
|
|
struct rtc_timer *timer;
|
|
struct timerqueue_node *next;
|
|
ktime_t now;
|
|
struct rtc_time tm;
|
|
|
|
struct rtc_device *rtc =
|
|
container_of(work, struct rtc_device, irqwork);
|
|
|
|
mutex_lock(&rtc->ops_lock);
|
|
again:
|
|
__rtc_read_time(rtc, &tm);
|
|
now = rtc_tm_to_ktime(tm);
|
|
while ((next = timerqueue_getnext(&rtc->timerqueue))) {
|
|
if (next->expires.tv64 > now.tv64)
|
|
break;
|
|
|
|
/* expire timer */
|
|
timer = container_of(next, struct rtc_timer, node);
|
|
timerqueue_del(&rtc->timerqueue, &timer->node);
|
|
timer->enabled = 0;
|
|
if (timer->task.func)
|
|
timer->task.func(timer->task.private_data);
|
|
|
|
/* Re-add/fwd periodic timers */
|
|
if (ktime_to_ns(timer->period)) {
|
|
timer->node.expires = ktime_add(timer->node.expires,
|
|
timer->period);
|
|
timer->enabled = 1;
|
|
timerqueue_add(&rtc->timerqueue, &timer->node);
|
|
}
|
|
}
|
|
|
|
/* Set next alarm */
|
|
if (next) {
|
|
struct rtc_wkalrm alarm;
|
|
int err;
|
|
int retry = 3;
|
|
|
|
alarm.time = rtc_ktime_to_tm(next->expires);
|
|
alarm.enabled = 1;
|
|
reprogram:
|
|
err = __rtc_set_alarm(rtc, &alarm);
|
|
if (err == -ETIME)
|
|
goto again;
|
|
else if (err) {
|
|
if (retry-- > 0)
|
|
goto reprogram;
|
|
|
|
timer = container_of(next, struct rtc_timer, node);
|
|
timerqueue_del(&rtc->timerqueue, &timer->node);
|
|
timer->enabled = 0;
|
|
dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err);
|
|
goto again;
|
|
}
|
|
} else
|
|
rtc_alarm_disable(rtc);
|
|
|
|
pm_relax(rtc->dev.parent);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
}
|
|
|
|
|
|
/* rtc_timer_init - Initializes an rtc_timer
|
|
* @timer: timer to be intiialized
|
|
* @f: function pointer to be called when timer fires
|
|
* @data: private data passed to function pointer
|
|
*
|
|
* Kernel interface to initializing an rtc_timer.
|
|
*/
|
|
void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
|
|
{
|
|
timerqueue_init(&timer->node);
|
|
timer->enabled = 0;
|
|
timer->task.func = f;
|
|
timer->task.private_data = data;
|
|
}
|
|
|
|
/* rtc_timer_start - Sets an rtc_timer to fire in the future
|
|
* @ rtc: rtc device to be used
|
|
* @ timer: timer being set
|
|
* @ expires: time at which to expire the timer
|
|
* @ period: period that the timer will recur
|
|
*
|
|
* Kernel interface to set an rtc_timer
|
|
*/
|
|
int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
|
|
ktime_t expires, ktime_t period)
|
|
{
|
|
int ret = 0;
|
|
mutex_lock(&rtc->ops_lock);
|
|
if (timer->enabled)
|
|
rtc_timer_remove(rtc, timer);
|
|
|
|
timer->node.expires = expires;
|
|
timer->period = period;
|
|
|
|
ret = rtc_timer_enqueue(rtc, timer);
|
|
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return ret;
|
|
}
|
|
|
|
/* rtc_timer_cancel - Stops an rtc_timer
|
|
* @ rtc: rtc device to be used
|
|
* @ timer: timer being set
|
|
*
|
|
* Kernel interface to cancel an rtc_timer
|
|
*/
|
|
void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
|
|
{
|
|
mutex_lock(&rtc->ops_lock);
|
|
if (timer->enabled)
|
|
rtc_timer_remove(rtc, timer);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
}
|
|
|
|
/**
|
|
* rtc_read_offset - Read the amount of rtc offset in parts per billion
|
|
* @ rtc: rtc device to be used
|
|
* @ offset: the offset in parts per billion
|
|
*
|
|
* see below for details.
|
|
*
|
|
* Kernel interface to read rtc clock offset
|
|
* Returns 0 on success, or a negative number on error.
|
|
* If read_offset() is not implemented for the rtc, return -EINVAL
|
|
*/
|
|
int rtc_read_offset(struct rtc_device *rtc, long *offset)
|
|
{
|
|
int ret;
|
|
|
|
if (!rtc->ops)
|
|
return -ENODEV;
|
|
|
|
if (!rtc->ops->read_offset)
|
|
return -EINVAL;
|
|
|
|
mutex_lock(&rtc->ops_lock);
|
|
ret = rtc->ops->read_offset(rtc->dev.parent, offset);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* rtc_set_offset - Adjusts the duration of the average second
|
|
* @ rtc: rtc device to be used
|
|
* @ offset: the offset in parts per billion
|
|
*
|
|
* Some rtc's allow an adjustment to the average duration of a second
|
|
* to compensate for differences in the actual clock rate due to temperature,
|
|
* the crystal, capacitor, etc.
|
|
*
|
|
* Kernel interface to adjust an rtc clock offset.
|
|
* Return 0 on success, or a negative number on error.
|
|
* If the rtc offset is not setable (or not implemented), return -EINVAL
|
|
*/
|
|
int rtc_set_offset(struct rtc_device *rtc, long offset)
|
|
{
|
|
int ret;
|
|
|
|
if (!rtc->ops)
|
|
return -ENODEV;
|
|
|
|
if (!rtc->ops->set_offset)
|
|
return -EINVAL;
|
|
|
|
mutex_lock(&rtc->ops_lock);
|
|
ret = rtc->ops->set_offset(rtc->dev.parent, offset);
|
|
mutex_unlock(&rtc->ops_lock);
|
|
return ret;
|
|
}
|