* refs/heads/tmp-0ce03d1:
Revert "wait: Fix __wait_event_hrtimeout for RT/DL tasks"
Reverts below USB and netfilter patches
BACKPORT: Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is enabled
UPSTREAM: bpf: Ensure correct locking around vulnerable function find_vpid()
UPSTREAM: HID: roccat: Fix use-after-free in roccat_read()
ANDROID: arm64: mm: perform clean & invalidation in __dma_map_area
UPSTREAM: mmc: hsq: Fix data stomping during mmc recovery
UPSTREAM: pinctrl: sunxi: Fix name for A100 R_PIO
BACKPORT: mmc: core: Fix UHS-I SD 1.8V workaround branch
UPSTREAM: Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
UPSTREAM: wifi: mac80211_hwsim: set virtio device ready in probe()
BACKPORT: f2fs: don't use casefolded comparison for "." and ".."
UPSTREAM: Revert "mm/cma.c: remove redundant cma_mutex lock"
UPSTREAM: usb: dwc3: Try usb-role-switch first in dwc3_drd_init
BACKPORT: usb: typec: ucsi: Fix reuse of completion structure
BACKPORT: tipc: fix incorrect order of state message data sanity check
UPSTREAM: net: fix up skbs delta_truesize in UDP GRO frag_list
UPSTREAM: cgroup-v1: Correct privileges check in release_agent writes
UPSTREAM: mm: don't try to NUMA-migrate COW pages that have other uses
UPSTREAM: usb: raw-gadget: fix handling of dual-direction-capable endpoints
UPSTREAM: selinux: check return value of sel_make_avc_files
UPSTREAM: usb: musb: select GENERIC_PHY instead of depending on it
BACKPORT: driver core: Fix error return code in really_probe()
UPSTREAM: fscrypt: fix derivation of SipHash keys on big endian CPUs
BACKPORT: fscrypt: rename FS_KEY_DERIVATION_NONCE_SIZE
UPSTREAM: socionext: account for napi_gro_receive never returning GRO_DROP
UPSTREAM: net: socionext: netsec: fix xdp stats accounting
BACKPORT: fs: align IOCB_* flags with RWF_* flags
UPSTREAM: efi: capsule-loader: Fix use-after-free in efi_capsule_write
BACKPORT: ARM: 9039/1: assembler: generalize byte swapping macro into rev_l
BACKPORT: ARM: 9035/1: uncompress: Add be32tocpu macro
UPSTREAM: drm/meson: Fix overflow implicit truncation warnings
UPSTREAM: irqchip/tegra: Fix overflow implicit truncation warnings
UPSTREAM: video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
UPSTREAM: mm/mremap: hold the rmap lock in write mode when moving page table entries.
FROMLIST: binder: fix UAF of alloc->vma in race with munmap()
UPSTREAM: mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
UPSTREAM: mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
UPSTREAM: af_key: Do not call xfrm_probe_algs in parallel
UPSTREAM: wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans()
UPSTREAM: wifi: cfg80211/mac80211: reject bad MBSSID elements
UPSTREAM: wifi: cfg80211: ensure length byte is present before access
UPSTREAM: wifi: cfg80211: fix BSS refcounting bugs
UPSTREAM: wifi: cfg80211: avoid nontransmitted BSS list corruption
UPSTREAM: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
UPSTREAM: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
UPSTREAM: mac80211: mlme: find auth challenge directly
UPSTREAM: wifi: mac80211: don't parse mbssid in assoc response
ANDROID: GKI: db845c: Update symbols list and ABI
UPSTREAM: wifi: mac80211: fix MBSSID parsing use-after-free
ANDROID: Drop explicit 'CONFIG_INIT_STACK_ALL_ZERO=y' from gki_defconfig
UPSTREAM: hardening: Remove Clang's enable flag for -ftrivial-auto-var-init=zero
UPSTREAM: hardening: Avoid harmless Clang option under CONFIG_INIT_STACK_ALL_ZERO
UPSTREAM: hardening: Clarify Kconfig text for auto-var-init
ANDROID: GKI: Update FCNT KMI symbol list
Linux 5.4.219
wifi: mac80211: fix MBSSID parsing use-after-free
wifi: mac80211: don't parse mbssid in assoc response
mac80211: mlme: find auth challenge directly
Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
Linux 5.4.218
Input: xpad - fix wireless 360 controller breaking after suspend
Input: xpad - add supported devices as contributed on github
wifi: cfg80211: update hidden BSSes to avoid WARN_ON
wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
wifi: cfg80211: avoid nontransmitted BSS list corruption
wifi: cfg80211: fix BSS refcounting bugs
wifi: cfg80211: ensure length byte is present before access
wifi: cfg80211/mac80211: reject bad MBSSID elements
wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans()
random: use expired timer rather than wq for mixing fast pool
random: avoid reading two cache lines on irq randomness
random: restore O_NONBLOCK support
USB: serial: qcserial: add new usb-id for Dell branded EM7455
scsi: stex: Properly zero out the passthrough command structure
efi: Correct Macmini DMI match in uefi cert quirk
ALSA: hda: Fix position reporting on Poulsbo
random: clamp credited irq bits to maximum mixed
ceph: don't truncate file in atomic_open
nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
nilfs2: fix leak of nilfs_root in case of writer thread creation failure
nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
mmc: core: Terminate infinite loop in SD-UHS voltage switch
mmc: core: Replace with already defined values for readability
USB: serial: ftdi_sio: fix 300 bps rate for SIO
usb: mon: make mmapped memory read only
arch: um: Mark the stack non-executable to fix a binutils warning
um: Cleanup compiler warning in arch/x86/um/tls_32.c
um: Cleanup syscall_handler_t cast in syscalls_32.h
net/ieee802154: fix uninit value bug in dgram_sendmsg
scsi: qedf: Fix a UAF bug in __qedf_probe()
ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API failure
dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
firmware: arm_scmi: Add SCMI PM driver remove routine
fs: fix UAF/GPF bug in nilfs_mdt_destroy
perf tools: Fixup get_current_dir_name() compilation
mm: pagewalk: Fix race between unmap and page walker
ANDROID: Fix kenelci build-break for !CONFIG_PERF_EVENTS
BACKPORT: HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
Linux 5.4.217
docs: update mediator information in CoC docs
Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
Revert "drm/amdgpu: use dirty framebuffer helper"
xfs: remove unused variable 'done'
xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
xfs: streamline xfs_attr3_leaf_inactive
xfs: move incore structures out of xfs_da_format.h
xfs: fix memory corruption during remote attr value buffer invalidation
xfs: refactor remote attr value buffer invalidation
xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
xfs: fix s_maxbytes computation on 32-bit kernels
xfs: truncate should remove all blocks, not just to the end of the page cache
xfs: introduce XFS_MAX_FILEOFF
xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
x86/speculation: Add RSB VM Exit protections
x86/bugs: Warn when "ibrs" mitigation is selected on Enhanced IBRS parts
x86/speculation: Use DECLARE_PER_CPU for x86_spec_ctrl_current
x86/speculation: Disable RRSBA behavior
x86/bugs: Add Cannon lake to RETBleed affected CPU list
x86/cpu/amd: Enumerate BTC_NO
x86/common: Stamp out the stepping madness
x86/speculation: Fill RSB on vmexit for IBRS
KVM: VMX: Fix IBRS handling after vmexit
KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS
KVM: VMX: Convert launched argument to flags
KVM: VMX: Flatten __vmx_vcpu_run()
KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
x86/speculation: Remove x86_spec_ctrl_mask
x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit
x86/speculation: Fix SPEC_CTRL write on SMT state change
x86/speculation: Fix firmware entry SPEC_CTRL handling
x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n
x86/speculation: Change FILL_RETURN_BUFFER to work with objtool
intel_idle: Disable IBRS during long idle
x86/bugs: Report Intel retbleed vulnerability
x86/bugs: Split spectre_v2_select_mitigation() and spectre_v2_user_select_mitigation()
x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
x86/bugs: Optimize SPEC_CTRL MSR writes
x86/entry: Add kernel IBRS implementation
x86/entry: Remove skip_r11rcx
x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
x86/bugs: Add AMD retbleed= boot parameter
x86/bugs: Report AMD retbleed vulnerability
x86/cpufeatures: Move RETPOLINE flags to word 11
x86/kvm/vmx: Make noinstr clean
x86/cpu: Add a steppings field to struct x86_cpu_id
x86/cpu: Add consistent CPU match macros
x86/devicetable: Move x86 specific macro out of generic code
Revert "x86/cpu: Add a steppings field to struct x86_cpu_id"
Revert "x86/speculation: Add RSB VM Exit protections"
Linux 5.4.216
clk: iproc: Do not rely on node name for correct PLL setup
clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
selftests: Fix the if conditions of in test_extra_filter()
nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
nvme: add new line after variable declatation
usbnet: Fix memory leak in usbnet_disconnect()
Input: melfas_mip4 - fix return value check in mip4_probe()
Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in suspend/resume time"
soc: sunxi: sram: Fix debugfs info for A64 SRAM C
soc: sunxi: sram: Fix probe function ordering issues
soc: sunxi_sram: Make use of the helper function devm_platform_ioremap_resource()
soc: sunxi: sram: Prevent the driver from being unbound
soc: sunxi: sram: Actually claim SRAM regions
ARM: dts: am33xx: Fix MMCHS0 dma properties
ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
media: dvb_vb2: fix possible out of bound access
mm: fix madivse_pageout mishandling on non-LRU page
mm/migrate_device.c: flush TLB while holding PTL
mm: prevent page_frag_alloc() from corrupting the memory
mm/page_alloc: fix race condition between build_all_zonelists and page allocation
mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
Revert "net: mvpp2: debugfs: fix memory leak when using debugfs_lookup()"
ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
ARM: dts: integrator: Tag PCI host with device_type
clk: ingenic-tcu: Properly enable registers before accessing timers
net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
uas: ignore UAS for Thinkplus chips
usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
uas: add no-uas quirk for Hiksemi usb_disk
ANDROID: ABI: Update allowed list for QCOM
UPSTREAM: wifi: mac80211_hwsim: use 32-bit skb cookie
UPSTREAM: wifi: mac80211_hwsim: add back erroneously removed cast
UPSTREAM: wifi: mac80211_hwsim: fix race condition in pending packet
Linux 5.4.215
ext4: make directory inode spreading reflect flexbg size
xfs: fix use-after-free when aborting corrupt attr inactivation
xfs: fix an ABBA deadlock in xfs_rename
xfs: don't commit sunit/swidth updates to disk if that would cause repair failures
xfs: split the sunit parameter update into two parts
xfs: refactor agfl length computation function
xfs: use bitops interface for buf log item AIL flag check
xfs: stabilize insert range start boundary to avoid COW writeback race
xfs: fix some memory leaks in log recovery
xfs: always log corruption errors
xfs: constify the buffer pointer arguments to error functions
xfs: convert EIO to EFSCORRUPTED when log contents are invalid
xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
xfs: attach dquots and reserve quota blocks during unwritten conversion
xfs: range check ri_cnt when recovering log items
xfs: add missing assert in xfs_fsmap_owner_from_rmap
xfs: slightly tweak an assert in xfs_fs_map_blocks
xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
workqueue: don't skip lockdep work dependency in cancel_work_sync()
drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
drm/amd/display: Limit user regamma to a valid value
drm/amdgpu: use dirty framebuffer helper
Drivers: hv: Never allocate anything besides framebuffer from framebuffer memory region
cifs: always initialize struct msghdr smb_msg completely
usb: xhci-mtk: fix issue of out-of-bounds array access
s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
serial: Create uart_xmit_advance()
net: sched: fix possible refcount leak in tc_new_tfilter()
net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
perf kcore_copy: Do not check /proc/modules is unchanged
perf jit: Include program header in ELF files
can: gs_usb: gs_can_open(): fix race dev->can.state condition
netfilter: ebtables: fix memory leak when blob is malformed
net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child qdiscs
net/sched: taprio: avoid disabling offload when it was never enabled
of: mdio: Add of_node_put() when breaking out of for_each_xx
i40e: Fix set max_tx_rate when it is lower than 1 Mbps
i40e: Fix VF set max MTU size
iavf: Fix set max MTU size with port VLAN and jumbo frames
iavf: Fix bad page state
MIPS: Loongson32: Fix PHY-mode being left unspecified
MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
net: team: Unsync device addresses on ndo_stop
ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
iavf: Fix cached head and tail value for iavf_get_tx_pending
netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
netfilter: nf_conntrack_irc: Tighten matching on DCC message
netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
mm/slub: fix to return errno if kmalloc() fails
efi: libstub: check Shim mode using MokSBStateRT
ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
ALSA: hda/realtek: Re-arrange quirk table entries
ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
ALSA: hda: add Intel 5 Series / 3400 PCI DID
ALSA: hda/tegra: set depop delay for tegra
USB: serial: option: add Quectel RM520N
USB: serial: option: add Quectel BG95 0x0203 composition
USB: core: Fix RST error in hub.c
Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
Revert "usb: add quirks for Lenovo OneLink+ Dock"
usb: cdns3: fix issue with rearming ISO OUT endpoint
usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
usb: add quirks for Lenovo OneLink+ Dock
tty: serial: atmel: Preserve previous USART mode if RS485 disabled
serial: atmel: remove redundant assignment in rs485_config
tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
wifi: mac80211: Fix UAF in ieee80211_scan_rx()
usb: xhci-mtk: relax TT periodic bandwidth allocation
usb: xhci-mtk: allow multiple Start-Split in a microframe
usb: xhci-mtk: add some schedule error number
usb: xhci-mtk: add a function to (un)load bandwidth info
usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
usb: xhci-mtk: add only one extra CS for FS/LS INTR
usb: xhci-mtk: get the microframe boundary for ESIT
usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
usb: dwc3: gadget: Refactor pullup()
usb: dwc3: gadget: Prevent repeat pullup()
usb: dwc3: Issue core soft reset before enabling run/stop
usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
ALSA: hda/sigmatel: Fix unused variable warning for beep power change
cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
mksysmap: Fix the mismatch of 'L0' symbols in System.map
MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
net: usb: qmi_wwan: add Quectel RM520N
ALSA: hda/tegra: Align BDL entry to 4KB boundary
ALSA: hda/sigmatel: Keep power up while beep is enabled
rxrpc: Fix calc of resend age
rxrpc: Fix local destruction being repeated
regulator: pfuze100: Fix the global-out-of-bounds access in pfuze100_regulator_probe()
ASoC: nau8824: Fix semaphore unbalance at error paths
iomap: iomap that extends beyond EOF should be marked dirty
MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
cifs: revalidate mapping when doing direct writes
tracing: hold caller_addr to hardirq_{enable,disable}_ip
task_stack, x86/cea: Force-inline stack helpers
ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
drm/meson: Fix OSD1 RGB to YCbCr coefficient
drm/meson: Correct OSD1 global alpha value
gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
of: fdt: fix off-by-one error in unflatten_dt_nodes()
Revert "USB: core: Prevent nested device-reset calls"
Revert "io_uring: disable polling pollfree files"
Revert "netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y"
Revert "sched/deadline: Fix priority inheritance with multiple scheduling classes"
Revert "kernel/sched: Remove dl_boosted flag comment"
Revert "mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse"
Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
Linux 5.4.214
tracefs: Only clobber mode/uid/gid on remount if asked
soc: fsl: select FSL_GUTS driver for DPIO
net: dp83822: disable rx error interrupt
mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
perf/arm_pmu_platform: fix tests for platform_get_irq() failure
nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
Input: iforce - add support for Boeder Force Feedback Wheel
ieee802154: cc2520: add rc code in cc2520_tx()
tg3: Disable tg3 device on system reboot to avoid triggering AER
hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
drm/msm/rd: Fix FIFO-full deadlock
Linux 5.4.213
MIPS: loongson32: ls1c: Fix hang during startup
x86/nospec: Fix i386 RSB stuffing
sch_sfb: Also store skb len before calling child enqueue
tcp: fix early ETIMEDOUT after spurious non-SACK RTO
nvme-tcp: fix UAF when detecting digest errors
RDMA/mlx5: Set local port to one when accessing counters
ipv6: sr: fix out-of-bounds read when setting HMAC data.
RDMA/siw: Pass a pointer to virt_to_page()
i40e: Fix kernel crash during module removal
tipc: fix shift wrapping bug in map_get()
sch_sfb: Don't assume the skb is still around after enqueueing to child
afs: Use the operation issue time instead of the reply time for callbacks
rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
netfilter: nf_conntrack_irc: Fix forged IP logic
netfilter: br_netfilter: Drop dst references before setting.
RDMA/hns: Fix supported page size
soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
RDMA/cma: Fix arguments order in net device validation
regulator: core: Clean up on enable failure
ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
smb3: missing inode locks in punch hole
cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
cgroup: Elide write-locking threadgroup_rwsem when updating csses on an empty subtree
cgroup: Optimize single thread migration
scsi: lpfc: Add missing destroy_workqueue() in error path
scsi: mpt3sas: Fix use-after-free warning
nvmet: fix a use-after-free
debugfs: add debugfs_lookup_and_remove()
kprobes: Prohibit probes in gate area
ALSA: usb-audio: Fix an out-of-bounds bug in __snd_usb_parse_audio_interface()
ALSA: aloop: Fix random zeros in capture data when using jiffies timer
ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned fw_level
parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
drm/radeon: add a force flush to delay work when radeon
drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
drm/gem: Fix GEM handle release errors
scsi: megaraid_sas: Fix double kfree()
USB: serial: ch341: fix disabled rx timer on older devices
USB: serial: ch341: fix lost character on LCR updates
usb: dwc3: disable USB core PHY management
usb: dwc3: fix PHY disable sequence
btrfs: harden identification of a stale device
drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
ALSA: seq: Fix data-race at module auto-loading
ALSA: seq: oss: Fix data-race for max_midi_devs access
net: mac802154: Fix a condition in the receive path
ip: fix triggering of 'icmp redirect'
wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
driver core: Don't probe devices after bus_type.match() probe deferral
usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
USB: core: Prevent nested device-reset calls
s390: fix nospec table alignments
s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
usb-storage: Add ignore-residue quirk for NXP PN7462AU
USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
usb: dwc2: fix wrong order of phy_power_on and phy_init
usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
USB: serial: option: add Quectel EM060K modem
USB: serial: option: add support for OPPO R11 diag port
USB: serial: cp210x: add Decagon UCA device id
xhci: Add grace period after xHC start to prevent premature runtime suspend.
thunderbolt: Use the actual buffer in tb_async_error()
gpio: pca953x: Add mutex_lock for regcache sync in PM
hwmon: (gpio-fan) Fix array out of bounds access
clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
Input: rk805-pwrkey - fix module autoloading
clk: core: Fix runtime PM sequence in clk_core_unprepare()
Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
binder: fix UAF of ref->proc caused by race condition
USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
misc: fastrpc: fix memory corruption on open
misc: fastrpc: fix memory corruption on probe
iio: adc: mcp3911: use correct formula for AD conversion
Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
tty: serial: lpuart: disable flow control while waiting for the transmit engine to complete
vt: Clear selection before changing the font
powerpc: align syscall table for ppc32
staging: rtl8712: fix use after free bugs
serial: fsl_lpuart: RS485 RTS polariy is inverse
net/smc: Remove redundant refcount increase
Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
tcp: annotate data-race around challenge_timestamp
sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
kcm: fix strp_init() order and cleanup
ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
net: sched: tbf: don't call qdisc_put() while holding tree lock
Revert "xhci: turn off port power in shutdown"
wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
ieee802154/adf7242: defer destroy_workqueue call
iio: adc: mcp3911: make use of the sign bit
platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
drm/msm/dsi: fix the inconsistent indenting
net: dp83822: disable false carrier interrupt
Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
fs: only do a memory barrier for the first set_buffer_uptodate()
net: mvpp2: debugfs: fix memory leak when using debugfs_lookup()
wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in il4965_rs_fill_link_cmd()
efi: capsule-loader: Fix use-after-free in efi_capsule_write
Linux 5.4.212
net: neigh: don't call kfree_skb() under spin_lock_irqsave()
net/af_packet: check len when min_header_len equals to 0
io_uring: disable polling pollfree files
kprobes: don't call disarm_kprobe() for disabled kprobes
lib/vdso: Mark do_hres() and do_coarse() as __always_inline
lib/vdso: Let do_coarse() return 0 to simplify the callsite
btrfs: tree-checker: check for overlapping extent items
netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y
drm/amd/display: Fix pixel clock programming
s390/hypfs: avoid error message under KVM
neigh: fix possible DoS due to net iface start/stop loop
drm/amd/display: clear optc underflow before turn off odm clock
drm/amd/display: Avoid MPC infinite loop
btrfs: unify lookup return value when dir entry is missing
btrfs: do not pin logs too early during renames
btrfs: introduce btrfs_lookup_match_dir
mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse
bpf: Don't redirect packets with invalid pkt_len
ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is dead
fbdev: fb_pm2fb: Avoid potential divide by zero error
HID: hidraw: fix memory leak in hidraw_release()
media: pvrusb2: fix memory leak in pvr_probe
udmabuf: Set the DMA mask for the udmabuf device (v2)
HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
Bluetooth: L2CAP: Fix build errors in some archs
kbuild: Fix include path in scripts/Makefile.modpost
x86/bugs: Add "unknown" reporting for MMIO Stale Data
s390/mm: do not trigger write fault when vma does not allow VM_WRITE
mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
scsi: storvsc: Remove WQ_MEM_RECLAIM from storvsc_error_wq
perf/x86/intel/uncore: Fix broken read_counter() for SNB IMC PMU
md: call __md_stop_writes in md_stop
mm/hugetlb: fix hugetlb not supporting softdirty tracking
ACPI: processor: Remove freq Qos request for all CPUs
s390: fix double free of GS and RI CBs on fork() failure
asm-generic: sections: refactor memory_intersects
loop: Check for overflow while configuring loop
x86/unwind/orc: Unwind ftrace trampolines with correct ORC entry
btrfs: check if root is readonly while setting security xattr
btrfs: add info when mount fails due to stale replace target
btrfs: replace: drop assert for suspended replace
btrfs: fix silent failure when deleting root reference
ixgbe: stop resetting SYSTIME in ixgbe_ptp_start_cyclecounter
net: Fix a data-race around sysctl_somaxconn.
net: Fix a data-race around netdev_budget_usecs.
net: Fix a data-race around netdev_budget.
net: Fix a data-race around sysctl_net_busy_read.
net: Fix a data-race around sysctl_net_busy_poll.
net: Fix a data-race around sysctl_tstamp_allow_data.
ratelimit: Fix data-races in ___ratelimit().
net: Fix data-races around netdev_tstamp_prequeue.
net: Fix data-races around weight_p and dev_weight_[rt]x_bias.
netfilter: nft_tunnel: restrict it to netdev family
netfilter: nft_osf: restrict osf to ipv4, ipv6 and inet families
netfilter: nft_payload: do not truncate csum_offset and csum_type
netfilter: nft_payload: report ERANGE for too long offset and length
bnxt_en: fix NQ resource accounting during vf creation on 57500 chips
netfilter: ebtables: reject blobs that don't provide all entry points
net: ipvtap - add __init/__exit annotations to module init/exit funcs
bonding: 802.3ad: fix no transmission of LACPDUs
net: moxa: get rid of asymmetry in DMA mapping/unmapping
net/mlx5e: Properly disable vlan strip on non-UL reps
rose: check NULL rose_loopback_neigh->loopback
SUNRPC: RPC level errors should set task->tk_rpc_status
af_key: Do not call xfrm_probe_algs in parallel
xfrm: fix refcount leak in __xfrm_policy_check()
kernel/sched: Remove dl_boosted flag comment
sched/deadline: Fix priority inheritance with multiple scheduling classes
sched/deadline: Fix stale throttling on de-/boosted tasks
sched/deadline: Unthrottle PI boosted threads while enqueuing
pinctrl: amd: Don't save/restore interrupt status and wake status bits
Revert "selftests/bpf: Fix test_align verifier log patterns"
Revert "selftests/bpf: Fix "dubious pointer arithmetic" test"
usb: cdns3: Fix issue for clear halt endpoint
kernel/sys_ni: add compat entry for fadvise64_64
parisc: Fix exception handler for fldw and fstw instructions
audit: fix potential double free on error path from fsnotify_add_inode_mark
Revert "USB: HCD: Fix URB giveback issue in tasklet function"
Linux 5.4.211
btrfs: raid56: don't trust any cached sector in __raid56_parity_recover()
btrfs: only write the sectors in the vertical stripe which has data stripes
can: j1939: j1939_session_destroy(): fix memory leak of skbs
can: j1939: j1939_sk_queue_activate_next_locked(): replace WARN_ON_ONCE with netdev_warn_once()
tracing/probes: Have kprobes and uprobes use $COMM too
MIPS: tlbex: Explicitly compare _PAGE_NO_EXEC against 0
video: fbdev: i740fb: Check the argument of i740_calc_vclk()
powerpc/64: Init jump labels before parse_early_param()
smb3: check xattr value length earlier
f2fs: fix to avoid use f2fs_bug_on() in f2fs_new_node_page()
ALSA: timer: Use deferred fasync helper
ALSA: core: Add async signal helpers
powerpc/32: Don't always pass -mcpu=powerpc to the compiler
watchdog: export lockup_detector_reconfigure
RISC-V: Add fast call path of crash_kexec()
riscv: mmap with PROT_WRITE but no PROT_READ is invalid
mips: cavium-octeon: Fix missing of_node_put() in octeon2_usb_clocks_start
vfio: Clear the caps->buf to NULL after free
tty: serial: Fix refcount leak bug in ucc_uart.c
lib/list_debug.c: Detect uninitialized lists
ext4: avoid resizing to a partial cluster size
ext4: avoid remove directory when directory is corrupted
drivers:md:fix a potential use-after-free bug
nvmet-tcp: fix lockdep complaint on nvmet_tcp_wq flush during queue teardown
dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed
selftests/kprobe: Do not test for GRP/ without event failures
um: add "noreboot" command line option for PANIC_TIMEOUT=-1 setups
PCI/ACPI: Guard ARM64-specific mcfg_quirks
cxl: Fix a memory leak in an error handling path
gadgetfs: ep_io - wait until IRQ finishes
scsi: lpfc: Prevent buffer overflow crashes in debugfs with malformed user input
clk: qcom: ipq8074: dont disable gcc_sleep_clk_src
vboxguest: Do not use devm for irq
usb: renesas: Fix refcount leak bug
usb: host: ohci-ppc-of: Fix refcount leak bug
drm/meson: Fix overflow implicit truncation warnings
irqchip/tegra: Fix overflow implicit truncation warnings
usb: gadget: uvc: call uvc uvcg_warn on completed status instead of uvcg_info
usb: cdns3 fix use-after-free at workaround 2
PCI: Add ACS quirk for Broadcom BCM5750x NICs
drm/meson: Fix refcount bugs in meson_vpu_has_available_connectors()
locking/atomic: Make test_and_*_bit() ordered on failure
gcc-plugins: Undefine LATENT_ENTROPY_PLUGIN when plugin disabled for a file
igb: Add lock to avoid data race
fec: Fix timer capture timing in `fec_ptp_enable_pps()`
i40e: Fix to stop tx_timeout recovery if GLOBR fails
ice: Ignore EEXIST when setting promisc mode
net: dsa: microchip: ksz9477: fix fdb_dump last invalid entry
net: moxa: pass pdev instead of ndev to DMA functions
net: dsa: mv88e6060: prevent crash on an unused port
powerpc/pci: Fix get_phb_number() locking
netfilter: nf_tables: really skip inactive sets when allocating name
clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks
iavf: Fix adminq error handling
nios2: add force_successful_syscall_return()
nios2: restarts apply only to the first sigframe we build...
nios2: fix syscall restart checks
nios2: traced syscall does need to check the syscall number
nios2: don't leave NULLs in sys_call_table[]
nios2: page fault et.al. are *not* restartable syscalls...
tee: add overflow check in register_shm_helper()
dpaa2-eth: trace the allocated address instead of page struct
atm: idt77252: fix use-after-free bugs caused by tst_timer
xen/xenbus: fix return type in xenbus_file_read()
nfp: ethtool: fix the display error of `ethtool -m DEVNAME`
NTB: ntb_tool: uninitialized heap data in tool_fn_write()
tools build: Switch to new openssl API for test-libcrypto
tools/vm/slabinfo: use alphabetic order when two values are equal
dt-bindings: arm: qcom: fix MSM8916 MTP compatibles
vsock: Set socket state back to SS_UNCONNECTED in vsock_connect_timeout()
vsock: Fix memory leak in vsock_connect()
plip: avoid rcu debug splat
geneve: do not use RT_TOS for IPv6 flowlabel
ACPI: property: Return type of acpi_add_nondev_subnodes() should be bool
pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
pinctrl: qcom: msm8916: Allow CAMSS GP clocks to be muxed
pinctrl: nomadik: Fix refcount leak in nmk_pinctrl_dt_subnode_to_map
net: bgmac: Fix a BUG triggered by wrong bytes_compl
devlink: Fix use-after-free after a failed reload
SUNRPC: Reinitialise the backchannel request buffers before reuse
sunrpc: fix expiry of auth creds
can: mcp251x: Fix race condition on receive interrupt
NFSv4/pnfs: Fix a use-after-free bug in open
NFSv4.1: RECLAIM_COMPLETE must handle EACCES
NFSv4: Fix races in the legacy idmapper upcall
NFSv4.1: Handle NFS4ERR_DELAY replies to OP_SEQUENCE correctly
NFSv4.1: Don't decrease the value of seq_nr_highest_sent
Documentation: ACPI: EINJ: Fix obsolete example
apparmor: Fix memleak in aa_simple_write_to_buffer()
apparmor: fix reference count leak in aa_pivotroot()
apparmor: fix overlapping attachment computation
apparmor: fix aa_label_asxprint return check
apparmor: Fix failed mount permission check error message
apparmor: fix absroot causing audited secids to begin with =
apparmor: fix quiet_denied for file rules
can: ems_usb: fix clang's -Wunaligned-access warning
tracing: Have filter accept "common_cpu" to be consistent
btrfs: fix lost error handling when looking up extended ref on log replay
mmc: pxamci: Fix an error handling path in pxamci_probe()
mmc: pxamci: Fix another error handling path in pxamci_probe()
ata: libata-eh: Add missing command name
rds: add missing barrier to release_refill
ALSA: info: Fix llseek return value when using callback
net_sched: cls_route: disallow handle of 0
net/9p: Initialize the iounit field during fid creation
Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
Revert "net: usb: ax88179_178a needs FLAG_SEND_ZLP"
scsi: sg: Allow waiting for commands to complete on removed device
tcp: fix over estimation in sk_forced_mem_schedule()
KVM: x86: Avoid theoretical NULL pointer dereference in kvm_irq_delivery_to_apic_fast()
KVM: x86: Check lapic_in_kernel() before attempting to set a SynIC irq
KVM: Add infrastructure and macro to mark VM as bugged
btrfs: reject log replay if there is unsupported RO compat flag
net_sched: cls_route: remove from list when handle is 0
iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails
timekeeping: contribute wall clock to rng on time change
ACPI: CPPC: Do not prevent CPPC from working in the future
dm writecache: set a default MAX_WRITEBACK_JOBS
dm thin: fix use-after-free crash in dm_sm_register_threshold_callback
dm raid: fix address sanitizer warning in raid_status
dm raid: fix address sanitizer warning in raid_resume
intel_th: pci: Add Meteor Lake-P support
intel_th: pci: Add Raptor Lake-S PCH support
intel_th: pci: Add Raptor Lake-S CPU support
ext4: correct the misjudgment in ext4_iget_extra_inode
ext4: correct max_inline_xattr_value_size computing
ext4: fix extent status tree race in writeback error recovery path
ext4: update s_overhead_clusters in the superblock during an on-line resize
ext4: fix use-after-free in ext4_xattr_set_entry
ext4: make sure ext4_append() always allocates new block
ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h
btrfs: reset block group chunk force if we have to wait
tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH
kexec, KEYS, s390: Make use of built-in and secondary keyring for signature verification
spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
x86/olpc: fix 'logical not is only applied to the left hand side'
scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error injection
scsi: qla2xxx: Turn off multi-queue for 8G adapters
scsi: qla2xxx: Fix discovery issues in FC-AL topology
scsi: zfcp: Fix missing auto port scan and thus missing target ports
video: fbdev: s3fb: Check the size of screen before memset_io()
video: fbdev: arkfb: Check the size of screen before memset_io()
video: fbdev: vt8623fb: Check the size of screen before memset_io()
tools/thermal: Fix possible path truncations
video: fbdev: arkfb: Fix a divide-by-zero bug in ark_set_pixclock()
x86/numa: Use cpumask_available instead of hardcoded NULL check
scripts/faddr2line: Fix vmlinux detection on arm64
genelf: Use HAVE_LIBCRYPTO_SUPPORT, not the never defined HAVE_LIBCRYPTO
powerpc/pci: Fix PHB numbering when using opal-phbid
kprobes: Forbid probing on trampoline and BPF code areas
perf symbol: Fail to read phdr workaround
powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address
powerpc/xive: Fix refcount leak in xive_get_max_prio
powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader
powerpc/pci: Prefer PCI domain assignment via DT 'linux,pci-domain' and alias
powerpc/32: Do not allow selection of e5500 or e6500 CPUs on PPC32
video: fbdev: sis: fix typos in SiS_GetModeID()
video: fbdev: amba-clcd: Fix refcount leak bugs
watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in armada_37xx_wdt_probe()
ASoC: audio-graph-card: Add of_node_put() in fail path
fuse: Remove the control interface for virtio-fs
ASoC: qcom: q6dsp: Fix an off-by-one in q6adm_alloc_copp()
s390/zcore: fix race when reading from hardware system area
iommu/arm-smmu: qcom_iommu: Add of_node_put() when breaking out of loop
mfd: max77620: Fix refcount leak in max77620_initialise_fps
mfd: t7l66xb: Drop platform disable callback
kfifo: fix kfifo_to_user() return type
rpmsg: qcom_smd: Fix refcount leak in qcom_smd_parse_edge
iommu/exynos: Handle failed IOMMU device registration properly
tty: n_gsm: fix missing corner cases in gsmld_poll()
tty: n_gsm: fix DM command
tty: n_gsm: fix wrong T1 retry count handling
vfio/ccw: Do not change FSM state in subchannel event
remoteproc: qcom: wcnss: Fix handling of IRQs
tty: n_gsm: fix race condition in gsmld_write()
tty: n_gsm: fix packet re-transmission without open control channel
tty: n_gsm: fix non flow control frames during mux flow off
profiling: fix shift too large makes kernel panic
ASoC: codecs: wcd9335: move gains from SX_TLV to S8_TLV
ASoC: codecs: msm8916-wcd-digital: move gains from SX_TLV to S8_TLV
serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty()
ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe
ASoC: codecs: da7210: add check for i2c_add_driver
ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
opp: Fix error check in dev_pm_opp_attach_genpd()
jbd2: fix assertion 'jh->b_frozen_data == NULL' failure when journal aborted
ext4: recover csum seed of tmp_inode after migrating to extents
jbd2: fix outstanding credits assert in jbd2_journal_commit_transaction()
null_blk: fix ida error handling in null_add_dev()
RDMA/rxe: Fix error unwind in rxe_create_qp()
mm/mmap.c: fix missing call to vm_unacct_memory in mmap_region
platform/olpc: Fix uninitialized data in debugfs write
USB: serial: fix tty-port initialized comments
PCI: tegra194: Fix link up retry sequence
PCI: tegra194: Fix Root Port interrupt handling
HID: alps: Declare U1_UNICORN_LEGACY support
mmc: cavium-thunderx: Add of_node_put() when breaking out of loop
mmc: cavium-octeon: Add of_node_put() when breaking out of loop
gpio: gpiolib-of: Fix refcount bugs in of_mm_gpiochip_add_data()
RDMA/hfi1: fix potential memory leak in setup_base_ctxt()
RDMA/siw: Fix duplicated reported IW_CM_EVENT_CONNECT_REPLY event
RDMA/hns: Fix incorrect clearing of interrupt status register
usb: gadget: udc: amd5536 depends on HAS_DMA
scsi: smartpqi: Fix DMA direction for RAID requests
mmc: sdhci-of-at91: fix set_uhs_signaling rewriting of MC1R
memstick/ms_block: Fix a memory leak
memstick/ms_block: Fix some incorrect memory allocation
mmc: sdhci-of-esdhc: Fix refcount leak in esdhc_signal_voltage_switch
staging: rtl8192u: Fix sleep in atomic context bug in dm_fsync_timer_callback
intel_th: msu: Fix vmalloced buffers
intel_th: msu-sink: Potential dereference of null pointer
intel_th: Fix a resource leak in an error handling path
soundwire: bus_type: fix remove and shutdown support
clk: qcom: camcc-sdm845: Fix topology around titan_top power domain
clk: qcom: ipq8074: set BRANCH_HALT_DELAY flag for UBI clocks
clk: qcom: ipq8074: fix NSS port frequency tables
usb: host: xhci: use snprintf() in xhci_decode_trb()
clk: qcom: clk-krait: unlock spin after mux completion
driver core: fix potential deadlock in __driver_attach
misc: rtsx: Fix an error handling path in rtsx_pci_probe()
clk: mediatek: reset: Fix written reset bit offset
usb: xhci: tegra: Fix error check
usb: ohci-nxp: Fix refcount leak in ohci_hcd_nxp_probe
usb: host: Fix refcount leak in ehci_hcd_ppc_of_probe
fpga: altera-pr-ip: fix unsigned comparison with less than zero
mtd: st_spi_fsm: Add a clk_disable_unprepare() in .probe()'s error path
mtd: partitions: Fix refcount leak in parse_redboot_of
mtd: sm_ftl: Fix deadlock caused by cancel_work_sync in sm_release
HID: cp2112: prevent a buffer overflow in cp2112_xfer()
mtd: rawnand: meson: Fix a potential double free issue
mtd: maps: Fix refcount leak in ap_flash_init
mtd: maps: Fix refcount leak in of_flash_probe_versatile
clk: renesas: r9a06g032: Fix UART clkgrp bitsel
dccp: put dccp_qpolicy_full() and dccp_qpolicy_push() in the same lock
net: rose: fix netdev reference changes
netdevsim: Avoid allocation warnings triggered from user space
iavf: Fix max_rate limiting
crypto: inside-secure - Add missing MODULE_DEVICE_TABLE for of
net/mlx5e: Fix the value of MLX5E_MAX_RQ_NUM_MTTS
wifi: libertas: Fix possible refcount leak in if_usb_probe()
wifi: iwlwifi: mvm: fix double list_add at iwl_mvm_mac_wake_tx_queue
wifi: wil6210: debugfs: fix uninitialized variable use in `wil_write_file_wmi()`
i2c: mux-gpmux: Add of_node_put() when breaking out of loop
i2c: cadence: Support PEC for SMBus block read
Bluetooth: hci_intel: Add check for platform_driver_register
can: pch_can: pch_can_error(): initialize errc before using it
can: error: specify the values of data[5..7] of CAN error frames
can: usb_8dev: do not report txerr and rxerr during bus-off
can: kvaser_usb_leaf: do not report txerr and rxerr during bus-off
can: kvaser_usb_hydra: do not report txerr and rxerr during bus-off
can: sun4i_can: do not report txerr and rxerr during bus-off
can: hi311x: do not report txerr and rxerr during bus-off
can: sja1000: do not report txerr and rxerr during bus-off
can: rcar_can: do not report txerr and rxerr during bus-off
can: pch_can: do not report txerr and rxerr during bus-off
selftests/bpf: fix a test for snprintf() overflow
wifi: p54: add missing parentheses in p54_flush()
wifi: p54: Fix an error handling path in p54spi_probe()
wifi: wil6210: debugfs: fix info leak in wil_write_file_wmi()
fs: check FMODE_LSEEK to control internal pipe splicing
selftests: timers: clocksource-switch: fix passing errors from child
selftests: timers: valid-adjtimex: build fix for newer toolchains
libbpf: Fix the name of a reused map
tcp: make retransmitted SKB fit into the send window
drm/exynos/exynos7_drm_decon: free resources when clk_set_parent() failed.
mediatek: mt76: mac80211: Fix missing of_node_put() in mt76_led_init()
media: platform: mtk-mdp: Fix mdp_ipi_comm structure alignment
crypto: hisilicon - Kunpeng916 crypto driver don't sleep when in softirq
drm/msm/mdp5: Fix global state lock backoff
drm: bridge: sii8620: fix possible off-by-one
drm/mediatek: dpi: Only enable dpi after the bridge is enabled
drm/mediatek: dpi: Remove output format of YUV
drm/rockchip: Fix an error handling path rockchip_dp_probe()
drm/rockchip: vop: Don't crash for invalid duplicate_state()
crypto: arm64/gcm - Select AEAD for GHASH_ARM64_CE
drm/vc4: dsi: Correct DSI divider calculations
drm/vc4: plane: Fix margin calculations for the right/bottom edges
drm/vc4: plane: Remove subpixel positioning check
media: hdpvr: fix error value returns in hdpvr_read
drm/mcde: Fix refcount leak in mcde_dsi_bind
drm: bridge: adv7511: Add check for mipi_dsi_driver_register
wifi: iwlegacy: 4965: fix potential off-by-one overflow in il4965_rs_fill_link_cmd()
ath9k: fix use-after-free in ath9k_hif_usb_rx_cb
media: tw686x: Register the irq at the end of probe
i2c: Fix a potential use after free
drm: adv7511: override i2c address of cec before accessing it
drm/mediatek: Add pull-down MIPI operation in mtk_dsi_poweroff function
drm/radeon: fix potential buffer overflow in ni_set_mc_special_registers()
drm/mipi-dbi: align max_chunk to 2 in spi_transfer
wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c()
ath10k: do not enforce interrupt trigger type
dm: return early from dm_pr_call() if DM device is suspended
thermal/tools/tmon: Include pthread and time headers in tmon.h
nohz/full, sched/rt: Fix missed tick-reenabling bug in dequeue_task_rt()
regulator: of: Fix refcount leak bug in of_get_regulation_constraints()
blk-mq: don't create hctx debugfs dir until q->debugfs_dir is created
erofs: avoid consecutive detection for Highmem memory
arm64: dts: mt7622: fix BPI-R64 WPS button
bus: hisi_lpc: fix missing platform_device_put() in hisi_lpc_acpi_probe()
ARM: dts: qcom: pm8841: add required thermal-sensor-cells
soc: qcom: aoss: Fix refcount leak in qmp_cooling_devices_register
cpufreq: zynq: Fix refcount leak in zynq_get_revision
ARM: OMAP2+: Fix refcount leak in omap3xxx_prm_late_init
ARM: OMAP2+: Fix refcount leak in omapdss_init_of
ARM: dts: qcom: mdm9615: add missing PMIC GPIO reg
soc: fsl: guts: machine variable might be unset
ARM: dts: ast2600-evb: fix board compatible
ARM: dts: ast2500-evb: fix board compatible
x86/pmem: Fix platform-device leak in error path
ARM: bcm: Fix refcount leak in bcm_kona_smc_init
meson-mx-socinfo: Fix refcount leak in meson_mx_socinfo_init
ARM: findbit: fix overflowing offset
spi: spi-rspi: Fix PIO fallback on RZ platforms
selinux: Add boundary check in put_entry()
PM: hibernate: defer device probing when resuming from hibernation
ARM: shmobile: rcar-gen2: Increase refcount for new reference
arm64: dts: allwinner: a64: orangepi-win: Fix LED node name
arm64: dts: qcom: ipq8074: fix NAND node name
ACPI: LPSS: Fix missing check in register_device_clock()
ACPI: PM: save NVS memory for Lenovo G40-45
ACPI: EC: Remove duplicate ThinkPad X1 Carbon 6th entry from DMI quirks
ARM: OMAP2+: display: Fix refcount leak bug
spi: synquacer: Add missing clk_disable_unprepare()
ARM: dts: imx6ul: fix qspi node compatible
ARM: dts: imx6ul: fix lcdif node compatible
ARM: dts: imx6ul: fix csi node compatible
ARM: dts: imx6ul: change operating-points to uint32-matrix
ARM: dts: imx6ul: add missing properties for sram
wait: Fix __wait_event_hrtimeout for RT/DL tasks
genirq: Don't return error on missing optional irq_request_resources()
ext2: Add more validity checks for inode counts
arm64: fix oops in concurrently setting insn_emulation sysctls
arm64: Do not forget syscall when starting a new thread.
x86: Handle idle=nomwait cmdline properly for x86_idle
epoll: autoremove wakers even more aggressively
netfilter: nf_tables: fix null deref due to zeroed list head
netfilter: nf_tables: do not allow RULE_ID to refer to another chain
netfilter: nf_tables: do not allow SET_ID to refer to another table
arm64: dts: uniphier: Fix USB interrupts for PXs3 SoC
ARM: dts: uniphier: Fix USB interrupts for PXs2 SoC
USB: HCD: Fix URB giveback issue in tasklet function
coresight: Clear the connection field properly
MIPS: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
powerpc/powernv: Avoid crashing if rng is NULL
powerpc/ptdump: Fix display of RW pages on FSL_BOOK3E
powerpc/fsl-pci: Fix Class Code of PCIe Root Port
PCI: Add defines for normal and subtractive PCI bridges
ia64, processor: fix -Wincompatible-pointer-types in ia64_get_irr()
md-raid10: fix KASAN warning
serial: mvebu-uart: uart2 error bits clearing
fuse: limit nsec
iio: light: isl29028: Fix the warning in isl29028_remove()
drm/amdgpu: Check BO's requested pinning domains against its preferred_domains
drm/nouveau: fix another off-by-one in nvbios_addr
drm/gem: Properly annotate WW context on drm_gem_lock_reservations() error
parisc: io_pgetevents_time64() needs compat syscall in 32-bit compat mode
parisc: Fix device names in /proc/iomem
ovl: drop WARN_ON() dentry is NULL in ovl_encode_fh()
usbnet: Fix linkwatch use-after-free on disconnect
fbcon: Fix boundary checks for fbcon=vc:n1-n2 parameters
thermal: sysfs: Fix cooling_device_stats_setup() error code path
fs: Add missing umask strip in vfs_tmpfile
vfs: Check the truncate maximum size in inode_newsize_ok()
tty: vt: initialize unicode screen buffer
ALSA: hda/realtek: Add quirk for another Asus K42JZ model
ALSA: hda/cirrus - support for iMac 12,1 model
ALSA: hda/conexant: Add quirk for LENOVO 20149 Notebook model
mm/mremap: hold the rmap lock in write mode when moving page table entries.
KVM: x86: Set error code to segment selector on LLDT/LTR non-canonical #GP
KVM: x86: Mark TSS busy during LTR emulation _after_ all fault checks
KVM: nVMX: Let userspace set nVMX MSR to any _host_ supported value
KVM: SVM: Don't BUG if userspace injects an interrupt with GIF=0
KVM: nVMX: Snapshot pre-VM-Enter DEBUGCTL for !nested_run_pending case
KVM: nVMX: Snapshot pre-VM-Enter BNDCFGS for !nested_run_pending case
HID: wacom: Don't register pad_input for touch switch
HID: wacom: Only report rotation for art pen
add barriers to buffer_uptodate and set_buffer_uptodate
wifi: mac80211_hwsim: use 32-bit skb cookie
wifi: mac80211_hwsim: add back erroneously removed cast
wifi: mac80211_hwsim: fix race condition in pending packet
igc: Remove _I_PHY_ID checking
ALSA: bcd2000: Fix a UAF bug on the error path of probing
scsi: Revert "scsi: qla2xxx: Fix disk failure to rediscover"
x86: link vdso and boot with -z noexecstack --no-warn-rwx-segments
Makefile: link with -z noexecstack --no-warn-rwx-segments
Conflicts:
Documentation/devicetree/bindings
Documentation/devicetree/bindings/arm/qcom.yaml
Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
drivers/mmc/core/sd.c
drivers/net/usb/ax88179_178a.c
drivers/rpmsg/qcom_glink_native.c
drivers/usb/dwc3/core.c
drivers/usb/typec/ucsi/ucsi.c
net/core/dev.c
net/wireless/scan.c
Change-Id: Id1996866ef5d9b7c097c39a5bdb00db413763104
Signed-off-by: Srinivasarao Pathipati <quic_c_spathi@quicinc.com>
2618 lines
64 KiB
C
2618 lines
64 KiB
C
/* CPU control.
|
|
* (C) 2001, 2002, 2003, 2004 Rusty Russell
|
|
*
|
|
* This code is licenced under the GPL.
|
|
*/
|
|
#include <linux/sched/mm.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/init.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/sched/signal.h>
|
|
#include <linux/sched/hotplug.h>
|
|
#include <linux/sched/isolation.h>
|
|
#include <linux/sched/task.h>
|
|
#include <linux/sched/smt.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/nmi.h>
|
|
#include <linux/smpboot.h>
|
|
#include <linux/relay.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/percpu-rwsem.h>
|
|
#include <uapi/linux/sched/types.h>
|
|
#include <linux/cpuset.h>
|
|
#include <linux/random.h>
|
|
|
|
#include <trace/events/power.h>
|
|
#define CREATE_TRACE_POINTS
|
|
#include <trace/events/cpuhp.h>
|
|
#include <linux/sched/clock.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_up: Signal completion to the issuer of the task for cpu-up
|
|
* @done_down: Signal completion to the issuer of the task for cpu-down
|
|
*/
|
|
struct cpuhp_cpu_state {
|
|
enum cpuhp_state state;
|
|
enum cpuhp_state target;
|
|
enum cpuhp_state fail;
|
|
#ifdef CONFIG_SMP
|
|
struct task_struct *thread;
|
|
bool should_run;
|
|
bool rollback;
|
|
bool single;
|
|
bool bringup;
|
|
struct hlist_node *node;
|
|
struct hlist_node *last;
|
|
enum cpuhp_state cb_state;
|
|
int result;
|
|
struct completion done_up;
|
|
struct completion done_down;
|
|
#endif
|
|
};
|
|
|
|
static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = {
|
|
.fail = CPUHP_INVALID,
|
|
};
|
|
|
|
#ifdef CONFIG_SMP
|
|
cpumask_t cpus_booted_once_mask;
|
|
#endif
|
|
|
|
#if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP)
|
|
static struct lockdep_map cpuhp_state_up_map =
|
|
STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map);
|
|
static struct lockdep_map cpuhp_state_down_map =
|
|
STATIC_LOCKDEP_MAP_INIT("cpuhp_state-down", &cpuhp_state_down_map);
|
|
|
|
|
|
static inline void cpuhp_lock_acquire(bool bringup)
|
|
{
|
|
lock_map_acquire(bringup ? &cpuhp_state_up_map : &cpuhp_state_down_map);
|
|
}
|
|
|
|
static inline void cpuhp_lock_release(bool bringup)
|
|
{
|
|
lock_map_release(bringup ? &cpuhp_state_up_map : &cpuhp_state_down_map);
|
|
}
|
|
#else
|
|
|
|
static inline void cpuhp_lock_acquire(bool bringup) { }
|
|
static inline void cpuhp_lock_release(bool bringup) { }
|
|
|
|
#endif
|
|
|
|
/**
|
|
* cpuhp_step - Hotplug state machine step
|
|
* @name: Name of the step
|
|
* @startup: Startup function of the step
|
|
* @teardown: Teardown function of the step
|
|
* @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 cant_stop;
|
|
bool multi_instance;
|
|
};
|
|
|
|
static DEFINE_MUTEX(cpuhp_state_mutex);
|
|
static struct cpuhp_step cpuhp_hp_states[];
|
|
|
|
static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
|
|
{
|
|
return cpuhp_hp_states + state;
|
|
}
|
|
|
|
/**
|
|
* cpuhp_invoke_callback _ Invoke the callbacks for a given state
|
|
* @cpu: The cpu for which the callback should be invoked
|
|
* @state: The state to do callbacks for
|
|
* @bringup: True if the bringup callback should be invoked
|
|
* @node: For multi-instance, do a single entry callback for install/remove
|
|
* @lastp: For multi-instance rollback, remember how far we got
|
|
*
|
|
* 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 hlist_node **lastp)
|
|
{
|
|
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 (st->fail == state) {
|
|
st->fail = CPUHP_INVALID;
|
|
|
|
if (!(bringup ? step->startup.single : step->teardown.single))
|
|
return 0;
|
|
|
|
return -EAGAIN;
|
|
}
|
|
|
|
if (!step->multi_instance) {
|
|
WARN_ON_ONCE(lastp && *lastp);
|
|
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) {
|
|
WARN_ON_ONCE(lastp && *lastp);
|
|
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) {
|
|
if (lastp && node == *lastp)
|
|
break;
|
|
|
|
trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
|
|
ret = cbm(cpu, node);
|
|
trace_cpuhp_exit(cpu, st->state, state, ret);
|
|
if (ret) {
|
|
if (!lastp)
|
|
goto err;
|
|
|
|
*lastp = node;
|
|
return ret;
|
|
}
|
|
cnt++;
|
|
}
|
|
if (lastp)
|
|
*lastp = NULL;
|
|
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;
|
|
|
|
trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
|
|
ret = cbm(cpu, node);
|
|
trace_cpuhp_exit(cpu, st->state, state, ret);
|
|
/*
|
|
* Rollback must not fail,
|
|
*/
|
|
WARN_ON_ONCE(ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_SMP
|
|
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 inline void wait_for_ap_thread(struct cpuhp_cpu_state *st, bool bringup)
|
|
{
|
|
struct completion *done = bringup ? &st->done_up : &st->done_down;
|
|
wait_for_completion(done);
|
|
}
|
|
|
|
static inline void complete_ap_thread(struct cpuhp_cpu_state *st, bool bringup)
|
|
{
|
|
struct completion *done = bringup ? &st->done_up : &st->done_down;
|
|
complete(done);
|
|
}
|
|
|
|
/*
|
|
* The former STARTING/DYING states, ran with IRQs disabled and must not fail.
|
|
*/
|
|
static bool cpuhp_is_atomic_state(enum cpuhp_state state)
|
|
{
|
|
return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE;
|
|
}
|
|
|
|
/* 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.
|
|
*/
|
|
void cpu_maps_update_begin(void)
|
|
{
|
|
mutex_lock(&cpu_add_remove_lock);
|
|
}
|
|
|
|
void cpu_maps_update_done(void)
|
|
{
|
|
mutex_unlock(&cpu_add_remove_lock);
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
|
|
DEFINE_STATIC_PERCPU_RWSEM(cpu_hotplug_lock);
|
|
|
|
void cpus_read_lock(void)
|
|
{
|
|
percpu_down_read(&cpu_hotplug_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpus_read_lock);
|
|
|
|
int cpus_read_trylock(void)
|
|
{
|
|
return percpu_down_read_trylock(&cpu_hotplug_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpus_read_trylock);
|
|
|
|
void cpus_read_unlock(void)
|
|
{
|
|
percpu_up_read(&cpu_hotplug_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpus_read_unlock);
|
|
|
|
void cpus_write_lock(void)
|
|
{
|
|
percpu_down_write(&cpu_hotplug_lock);
|
|
}
|
|
|
|
void cpus_write_unlock(void)
|
|
{
|
|
percpu_up_write(&cpu_hotplug_lock);
|
|
}
|
|
|
|
void lockdep_assert_cpus_held(void)
|
|
{
|
|
/*
|
|
* We can't have hotplug operations before userspace starts running,
|
|
* and some init codepaths will knowingly not take the hotplug lock.
|
|
* This is all valid, so mute lockdep until it makes sense to report
|
|
* unheld locks.
|
|
*/
|
|
if (system_state < SYSTEM_RUNNING)
|
|
return;
|
|
|
|
percpu_rwsem_assert_held(&cpu_hotplug_lock);
|
|
}
|
|
|
|
static void lockdep_acquire_cpus_lock(void)
|
|
{
|
|
rwsem_acquire(&cpu_hotplug_lock.rw_sem.dep_map, 0, 0, _THIS_IP_);
|
|
}
|
|
|
|
static void lockdep_release_cpus_lock(void)
|
|
{
|
|
rwsem_release(&cpu_hotplug_lock.rw_sem.dep_map, 1, _THIS_IP_);
|
|
}
|
|
|
|
/*
|
|
* 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);
|
|
|
|
#else
|
|
|
|
static void lockdep_acquire_cpus_lock(void)
|
|
{
|
|
}
|
|
|
|
static void lockdep_release_cpus_lock(void)
|
|
{
|
|
}
|
|
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
/*
|
|
* Architectures that need SMT-specific errata handling during SMT hotplug
|
|
* should override this.
|
|
*/
|
|
void __weak arch_smt_update(void) { }
|
|
|
|
#ifdef CONFIG_HOTPLUG_SMT
|
|
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
|
|
|
|
void __init cpu_smt_disable(bool force)
|
|
{
|
|
if (!cpu_smt_possible())
|
|
return;
|
|
|
|
if (force) {
|
|
pr_info("SMT: Force disabled\n");
|
|
cpu_smt_control = CPU_SMT_FORCE_DISABLED;
|
|
} else {
|
|
pr_info("SMT: disabled\n");
|
|
cpu_smt_control = CPU_SMT_DISABLED;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The decision whether SMT is supported can only be done after the full
|
|
* CPU identification. Called from architecture code.
|
|
*/
|
|
void __init cpu_smt_check_topology(void)
|
|
{
|
|
if (!topology_smt_supported())
|
|
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
|
|
}
|
|
|
|
static int __init smt_cmdline_disable(char *str)
|
|
{
|
|
cpu_smt_disable(str && !strcmp(str, "force"));
|
|
return 0;
|
|
}
|
|
early_param("nosmt", smt_cmdline_disable);
|
|
|
|
static inline bool cpu_smt_allowed(unsigned int cpu)
|
|
{
|
|
if (cpu_smt_control == CPU_SMT_ENABLED)
|
|
return true;
|
|
|
|
if (topology_is_primary_thread(cpu))
|
|
return true;
|
|
|
|
/*
|
|
* On x86 it's required to boot all logical CPUs at least once so
|
|
* that the init code can get a chance to set CR4.MCE on each
|
|
* CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any
|
|
* core will shutdown the machine.
|
|
*/
|
|
return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
|
|
}
|
|
|
|
/* Returns true if SMT is not supported of forcefully (irreversibly) disabled */
|
|
bool cpu_smt_possible(void)
|
|
{
|
|
return cpu_smt_control != CPU_SMT_FORCE_DISABLED &&
|
|
cpu_smt_control != CPU_SMT_NOT_SUPPORTED;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_smt_possible);
|
|
#else
|
|
static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
|
|
#endif
|
|
|
|
static inline enum cpuhp_state
|
|
cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target)
|
|
{
|
|
enum cpuhp_state prev_state = st->state;
|
|
|
|
st->rollback = false;
|
|
st->last = NULL;
|
|
|
|
st->target = target;
|
|
st->single = false;
|
|
st->bringup = st->state < target;
|
|
|
|
return prev_state;
|
|
}
|
|
|
|
static inline void
|
|
cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
|
|
{
|
|
st->rollback = true;
|
|
|
|
/*
|
|
* If we have st->last we need to undo partial multi_instance of this
|
|
* state first. Otherwise start undo at the previous state.
|
|
*/
|
|
if (!st->last) {
|
|
if (st->bringup)
|
|
st->state--;
|
|
else
|
|
st->state++;
|
|
}
|
|
|
|
st->target = prev_state;
|
|
st->bringup = !st->bringup;
|
|
}
|
|
|
|
/* Regular hotplug invocation of the AP hotplug thread */
|
|
static void __cpuhp_kick_ap(struct cpuhp_cpu_state *st)
|
|
{
|
|
if (!st->single && st->state == st->target)
|
|
return;
|
|
|
|
st->result = 0;
|
|
/*
|
|
* 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_ap_thread(st, st->bringup);
|
|
}
|
|
|
|
static int cpuhp_kick_ap(struct cpuhp_cpu_state *st, enum cpuhp_state target)
|
|
{
|
|
enum cpuhp_state prev_state;
|
|
int ret;
|
|
|
|
prev_state = cpuhp_set_state(st, target);
|
|
__cpuhp_kick_ap(st);
|
|
if ((ret = st->result)) {
|
|
cpuhp_reset_state(st, prev_state);
|
|
__cpuhp_kick_ap(st);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
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_ap_thread(st, true);
|
|
if (WARN_ON_ONCE((!cpu_online(cpu))))
|
|
return -ECANCELED;
|
|
|
|
/* Unpark the hotplug thread of the target cpu */
|
|
kthread_unpark(st->thread);
|
|
|
|
/*
|
|
* SMT soft disabling on X86 requires to bring the CPU out of the
|
|
* BIOS 'wait for SIPI' state in order to set the CR4.MCE bit. The
|
|
* CPU marked itself as booted_once in notify_cpu_starting() so the
|
|
* cpu_smt_allowed() check will now return false if this is not the
|
|
* primary sibling.
|
|
*/
|
|
if (!cpu_smt_allowed(cpu))
|
|
return -ECANCELED;
|
|
|
|
if (st->target <= CPUHP_AP_ONLINE_IDLE)
|
|
return 0;
|
|
|
|
return cpuhp_kick_ap(st, st->target);
|
|
}
|
|
|
|
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)
|
|
return ret;
|
|
return bringup_wait_for_ap(cpu);
|
|
}
|
|
|
|
static int finish_cpu(unsigned int cpu)
|
|
{
|
|
struct task_struct *idle = idle_thread_get(cpu);
|
|
struct mm_struct *mm = idle->active_mm;
|
|
|
|
/*
|
|
* idle_task_exit() will have switched to &init_mm, now
|
|
* clean up any remaining active_mm state.
|
|
*/
|
|
if (mm != &init_mm)
|
|
idle->active_mm = &init_mm;
|
|
mmdrop(mm);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Hotplug state machine related functions
|
|
*/
|
|
|
|
static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
for (st->state--; st->state > st->target; st->state--)
|
|
cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
|
|
}
|
|
|
|
static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st)
|
|
{
|
|
if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
|
|
return true;
|
|
/*
|
|
* When CPU hotplug is disabled, then taking the CPU down is not
|
|
* possible because takedown_cpu() and the architecture and
|
|
* subsystem specific mechanisms are not available. So the CPU
|
|
* which would be completely unplugged again needs to stay around
|
|
* in the current state.
|
|
*/
|
|
return st->state <= CPUHP_BRINGUP_CPU;
|
|
}
|
|
|
|
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, NULL);
|
|
if (ret) {
|
|
if (can_rollback_cpu(st)) {
|
|
st->target = prev_state;
|
|
undo_cpu_up(cpu, st);
|
|
}
|
|
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_up);
|
|
init_completion(&st->done_down);
|
|
}
|
|
|
|
static int cpuhp_should_run(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
|
|
return st->should_run;
|
|
}
|
|
|
|
/*
|
|
* Execute teardown/startup callbacks on the plugged cpu. Also used to invoke
|
|
* callbacks when a state gets [un]installed at runtime.
|
|
*
|
|
* Each invocation of this function by the smpboot thread does a single AP
|
|
* state callback.
|
|
*
|
|
* It has 3 modes of operation:
|
|
* - single: runs st->cb_state
|
|
* - up: runs ++st->state, while st->state < st->target
|
|
* - down: runs st->state--, while st->state > st->target
|
|
*
|
|
* When complete or on error, should_run is cleared and the completion is fired.
|
|
*/
|
|
static void cpuhp_thread_fun(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
bool bringup = st->bringup;
|
|
enum cpuhp_state state;
|
|
|
|
if (WARN_ON_ONCE(!st->should_run))
|
|
return;
|
|
|
|
/*
|
|
* ACQUIRE for the cpuhp_should_run() load of ->should_run. Ensures
|
|
* that if we see ->should_run we also see the rest of the state.
|
|
*/
|
|
smp_mb();
|
|
|
|
/*
|
|
* The BP holds the hotplug lock, but we're now running on the AP,
|
|
* ensure that anybody asserting the lock is held, will actually find
|
|
* it so.
|
|
*/
|
|
lockdep_acquire_cpus_lock();
|
|
cpuhp_lock_acquire(bringup);
|
|
|
|
if (st->single) {
|
|
state = st->cb_state;
|
|
st->should_run = false;
|
|
} else {
|
|
if (bringup) {
|
|
st->state++;
|
|
state = st->state;
|
|
st->should_run = (st->state < st->target);
|
|
WARN_ON_ONCE(st->state > st->target);
|
|
} else {
|
|
state = st->state;
|
|
st->state--;
|
|
st->should_run = (st->state > st->target);
|
|
WARN_ON_ONCE(st->state < st->target);
|
|
}
|
|
}
|
|
|
|
WARN_ON_ONCE(!cpuhp_is_ap_state(state));
|
|
|
|
if (cpuhp_is_atomic_state(state)) {
|
|
local_irq_disable();
|
|
st->result = cpuhp_invoke_callback(cpu, state, bringup, st->node, &st->last);
|
|
local_irq_enable();
|
|
|
|
/*
|
|
* STARTING/DYING must not fail!
|
|
*/
|
|
WARN_ON_ONCE(st->result);
|
|
} else {
|
|
st->result = cpuhp_invoke_callback(cpu, state, bringup, st->node, &st->last);
|
|
}
|
|
|
|
if (st->result) {
|
|
/*
|
|
* If we fail on a rollback, we're up a creek without no
|
|
* paddle, no way forward, no way back. We loose, thanks for
|
|
* playing.
|
|
*/
|
|
WARN_ON_ONCE(st->rollback);
|
|
st->should_run = false;
|
|
}
|
|
|
|
cpuhp_lock_release(bringup);
|
|
lockdep_release_cpus_lock();
|
|
|
|
if (!st->should_run)
|
|
complete_ap_thread(st, bringup);
|
|
}
|
|
|
|
/* 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);
|
|
int ret;
|
|
|
|
if (!cpu_online(cpu))
|
|
return 0;
|
|
|
|
cpuhp_lock_acquire(false);
|
|
cpuhp_lock_release(false);
|
|
|
|
cpuhp_lock_acquire(true);
|
|
cpuhp_lock_release(true);
|
|
|
|
/*
|
|
* 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, NULL);
|
|
|
|
st->rollback = false;
|
|
st->last = NULL;
|
|
|
|
st->node = node;
|
|
st->bringup = bringup;
|
|
st->cb_state = state;
|
|
st->single = true;
|
|
|
|
__cpuhp_kick_ap(st);
|
|
|
|
/*
|
|
* If we failed and did a partial, do a rollback.
|
|
*/
|
|
if ((ret = st->result) && st->last) {
|
|
st->rollback = true;
|
|
st->bringup = !bringup;
|
|
|
|
__cpuhp_kick_ap(st);
|
|
}
|
|
|
|
/*
|
|
* Clean up the leftovers so the next hotplug operation wont use stale
|
|
* data.
|
|
*/
|
|
st->node = st->last = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static int cpuhp_kick_ap_work(unsigned int cpu)
|
|
{
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
enum cpuhp_state prev_state = st->state;
|
|
int ret;
|
|
|
|
cpuhp_lock_acquire(false);
|
|
cpuhp_lock_release(false);
|
|
|
|
cpuhp_lock_acquire(true);
|
|
cpuhp_lock_release(true);
|
|
|
|
trace_cpuhp_enter(cpu, st->target, prev_state, cpuhp_kick_ap_work);
|
|
ret = cpuhp_kick_ap(st, st->target);
|
|
trace_cpuhp_exit(cpu, st->state, prev_state, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
/*
|
|
*
|
|
* Serialize hotplug trainwrecks outside of the cpu_hotplug_lock
|
|
* protected region.
|
|
*
|
|
* The operation is still serialized against concurrent CPU hotplug via
|
|
* cpu_add_remove_lock, i.e. CPU map protection. But it is _not_
|
|
* serialized against other hotplug related activity like adding or
|
|
* removing of state callbacks and state instances, which invoke either the
|
|
* startup or the teardown callback of the affected state.
|
|
*
|
|
* This is required for subsystems which are unfixable vs. CPU hotplug and
|
|
* evade lock inversion problems by scheduling work which has to be
|
|
* completed _before_ cpu_up()/_cpu_down() returns.
|
|
*
|
|
* Don't even think about adding anything to this for any new code or even
|
|
* drivers. It's only purpose is to keep existing lock order trainwrecks
|
|
* working.
|
|
*
|
|
* For cpu_down() there might be valid reasons to finish cleanups which are
|
|
* not required to be done under cpu_hotplug_lock, but that's a different
|
|
* story and would be not invoked via this.
|
|
*/
|
|
static void cpu_up_down_serialize_trainwrecks(bool tasks_frozen)
|
|
{
|
|
/*
|
|
* cpusets delegate hotplug operations to a worker to "solve" the
|
|
* lock order problems. Wait for the worker, but only if tasks are
|
|
* _not_ frozen (suspend, hibernate) as that would wait forever.
|
|
*
|
|
* The wait is required because otherwise the hotplug operation
|
|
* returns with inconsistent state, which could even be observed in
|
|
* user space when a new CPU is brought up. The CPU plug uevent
|
|
* would be delivered and user space reacting on it would fail to
|
|
* move tasks to the newly plugged CPU up to the point where the
|
|
* work has finished because up to that point the newly plugged CPU
|
|
* is not assignable in cpusets/cgroups. On unplug that's not
|
|
* necessarily a visible issue, but it is still inconsistent state,
|
|
* which is the real problem which needs to be "fixed". This can't
|
|
* prevent the transient state between scheduling the work and
|
|
* returning from waiting for it.
|
|
*/
|
|
if (!tasks_frozen)
|
|
cpuset_wait_for_hotplug();
|
|
}
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
#ifndef arch_clear_mm_cpumask_cpu
|
|
#define arch_clear_mm_cpumask_cpu(cpu, mm) cpumask_clear_cpu(cpu, mm_cpumask(mm))
|
|
#endif
|
|
|
|
/**
|
|
* 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;
|
|
arch_clear_mm_cpumask_cpu(cpu, t->mm);
|
|
task_unlock(t);
|
|
}
|
|
rcu_read_unlock();
|
|
}
|
|
|
|
/* 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();
|
|
int ret;
|
|
|
|
/* 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--) {
|
|
ret = cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
|
|
/*
|
|
* DYING must not fail!
|
|
*/
|
|
WARN_ON_ONCE(ret);
|
|
}
|
|
|
|
/* Give up timekeeping duties */
|
|
tick_handover_do_timer();
|
|
/* Remove CPU from timer broadcasting */
|
|
tick_offline_cpu(cpu);
|
|
/* 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);
|
|
|
|
/*
|
|
* 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_cpuslocked(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 teardown callback for CPUHP_AP_SCHED_STARTING 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_ap_thread(st, false);
|
|
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);
|
|
rcutree_migrate_callbacks(cpu);
|
|
return 0;
|
|
}
|
|
|
|
static void cpuhp_complete_idle_dead(void *arg)
|
|
{
|
|
struct cpuhp_cpu_state *st = arg;
|
|
|
|
complete_ap_thread(st, false);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
{
|
|
for (st->state++; st->state < st->target; st->state++)
|
|
cpuhp_invoke_callback(cpu, st->state, true, NULL, 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, NULL);
|
|
if (ret) {
|
|
st->target = prev_state;
|
|
if (st->state < prev_state)
|
|
undo_cpu_down(cpu, st);
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* 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;
|
|
u64 start_time = 0;
|
|
|
|
if (num_online_cpus() == 1)
|
|
return -EBUSY;
|
|
|
|
if (!cpu_present(cpu))
|
|
return -EINVAL;
|
|
|
|
#ifdef CONFIG_SCHED_WALT
|
|
if (!tasks_frozen && !cpu_isolated(cpu) && num_online_uniso_cpus() == 1)
|
|
return -EBUSY;
|
|
#endif
|
|
|
|
cpus_write_lock();
|
|
if (trace_cpuhp_latency_enabled())
|
|
start_time = sched_clock();
|
|
|
|
cpuhp_tasks_frozen = tasks_frozen;
|
|
|
|
prev_state = cpuhp_set_state(st, 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) {
|
|
st->target = max((int)target, 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;
|
|
|
|
st->target = target;
|
|
}
|
|
/*
|
|
* 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) {
|
|
cpuhp_reset_state(st, prev_state);
|
|
__cpuhp_kick_ap(st);
|
|
}
|
|
|
|
out:
|
|
trace_cpuhp_latency(cpu, 0, start_time, ret);
|
|
cpus_write_unlock();
|
|
/*
|
|
* Do post unplug cleanup. This is still protected against
|
|
* concurrent CPU hotplug via cpu_add_remove_lock.
|
|
*/
|
|
lockup_detector_cleanup();
|
|
arch_smt_update();
|
|
cpu_up_down_serialize_trainwrecks(tasks_frozen);
|
|
return ret;
|
|
}
|
|
|
|
static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target)
|
|
{
|
|
if (cpu_hotplug_disabled)
|
|
return -EBUSY;
|
|
return _cpu_down(cpu, 0, target);
|
|
}
|
|
|
|
static int do_cpu_down(unsigned int cpu, enum cpuhp_state target)
|
|
{
|
|
int err;
|
|
|
|
/*
|
|
* When cpusets are enabled, the rebuilding of the scheduling
|
|
* domains is deferred to a workqueue context. Make sure
|
|
* that the work is completed before proceeding to the next
|
|
* hotplug. Otherwise scheduler observes an inconsistent
|
|
* view of online and offline CPUs in the root domain. If
|
|
* the online CPUs are still stuck in the offline (default)
|
|
* domain, those CPUs would not be visible when scheduling
|
|
* happens on from other CPUs in the root domain.
|
|
*/
|
|
cpuset_wait_for_hotplug();
|
|
|
|
cpu_maps_update_begin();
|
|
err = cpu_down_maps_locked(cpu, target);
|
|
cpu_maps_update_done();
|
|
return err;
|
|
}
|
|
|
|
int cpu_down(unsigned int cpu)
|
|
{
|
|
return do_cpu_down(cpu, CPUHP_OFFLINE);
|
|
}
|
|
EXPORT_SYMBOL(cpu_down);
|
|
|
|
#else
|
|
#define takedown_cpu NULL
|
|
#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);
|
|
int ret;
|
|
|
|
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
|
|
cpumask_set_cpu(cpu, &cpus_booted_once_mask);
|
|
while (st->state < target) {
|
|
st->state++;
|
|
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
|
|
/*
|
|
* STARTING must not fail!
|
|
*/
|
|
WARN_ON_ONCE(ret);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Called from the idle task. Wake up the controlling task which brings 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;
|
|
|
|
/*
|
|
* Unpart the stopper thread before we start the idle loop (and start
|
|
* scheduling); this ensures the stopper task is always available.
|
|
*/
|
|
stop_machine_unpark(smp_processor_id());
|
|
|
|
st->state = CPUHP_AP_ONLINE_IDLE;
|
|
complete_ap_thread(st, true);
|
|
}
|
|
|
|
/* 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;
|
|
|
|
cpus_write_lock();
|
|
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;
|
|
|
|
cpuhp_set_state(st, 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);
|
|
cpus_write_unlock();
|
|
arch_smt_update();
|
|
cpu_up_down_serialize_trainwrecks(tasks_frozen);
|
|
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;
|
|
}
|
|
|
|
cpuset_wait_for_hotplug();
|
|
|
|
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;
|
|
}
|
|
if (!cpu_smt_allowed(cpu)) {
|
|
err = -EPERM;
|
|
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, bool suspend)
|
|
{
|
|
int cpu, error = 0;
|
|
|
|
cpu_maps_update_begin();
|
|
if (primary == -1) {
|
|
primary = cpumask_first(cpu_online_mask);
|
|
if (!housekeeping_cpu(primary, HK_FLAG_TIMER))
|
|
primary = housekeeping_any_cpu(HK_FLAG_TIMER);
|
|
} else {
|
|
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;
|
|
|
|
if (suspend && pm_wakeup_pending()) {
|
|
pr_info("Wakeup pending. Abort CPU freeze\n");
|
|
error = -EBUSY;
|
|
break;
|
|
}
|
|
|
|
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 */
|
|
|
|
int __boot_cpu_id;
|
|
|
|
/* Horrific hacks because we can't add more to cpuhp_hp_states. */
|
|
static int random_and_perf_prepare_fusion(unsigned int cpu)
|
|
{
|
|
#ifdef CONFIG_PERF_EVENTS
|
|
perf_event_init_cpu(cpu);
|
|
#endif
|
|
random_prepare_cpu(cpu);
|
|
return 0;
|
|
}
|
|
static int random_and_workqueue_online_fusion(unsigned int cpu)
|
|
{
|
|
workqueue_online_cpu(cpu);
|
|
random_online_cpu(cpu);
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
/* Boot processor state steps */
|
|
static struct cpuhp_step cpuhp_hp_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 = random_and_perf_prepare_fusion,
|
|
.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,
|
|
},
|
|
/*
|
|
* 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_PREPARE] = {
|
|
.name = "timers:prepare",
|
|
.startup.single = timers_prepare_cpu,
|
|
.teardown.single = timers_dead_cpu,
|
|
},
|
|
/* Kicks the plugged cpu into life */
|
|
[CPUHP_BRINGUP_CPU] = {
|
|
.name = "cpu:bringup",
|
|
.startup.single = bringup_cpu,
|
|
.teardown.single = finish_cpu,
|
|
.cant_stop = true,
|
|
},
|
|
/* 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_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",
|
|
},
|
|
/*
|
|
* 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,
|
|
},
|
|
/* Handle smpboot threads park/unpark */
|
|
[CPUHP_AP_SMPBOOT_THREADS] = {
|
|
.name = "smpboot/threads:online",
|
|
.startup.single = smpboot_unpark_threads,
|
|
.teardown.single = smpboot_park_threads,
|
|
},
|
|
[CPUHP_AP_IRQ_AFFINITY_ONLINE] = {
|
|
.name = "irq/affinity:online",
|
|
.startup.single = irq_affinity_online_cpu,
|
|
.teardown.single = NULL,
|
|
},
|
|
[CPUHP_AP_PERF_ONLINE] = {
|
|
.name = "perf:online",
|
|
.startup.single = perf_event_init_cpu,
|
|
.teardown.single = perf_event_exit_cpu,
|
|
},
|
|
[CPUHP_AP_WATCHDOG_ONLINE] = {
|
|
.name = "lockup_detector:online",
|
|
.startup.single = lockup_detector_online_cpu,
|
|
.teardown.single = lockup_detector_offline_cpu,
|
|
},
|
|
[CPUHP_AP_WORKQUEUE_ONLINE] = {
|
|
.name = "workqueue:online",
|
|
.startup.single = random_and_workqueue_online_fusion,
|
|
.teardown.single = workqueue_offline_cpu,
|
|
},
|
|
[CPUHP_AP_RCUTREE_ONLINE] = {
|
|
.name = "RCU/tree:online",
|
|
.startup.single = rcutree_online_cpu,
|
|
.teardown.single = rcutree_offline_cpu,
|
|
},
|
|
#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;
|
|
}
|
|
|
|
/*
|
|
* 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, end;
|
|
struct cpuhp_step *step;
|
|
|
|
switch (state) {
|
|
case CPUHP_AP_ONLINE_DYN:
|
|
step = cpuhp_hp_states + CPUHP_AP_ONLINE_DYN;
|
|
end = CPUHP_AP_ONLINE_DYN_END;
|
|
break;
|
|
case CPUHP_BP_PREPARE_DYN:
|
|
step = cpuhp_hp_states + CPUHP_BP_PREPARE_DYN;
|
|
end = CPUHP_BP_PREPARE_DYN_END;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = state; i <= end; i++, step++) {
|
|
if (!step->name)
|
|
return i;
|
|
}
|
|
WARN(1, "No more dynamic states available for CPU hotplug\n");
|
|
return -ENOSPC;
|
|
}
|
|
|
|
static int 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;
|
|
int ret = 0;
|
|
|
|
/*
|
|
* If name is NULL, then the state gets removed.
|
|
*
|
|
* CPUHP_AP_ONLINE_DYN and CPUHP_BP_PREPARE_DYN are handed out on
|
|
* the first allocation from these dynamic ranges, so the removal
|
|
* would trigger a new allocation and clear the wrong (already
|
|
* empty) state, leaving the callbacks of the to be cleared state
|
|
* dangling, which causes wreckage on the next hotplug operation.
|
|
*/
|
|
if (name && (state == CPUHP_AP_ONLINE_DYN ||
|
|
state == CPUHP_BP_PREPARE_DYN)) {
|
|
ret = cpuhp_reserve_state(state);
|
|
if (ret < 0)
|
|
return ret;
|
|
state = ret;
|
|
}
|
|
sp = cpuhp_get_step(state);
|
|
if (name && sp->name)
|
|
return -EBUSY;
|
|
|
|
sp->startup.single = startup;
|
|
sp->teardown.single = teardown;
|
|
sp->name = name;
|
|
sp->multi_instance = multi_instance;
|
|
INIT_HLIST_HEAD(&sp->list);
|
|
return ret;
|
|
}
|
|
|
|
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 there's nothing to do, we done.
|
|
* Relies on the union for multi_instance.
|
|
*/
|
|
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, NULL);
|
|
#else
|
|
ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
|
|
#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);
|
|
}
|
|
}
|
|
|
|
int __cpuhp_state_add_instance_cpuslocked(enum cpuhp_state state,
|
|
struct hlist_node *node,
|
|
bool invoke)
|
|
{
|
|
struct cpuhp_step *sp;
|
|
int cpu;
|
|
int ret;
|
|
|
|
lockdep_assert_cpus_held();
|
|
|
|
sp = cpuhp_get_step(state);
|
|
if (sp->multi_instance == false)
|
|
return -EINVAL;
|
|
|
|
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 unlock;
|
|
}
|
|
}
|
|
add_node:
|
|
ret = 0;
|
|
hlist_add_head(node, &sp->list);
|
|
unlock:
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
return ret;
|
|
}
|
|
|
|
int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
|
|
bool invoke)
|
|
{
|
|
int ret;
|
|
|
|
cpus_read_lock();
|
|
ret = __cpuhp_state_add_instance_cpuslocked(state, node, invoke);
|
|
cpus_read_unlock();
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__cpuhp_state_add_instance);
|
|
|
|
/**
|
|
* __cpuhp_setup_state_cpuslocked - 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
|
|
* @multi_instance: State is set up for multiple instances which get
|
|
* added afterwards.
|
|
*
|
|
* The caller needs to hold cpus read locked while calling this function.
|
|
* Returns:
|
|
* On success:
|
|
* Positive state number if @state is CPUHP_AP_ONLINE_DYN
|
|
* 0 for all other states
|
|
* On failure: proper (negative) error code
|
|
*/
|
|
int __cpuhp_setup_state_cpuslocked(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;
|
|
bool dynstate;
|
|
|
|
lockdep_assert_cpus_held();
|
|
|
|
if (cpuhp_cb_check(state) || !name)
|
|
return -EINVAL;
|
|
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
|
|
ret = cpuhp_store_callbacks(state, name, startup, teardown,
|
|
multi_instance);
|
|
|
|
dynstate = state == CPUHP_AP_ONLINE_DYN;
|
|
if (ret > 0 && dynstate) {
|
|
state = ret;
|
|
ret = 0;
|
|
}
|
|
|
|
if (ret || !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);
|
|
/*
|
|
* If the requested state is CPUHP_AP_ONLINE_DYN, return the
|
|
* dynamically allocated state in case of success.
|
|
*/
|
|
if (!ret && dynstate)
|
|
return state;
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(__cpuhp_setup_state_cpuslocked);
|
|
|
|
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 ret;
|
|
|
|
cpus_read_lock();
|
|
ret = __cpuhp_setup_state_cpuslocked(state, name, invoke, startup,
|
|
teardown, multi_instance);
|
|
cpus_read_unlock();
|
|
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;
|
|
|
|
cpus_read_lock();
|
|
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);
|
|
cpus_read_unlock();
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__cpuhp_state_remove_instance);
|
|
|
|
/**
|
|
* __cpuhp_remove_state_cpuslocked - 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 caller needs to hold cpus read locked while calling this function.
|
|
* The teardown callback is currently not allowed to fail. Think
|
|
* about module removal!
|
|
*/
|
|
void __cpuhp_remove_state_cpuslocked(enum cpuhp_state state, bool invoke)
|
|
{
|
|
struct cpuhp_step *sp = cpuhp_get_step(state);
|
|
int cpu;
|
|
|
|
BUG_ON(cpuhp_cb_check(state));
|
|
|
|
lockdep_assert_cpus_held();
|
|
|
|
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);
|
|
}
|
|
EXPORT_SYMBOL(__cpuhp_remove_state_cpuslocked);
|
|
|
|
void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
|
|
{
|
|
cpus_read_lock();
|
|
__cpuhp_remove_state_cpuslocked(state, invoke);
|
|
cpus_read_unlock();
|
|
}
|
|
EXPORT_SYMBOL(__cpuhp_remove_state);
|
|
|
|
#ifdef CONFIG_HOTPLUG_SMT
|
|
static void cpuhp_offline_cpu_device(unsigned int cpu)
|
|
{
|
|
struct device *dev = get_cpu_device(cpu);
|
|
|
|
dev->offline = true;
|
|
/* Tell user space about the state change */
|
|
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
|
}
|
|
|
|
static void cpuhp_online_cpu_device(unsigned int cpu)
|
|
{
|
|
struct device *dev = get_cpu_device(cpu);
|
|
|
|
dev->offline = false;
|
|
/* Tell user space about the state change */
|
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
|
}
|
|
|
|
int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
|
|
{
|
|
int cpu, ret = 0;
|
|
|
|
cpu_maps_update_begin();
|
|
for_each_online_cpu(cpu) {
|
|
if (topology_is_primary_thread(cpu))
|
|
continue;
|
|
ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
|
|
if (ret)
|
|
break;
|
|
/*
|
|
* As this needs to hold the cpu maps lock it's impossible
|
|
* to call device_offline() because that ends up calling
|
|
* cpu_down() which takes cpu maps lock. cpu maps lock
|
|
* needs to be held as this might race against in kernel
|
|
* abusers of the hotplug machinery (thermal management).
|
|
*
|
|
* So nothing would update device:offline state. That would
|
|
* leave the sysfs entry stale and prevent onlining after
|
|
* smt control has been changed to 'off' again. This is
|
|
* called under the sysfs hotplug lock, so it is properly
|
|
* serialized against the regular offline usage.
|
|
*/
|
|
cpuhp_offline_cpu_device(cpu);
|
|
}
|
|
if (!ret)
|
|
cpu_smt_control = ctrlval;
|
|
cpu_maps_update_done();
|
|
return ret;
|
|
}
|
|
|
|
int cpuhp_smt_enable(void)
|
|
{
|
|
int cpu, ret = 0;
|
|
|
|
cpu_maps_update_begin();
|
|
cpu_smt_control = CPU_SMT_ENABLED;
|
|
for_each_present_cpu(cpu) {
|
|
/* Skip online CPUs and CPUs on offline nodes */
|
|
if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
|
|
continue;
|
|
ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
|
|
if (ret)
|
|
break;
|
|
/* See comment in cpuhp_smt_disable() */
|
|
cpuhp_online_cpu_device(cpu);
|
|
}
|
|
cpu_maps_update_done();
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#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 ssize_t write_cpuhp_fail(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 fail, ret;
|
|
|
|
ret = kstrtoint(buf, 10, &fail);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (fail < CPUHP_OFFLINE || fail > CPUHP_ONLINE)
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* Cannot fail STARTING/DYING callbacks.
|
|
*/
|
|
if (cpuhp_is_atomic_state(fail))
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* Cannot fail anything that doesn't have callbacks.
|
|
*/
|
|
mutex_lock(&cpuhp_state_mutex);
|
|
sp = cpuhp_get_step(fail);
|
|
if (!sp->startup.single && !sp->teardown.single)
|
|
ret = -EINVAL;
|
|
mutex_unlock(&cpuhp_state_mutex);
|
|
if (ret)
|
|
return ret;
|
|
|
|
st->fail = fail;
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t show_cpuhp_fail(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->fail);
|
|
}
|
|
|
|
static DEVICE_ATTR(fail, 0644, show_cpuhp_fail, write_cpuhp_fail);
|
|
|
|
static struct attribute *cpuhp_cpu_attrs[] = {
|
|
&dev_attr_state.attr,
|
|
&dev_attr_target.attr,
|
|
&dev_attr_fail.attr,
|
|
NULL
|
|
};
|
|
|
|
static const 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 const struct attribute_group cpuhp_cpu_root_attr_group = {
|
|
.attrs = cpuhp_cpu_root_attrs,
|
|
.name = "hotplug",
|
|
NULL
|
|
};
|
|
|
|
#ifdef CONFIG_HOTPLUG_SMT
|
|
|
|
static ssize_t
|
|
__store_smt_control(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int ctrlval, ret;
|
|
|
|
if (sysfs_streq(buf, "on"))
|
|
ctrlval = CPU_SMT_ENABLED;
|
|
else if (sysfs_streq(buf, "off"))
|
|
ctrlval = CPU_SMT_DISABLED;
|
|
else if (sysfs_streq(buf, "forceoff"))
|
|
ctrlval = CPU_SMT_FORCE_DISABLED;
|
|
else
|
|
return -EINVAL;
|
|
|
|
if (cpu_smt_control == CPU_SMT_FORCE_DISABLED)
|
|
return -EPERM;
|
|
|
|
if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
|
|
return -ENODEV;
|
|
|
|
ret = lock_device_hotplug_sysfs();
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (ctrlval != cpu_smt_control) {
|
|
switch (ctrlval) {
|
|
case CPU_SMT_ENABLED:
|
|
ret = cpuhp_smt_enable();
|
|
break;
|
|
case CPU_SMT_DISABLED:
|
|
case CPU_SMT_FORCE_DISABLED:
|
|
ret = cpuhp_smt_disable(ctrlval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
unlock_device_hotplug();
|
|
return ret ? ret : count;
|
|
}
|
|
|
|
#else /* !CONFIG_HOTPLUG_SMT */
|
|
static ssize_t
|
|
__store_smt_control(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
#endif /* CONFIG_HOTPLUG_SMT */
|
|
|
|
static const char *smt_states[] = {
|
|
[CPU_SMT_ENABLED] = "on",
|
|
[CPU_SMT_DISABLED] = "off",
|
|
[CPU_SMT_FORCE_DISABLED] = "forceoff",
|
|
[CPU_SMT_NOT_SUPPORTED] = "notsupported",
|
|
[CPU_SMT_NOT_IMPLEMENTED] = "notimplemented",
|
|
};
|
|
|
|
static ssize_t
|
|
show_smt_control(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
const char *state = smt_states[cpu_smt_control];
|
|
|
|
return snprintf(buf, PAGE_SIZE - 2, "%s\n", state);
|
|
}
|
|
|
|
static ssize_t
|
|
store_smt_control(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
return __store_smt_control(dev, attr, buf, count);
|
|
}
|
|
static DEVICE_ATTR(control, 0644, show_smt_control, store_smt_control);
|
|
|
|
static ssize_t
|
|
show_smt_active(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE - 2, "%d\n", sched_smt_active());
|
|
}
|
|
static DEVICE_ATTR(active, 0444, show_smt_active, NULL);
|
|
|
|
static struct attribute *cpuhp_smt_attrs[] = {
|
|
&dev_attr_control.attr,
|
|
&dev_attr_active.attr,
|
|
NULL
|
|
};
|
|
|
|
static const struct attribute_group cpuhp_smt_attr_group = {
|
|
.attrs = cpuhp_smt_attrs,
|
|
.name = "smt",
|
|
NULL
|
|
};
|
|
|
|
static int __init cpu_smt_sysfs_init(void)
|
|
{
|
|
return sysfs_create_group(&cpu_subsys.dev_root->kobj,
|
|
&cpuhp_smt_attr_group);
|
|
}
|
|
|
|
static int __init cpuhp_sysfs_init(void)
|
|
{
|
|
int cpu, ret;
|
|
|
|
ret = cpu_smt_sysfs_init();
|
|
if (ret)
|
|
return 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 /* CONFIG_SYSFS && CONFIG_HOTPLUG_CPU */
|
|
|
|
/*
|
|
* 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);
|
|
|
|
#ifdef CONFIG_SCHED_WALT
|
|
struct cpumask __cpu_isolated_mask __read_mostly;
|
|
EXPORT_SYMBOL(__cpu_isolated_mask);
|
|
#endif
|
|
|
|
atomic_t __num_online_cpus __read_mostly;
|
|
EXPORT_SYMBOL(__num_online_cpus);
|
|
|
|
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);
|
|
}
|
|
|
|
#ifdef CONFIG_SCHED_WALT
|
|
void init_cpu_isolated(const struct cpumask *src)
|
|
{
|
|
cpumask_copy(&__cpu_isolated_mask, src);
|
|
}
|
|
#endif
|
|
|
|
void set_cpu_online(unsigned int cpu, bool online)
|
|
{
|
|
/*
|
|
* atomic_inc/dec() is required to handle the horrid abuse of this
|
|
* function by the reboot and kexec code which invoke it from
|
|
* IPI/NMI broadcasts when shutting down CPUs. Invocation from
|
|
* regular CPU hotplug is properly serialized.
|
|
*
|
|
* Note, that the fact that __num_online_cpus is of type atomic_t
|
|
* does not protect readers which are not serialized against
|
|
* concurrent hotplug operations.
|
|
*/
|
|
if (online) {
|
|
if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask))
|
|
atomic_inc(&__num_online_cpus);
|
|
} else {
|
|
if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask))
|
|
atomic_dec(&__num_online_cpus);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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);
|
|
|
|
#ifdef CONFIG_SMP
|
|
__boot_cpu_id = cpu;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Must be called _AFTER_ setting up the per_cpu areas
|
|
*/
|
|
void __init boot_cpu_hotplug_init(void)
|
|
{
|
|
#ifdef CONFIG_SMP
|
|
cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
|
|
#endif
|
|
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
|
|
}
|
|
|
|
/*
|
|
* These are used for a global "mitigations=" cmdline option for toggling
|
|
* optional CPU mitigations.
|
|
*/
|
|
enum cpu_mitigations {
|
|
CPU_MITIGATIONS_OFF,
|
|
CPU_MITIGATIONS_AUTO,
|
|
CPU_MITIGATIONS_AUTO_NOSMT,
|
|
};
|
|
|
|
static enum cpu_mitigations cpu_mitigations __ro_after_init =
|
|
CPU_MITIGATIONS_AUTO;
|
|
|
|
static int __init mitigations_parse_cmdline(char *arg)
|
|
{
|
|
if (!strcmp(arg, "off"))
|
|
cpu_mitigations = CPU_MITIGATIONS_OFF;
|
|
else if (!strcmp(arg, "auto"))
|
|
cpu_mitigations = CPU_MITIGATIONS_AUTO;
|
|
else if (!strcmp(arg, "auto,nosmt"))
|
|
cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
|
|
else
|
|
pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n",
|
|
arg);
|
|
|
|
return 0;
|
|
}
|
|
early_param("mitigations", mitigations_parse_cmdline);
|
|
|
|
/* mitigations=off */
|
|
bool cpu_mitigations_off(void)
|
|
{
|
|
return cpu_mitigations == CPU_MITIGATIONS_OFF;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_mitigations_off);
|
|
|
|
/* mitigations=auto,nosmt */
|
|
bool cpu_mitigations_auto_nosmt(void)
|
|
{
|
|
return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt);
|
|
|
|
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);
|