mirror of
https://github.com/commaai/agnos-kernel-sdm845.git
synced 2026-06-13 05:45:24 +08:00
* 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>
2038 lines
50 KiB
C
2038 lines
50 KiB
C
/* CPU control.
|
|
* (C) 2001, 2002, 2003, 2004 Rusty Russell
|
|
*
|
|
* This code is licenced under the GPL.
|
|
*/
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/init.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/unistd.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/oom.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/export.h>
|
|
#include <linux/bug.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/stop_machine.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/lockdep.h>
|
|
#include <linux/tick.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/smpboot.h>
|
|
#include <linux/relay.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/highmem.h>
|
|
|
|
#include <trace/events/power.h>
|
|
#define CREATE_TRACE_POINTS
|
|
#include <trace/events/cpuhp.h>
|
|
|
|
#include "smpboot.h"
|
|
|
|
/**
|
|
* cpuhp_cpu_state - Per cpu hotplug state storage
|
|
* @state: The current cpu state
|
|
* @target: The target state
|
|
* @thread: Pointer to the hotplug thread
|
|
* @should_run: Thread should execute
|
|
* @rollback: Perform a rollback
|
|
* @single: Single callback invocation
|
|
* @bringup: Single callback bringup or teardown selector
|
|
* @cb_state: The state for a single callback (install/uninstall)
|
|
* @result: Result of the operation
|
|
* @done: Signal completion to the issuer of the task
|
|
*/
|
|
struct cpuhp_cpu_state {
|
|
enum cpuhp_state state;
|
|
enum cpuhp_state target;
|
|
#ifdef CONFIG_SMP
|
|
struct task_struct *thread;
|
|
bool should_run;
|
|
bool rollback;
|
|
bool single;
|
|
bool bringup;
|
|
struct hlist_node *node;
|
|
enum cpuhp_state cb_state;
|
|
int result;
|
|
struct completion done;
|
|
#endif
|
|
};
|
|
|
|
static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state);
|
|
|
|
/**
|
|
* cpuhp_step - Hotplug state machine step
|
|
* @name: Name of the step
|
|
* @startup: Startup function of the step
|
|
* @teardown: Teardown function of the step
|
|
* @skip_onerr: Do not invoke the functions on error rollback
|
|
* Will go away once the notifiers are gone
|
|
* @cant_stop: Bringup/teardown can't be stopped at this step
|
|
*/
|
|
struct cpuhp_step {
|
|
const char *name;
|
|
union {
|
|
int (*single)(unsigned int cpu);
|
|
int (*multi)(unsigned int cpu,
|
|
struct hlist_node *node);
|
|
} startup;
|
|
union {
|
|
int (*single)(unsigned int cpu);
|
|
int (*multi)(unsigned int cpu,
|
|
struct hlist_node *node);
|
|
} teardown;
|
|
struct hlist_head list;
|
|
bool skip_onerr;
|
|
bool cant_stop;
|
|
bool multi_instance;
|
|
};
|
|
|
|
static DEFINE_MUTEX(cpuhp_state_mutex);
|
|
static struct cpuhp_step cpuhp_bp_states[];
|
|
static struct cpuhp_step cpuhp_ap_states[];
|
|
|
|
static bool cpuhp_is_ap_state(enum cpuhp_state state)
|
|
{
|
|
/*
|
|
* The extra check for CPUHP_TEARDOWN_CPU is only for documentation
|
|
* purposes as that state is handled explicitly in cpu_down.
|
|
*/
|
|
return state > CPUHP_BRINGUP_CPU && state != CPUHP_TEARDOWN_CPU;
|
|
}
|
|
|
|
static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
|
|
{
|
|
struct cpuhp_step *sp;
|
|
|
|
sp = cpuhp_is_ap_state(state) ? cpuhp_ap_states : cpuhp_bp_states;
|
|
return sp + state;
|
|
}
|
|
|
|
/**
|
|
* cpuhp_invoke_callback _ Invoke the callbacks for a given state
|
|
* @cpu: The cpu for which the callback should be invoked
|
|
* @step: The step in the state machine
|
|
* @bringup: True if the bringup callback should be invoked
|
|
*
|
|
* Called from cpu hotplug and from the state register machinery.
|
|
*/
|
|
static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
|
|
bool bringup, struct hlist_node *node)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
struct cpuhp_step *step = cpuhp_get_step(state);
|
|
int (*cbm)(unsigned int cpu, struct hlist_node *node);
|
|
int (*cb)(unsigned int cpu);
|
|
int ret, cnt;
|
|
|
|
if (!step->multi_instance) {
|
|
cb = bringup ? step->startup.single : step->teardown.single;
|
|
if (!cb)
|
|
return 0;
|
|
trace_cpuhp_enter(cpu, st->target, state, cb);
|
|
ret = cb(cpu);
|
|
trace_cpuhp_exit(cpu, st->state, state, ret);
|
|
return ret;
|
|
}
|
|
cbm = bringup ? step->startup.multi : step->teardown.multi;
|
|
if (!cbm)
|
|
return 0;
|
|
|
|
/* Single invocation for instance add/remove */
|
|
if (node) {
|
|
trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
|
|
ret = cbm(cpu, node);
|
|
trace_cpuhp_exit(cpu, st->state, state, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* State transition. Invoke on all instances */
|
|
cnt = 0;
|
|
hlist_for_each(node, &step->list) {
|
|
trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
|
|
ret = cbm(cpu, node);
|
|
trace_cpuhp_exit(cpu, st->state, state, ret);
|
|
if (ret)
|
|
goto err;
|
|
cnt++;
|
|
}
|
|
return 0;
|
|
err:
|
|
/* Rollback the instances if one failed */
|
|
cbm = !bringup ? step->startup.multi : step->teardown.multi;
|
|
if (!cbm)
|
|
return ret;
|
|
|
|
hlist_for_each(node, &step->list) {
|
|
if (!cnt--)
|
|
break;
|
|
cbm(cpu, node);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_SMP
|
|
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
|
|
static DEFINE_MUTEX(cpu_add_remove_lock);
|
|
bool cpuhp_tasks_frozen;
|
|
EXPORT_SYMBOL_GPL(cpuhp_tasks_frozen);
|
|
|
|
/*
|
|
* The following two APIs (cpu_maps_update_begin/done) must be used when
|
|
* attempting to serialize the updates to cpu_online_mask & cpu_present_mask.
|
|
* The APIs cpu_notifier_register_begin/done() must be used to protect CPU
|
|
* hotplug callback (un)registration performed using __register_cpu_notifier()
|
|
* or __unregister_cpu_notifier().
|
|
*/
|
|
void cpu_maps_update_begin(void)
|
|
{
|
|
mutex_lock(&cpu_add_remove_lock);
|
|
}
|
|
EXPORT_SYMBOL(cpu_notifier_register_begin);
|
|
|
|
void cpu_maps_update_done(void)
|
|
{
|
|
mutex_unlock(&cpu_add_remove_lock);
|
|
}
|
|
EXPORT_SYMBOL(cpu_notifier_register_done);
|
|
|
|
static RAW_NOTIFIER_HEAD(cpu_chain);
|
|
|
|
/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
|
|
* Should always be manipulated under cpu_add_remove_lock
|
|
*/
|
|
static int cpu_hotplug_disabled;
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
|
static struct {
|
|
struct task_struct *active_writer;
|
|
/* wait queue to wake up the active_writer */
|
|
wait_queue_head_t wq;
|
|
/* verifies that no writer will get active while readers are active */
|
|
struct mutex lock;
|
|
/*
|
|
* Also blocks the new readers during
|
|
* an ongoing cpu hotplug operation.
|
|
*/
|
|
atomic_t refcount;
|
|
|
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
struct lockdep_map dep_map;
|
|
#endif
|
|
} cpu_hotplug = {
|
|
.active_writer = NULL,
|
|
.wq = __WAIT_QUEUE_HEAD_INITIALIZER(cpu_hotplug.wq),
|
|
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
.dep_map = STATIC_LOCKDEP_MAP_INIT("cpu_hotplug.dep_map", &cpu_hotplug.dep_map),
|
|
#endif
|
|
};
|
|
|
|
/* Lockdep annotations for get/put_online_cpus() and cpu_hotplug_begin/end() */
|
|
#define cpuhp_lock_acquire_read() lock_map_acquire_read(&cpu_hotplug.dep_map)
|
|
#define cpuhp_lock_acquire_tryread() \
|
|
lock_map_acquire_tryread(&cpu_hotplug.dep_map)
|
|
#define cpuhp_lock_acquire() lock_map_acquire(&cpu_hotplug.dep_map)
|
|
#define cpuhp_lock_release() lock_map_release(&cpu_hotplug.dep_map)
|
|
|
|
void cpu_hotplug_mutex_held(void)
|
|
{
|
|
lockdep_assert_held(&cpu_hotplug.lock);
|
|
}
|
|
EXPORT_SYMBOL(cpu_hotplug_mutex_held);
|
|
|
|
void get_online_cpus(void)
|
|
{
|
|
might_sleep();
|
|
if (cpu_hotplug.active_writer == current)
|
|
return;
|
|
cpuhp_lock_acquire_read();
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
atomic_inc(&cpu_hotplug.refcount);
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(get_online_cpus);
|
|
|
|
void put_online_cpus(void)
|
|
{
|
|
int refcount;
|
|
|
|
if (cpu_hotplug.active_writer == current)
|
|
return;
|
|
|
|
refcount = atomic_dec_return(&cpu_hotplug.refcount);
|
|
if (WARN_ON(refcount < 0)) /* try to fix things up */
|
|
atomic_inc(&cpu_hotplug.refcount);
|
|
|
|
if (refcount <= 0 && waitqueue_active(&cpu_hotplug.wq))
|
|
wake_up(&cpu_hotplug.wq);
|
|
|
|
cpuhp_lock_release();
|
|
|
|
}
|
|
EXPORT_SYMBOL_GPL(put_online_cpus);
|
|
|
|
/*
|
|
* This ensures that the hotplug operation can begin only when the
|
|
* refcount goes to zero.
|
|
*
|
|
* Note that during a cpu-hotplug operation, the new readers, if any,
|
|
* will be blocked by the cpu_hotplug.lock
|
|
*
|
|
* Since cpu_hotplug_begin() is always called after invoking
|
|
* cpu_maps_update_begin(), we can be sure that only one writer is active.
|
|
*
|
|
* Note that theoretically, there is a possibility of a livelock:
|
|
* - Refcount goes to zero, last reader wakes up the sleeping
|
|
* writer.
|
|
* - Last reader unlocks the cpu_hotplug.lock.
|
|
* - A new reader arrives at this moment, bumps up the refcount.
|
|
* - The writer acquires the cpu_hotplug.lock finds the refcount
|
|
* non zero and goes to sleep again.
|
|
*
|
|
* However, this is very difficult to achieve in practice since
|
|
* get_online_cpus() not an api which is called all that often.
|
|
*
|
|
*/
|
|
void cpu_hotplug_begin(void)
|
|
{
|
|
DEFINE_WAIT(wait);
|
|
|
|
cpu_hotplug.active_writer = current;
|
|
cpuhp_lock_acquire();
|
|
|
|
for (;;) {
|
|
mutex_lock(&cpu_hotplug.lock);
|
|
prepare_to_wait(&cpu_hotplug.wq, &wait, TASK_UNINTERRUPTIBLE);
|
|
if (likely(!atomic_read(&cpu_hotplug.refcount)))
|
|
break;
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
schedule();
|
|
}
|
|
finish_wait(&cpu_hotplug.wq, &wait);
|
|
}
|
|
|
|
void cpu_hotplug_done(void)
|
|
{
|
|
cpu_hotplug.active_writer = NULL;
|
|
mutex_unlock(&cpu_hotplug.lock);
|
|
cpuhp_lock_release();
|
|
}
|
|
|
|
/*
|
|
* Wait for currently running CPU hotplug operations to complete (if any) and
|
|
* disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects
|
|
* the 'cpu_hotplug_disabled' flag. The same lock is also acquired by the
|
|
* hotplug path before performing hotplug operations. So acquiring that lock
|
|
* guarantees mutual exclusion from any currently running hotplug operations.
|
|
*/
|
|
void cpu_hotplug_disable(void)
|
|
{
|
|
cpu_maps_update_begin();
|
|
cpu_hotplug_disabled++;
|
|
cpu_maps_update_done();
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_hotplug_disable);
|
|
|
|
static void __cpu_hotplug_enable(void)
|
|
{
|
|
if (WARN_ONCE(!cpu_hotplug_disabled, "Unbalanced cpu hotplug enable\n"))
|
|
return;
|
|
cpu_hotplug_disabled--;
|
|
}
|
|
|
|
void cpu_hotplug_enable(void)
|
|
{
|
|
cpu_maps_update_begin();
|
|
__cpu_hotplug_enable();
|
|
cpu_maps_update_done();
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
/* Need to know about CPUs going up/down? */
|
|
int register_cpu_notifier(struct notifier_block *nb)
|
|
{
|
|
int ret;
|
|
cpu_maps_update_begin();
|
|
ret = raw_notifier_chain_register(&cpu_chain, nb);
|
|
cpu_maps_update_done();
|
|
return ret;
|
|
}
|
|
|
|
int __register_cpu_notifier(struct notifier_block *nb)
|
|
{
|
|
return raw_notifier_chain_register(&cpu_chain, nb);
|
|
}
|
|
|
|
static int __cpu_notify(unsigned long val, unsigned int cpu, int nr_to_call,
|
|
int *nr_calls)
|
|
{
|
|
unsigned long mod = cpuhp_tasks_frozen ? CPU_TASKS_FROZEN : 0;
|
|
void *hcpu = (void *)(long)cpu;
|
|
|
|
int ret;
|
|
|
|
ret = __raw_notifier_call_chain(&cpu_chain, val | mod, hcpu, nr_to_call,
|
|
nr_calls);
|
|
|
|
return notifier_to_errno(ret);
|
|
}
|
|
|
|
static int cpu_notify(unsigned long val, unsigned int cpu)
|
|
{
|
|
return __cpu_notify(val, cpu, -1, NULL);
|
|
}
|
|
|
|
static void cpu_notify_nofail(unsigned long val, unsigned int cpu)
|
|
{
|
|
BUG_ON(cpu_notify(val, cpu));
|
|
}
|
|
|
|
/* Notifier wrappers for transitioning to state machine */
|
|
static int notify_prepare(unsigned int cpu)
|
|
{
|
|
int nr_calls = 0;
|
|
int ret;
|
|
|
|
ret = __cpu_notify(CPU_UP_PREPARE, cpu, -1, &nr_calls);
|
|
if (ret) {
|
|
nr_calls--;
|
|
printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
|
|
__func__, cpu);
|
|
__cpu_notify(CPU_UP_CANCELED, cpu, nr_calls, NULL);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int notify_online(unsigned int cpu)
|
|
{
|
|
cpu_notify(CPU_ONLINE, cpu);
|
|
return 0;
|
|
}
|
|
static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
|
|
|
|
static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
|
|
|
|
static int bringup_wait_for_ap(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
|
|
/* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
|
|
wait_for_completion(&st->done);
|
|
if (WARN_ON_ONCE((!cpu_online(cpu))))
|
|
return -ECANCELED;
|
|
|
|
/* Unpark the stopper thread and the hotplug thread of the target cpu */
|
|
stop_machine_unpark(cpu);
|
|
kthread_unpark(st->thread);
|
|
|
|
/* Should we go further up ? */
|
|
if (st->target > CPUHP_AP_ONLINE_IDLE) {
|
|
__cpuhp_kick_ap_work(st);
|
|
wait_for_completion(&st->done);
|
|
}
|
|
return st->result;
|
|
}
|
|
|
|
static int bringup_cpu(unsigned int cpu)
|
|
{
|
|
struct task_struct *idle = idle_thread_get(cpu);
|
|
int ret;
|
|
|
|
/*
|
|
* Some architectures have to walk the irq descriptors to
|
|
* setup the vector space for the cpu which comes online.
|
|
* Prevent irq alloc/free across the bringup.
|
|
*/
|
|
irq_lock_sparse();
|
|
|
|
/* Arch-specific enabling code. */
|
|
ret = __cpu_up(cpu, idle);
|
|
irq_unlock_sparse();
|
|
if (ret) {
|
|
cpu_notify(CPU_UP_CANCELED, cpu);
|
|
return ret;
|
|
}
|
|
return bringup_wait_for_ap(cpu);
|
|
}
|
|
|
|
/*
|
|
* Hotplug state machine related functions
|
|
*/
|
|
static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
for (st->state++; st->state < st->target; st->state++) {
|
|
struct cpuhp_step *step = cpuhp_get_step(st->state);
|
|
|
|
if (!step->skip_onerr)
|
|
cpuhp_invoke_callback(cpu, st->state, true, NULL);
|
|
}
|
|
}
|
|
|
|
static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
|
|
enum cpuhp_state target)
|
|
{
|
|
enum cpuhp_state prev_state = st->state;
|
|
int ret = 0;
|
|
|
|
for (; st->state > target; st->state--) {
|
|
ret = cpuhp_invoke_callback(cpu, st->state, false, NULL);
|
|
BUG_ON(ret && st->state < CPUHP_AP_IDLE_DEAD);
|
|
if (ret) {
|
|
st->target = prev_state;
|
|
undo_cpu_down(cpu, st);
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
for (st->state--; st->state > st->target; st->state--) {
|
|
struct cpuhp_step *step = cpuhp_get_step(st->state);
|
|
|
|
if (!step->skip_onerr)
|
|
cpuhp_invoke_callback(cpu, st->state, false, NULL);
|
|
}
|
|
}
|
|
|
|
static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
|
|
enum cpuhp_state target)
|
|
{
|
|
enum cpuhp_state prev_state = st->state;
|
|
int ret = 0;
|
|
|
|
while (st->state < target) {
|
|
st->state++;
|
|
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL);
|
|
if (ret) {
|
|
st->target = prev_state;
|
|
undo_cpu_up(cpu, st);
|
|
cpu_notify(CPU_UP_CANCELED, cpu);
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* The cpu hotplug threads manage the bringup and teardown of the cpus
|
|
*/
|
|
static void cpuhp_create(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
|
|
init_completion(&st->done);
|
|
}
|
|
|
|
static int cpuhp_should_run(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
|
|
return st->should_run;
|
|
}
|
|
|
|
/* Execute the teardown callbacks. Used to be CPU_DOWN_PREPARE */
|
|
static int cpuhp_ap_offline(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
enum cpuhp_state target = max((int)st->target, CPUHP_TEARDOWN_CPU);
|
|
|
|
return cpuhp_down_callbacks(cpu, st, target);
|
|
}
|
|
|
|
/* Execute the online startup callbacks. Used to be CPU_ONLINE */
|
|
static int cpuhp_ap_online(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
return cpuhp_up_callbacks(cpu, st, st->target);
|
|
}
|
|
|
|
/*
|
|
* Execute teardown/startup callbacks on the plugged cpu. Also used to invoke
|
|
* callbacks when a state gets [un]installed at runtime.
|
|
*/
|
|
static void cpuhp_thread_fun(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
int ret = 0;
|
|
|
|
/*
|
|
* Paired with the mb() in cpuhp_kick_ap_work and
|
|
* cpuhp_invoke_ap_callback, so the work set is consistent visible.
|
|
*/
|
|
smp_mb();
|
|
if (!st->should_run)
|
|
return;
|
|
|
|
st->should_run = false;
|
|
|
|
/* Single callback invocation for [un]install ? */
|
|
if (st->single) {
|
|
if (st->cb_state < CPUHP_AP_ONLINE) {
|
|
local_irq_disable();
|
|
ret = cpuhp_invoke_callback(cpu, st->cb_state,
|
|
st->bringup, st->node);
|
|
local_irq_enable();
|
|
} else {
|
|
ret = cpuhp_invoke_callback(cpu, st->cb_state,
|
|
st->bringup, st->node);
|
|
}
|
|
} else if (st->rollback) {
|
|
BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
|
|
|
|
undo_cpu_down(cpu, st);
|
|
/*
|
|
* This is a momentary workaround to keep the notifier users
|
|
* happy. Will go away once we got rid of the notifiers.
|
|
*/
|
|
cpu_notify_nofail(CPU_DOWN_FAILED, cpu);
|
|
st->rollback = false;
|
|
} else {
|
|
/* Cannot happen .... */
|
|
BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
|
|
|
|
/* Regular hotplug work */
|
|
if (st->state < st->target)
|
|
ret = cpuhp_ap_online(cpu, st);
|
|
else if (st->state > st->target)
|
|
ret = cpuhp_ap_offline(cpu, st);
|
|
}
|
|
st->result = ret;
|
|
complete(&st->done);
|
|
}
|
|
|
|
/* Invoke a single callback on a remote cpu */
|
|
static int
|
|
cpuhp_invoke_ap_callback(int cpu, enum cpuhp_state state, bool bringup,
|
|
struct hlist_node *node)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
|
|
if (!cpu_online(cpu))
|
|
return 0;
|
|
|
|
/*
|
|
* If we are up and running, use the hotplug thread. For early calls
|
|
* we invoke the thread function directly.
|
|
*/
|
|
if (!st->thread)
|
|
return cpuhp_invoke_callback(cpu, state, bringup, node);
|
|
|
|
st->cb_state = state;
|
|
st->single = true;
|
|
st->bringup = bringup;
|
|
st->node = node;
|
|
|
|
/*
|
|
* Make sure the above stores are visible before should_run becomes
|
|
* true. Paired with the mb() above in cpuhp_thread_fun()
|
|
*/
|
|
smp_mb();
|
|
st->should_run = true;
|
|
wake_up_process(st->thread);
|
|
wait_for_completion(&st->done);
|
|
return st->result;
|
|
}
|
|
|
|
/* Regular hotplug invocation of the AP hotplug thread */
|
|
static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st)
|
|
{
|
|
st->result = 0;
|
|
st->single = false;
|
|
/*
|
|
* Make sure the above stores are visible before should_run becomes
|
|
* true. Paired with the mb() above in cpuhp_thread_fun()
|
|
*/
|
|
smp_mb();
|
|
st->should_run = true;
|
|
wake_up_process(st->thread);
|
|
}
|
|
|
|
static int cpuhp_kick_ap_work(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
enum cpuhp_state state = st->state;
|
|
|
|
trace_cpuhp_enter(cpu, st->target, state, cpuhp_kick_ap_work);
|
|
__cpuhp_kick_ap_work(st);
|
|
wait_for_completion(&st->done);
|
|
trace_cpuhp_exit(cpu, st->state, state, st->result);
|
|
return st->result;
|
|
}
|
|
|
|
static struct smp_hotplug_thread cpuhp_threads = {
|
|
.store = &cpuhp_state.thread,
|
|
.create = &cpuhp_create,
|
|
.thread_should_run = cpuhp_should_run,
|
|
.thread_fn = cpuhp_thread_fun,
|
|
.thread_comm = "cpuhp/%u",
|
|
.selfparking = true,
|
|
};
|
|
|
|
void __init cpuhp_threads_init(void)
|
|
{
|
|
BUG_ON(smpboot_register_percpu_thread(&cpuhp_threads));
|
|
kthread_unpark(this_cpu_read(cpuhp_state.thread));
|
|
}
|
|
|
|
EXPORT_SYMBOL(register_cpu_notifier);
|
|
EXPORT_SYMBOL(__register_cpu_notifier);
|
|
void unregister_cpu_notifier(struct notifier_block *nb)
|
|
{
|
|
cpu_maps_update_begin();
|
|
raw_notifier_chain_unregister(&cpu_chain, nb);
|
|
cpu_maps_update_done();
|
|
}
|
|
EXPORT_SYMBOL(unregister_cpu_notifier);
|
|
|
|
void __unregister_cpu_notifier(struct notifier_block *nb)
|
|
{
|
|
raw_notifier_chain_unregister(&cpu_chain, nb);
|
|
}
|
|
EXPORT_SYMBOL(__unregister_cpu_notifier);
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
/**
|
|
* clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
|
|
* @cpu: a CPU id
|
|
*
|
|
* This function walks all processes, finds a valid mm struct for each one and
|
|
* then clears a corresponding bit in mm's cpumask. While this all sounds
|
|
* trivial, there are various non-obvious corner cases, which this function
|
|
* tries to solve in a safe manner.
|
|
*
|
|
* Also note that the function uses a somewhat relaxed locking scheme, so it may
|
|
* be called only for an already offlined CPU.
|
|
*/
|
|
void clear_tasks_mm_cpumask(int cpu)
|
|
{
|
|
struct task_struct *p;
|
|
|
|
/*
|
|
* This function is called after the cpu is taken down and marked
|
|
* offline, so its not like new tasks will ever get this cpu set in
|
|
* their mm mask. -- Peter Zijlstra
|
|
* Thus, we may use rcu_read_lock() here, instead of grabbing
|
|
* full-fledged tasklist_lock.
|
|
*/
|
|
WARN_ON(cpu_online(cpu));
|
|
rcu_read_lock();
|
|
for_each_process(p) {
|
|
struct task_struct *t;
|
|
|
|
/*
|
|
* Main thread might exit, but other threads may still have
|
|
* a valid mm. Find one.
|
|
*/
|
|
t = find_lock_task_mm(p);
|
|
if (!t)
|
|
continue;
|
|
cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
|
|
task_unlock(t);
|
|
}
|
|
rcu_read_unlock();
|
|
}
|
|
|
|
static inline void check_for_tasks(int dead_cpu)
|
|
{
|
|
struct task_struct *g, *p;
|
|
|
|
read_lock(&tasklist_lock);
|
|
for_each_process_thread(g, p) {
|
|
if (!p->on_rq)
|
|
continue;
|
|
/*
|
|
* We do the check with unlocked task_rq(p)->lock.
|
|
* Order the reading to do not warn about a task,
|
|
* which was running on this cpu in the past, and
|
|
* it's just been woken on another cpu.
|
|
*/
|
|
rmb();
|
|
if (task_cpu(p) != dead_cpu)
|
|
continue;
|
|
|
|
pr_warn("Task %s (pid=%d) is on cpu %d (state=%ld, flags=%x)\n",
|
|
p->comm, task_pid_nr(p), dead_cpu, p->state, p->flags);
|
|
}
|
|
read_unlock(&tasklist_lock);
|
|
}
|
|
|
|
static int notify_down_prepare(unsigned int cpu)
|
|
{
|
|
int err, nr_calls = 0;
|
|
|
|
err = __cpu_notify(CPU_DOWN_PREPARE, cpu, -1, &nr_calls);
|
|
if (err) {
|
|
nr_calls--;
|
|
__cpu_notify(CPU_DOWN_FAILED, cpu, nr_calls, NULL);
|
|
pr_warn("%s: attempt to take down CPU %u failed\n",
|
|
__func__, cpu);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/* Take this CPU down. */
|
|
static int take_cpu_down(void *_param)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
|
|
int err, cpu = smp_processor_id();
|
|
|
|
/* Ensure this CPU doesn't handle any more interrupts. */
|
|
err = __cpu_disable();
|
|
if (err < 0)
|
|
return err;
|
|
|
|
/*
|
|
* We get here while we are in CPUHP_TEARDOWN_CPU state and we must not
|
|
* do this step again.
|
|
*/
|
|
WARN_ON(st->state != CPUHP_TEARDOWN_CPU);
|
|
st->state--;
|
|
/* Invoke the former CPU_DYING callbacks */
|
|
for (; st->state > target; st->state--)
|
|
cpuhp_invoke_callback(cpu, st->state, false, NULL);
|
|
|
|
/* Give up timekeeping duties */
|
|
tick_handover_do_timer();
|
|
/* Park the stopper thread */
|
|
stop_machine_park(cpu);
|
|
return 0;
|
|
}
|
|
|
|
static int takedown_cpu(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int err;
|
|
|
|
/* Park the smpboot threads */
|
|
kthread_park(per_cpu_ptr(&cpuhp_state, cpu)->thread);
|
|
smpboot_park_threads(cpu);
|
|
|
|
/*
|
|
* Prevent irq alloc/free while the dying cpu reorganizes the
|
|
* interrupt affinities.
|
|
*/
|
|
irq_lock_sparse();
|
|
|
|
/*
|
|
* So now all preempt/rcu users must observe !cpu_active().
|
|
*/
|
|
err = stop_machine(take_cpu_down, NULL, cpumask_of(cpu));
|
|
if (err) {
|
|
/* CPU refused to die */
|
|
irq_unlock_sparse();
|
|
/* Unpark the hotplug thread so we can rollback there */
|
|
kthread_unpark(per_cpu_ptr(&cpuhp_state, cpu)->thread);
|
|
return err;
|
|
}
|
|
BUG_ON(cpu_online(cpu));
|
|
|
|
/*
|
|
* The CPUHP_AP_SCHED_MIGRATE_DYING callback will have removed all
|
|
* runnable tasks from the cpu, there's only the idle task left now
|
|
* that the migration thread is done doing the stop_machine thing.
|
|
*
|
|
* Wait for the stop thread to go away.
|
|
*/
|
|
wait_for_completion(&st->done);
|
|
BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
|
|
|
|
/* Interrupts are moved away from the dying cpu, reenable alloc/free */
|
|
irq_unlock_sparse();
|
|
|
|
hotplug_cpu__broadcast_tick_pull(cpu);
|
|
/* This actually kills the CPU. */
|
|
__cpu_die(cpu);
|
|
|
|
tick_cleanup_dead_cpu(cpu);
|
|
return 0;
|
|
}
|
|
|
|
static int notify_dead(unsigned int cpu)
|
|
{
|
|
cpu_notify_nofail(CPU_DEAD, cpu);
|
|
check_for_tasks(cpu);
|
|
return 0;
|
|
}
|
|
|
|
static void cpuhp_complete_idle_dead(void *arg)
|
|
{
|
|
struct cpuhp_cpu_state *st = arg;
|
|
|
|
complete(&st->done);
|
|
}
|
|
|
|
void cpuhp_report_idle_dead(void)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
|
|
BUG_ON(st->state != CPUHP_AP_OFFLINE);
|
|
rcu_report_dead(smp_processor_id());
|
|
st->state = CPUHP_AP_IDLE_DEAD;
|
|
/*
|
|
* We cannot call complete after rcu_report_dead() so we delegate it
|
|
* to an online cpu.
|
|
*/
|
|
smp_call_function_single(cpumask_first(cpu_online_mask),
|
|
cpuhp_complete_idle_dead, st, 0);
|
|
}
|
|
|
|
#else
|
|
#define notify_down_prepare NULL
|
|
#define takedown_cpu NULL
|
|
#define notify_dead NULL
|
|
#endif
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
|
/* Requires cpu_add_remove_lock to be held */
|
|
static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
|
|
enum cpuhp_state target)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int prev_state, ret = 0;
|
|
bool hasdied = false;
|
|
u64 start_time = 0;
|
|
|
|
if (num_online_cpus() == 1)
|
|
return -EBUSY;
|
|
|
|
if (!cpu_present(cpu))
|
|
return -EINVAL;
|
|
|
|
if (!tasks_frozen && !cpu_isolated(cpu) && num_online_uniso_cpus() == 1)
|
|
return -EBUSY;
|
|
|
|
cpu_hotplug_begin();
|
|
if (trace_cpuhp_latency_enabled())
|
|
start_time = sched_clock();
|
|
|
|
cpuhp_tasks_frozen = tasks_frozen;
|
|
|
|
prev_state = st->state;
|
|
st->target = target;
|
|
/*
|
|
* If the current CPU state is in the range of the AP hotplug thread,
|
|
* then we need to kick the thread.
|
|
*/
|
|
if (st->state > CPUHP_TEARDOWN_CPU) {
|
|
ret = cpuhp_kick_ap_work(cpu);
|
|
/*
|
|
* The AP side has done the error rollback already. Just
|
|
* return the error code..
|
|
*/
|
|
if (ret)
|
|
goto out;
|
|
|
|
/*
|
|
* We might have stopped still in the range of the AP hotplug
|
|
* thread. Nothing to do anymore.
|
|
*/
|
|
if (st->state > CPUHP_TEARDOWN_CPU)
|
|
goto out;
|
|
}
|
|
/*
|
|
* The AP brought itself down to CPUHP_TEARDOWN_CPU. So we need
|
|
* to do the further cleanups.
|
|
*/
|
|
ret = cpuhp_down_callbacks(cpu, st, target);
|
|
if (ret && st->state > CPUHP_TEARDOWN_CPU && st->state < prev_state) {
|
|
st->target = prev_state;
|
|
st->rollback = true;
|
|
cpuhp_kick_ap_work(cpu);
|
|
}
|
|
|
|
hasdied = prev_state != st->state && st->state == CPUHP_OFFLINE;
|
|
out:
|
|
trace_cpuhp_latency(cpu, 0, start_time, ret);
|
|
cpu_hotplug_done();
|
|
/* This post dead nonsense must die */
|
|
if (!ret && hasdied)
|
|
cpu_notify_nofail(CPU_POST_DEAD, cpu);
|
|
return ret;
|
|
}
|
|
|
|
static int do_cpu_down(unsigned int cpu, enum cpuhp_state target)
|
|
{
|
|
int err;
|
|
|
|
cpu_maps_update_begin();
|
|
|
|
if (cpu_hotplug_disabled) {
|
|
err = -EBUSY;
|
|
goto out;
|
|
}
|
|
|
|
err = _cpu_down(cpu, 0, target);
|
|
|
|
out:
|
|
cpu_maps_update_done();
|
|
return err;
|
|
}
|
|
int cpu_down(unsigned int cpu)
|
|
{
|
|
return do_cpu_down(cpu, CPUHP_OFFLINE);
|
|
}
|
|
EXPORT_SYMBOL(cpu_down);
|
|
#endif /*CONFIG_HOTPLUG_CPU*/
|
|
|
|
/**
|
|
* notify_cpu_starting(cpu) - Invoke the callbacks on the starting CPU
|
|
* @cpu: cpu that just started
|
|
*
|
|
* It must be called by the arch code on the new cpu, before the new cpu
|
|
* enables interrupts and before the "boot" cpu returns from __cpu_up().
|
|
*/
|
|
void notify_cpu_starting(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
|
|
|
|
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
|
|
while (st->state < target) {
|
|
st->state++;
|
|
cpuhp_invoke_callback(cpu, st->state, true, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Called from the idle task. Wake up the controlling task which brings the
|
|
* stopper and the hotplug thread of the upcoming CPU up and then delegates
|
|
* the rest of the online bringup to the hotplug thread.
|
|
*/
|
|
void cpuhp_online_idle(enum cpuhp_state state)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
|
|
/* Happens for the boot cpu */
|
|
if (state != CPUHP_AP_ONLINE_IDLE)
|
|
return;
|
|
|
|
st->state = CPUHP_AP_ONLINE_IDLE;
|
|
complete(&st->done);
|
|
}
|
|
|
|
/* Requires cpu_add_remove_lock to be held */
|
|
static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
struct task_struct *idle;
|
|
int ret = 0;
|
|
u64 start_time = 0;
|
|
|
|
cpu_hotplug_begin();
|
|
if (trace_cpuhp_latency_enabled())
|
|
start_time = sched_clock();
|
|
|
|
if (!cpu_present(cpu)) {
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* The caller of do_cpu_up might have raced with another
|
|
* caller. Ignore it for now.
|
|
*/
|
|
if (st->state >= target)
|
|
goto out;
|
|
|
|
if (st->state == CPUHP_OFFLINE) {
|
|
/* Let it fail before we try to bring the cpu up */
|
|
idle = idle_thread_get(cpu);
|
|
if (IS_ERR(idle)) {
|
|
ret = PTR_ERR(idle);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
cpuhp_tasks_frozen = tasks_frozen;
|
|
|
|
st->target = target;
|
|
/*
|
|
* If the current CPU state is in the range of the AP hotplug thread,
|
|
* then we need to kick the thread once more.
|
|
*/
|
|
if (st->state > CPUHP_BRINGUP_CPU) {
|
|
ret = cpuhp_kick_ap_work(cpu);
|
|
/*
|
|
* The AP side has done the error rollback already. Just
|
|
* return the error code..
|
|
*/
|
|
if (ret)
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Try to reach the target state. We max out on the BP at
|
|
* CPUHP_BRINGUP_CPU. After that the AP hotplug thread is
|
|
* responsible for bringing it up to the target state.
|
|
*/
|
|
target = min((int)target, CPUHP_BRINGUP_CPU);
|
|
ret = cpuhp_up_callbacks(cpu, st, target);
|
|
out:
|
|
trace_cpuhp_latency(cpu, 1, start_time, ret);
|
|
cpu_hotplug_done();
|
|
return ret;
|
|
}
|
|
|
|
static int switch_to_rt_policy(void)
|
|
{
|
|
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
|
|
unsigned int policy = current->policy;
|
|
int err;
|
|
|
|
/* Nobody should be attempting hotplug from these policy contexts. */
|
|
if (policy == SCHED_BATCH || policy == SCHED_IDLE ||
|
|
policy == SCHED_DEADLINE)
|
|
return -EPERM;
|
|
|
|
if (policy == SCHED_FIFO || policy == SCHED_RR)
|
|
return 1;
|
|
|
|
/* Only SCHED_NORMAL left. */
|
|
err = sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m);
|
|
return err;
|
|
|
|
}
|
|
|
|
static int switch_to_fair_policy(void)
|
|
{
|
|
struct sched_param param = { .sched_priority = 0 };
|
|
|
|
return sched_setscheduler_nocheck(current, SCHED_NORMAL, ¶m);
|
|
}
|
|
|
|
static int do_cpu_up(unsigned int cpu, enum cpuhp_state target)
|
|
{
|
|
int err = 0;
|
|
int switch_err = 0;
|
|
|
|
if (!cpu_possible(cpu)) {
|
|
pr_err("can't online cpu %d because it is not configured as may-hotadd at boot time\n",
|
|
cpu);
|
|
#if defined(CONFIG_IA64)
|
|
pr_err("please check additional_cpus= boot parameter\n");
|
|
#endif
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch_err = switch_to_rt_policy();
|
|
if (switch_err < 0)
|
|
return switch_err;
|
|
|
|
err = try_online_node(cpu_to_node(cpu));
|
|
if (err)
|
|
return err;
|
|
|
|
cpu_maps_update_begin();
|
|
|
|
if (cpu_hotplug_disabled) {
|
|
err = -EBUSY;
|
|
goto out;
|
|
}
|
|
|
|
err = _cpu_up(cpu, 0, target);
|
|
out:
|
|
cpu_maps_update_done();
|
|
|
|
if (!switch_err) {
|
|
switch_err = switch_to_fair_policy();
|
|
if (switch_err)
|
|
pr_err("Hotplug policy switch err=%d Task %s pid=%d\n",
|
|
switch_err, current->comm, current->pid);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int cpu_up(unsigned int cpu)
|
|
{
|
|
return do_cpu_up(cpu, CPUHP_ONLINE);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_up);
|
|
|
|
#ifdef CONFIG_PM_SLEEP_SMP
|
|
static cpumask_var_t frozen_cpus;
|
|
|
|
int freeze_secondary_cpus(int primary)
|
|
{
|
|
int cpu, error = 0;
|
|
|
|
cpu_maps_update_begin();
|
|
if (!cpu_online(primary))
|
|
primary = cpumask_first(cpu_online_mask);
|
|
/*
|
|
* We take down all of the non-boot CPUs in one shot to avoid races
|
|
* with the userspace trying to use the CPU hotplug at the same time
|
|
*/
|
|
cpumask_clear(frozen_cpus);
|
|
|
|
pr_info("Disabling non-boot CPUs ...\n");
|
|
for_each_online_cpu(cpu) {
|
|
if (cpu == primary)
|
|
continue;
|
|
trace_suspend_resume(TPS("CPU_OFF"), cpu, true);
|
|
error = _cpu_down(cpu, 1, CPUHP_OFFLINE);
|
|
trace_suspend_resume(TPS("CPU_OFF"), cpu, false);
|
|
if (!error)
|
|
cpumask_set_cpu(cpu, frozen_cpus);
|
|
else {
|
|
pr_err("Error taking CPU%d down: %d\n", cpu, error);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!error)
|
|
BUG_ON(num_online_cpus() > 1);
|
|
else
|
|
pr_err("Non-boot CPUs are not disabled\n");
|
|
|
|
/*
|
|
* Make sure the CPUs won't be enabled by someone else. We need to do
|
|
* this even in case of failure as all disable_nonboot_cpus() users are
|
|
* supposed to do enable_nonboot_cpus() on the failure path.
|
|
*/
|
|
cpu_hotplug_disabled++;
|
|
|
|
cpu_maps_update_done();
|
|
return error;
|
|
}
|
|
|
|
void __weak arch_enable_nonboot_cpus_begin(void)
|
|
{
|
|
}
|
|
|
|
void __weak arch_enable_nonboot_cpus_end(void)
|
|
{
|
|
}
|
|
|
|
void enable_nonboot_cpus(void)
|
|
{
|
|
int cpu, error;
|
|
struct device *cpu_device;
|
|
|
|
/* Allow everyone to use the CPU hotplug again */
|
|
cpu_maps_update_begin();
|
|
__cpu_hotplug_enable();
|
|
if (cpumask_empty(frozen_cpus))
|
|
goto out;
|
|
|
|
pr_info("Enabling non-boot CPUs ...\n");
|
|
|
|
arch_enable_nonboot_cpus_begin();
|
|
|
|
for_each_cpu(cpu, frozen_cpus) {
|
|
trace_suspend_resume(TPS("CPU_ON"), cpu, true);
|
|
error = _cpu_up(cpu, 1, CPUHP_ONLINE);
|
|
trace_suspend_resume(TPS("CPU_ON"), cpu, false);
|
|
if (!error) {
|
|
pr_info("CPU%d is up\n", cpu);
|
|
cpu_device = get_cpu_device(cpu);
|
|
if (!cpu_device)
|
|
pr_err("%s: failed to get cpu%d device\n",
|
|
__func__, cpu);
|
|
else
|
|
kobject_uevent(&cpu_device->kobj, KOBJ_ONLINE);
|
|
continue;
|
|
}
|
|
pr_warn("Error taking CPU%d up: %d\n", cpu, error);
|
|
}
|
|
|
|
arch_enable_nonboot_cpus_end();
|
|
|
|
cpumask_clear(frozen_cpus);
|
|
out:
|
|
cpu_maps_update_done();
|
|
}
|
|
|
|
static int __init alloc_frozen_cpus(void)
|
|
{
|
|
if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
|
|
return -ENOMEM;
|
|
return 0;
|
|
}
|
|
core_initcall(alloc_frozen_cpus);
|
|
|
|
/*
|
|
* When callbacks for CPU hotplug notifications are being executed, we must
|
|
* ensure that the state of the system with respect to the tasks being frozen
|
|
* or not, as reported by the notification, remains unchanged *throughout the
|
|
* duration* of the execution of the callbacks.
|
|
* Hence we need to prevent the freezer from racing with regular CPU hotplug.
|
|
*
|
|
* This synchronization is implemented by mutually excluding regular CPU
|
|
* hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/
|
|
* Hibernate notifications.
|
|
*/
|
|
static int
|
|
cpu_hotplug_pm_callback(struct notifier_block *nb,
|
|
unsigned long action, void *ptr)
|
|
{
|
|
switch (action) {
|
|
|
|
case PM_SUSPEND_PREPARE:
|
|
case PM_HIBERNATION_PREPARE:
|
|
cpu_hotplug_disable();
|
|
break;
|
|
|
|
case PM_POST_SUSPEND:
|
|
case PM_POST_HIBERNATION:
|
|
cpu_hotplug_enable();
|
|
break;
|
|
|
|
default:
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
return NOTIFY_OK;
|
|
}
|
|
|
|
|
|
static int __init cpu_hotplug_pm_sync_init(void)
|
|
{
|
|
/*
|
|
* cpu_hotplug_pm_callback has higher priority than x86
|
|
* bsp_pm_callback which depends on cpu_hotplug_pm_callback
|
|
* to disable cpu hotplug to avoid cpu hotplug race.
|
|
*/
|
|
pm_notifier(cpu_hotplug_pm_callback, 0);
|
|
return 0;
|
|
}
|
|
core_initcall(cpu_hotplug_pm_sync_init);
|
|
|
|
#endif /* CONFIG_PM_SLEEP_SMP */
|
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
/* Boot processor state steps */
|
|
static struct cpuhp_step cpuhp_bp_states[] = {
|
|
[CPUHP_OFFLINE] = {
|
|
.name = "offline",
|
|
.startup.single = NULL,
|
|
.teardown.single = NULL,
|
|
},
|
|
#ifdef CONFIG_SMP
|
|
[CPUHP_CREATE_THREADS]= {
|
|
.name = "threads:prepare",
|
|
.startup.single = smpboot_create_threads,
|
|
.teardown.single = NULL,
|
|
.cant_stop = true,
|
|
},
|
|
[CPUHP_PERF_PREPARE] = {
|
|
.name = "perf:prepare",
|
|
.startup.single = perf_event_init_cpu,
|
|
.teardown.single = perf_event_exit_cpu,
|
|
},
|
|
[CPUHP_WORKQUEUE_PREP] = {
|
|
.name = "workqueue:prepare",
|
|
.startup.single = workqueue_prepare_cpu,
|
|
.teardown.single = NULL,
|
|
},
|
|
[CPUHP_HRTIMERS_PREPARE] = {
|
|
.name = "hrtimers:prepare",
|
|
.startup.single = hrtimers_prepare_cpu,
|
|
.teardown.single = hrtimers_dead_cpu,
|
|
},
|
|
[CPUHP_SMPCFD_PREPARE] = {
|
|
.name = "smpcfd:prepare",
|
|
.startup.single = smpcfd_prepare_cpu,
|
|
.teardown.single = smpcfd_dead_cpu,
|
|
},
|
|
[CPUHP_RELAY_PREPARE] = {
|
|
.name = "relay:prepare",
|
|
.startup.single = relay_prepare_cpu,
|
|
.teardown.single = NULL,
|
|
},
|
|
[CPUHP_SLAB_PREPARE] = {
|
|
.name = "slab:prepare",
|
|
.startup.single = slab_prepare_cpu,
|
|
.teardown.single = slab_dead_cpu,
|
|
},
|
|
[CPUHP_RCUTREE_PREP] = {
|
|
.name = "RCU/tree:prepare",
|
|
.startup.single = rcutree_prepare_cpu,
|
|
.teardown.single = rcutree_dead_cpu,
|
|
},
|
|
/*
|
|
* Preparatory and dead notifiers. Will be replaced once the notifiers
|
|
* are converted to states.
|
|
*/
|
|
[CPUHP_NOTIFY_PREPARE] = {
|
|
.name = "notify:prepare",
|
|
.startup.single = notify_prepare,
|
|
.teardown.single = notify_dead,
|
|
.skip_onerr = true,
|
|
.cant_stop = true,
|
|
},
|
|
/*
|
|
* On the tear-down path, timers_dead_cpu() must be invoked
|
|
* before blk_mq_queue_reinit_notify() from notify_dead(),
|
|
* otherwise a RCU stall occurs.
|
|
*/
|
|
[CPUHP_TIMERS_DEAD] = {
|
|
.name = "timers:dead",
|
|
.startup.single = NULL,
|
|
.teardown.single = timers_dead_cpu,
|
|
},
|
|
/* Kicks the plugged cpu into life */
|
|
[CPUHP_BRINGUP_CPU] = {
|
|
.name = "cpu:bringup",
|
|
.startup.single = bringup_cpu,
|
|
.teardown.single = NULL,
|
|
.cant_stop = true,
|
|
},
|
|
/*
|
|
* Handled on controll processor until the plugged processor manages
|
|
* this itself.
|
|
*/
|
|
[CPUHP_TEARDOWN_CPU] = {
|
|
.name = "cpu:teardown",
|
|
.startup.single = NULL,
|
|
.teardown.single = takedown_cpu,
|
|
.cant_stop = true,
|
|
},
|
|
#else
|
|
[CPUHP_BRINGUP_CPU] = { },
|
|
#endif
|
|
};
|
|
|
|
/* Application processor state steps */
|
|
static struct cpuhp_step cpuhp_ap_states[] = {
|
|
#ifdef CONFIG_SMP
|
|
/* Final state before CPU kills itself */
|
|
[CPUHP_AP_IDLE_DEAD] = {
|
|
.name = "idle:dead",
|
|
},
|
|
/*
|
|
* Last state before CPU enters the idle loop to die. Transient state
|
|
* for synchronization.
|
|
*/
|
|
[CPUHP_AP_OFFLINE] = {
|
|
.name = "ap:offline",
|
|
.cant_stop = true,
|
|
},
|
|
/* First state is scheduler control. Interrupts are disabled */
|
|
[CPUHP_AP_SCHED_STARTING] = {
|
|
.name = "sched:starting",
|
|
.startup.single = sched_cpu_starting,
|
|
.teardown.single = sched_cpu_dying,
|
|
},
|
|
[CPUHP_AP_RCUTREE_DYING] = {
|
|
.name = "RCU/tree:dying",
|
|
.startup.single = NULL,
|
|
.teardown.single = rcutree_dying_cpu,
|
|
},
|
|
[CPUHP_AP_KMAP_DYING] = {
|
|
.name = "KMAP:dying",
|
|
.startup.single = NULL,
|
|
.teardown.single = kmap_remove_unused_cpu,
|
|
},
|
|
[CPUHP_AP_SMPCFD_DYING] = {
|
|
.name = "smpcfd:dying",
|
|
.startup.single = NULL,
|
|
.teardown.single = smpcfd_dying_cpu,
|
|
},
|
|
/* Entry state on starting. Interrupts enabled from here on. Transient
|
|
* state for synchronsization */
|
|
[CPUHP_AP_ONLINE] = {
|
|
.name = "ap:online",
|
|
},
|
|
/* Handle smpboot threads park/unpark */
|
|
[CPUHP_AP_SMPBOOT_THREADS] = {
|
|
.name = "smpboot/threads:online",
|
|
.startup.single = smpboot_unpark_threads,
|
|
.teardown.single = NULL,
|
|
},
|
|
[CPUHP_AP_PERF_ONLINE] = {
|
|
.name = "perf:online",
|
|
.startup.single = perf_event_init_cpu,
|
|
.teardown.single = perf_event_exit_cpu,
|
|
},
|
|
[CPUHP_AP_WORKQUEUE_ONLINE] = {
|
|
.name = "workqueue:online",
|
|
.startup.single = workqueue_online_cpu,
|
|
.teardown.single = workqueue_offline_cpu,
|
|
},
|
|
[CPUHP_AP_RCUTREE_ONLINE] = {
|
|
.name = "RCU/tree:online",
|
|
.startup.single = rcutree_online_cpu,
|
|
.teardown.single = rcutree_offline_cpu,
|
|
},
|
|
|
|
/*
|
|
* Online/down_prepare notifiers. Will be removed once the notifiers
|
|
* are converted to states.
|
|
*/
|
|
[CPUHP_AP_NOTIFY_ONLINE] = {
|
|
.name = "notify:online",
|
|
.startup.single = notify_online,
|
|
.teardown.single = notify_down_prepare,
|
|
.skip_onerr = true,
|
|
},
|
|
#endif
|
|
/*
|
|
* The dynamically registered state space is here
|
|
*/
|
|
|
|
#ifdef CONFIG_SMP
|
|
/* Last state is scheduler control setting the cpu active */
|
|
[CPUHP_AP_ACTIVE] = {
|
|
.name = "sched:active",
|
|
.startup.single = sched_cpu_activate,
|
|
.teardown.single = sched_cpu_deactivate,
|
|
},
|
|
#endif
|
|
|
|
/* CPU is fully up and running. */
|
|
[CPUHP_ONLINE] = {
|
|
.name = "online",
|
|
.startup.single = NULL,
|
|
.teardown.single = NULL,
|
|
},
|
|
};
|
|
|
|
/* Sanity check for callbacks */
|
|
static int cpuhp_cb_check(enum cpuhp_state state)
|
|
{
|
|
if (state <= CPUHP_OFFLINE || state >= CPUHP_ONLINE)
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
static void cpuhp_store_callbacks(enum cpuhp_state state,
|
|
const char *name,
|
|
int (*startup)(unsigned int cpu),
|
|
int (*teardown)(unsigned int cpu),
|
|
bool multi_instance)
|
|
{
|
|
/* (Un)Install the callbacks for further cpu hotplug operations */
|
|
struct cpuhp_step *sp;
|
|
|
|
sp = cpuhp_get_step(state);
|
|
sp->startup.single = startup;
|
|
sp->teardown.single = teardown;
|
|
sp->name = name;
|
|
sp->multi_instance = multi_instance;
|
|
INIT_HLIST_HEAD(&sp->list);
|
|
}
|
|
|
|
static void *cpuhp_get_teardown_cb(enum cpuhp_state state)
|
|
{
|
|
return cpuhp_get_step(state)->teardown.single;
|
|
}
|
|
|
|
/*
|
|
* Call the startup/teardown function for a step either on the AP or
|
|
* on the current CPU.
|
|
*/
|
|
static int cpuhp_issue_call(int cpu, enum cpuhp_state state, bool bringup,
|
|
struct hlist_node *node)
|
|
{
|
|
struct cpuhp_step *sp = cpuhp_get_step(state);
|
|
int ret;
|
|
|
|
if ((bringup && !sp->startup.single) ||
|
|
(!bringup && !sp->teardown.single))
|
|
return 0;
|
|
/*
|
|
* The non AP bound callbacks can fail on bringup. On teardown
|
|
* e.g. module removal we crash for now.
|
|
*/
|
|
#ifdef CONFIG_SMP
|
|
if (cpuhp_is_ap_state(state))
|
|
ret = cpuhp_invoke_ap_callback(cpu, state, bringup, node);
|
|
else
|
|
ret = cpuhp_invoke_callback(cpu, state, bringup, node);
|
|
#else
|
|
ret = cpuhp_invoke_callback(cpu, state, bringup, node);
|
|
#endif
|
|
BUG_ON(ret && !bringup);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Called from __cpuhp_setup_state on a recoverable failure.
|
|
*
|
|
* Note: The teardown callbacks for rollback are not allowed to fail!
|
|
*/
|
|
static void cpuhp_rollback_install(int failedcpu, enum cpuhp_state state,
|
|
struct hlist_node *node)
|
|
{
|
|
int cpu;
|
|
|
|
/* Roll back the already executed steps on the other cpus */
|
|
for_each_present_cpu(cpu) {
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int cpustate = st->state;
|
|
|
|
if (cpu >= failedcpu)
|
|
break;
|
|
|
|
/* Did we invoke the startup call on that cpu ? */
|
|
if (cpustate >= state)
|
|
cpuhp_issue_call(cpu, state, false, node);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Returns a free for dynamic slot assignment of the Online state. The states
|
|
* are protected by the cpuhp_slot_states mutex and an empty slot is identified
|
|
* by having no name assigned.
|
|
*/
|
|
static int cpuhp_reserve_state(enum cpuhp_state state)
|
|
{
|
|
enum cpuhp_state i;
|
|
|
|
for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) {
|
|
if (cpuhp_ap_states[i].name)
|
|
continue;
|
|
|
|
cpuhp_ap_states[i].name = "Reserved";
|
|
return i;
|
|
}
|
|
WARN(1, "No more dynamic states available for CPU hotplug\n");
|
|
return -ENOSPC;
|
|
}
|
|
|
|
int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
|
|
bool invoke)
|
|
{
|
|
struct cpuhp_step *sp;
|
|
int cpu;
|
|
int ret;
|
|
|
|
sp = cpuhp_get_step(state);
|
|
if (sp->multi_instance == false)
|
|
return -EINVAL;
|
|
|
|
get_online_cpus();
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
|
|
if (!invoke || !sp->startup.multi)
|
|
goto add_node;
|
|
|
|
/*
|
|
* Try to call the startup callback for each present cpu
|
|
* depending on the hotplug state of the cpu.
|
|
*/
|
|
for_each_present_cpu(cpu) {
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int cpustate = st->state;
|
|
|
|
if (cpustate < state)
|
|
continue;
|
|
|
|
ret = cpuhp_issue_call(cpu, state, true, node);
|
|
if (ret) {
|
|
if (sp->teardown.multi)
|
|
cpuhp_rollback_install(cpu, state, node);
|
|
goto err;
|
|
}
|
|
}
|
|
add_node:
|
|
ret = 0;
|
|
hlist_add_head(node, &sp->list);
|
|
|
|
err:
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
put_online_cpus();
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__cpuhp_state_add_instance);
|
|
|
|
/**
|
|
* __cpuhp_setup_state - Setup the callbacks for an hotplug machine state
|
|
* @state: The state to setup
|
|
* @invoke: If true, the startup function is invoked for cpus where
|
|
* cpu state >= @state
|
|
* @startup: startup callback function
|
|
* @teardown: teardown callback function
|
|
*
|
|
* Returns 0 if successful, otherwise a proper error code
|
|
*/
|
|
int __cpuhp_setup_state(enum cpuhp_state state,
|
|
const char *name, bool invoke,
|
|
int (*startup)(unsigned int cpu),
|
|
int (*teardown)(unsigned int cpu),
|
|
bool multi_instance)
|
|
{
|
|
int cpu, ret = 0;
|
|
int dyn_state = 0;
|
|
|
|
if (cpuhp_cb_check(state) || !name)
|
|
return -EINVAL;
|
|
|
|
get_online_cpus();
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
|
|
/* currently assignments for the ONLINE state are possible */
|
|
if (state == CPUHP_AP_ONLINE_DYN) {
|
|
dyn_state = 1;
|
|
ret = cpuhp_reserve_state(state);
|
|
if (ret < 0)
|
|
goto out;
|
|
state = ret;
|
|
}
|
|
|
|
cpuhp_store_callbacks(state, name, startup, teardown, multi_instance);
|
|
|
|
if (!invoke || !startup)
|
|
goto out;
|
|
|
|
/*
|
|
* Try to call the startup callback for each present cpu
|
|
* depending on the hotplug state of the cpu.
|
|
*/
|
|
for_each_present_cpu(cpu) {
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int cpustate = st->state;
|
|
|
|
if (cpustate < state)
|
|
continue;
|
|
|
|
ret = cpuhp_issue_call(cpu, state, true, NULL);
|
|
if (ret) {
|
|
if (teardown)
|
|
cpuhp_rollback_install(cpu, state, NULL);
|
|
cpuhp_store_callbacks(state, NULL, NULL, NULL, false);
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
|
|
put_online_cpus();
|
|
if (!ret && dyn_state)
|
|
return state;
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(__cpuhp_setup_state);
|
|
|
|
int __cpuhp_state_remove_instance(enum cpuhp_state state,
|
|
struct hlist_node *node, bool invoke)
|
|
{
|
|
struct cpuhp_step *sp = cpuhp_get_step(state);
|
|
int cpu;
|
|
|
|
BUG_ON(cpuhp_cb_check(state));
|
|
|
|
if (!sp->multi_instance)
|
|
return -EINVAL;
|
|
|
|
get_online_cpus();
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
|
|
if (!invoke || !cpuhp_get_teardown_cb(state))
|
|
goto remove;
|
|
/*
|
|
* Call the teardown callback for each present cpu depending
|
|
* on the hotplug state of the cpu. This function is not
|
|
* allowed to fail currently!
|
|
*/
|
|
for_each_present_cpu(cpu) {
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int cpustate = st->state;
|
|
|
|
if (cpustate >= state)
|
|
cpuhp_issue_call(cpu, state, false, node);
|
|
}
|
|
|
|
remove:
|
|
hlist_del(node);
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
put_online_cpus();
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__cpuhp_state_remove_instance);
|
|
/**
|
|
* __cpuhp_remove_state - Remove the callbacks for an hotplug machine state
|
|
* @state: The state to remove
|
|
* @invoke: If true, the teardown function is invoked for cpus where
|
|
* cpu state >= @state
|
|
*
|
|
* The teardown callback is currently not allowed to fail. Think
|
|
* about module removal!
|
|
*/
|
|
void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
|
|
{
|
|
struct cpuhp_step *sp = cpuhp_get_step(state);
|
|
int cpu;
|
|
|
|
BUG_ON(cpuhp_cb_check(state));
|
|
|
|
get_online_cpus();
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
|
|
if (sp->multi_instance) {
|
|
WARN(!hlist_empty(&sp->list),
|
|
"Error: Removing state %d which has instances left.\n",
|
|
state);
|
|
goto remove;
|
|
}
|
|
|
|
if (!invoke || !cpuhp_get_teardown_cb(state))
|
|
goto remove;
|
|
|
|
/*
|
|
* Call the teardown callback for each present cpu depending
|
|
* on the hotplug state of the cpu. This function is not
|
|
* allowed to fail currently!
|
|
*/
|
|
for_each_present_cpu(cpu) {
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
int cpustate = st->state;
|
|
|
|
if (cpustate >= state)
|
|
cpuhp_issue_call(cpu, state, false, NULL);
|
|
}
|
|
remove:
|
|
cpuhp_store_callbacks(state, NULL, NULL, NULL, false);
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
put_online_cpus();
|
|
}
|
|
EXPORT_SYMBOL(__cpuhp_remove_state);
|
|
|
|
#if defined(CONFIG_SYSFS) && defined(CONFIG_HOTPLUG_CPU)
|
|
static ssize_t show_cpuhp_state(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
|
|
|
|
return sprintf(buf, "%d\n", st->state);
|
|
}
|
|
static DEVICE_ATTR(state, 0444, show_cpuhp_state, NULL);
|
|
|
|
static ssize_t write_cpuhp_target(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
|
|
struct cpuhp_step *sp;
|
|
int target, ret;
|
|
|
|
ret = kstrtoint(buf, 10, &target);
|
|
if (ret)
|
|
return ret;
|
|
|
|
#ifdef CONFIG_CPU_HOTPLUG_STATE_CONTROL
|
|
if (target < CPUHP_OFFLINE || target > CPUHP_ONLINE)
|
|
return -EINVAL;
|
|
#else
|
|
if (target != CPUHP_OFFLINE && target != CPUHP_ONLINE)
|
|
return -EINVAL;
|
|
#endif
|
|
|
|
ret = lock_device_hotplug_sysfs();
|
|
if (ret)
|
|
return ret;
|
|
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
sp = cpuhp_get_step(target);
|
|
ret = !sp->name || sp->cant_stop ? -EINVAL : 0;
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
if (ret)
|
|
goto out;
|
|
|
|
if (st->state < target)
|
|
ret = do_cpu_up(dev->id, target);
|
|
else
|
|
ret = do_cpu_down(dev->id, target);
|
|
out:
|
|
unlock_device_hotplug();
|
|
return ret ? ret : count;
|
|
}
|
|
|
|
static ssize_t show_cpuhp_target(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
|
|
|
|
return sprintf(buf, "%d\n", st->target);
|
|
}
|
|
static DEVICE_ATTR(target, 0644, show_cpuhp_target, write_cpuhp_target);
|
|
|
|
static struct attribute *cpuhp_cpu_attrs[] = {
|
|
&dev_attr_state.attr,
|
|
&dev_attr_target.attr,
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group cpuhp_cpu_attr_group = {
|
|
.attrs = cpuhp_cpu_attrs,
|
|
.name = "hotplug",
|
|
NULL
|
|
};
|
|
|
|
static ssize_t show_cpuhp_states(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
ssize_t cur, res = 0;
|
|
int i;
|
|
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
for (i = CPUHP_OFFLINE; i <= CPUHP_ONLINE; i++) {
|
|
struct cpuhp_step *sp = cpuhp_get_step(i);
|
|
|
|
if (sp->name) {
|
|
cur = sprintf(buf, "%3d: %s\n", i, sp->name);
|
|
buf += cur;
|
|
res += cur;
|
|
}
|
|
}
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
return res;
|
|
}
|
|
static DEVICE_ATTR(states, 0444, show_cpuhp_states, NULL);
|
|
|
|
static struct attribute *cpuhp_cpu_root_attrs[] = {
|
|
&dev_attr_states.attr,
|
|
NULL
|
|
};
|
|
|
|
static struct attribute_group cpuhp_cpu_root_attr_group = {
|
|
.attrs = cpuhp_cpu_root_attrs,
|
|
.name = "hotplug",
|
|
NULL
|
|
};
|
|
|
|
static int __init cpuhp_sysfs_init(void)
|
|
{
|
|
int cpu, ret;
|
|
|
|
ret = sysfs_create_group(&cpu_subsys.dev_root->kobj,
|
|
&cpuhp_cpu_root_attr_group);
|
|
if (ret)
|
|
return ret;
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
struct device *dev = get_cpu_device(cpu);
|
|
|
|
if (!dev)
|
|
continue;
|
|
ret = sysfs_create_group(&dev->kobj, &cpuhp_cpu_attr_group);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
device_initcall(cpuhp_sysfs_init);
|
|
#endif
|
|
|
|
/*
|
|
* cpu_bit_bitmap[] is a special, "compressed" data structure that
|
|
* represents all NR_CPUS bits binary values of 1<<nr.
|
|
*
|
|
* It is used by cpumask_of() to get a constant address to a CPU
|
|
* mask value that has a single bit set only.
|
|
*/
|
|
|
|
/* cpu_bit_bitmap[0] is empty - so we can back into it */
|
|
#define MASK_DECLARE_1(x) [x+1][0] = (1UL << (x))
|
|
#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
|
|
#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
|
|
#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
|
|
|
|
const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
|
|
|
|
MASK_DECLARE_8(0), MASK_DECLARE_8(8),
|
|
MASK_DECLARE_8(16), MASK_DECLARE_8(24),
|
|
#if BITS_PER_LONG > 32
|
|
MASK_DECLARE_8(32), MASK_DECLARE_8(40),
|
|
MASK_DECLARE_8(48), MASK_DECLARE_8(56),
|
|
#endif
|
|
};
|
|
EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
|
|
|
|
const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
|
|
EXPORT_SYMBOL(cpu_all_bits);
|
|
|
|
#ifdef CONFIG_INIT_ALL_POSSIBLE
|
|
struct cpumask __cpu_possible_mask __read_mostly
|
|
= {CPU_BITS_ALL};
|
|
#else
|
|
struct cpumask __cpu_possible_mask __read_mostly;
|
|
#endif
|
|
EXPORT_SYMBOL(__cpu_possible_mask);
|
|
|
|
struct cpumask __cpu_online_mask __read_mostly;
|
|
EXPORT_SYMBOL(__cpu_online_mask);
|
|
|
|
struct cpumask __cpu_present_mask __read_mostly;
|
|
EXPORT_SYMBOL(__cpu_present_mask);
|
|
|
|
struct cpumask __cpu_active_mask __read_mostly;
|
|
EXPORT_SYMBOL(__cpu_active_mask);
|
|
|
|
struct cpumask __cpu_isolated_mask __read_mostly;
|
|
EXPORT_SYMBOL(__cpu_isolated_mask);
|
|
|
|
void init_cpu_present(const struct cpumask *src)
|
|
{
|
|
cpumask_copy(&__cpu_present_mask, src);
|
|
}
|
|
|
|
void init_cpu_possible(const struct cpumask *src)
|
|
{
|
|
cpumask_copy(&__cpu_possible_mask, src);
|
|
}
|
|
|
|
void init_cpu_online(const struct cpumask *src)
|
|
{
|
|
cpumask_copy(&__cpu_online_mask, src);
|
|
}
|
|
|
|
void init_cpu_isolated(const struct cpumask *src)
|
|
{
|
|
cpumask_copy(&__cpu_isolated_mask, src);
|
|
}
|
|
|
|
/*
|
|
* Activate the first processor.
|
|
*/
|
|
void __init boot_cpu_init(void)
|
|
{
|
|
int cpu = smp_processor_id();
|
|
|
|
/* Mark the boot cpu "present", "online" etc for SMP and UP case */
|
|
set_cpu_online(cpu, true);
|
|
set_cpu_active(cpu, true);
|
|
set_cpu_present(cpu, true);
|
|
set_cpu_possible(cpu, true);
|
|
}
|
|
|
|
/*
|
|
* Must be called _AFTER_ setting up the per_cpu areas
|
|
*/
|
|
void __init boot_cpu_state_init(void)
|
|
{
|
|
per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE;
|
|
}
|
|
|
|
static ATOMIC_NOTIFIER_HEAD(idle_notifier);
|
|
|
|
void idle_notifier_register(struct notifier_block *n)
|
|
{
|
|
atomic_notifier_chain_register(&idle_notifier, n);
|
|
}
|
|
EXPORT_SYMBOL_GPL(idle_notifier_register);
|
|
|
|
void idle_notifier_unregister(struct notifier_block *n)
|
|
{
|
|
atomic_notifier_chain_unregister(&idle_notifier, n);
|
|
}
|
|
EXPORT_SYMBOL_GPL(idle_notifier_unregister);
|
|
|
|
void idle_notifier_call_chain(unsigned long val)
|
|
{
|
|
atomic_notifier_call_chain(&idle_notifier, val, NULL);
|
|
}
|
|
EXPORT_SYMBOL_GPL(idle_notifier_call_chain);
|