From nobody Thu Apr 9 17:23:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA8E63E3D9A; Fri, 6 Mar 2026 15:32:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772811120; cv=none; b=nHyVLNl01/jnPS+D5en/e9SIOmELhhuXshbEKxxGzpnhcnOIMZnaWVgKTBfPtNq63KSTdnfcNE7oY2kZC/UuATGM9KvzQqvrgpQ63DX+rDdWzkn27mAjnTb975z27QB0bWNxsw3Q9x9LhZYdppk/JNvq0svbu/Vnf222y3I9SiU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772811120; c=relaxed/simple; bh=cdc8HigW5cnppFAWQ2Fh/93sFYkXpCRIxDqkGdxvJZY=; h=From:Subject:Date:Message-ID:To; b=d92g0iHj9UxWurAKi0V0Ln/FldU4ZaU0jm5Fx2/LEUpniFmdUCNqlRPevw8Lc2mw5PMToYtKd9ZZcOHuKzqZ0lV40wUU67H+648oMYKpYPth7y4QCkiYR411lxWz70Y9EEGSDFbuhSWha6vg6semOLmoNH+Ukbo0HXJL10QDX9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 88A73C4CEF7; Fri, 6 Mar 2026 15:31:59 +0000 (UTC) From: Clark Williams Subject: [ANNOUNCE] 6.6.129-rt70 Date: Fri, 06 Mar 2026 15:29:04 -0000 Message-ID: <177281094449.800593.4671659230362381120@demetrius> To: LKML ,linux-rt-users ,Steven Rostedt ,Thomas Gleixner ,Carsten Emde ,John Kacur ,Sebastian Andrzej Siewior ,Daniel Wagner ,Tom Zanussi ,Clark Williams ,Pavel Machek ,Joseph Salisbury ,Luis Claudio R. Goncalves ,Stable RT List Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Hello RT-list! I'm pleased to announce the 6.6.129-rt70 stable release. Note that there is a gap between the previous update (6.6.127-rt69) and this one (6.6.129-rt70), due to a hiccup in the 6.6.128 release, which was quickly fixed by Sasha.=20 You can get this release via the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git branch: v6.6-rt Head SHA1: 1dba773c07d4db10ab0cffb999d79d8292ae1f9b Or to build 6.6.129-rt70 directly, the following patches should be applied: https://www.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz https://www.kernel.org/pub/linux/kernel/v6.x/patch-6.6.129.xz https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/patch-6.6.129-rt7= 0.patch.xz Enjoy! Clark Changes from v6.6.127-rt69: --- Abdun Nihaal (2): media: i2c/tw9903: Fix potential memory leak in tw9903_probe() media: i2c/tw9906: Fix potential memory leak in tw9906_probe() Abhishek Bapat (1): quota: fix livelock between quotactl and freeze_super Aboorva Devarajan (1): cpuidle: Skip governor when only one idle state is available Adarsh Das (1): btrfs: replace BUG() with error handling in __btrfs_balance() Adrian Hunter (1): i3c: master: Update hot-join flag only on success Aleksandar Gerasimovski (1): phy: mvebu-cp110-utmi: fix dr_mode property read from dts Aleksei Oladko (2): selftests: forwarding: vxlan_bridge_1d: fix test failure with br_netf= ilter enabled selftests: forwarding: vxlan_bridge_1d_ipv6: fix test failure with br= _netfilter enabled Alex Deucher (1): drm/amdgpu: avoid a warning in timedout job handler Alex Elder (1): mfd: simple-mfd-i2c: Add SpacemiT P1 support Alex Hung (1): drm/amd/display: Remove conditional for shaper 3DLUT power-on Alex Williamson (1): PCI: Mark ASM1164 SATA controller to avoid bus reset Alexander Egorenkov (1): s390/kexec: Make KEXEC_SIG available when CONFIG_MODULES=3Dn Alexander Grest (1): iommu/arm-smmu-v3: Improve CMDQ lock fairness and efficiency Alexander Koskovich (1): power: reset: nvmem-reboot-mode: respect cell size for nvmem_cell_wri= te Alexander Lobakin (1): cache: add __cacheline_group_{begin, end}_aligned() (+ couple more) Alexander Stein (1): arm64: dts: tqma8mpql-mba8mpxl: Fix HDMI CEC pad control settings Alexandre Ferrieux (1): ASoC: codecs: aw88261: Fix erroneous bitmask logic in Awinic init Alexey Simakov (1): ACPICA: Fix NULL pointer dereference in acpi_ev_address_space_dispatc= h() Allison Henderson (1): net/rds: rds_sendmsg should not discard payload_len Alok Tiwari (1): mtd: rawnand: cadence: Fix return type of CDMA send-and-wait helper Alper Ak (3): tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure tpm: st33zp24: Fix missing cleanup on get_burstcount() error media: qcom: camss: vfe: Fix out-of-bounds access in vfe_isr_reg_upda= te() Anders Grahn (1): netfilter: nft_counter: fix reset of counters on 32bit archs Andrea Scian (1): mtd: rawnand: pl353: Fix software ECC support Andreas Gruenbacher (3): gfs2: Retries missing in gfs2_{rename,exchange} gfs2: Add metapath_dibh helper gfs2: fiemap page fault fix Andreas Larsson (1): sparc: Synchronize user stack on fork and clone Andrey Vatoropin (1): fbcon: check return value of con2fb_acquire_newinfo() Andr\ufffd\ufffd Draszik (1): regulator: core: move supply check earlier in set_machine_constraints= () Andy Shevchenko (1): platform/chrome: cros_typec_switch: Don't touch struct fwnode_handle:= :dev AngeloGioacchino Del Regno (1): dmaengine: mediatek: uart-apdma: Fix above 4G addressing TX/RX Ankit Soni (1): iommu/amd: move wait_on_sem() out of spinlock Anshumali Gaur (1): octeontx2-af: Fix PF driver crash with kexec kernel booting Anthony Iliopoulos (2): nfsd: never defer requests during idmap lookup nfsd: fix return error code for nfsd_map_name_to_[ug]id Anthony Pighin (Nokia) (1): rtc: interface: Alarm race handling should not discard preceding error Antonio Borneo (1): coresight: etm3x: Fix cpulocked warning on cpuhp Antoniu Miclaus (1): iio: gyro: itg3200: Fix unchecked return value in read_raw Ard Biesheuvel (1): x86/kexec: Copy ACPI root pointer address from config table Aristeu Rozanski (1): selftests/memfd: use IPC semaphore instead of SIGSTOP/SIGCONT Armin Wolf (1): ACPICA: Abort AML bytecode execution when executing AML_FATAL_OP Arnd Bergmann (4): scsi: ufs: host: mediatek: Require CONFIG_PM vmw_vsock: bypass false-positive Wnonnull warning with gcc-16 myri10ge: avoid uninitialized variable use scsi: buslogic: Reduce stack usage Artem Shimko (1): serial: 8250_dw: handle clock enable errors in runtime_resume Baochen Qiang (1): wifi: ath12k: fix preferred hardware mode calculation Baokun Li (1): ext4: move ext4_percpu_param_init() before ext4_mb_init() Barnab\ufffd\ufffds Cz\ufffd\ufffdm\ufffd\ufffdn (4): clk: qcom: gcc-msm8953: Remove ALWAYS_ON flag from cpp_gdsc clk: qcom: gcc-msm8917: Remove ALWAYS_ON flag from cpp_gdsc backlight: qcom-wled: Support ovp values for PMI8994 backlight: qcom-wled: Change PM8950 WLED configurations Bartosz Golaszewski (1): clocksource/drivers/timer-integrator-ap: Add missing Kconfig dependen= cy on OF Baruch Siach (1): Documentation: PCI: endpoint: Fix ntb/vntb copy & paste errors Ben Dooks (2): audit: move the compat_xxx_class[] extern declarations to audit_arch.h fs: add for 'init_fs' Benjamin Gaignard (4): media: verisilicon: AV1: Fix enable cdef computation media: verisilicon: AV1: Fix tx mode bit setting media: verisilicon: AV1: Set IDR flag for intra_only frame type media: verisilicon: AV1: Fix tile info buffer size Benjamin Marzinski (1): dm mpath: make pg_init_delay_msecs settable Benson Leung (1): usb: typec: ucsi: psy: Fix voltage and current max for non-Fixed PDOs Billy Tsai (2): i3c: Move device name assignment after i3c_bus_init gpio: aspeed-sgpio: Change the macro to support deferred probe Bitterblue Smith (1): wifi: rtw88: 8822b: Avoid WARNING in rtw8822b_config_trx_mode() Bjorn Helgaas (4): PCI: Move pci_read_bridge_windows() below individual window accessors PCI: Supply bridge device, not secondary bus, to read window details PCI: Log bridge windows conditionally PCI: Log bridge info when first enumerating bridge Bo Sun (1): octeontx2-af: CGX: fix bitmap leaks Boris Burkov (1): btrfs: fix block_group_tree dirty_list corruption Breno Leitao (1): arm64: Disable branch profiling for all arm64 code Brian Masney (2): openrisc: define arch-specific version of nop() clk: microchip: core: correct return value on *_get_parent() Brian Norris (1): PCI/PM: Avoid redundant delays on D3hot->D3cold Carl Lee (1): nfc: nxp-nci: remove interrupt trigger type Casey Connolly (2): arm64: dts: qcom: sdm845-oneplus: Don't mark ts supply boot-on arm64: dts: qcom: sdm845-oneplus: Mark l14a regulator as boot-on Ce Sun (1): drm/amdgpu: Adjust usleep_range in fence wait Chaitanya Mishra (1): staging: greybus: lights: avoid NULL deref Chen Jinghuang (1): sched/rt: Skip currently executing CPU in rto_next_cpu() Chen Ni (2): ASoC: sunxi: sun50i-dmic: Add missing check for devm_regmap_init_mmio ASoC: codecs: max98390: Check return value of devm_gpiod_get_optional= () in max98390_i2c_probe() Chen-Yu Tsai (2): ARM: dts: allwinner: sun5i-a13-utoo-p66: delete "power-gpios" property dmaengine: sun6i: Choose appropriate burst length under maxburst Chengchang Tang (2): RDMA/hns: Fix WQ_MEM_RECLAIM warning RDMA/hns: Notify ULP of remaining soft-WCs during reset Chenghai Huang (3): crypto: hisilicon/zip - adjust the way to obtain the req in the callb= ack function crypto: hisilicon/trng - modifying the order of header files crypto: hisilicon/qm - move the barrier before writing to the mailbox= register Chin-Ting Kuo (1): spi: spi-mem: Protect dirmap_create() with spi_mem_access_start/end Chin-Yen Lee (1): wifi: rtw89: wow: add reason codes for disassociation in WoWLAN mode Chris Brandt (2): clk: renesas: rzg2l: Fix intin variable size clk: renesas: rzg2l: Select correct div round macro Christian Loehle (1): cpuidle: menu: Cleanup after loadavg removal Christoph Hellwig (1): iomap: fix submission side handling of completion side errors Christophe Leroy (1): powerpc/uaccess: Move barrier_nospec() out of allow_read_{from/write}= _user() Chuck Lever (7): RDMA/core: Fix a couple of obvious typos in comments svcrdma: Remove queue-shortening warnings svcrdma: Clean up comment in svc_rdma_accept() svcrdma: Increase the per-transport rw_ctx count svcrdma: Reduce the number of rdma_rw contexts per-QP RDMA/core: add rdma_rw_max_sge() helper for SQ sizing SUNRPC: auth_gss: fix memory leaks in XDR decoding error paths Clark Williams (3): Merge tag 'v6.6.128' into v6.6-rt Merge tag 'v6.6.129' into v6.6-rt Linux 6.6.129-rt70 Cl\ufffd\ufffdment Le Goffic (1): dmaengine: stm32-mdma: initialize m2m_hw_period and ccr to fix warnin= gs Coco Li (2): cache: enforce cache groups netns-ipv4: reorganize netns_ipv4 fast path variables Colin Ian King (1): scsi: csiostor: Fix dereference of null pointer rn Colin Lord (1): tracing: Fix false sharing in hwlat get_sample() Cristian Ciocaltea (3): ASoC: nau8821: Consistently clear interrupts before unmasking ASoC: nau8821: Avoid unnecessary blocking in IRQ handler ASoC: nau8821: Fixup nau8821_enable_jack_detect() Cupertino Miranda (1): bpf: verifier improvement in 32bit shift sign extension pattern Damien Le Moal (1): ata: libata-scsi: refactor ata_scsi_translate() Dan Carpenter (3): EDAC/i5000: Fix snprintf() size calculation in calculate_dimm_size() EDAC/i5400: Fix snprintf() limit calculation in calculate_dimm_size() apparmor: use passed in gfp flags in aa_alloc_null() Daniel Gomez (1): dm: replace -EEXIST with -EBUSY Daniel Hodges (2): SUNRPC: fix gss_auth kref leak in gss_alloc_msg error path tipc: fix RCU dereference race in tipc_aead_users_dec() Daniel Machon (2): net: sparx5/lan969x: fix DWRR cost max to match hardware register wid= th net: sparx5/lan969x: fix PTP clock max_adj value Daniel Palmer (1): m68k: nommu: fix memmove() with differently aligned src and dest for = 68000 Darrick J. Wong (4): xfs: mark data structures corrupt on EIO and ENODATA xfs: delete attr leaf freemap entries when empty xfs: fix freemap adjustments when adding xattrs to leaf blocks xfs: fix remote xattr valuelblk check David Heidelberg (1): media: ccs: Accommodate C-PHY into the calculation David Phillips (1): HID: elecom: Add support for ELECOM HUGE Plus M-HT1MRBK David Plowman (3): media: i2c: ov5647: Correct pixel array offset media: i2c: ov5647: Correct minimum VBLANK value media: i2c: ov5647: Sensor should report RAW color space Deepak Kumar (1): spi: stm32: fix Overrun issue at < 8bpw Deepakkumar Karn (1): fs/buffer: add alert in try_to_free_buffers() for folios without buff= ers Deepanshu Kartikey (1): gfs2: Fix use-after-free in iomap inline data write path Denis Pauk (1): hwmon: (nct6775) Add ASUS Pro WS WRX90E-SAGE SE Detlev Casanova (1): ASoC: rockchip: i2s-tdm: Use param rate if not provided by set_sysclk Dian-Syuan Yang (1): wifi: rtw89: pci: restore LDO setting after device resume Diksha Kumari (1): staging: rtl8723bs: fix memory leak on failure path Dikshita Agarwal (1): media: venus: vdec: restrict EOS addr quirk to IRIS2 only Ding Hui (1): dm: remove fake timeout to avoid leak request Diogo Ivo (1): arm64: tegra: smaug: Add usb-role-switch support Dmitry Baryshkov (6): arm64: dts: qcom: sdm630: fix gpu_speed_bin size arm64: dts: qcom: sdm845-db845c: drop CS from SPIO0 arm64: dts: qcom: sdm845-db845c: specify power for WiFi CH1 drm/msm/dpu: fix CMD panels on DPU 1.x - 3.x drm/msm/a2xx: fix pixel shader start on A225 clk: qcom: gfx3d: add parent to parent request map Dmytro Maluka (1): iommu/vt-d: Flush cache for PASID table before using it Donet Tom (1): drm/amdkfd: Fix GART PTE for non-4K pagesize in svm_migrate_gart_map() Douglas Anderson (1): mfd: core: Add locking around 'mfd_of_node_list' Duoming Zhou (2): net: wan: farsync: Fix use-after-free bugs caused by unfinished taskl= ets atm: fore200e: fix use-after-free in tasklets during device removal Dzmitry Sankouski (1): mfd: simple-mfd-i2c: Add MAX77705 support Edward Adam Davis (1): fs/ntfs3: prevent infinite loops caused by the next valid being the s= ame Eric Biggers (1): dm-verity: correctly handle dm_bufio_client_create() failure Eric Dumazet (14): tcp: tcp_tx_timestamp() must look at the rtx queue inet: RAW sockets using IPPROTO_RAW MUST drop incoming ICMP ipv6: fix a race in ip6_sock_set_v6only() ping: annotate data-races in ping_lookup() macvlan: observe an RCU grace period in macvlan_common_newlink() erro= r path icmp: move icmp_global.credit and icmp_global.stamp to per netns stor= age icmp: icmp_msgs_per_sec and icmp_msgs_burst sysctls become per netns icmp: prevent possible overflow in icmp_global_allow() tcp: defer regular ACK while processing socket backlog inet: move icmp_global_{credit,stamp} to a separate cache line ipv6: annotate data-races in ip6_multipath_hash_{policy,fields}() ipv6: exthdrs: annotate data-race over multiple sysctl gro: change the BUG_ON() in gro_pull_from_frag0() ipv4: igmp: annotate data-races around idev->mr_maxdelay Eric Joyner (1): ionic: Rate limit unknown xcvr type messages Ethan Nelson-Moore (3): net: usb: sr9700: remove code to drive nonexistent multicast filter net: ethernet: marvell: skge: remove incorrect conflicting PCI ID net: intel: fix PCI device ID conflict between i40e and ipw2200 Ethan Tidmore (2): x86/hyperv: Fix error pointer dereference staging: rtl8723bs: fix null dereference in find_network Etienne AUJAMES (1): IB/cache: update gid cache on client reregister event Felix Gu (4): fbdev: of_display_timing: Fix device node reference leak in of_get_di= splay_timings() fbdev: au1200fb: Fix a memory leak in au1200fb_drv_probe() pinctrl: equilibrium: Fix device node reference leak in pinbank_init() spi: wpcm-fiu: Fix potential NULL pointer dereference in wpcm_fiu_pro= be() Fernando Fernandez Mancera (3): netfilter: nf_conncount: make nf_conncount_gc_list() to disable BH netfilter: nf_conncount: increase the connection clean up limit to 64 netfilter: nf_conncount: fix tracking of connections from localhost Filipe Manana (2): btrfs: qgroup: return correct error when deleting qgroup relation item btrfs: fix invalid leaf access in btrfs_quota_enable() if ref key not= found Florian Westphal (5): netfilter: nf_tables: reset table validation state on abort netfilter: nft_compat: add more restrictions on netlink attributes netfilter: nft_set_hash: fix get operation on big endian netfilter: nf_conntrack_h323: don't pass uninitialised l3num value netfilter: xt_tcpmss: check remaining length before reading optlen Francesco Lavra (1): spi: tools: Add include folder to .gitignore Frank Li (1): i3c: master: svc: Initialize 'dev' to NULL in svc_i3c_master_ibi_isr() Frederic Weisbecker (2): rcu: s/boost_kthread_mutex/kthread_mutex rcu/exp: Move expedited kthread worker creation functions above rcutr= ee_prepare_cpu() Fredrik Markstrom (1): i3c: dw: Initialize spinlock to avoid upsetting lockdep Geert Uytterhoeven (1): clk: Move clk_{save,restore}_context() to COMMON_CLK section Geetha sowjanya (1): octeontx2-af: Workaround SQM/PSE stalls by disabling sticky George Moussalem (1): clk: qcom: gcc-ipq5018: flag sleep clock as critical Georgia Garcia (1): apparmor: fix invalid deref of rawdata when export_binary is unset Gerd Rausch (1): net/rds: No shortcut out of RDS_CONN_ERROR Giovanni Cabiddu (1): crypto: qat - fix warning on adf_pfvf_pf_proto.c Govindarajulu Varadarajan (1): ublk: Validate SQE128 flag before accessing the cmd Greg Kroah-Hartman (1): Revert "mmc: rtsx_pci_sdmmc: increase power-on settling delay to 5ms" Greg Thelen (1): selftests/memfd: delete unused declarations Guangshuo Li (1): powerpc/smp: Add check for kcalloc() failure in parse_thread_groups() Guenter Roeck (1): Revert "hwmon: (ibmpex) fix use-after-free in high/low store" Gui-Dong Han (2): PM: sleep: wakeirq: harden dev_pm_clear_wake_irq() against races rpmsg: core: fix race in driver_override_show() and use core helper Gustavo Salvini (1): ASoC: amd: yc: Add DMI quirk for ASUS Vivobook Pro 15X M6501RR G\ufffd\ufffdnther Noack (3): HID: magicmouse: Do not crash on missing msc->input HID: prodikeys: Check presence of pm->input_ep82 HID: logitech-hidpp: Check maxfield in hidpp_get_report_length() Haiyang Zhang (1): tcp: Set pingpong threshold via sysctl Hangbin Liu (1): bonding: alb: fix UAF in rlb_arp_recv during bond up/down Hans Verkuil (4): media: dvb-core: dmxdevfilter must always flush bufs media: omap3isp: isp_video_mbus_to_pix/pix_to_mbus fixes media: omap3isp: isppreview: always clamp in preview_try_format() media: omap3isp: set initial format Hans de Goede (5): media: i2c: ov01a10: Fix the horizontal flip control media: i2c: ov01a10: Fix reported pixel-rate value media: i2c: ov01a10: Fix analogue gain range media: i2c: ov01a10: Add missing v4l2_subdev_cleanup() calls media: i2c: ov01a10: Fix test-pattern disabling Haotian Zhang (9): clk: qcom: Return correct error code in qcom_cc_probe_by_index() soc: qcom: cmd-db: Use devm_memremap() to fix memory leak in cmd_db_d= ev_probe HID: playstation: Add missing check for input_ff_create_memless PCI: mediatek: Fix IRQ domain leak when MSI allocation fails power: supply: bq27xxx: fix wrong errno when bus ops are unsupported clk: mediatek: Fix error handling in runtime PM setup mfd: arizona: Fix regulator resource leak on wm5102_clear_write_seque= ncer() failure leds: qcom-lpg: Check the return value of regmap_bulk_write() jfs: Add missing set_freezable() for freezable kthread Haotien Hsu (1): usb: gadget: tegra-xudc: Add handling for BLCG_COREPLL_PWRDN Haoxiang Li (11): PCI/MSI: Unmap MSI-X region on error media: cx25821: Fix a resource leak in cx25821_dev_setup() media: mtk-mdp: Fix error handling in probe function media: mtk-mdp: Fix a reference leak bug in mtk_mdp_remove() media: cx88: Add missing unmap in snd_cx88_hw_params() media: cx23885: Add missing unmap in snd_cx23885_hw_params() media: cx25821: Add missing unmap in snd_cx25821_hw_params() clk: tegra: tegra124-emc: Fix potential memory leak in tegra124_clk_r= egister_emc() bus: fsl-mc: fix an error handling in fsl_mc_device_add() rapidio: replace rio_free_net() with kfree() in rio_scan_alloc_net() parisc: kernel: replace kfree() with put_device() in create_tree_node= () Hariprasad Kelam (2): octeontx2-pf: Unregister devlink on probe failure octeontx2-af: Fix default entries mcam entry action Harshit Mogalapalli (2): iio: sca3000: Fix a resource leak in sca3000_probe() x86/kexec: add a sanity check on previous kernel's ima kexec buffer Heiko Carstens (1): s390/purgatory: Add -Wno-default-const-init-unsafe to KBUILD_CFLAGS Helge Deller (1): parisc: Prevent interrupts during reboot Heming Zhao (1): ocfs2: fix reflink preserve cleanup issue Henrique Carvalho (2): smb: client: add proper locking around ses->iface_last_update smb: client: prevent races in ->query_interfaces() Henry Tseng (1): ata: libata: avoid long timeouts on hot-unplugged SATA DAS Honggang LI (1): RDMA/rtrs: server: remove dead code Hou Tao (1): PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails Hou Wenlong (1): x86/xen/pvh: Enable PAE mode for 32-bit guest only when CONFIG_X86_PA= E is set Hsieh Hung-En (1): ASoC: es8328: Add error unwind in resume Hsiu-Ming Chang (1): wifi: rtw88: rtw8821cu: Add ID for Mercusys MU6H Huacai Chen (1): LoongArch: Prefer top-down allocation after arch_mem_init() H\ufffd\ufffdkon Bugge (4): PCI: Do not attempt to set ExtTag for VFs PCI: Initialize RCB from pci_configure_device() PCI/ACPI: Restrict program_hpx_type2() to AER bits net/rds: Clear reconnect pending bit Ian Rogers (4): perf test stat: Update test expectations and events perf unwind-libdw: Fix invalid reference counts perf callchain: Fix srcline printing with inlines libperf build: Always place libperf includes first Ido Schimmel (1): selftests: mlxsw: tc_restrictions: Fix test failure with new iproute2 Ilpo J\ufffd\ufffdrvinen (1): PCI: Add defines for bridge window indexing Ilya Dryomov (1): libceph: define and enforce CEPH_MAX_KEY_LEN Inseo An (1): netfilter: nf_tables: fix use-after-free in nf_tables_addchain() Ioana Ciornei (2): mfd: simple-mfd-i2c: Add compatible strings for Layerscape QIXIS FPGA mfd: simple-mfd-i2c: Keep compatible strings in alphabetical order Irui Wang (1): media: mediatek: encoder: Fix uninitialized scalar variable issue Iuliana Prodan (1): remoteproc: imx_dsp_rproc: Skip RP_MBOX_SUSPEND_SYSTEM when mailbox T= X channel is uninitialized Jack Wang (1): md/bitmap: fix GPF in write_page caused by resize race Jacky Bai (1): mailbox: imx: Skip the suspend flag for i.MX7ULP Jacob Moroni (1): RDMA/umem: Fix double dma_buf_unpin in failure path Jacopo Scannella (1): Bluetooth: btusb: Add device ID for Realtek RTL8761BU Jaehun Gou (3): fs: ntfs3: check return value of indx_find to avoid infinite loop fs: ntfs3: fix infinite loop in attr_load_runs_range on inconsistent = metadata fs: ntfs3: fix infinite loop triggered by zero-sized ATTR_LIST Jagadeesh Kona (3): clk: qcom: gcc-sm8450: Update the SDCC RCGs to use shared_floor_ops clk: qcom: gcc-sdx75: Update the SDCC RCGs to use shared_floor_ops clk: qcom: gcc-qdu1000: Update the SDCC RCGs to use shared_floor_ops Jai Luthra (2): media: i2c: ov5647: Initialize subdev before controls media: i2c: ov5647: Fix PIXEL_RATE value for VGA mode Jakub Kicinski (2): bpftool: Fix truncated netlink dumps net: consume xmit errors of GSO frames James Clark (1): libperf: Don't remove -g when EXTRA_CFLAGS are used Jan Kara (1): ext4: use optimized mballoc scanning regardless of inode format Jani Nikula (1): drm/i915/wakeref: clean up INTEL_WAKEREF_PUT_* flag macros Janne Grunau (2): arm64: dts: apple: t8112-j473: Keep the HDMI port powered on clk: clk-apple-nco: Add "apple,t8103-nco" compatible Jared Kangas (1): dmaengine: fsl-edma: don't explicitly disable clocks in .remove() Jason Andryuk (1): xenbus: Use .freeze/.thaw to handle xenbus devices Jason Gunthorpe (1): RDMA/efa: Fix typo in efa_alloc_mr() Jeffrey Bencteux (2): audit: add fchmodat2() to change attributes class audit: add missing syscalls to read class Jens Axboe (3): io_uring/sync: validate passed in offset io_uring/cancel: de-unionize file and user_data in struct io_cancel_d= ata io_uring/filetable: clamp alloc_hint to the configured alloc range Jerome Brunet (4): arm64: dts: amlogic: axg: assign the MMC signal clocks arm64: dts: amlogic: gx: assign the MMC signal clocks arm64: dts: amlogic: g12: assign the MMC B and C signal clocks arm64: dts: amlogic: g12: assign the MMC A signal clock Ji-Ze Hong (Peter Hong) (1): hwmon: (f71882fg) Add F81968 support Jian Shen (1): net: hns3: fix double free issue for tx spare buffer Jian Zhang (1): net: mctp-i2c: fix duplicate reception of old data Jiasheng Jiang (3): RDMA/rxe: Fix double free in rxe_srq_from_init fs/ntfs3: Fix slab-out-of-bounds read in DeleteIndexEntryRoot md-cluster: fix NULL pointer dereference in process_metadata_update Jiaxun Yang (1): MIPS: rb532: Fix MMIO UART resource registration Jiayuan Chen (6): bpf, sockmap: Fix incorrect copied_seq calculation bpf, sockmap: Fix FIONREAD for sockmap net: atm: fix crash due to unvalidated vcc pointer in sigd_send() xfrm: fix ip_rt_bug race in icmp_route_lookup reverse path serial: caif: fix use-after-free in caif_serial ldisc_close() xfrm6: fix uninitialized saddr in xfrm6_get_saddr() Jijie Shao (1): net: hns3: extend HCLGE_FD_AD_QID to 11 bits Jinhui Guo (2): iommu/vt-d: Flush dev-IOTLB only when PCIe device is accessible in sc= alable mode PCI: Fix pci_slot_trylock() error handling Jinjie Ruan (3): spi: wpcm-fiu: Use devm_platform_ioremap_resource_byname() spi: wpcm-fiu: Fix uninitialized res spi: wpcm-fiu: Simplify with dev_err_probe() Jinliang Zheng (1): procfs: fix missing RCU protection when reading real_parent in do_tas= k_stat() Jinqian Yang (1): arm64: Add support for TSV110 Spectre-BHB mitigation Jinwang Li (1): Bluetooth: hci_qca: Cleanup on all setup failures Jiri Pirko (1): RDMA/core: Fix stale RoCE GIDs during netdev events at registration Jisheng Zhang (1): usb: dwc2: fix resume failure if dr_mode is host Joel Fernandes (1): rcu: Refactor expedited handling check in rcu_read_unlock_special() Joey Bednar (1): HID: apple: Add "SONiX KN85 Keyboard" to the list of non-apple keyboa= rds Johan Hovold (1): soc: ti: k3-socinfo: Fix regmap leak on probe failure Johannes Berg (1): wifi: cfg80211: wext: fix IGTK key ID off-by-one John Garry (2): MIPS: Loongson: Make cpumask_of_node() robust against NUMA_NO_NODE LoongArch: Make cpumask_of_node() robust against NUMA_NO_NODE John Johansen (7): apparmor: fix NULL sock in aa_sock_file_perm apparmor: fix rlimit for posix cpu timers apparmor: provide separate audit messages for file and policy checks apparmor: refcount the pdb apparmor: remove apply_modes_to_perms from label_match apparmor: make label_match return a consistent value apparmor: fix aa_label to return state from compount and component ma= tch Johnny-CC Chang (1): PCI: Mark Nvidia GB10 to avoid bus reset Jonathan Kim (1): drm/amdkfd: fix debug watchpoints for logical devices Jonathan Marek (2): spi-geni-qcom: initialize mode related registers to 0 spi-geni-qcom: use xfer->bits_per_word for can_dma() Jorge Ramirez-Ortiz (1): soc: qcom: smem: handle ENOMEM error during probe Jori Koolstra (2): minix: Add required sanity checking to minix_check_superblock() jfs: nlink overflow in jfs_rename Josh Poimboeuf (1): kbuild: Add objtool to top-level clean target Juergen Gross (1): x86/xen: make some functions static Jun Yan (1): arm64: dts: rockchip: Do not enable hdmi_sound node on Pinebook Pro Junrui Luo (1): dpaa2-switch: validate num_ifs to prevent out-of-bounds write Justin Chen (1): usb: bdc: fix sleep during atomic J\ufffd\ufffdrg Wedekind (1): PCI: Mark 3ware-9650SA Root Port Extended Tags as broken Kaushlendra Kumar (3): drm/i915/acpi: free _DSM package when no connectors tools/power cpupower: Reset errno before strtoull() thermal: int340x: Fix sysfs group leak on DLVR registration failure Kees Cook (1): media: solo6x10: Check for out of bounds chip_id Keith Busch (1): PCI: Fix pci_slot_lock () device locking Kery Qi (1): watchdog: starfive-wdt: Fix PM reference leak in probe error path Kevin Hao (2): net: cpsw_new: Fix unnecessary netdev unregistration in cpsw_probe() = error path net: macb: Fix tx/rx malfunction after phy link down and up Kiryl Shutsemau (Meta) (1): efi: Fix reservation of unaccepted memory table Koichiro Den (1): NTB: ntb_transport: Fix too small buffer for debugfs_name Kommula Shiva Shankar (1): vhost: fix caching attributes of MMIO regions by setting them explici= tly Konrad Dybcio (2): arm64: dts: qcom: sm6115: Add CX_MEM/DBGC GPU regions cpufreq: dt-platdev: Block the driver from probing on more QC platfor= ms Konstantin Andreev (2): smack: /smack/doi must be > 0 smack: /smack/doi: accept previously used values Konstantin Komarov (2): fs/ntfs3: drop preallocated clusters for sparse and compressed files fs/ntfs3: avoid calling run_get_entry() when run =3D=3D NULL in ntfs_= read_run_nb_ra() Krishna Chaitanya Chundru (1): PCI: Add ACS quirk for Qualcomm Hamoa & Glymur Krzysztof Kozlowski (1): nvmem: Drop OF node reference on nvmem_add_one_cell() failure Kuniyuki Iwashima (2): ipv6: Fix out-of-bound access in fib6_add_rt2node(). ipv4: fib: Annotate access to struct fib_alias.fa_state. Kuppuswamy Sathyanarayanan (1): powercap: intel_rapl_tpmi: Remove FW_BUG from invalid version check Lai Jiangshan (3): workqueue: Factor out assign_rescuer_work() workqueue: Only assign rescuer work when really needed workqueue: Process rescuer work items one-by-one using a cursor Leo Yan (2): perf: arm_spe: Properly set hw.state on failures tools: Fix bitfield dependency failure Leon Romanovsky (1): xfrm: skip templates check for packet offload tunnel mode Li Chen (4): nvdimm: virtio_pmem: serialize flush requests ext4: mark group add fast-commit ineligible ext4: mark group extend fast-commit ineligible kexec: derive purgatory entry from symbol Li Nan (1): md/raid10: fix any_working flag handling in raid10_sync_request Li Wang (1): selftests/mm/charge_reserved_hugetlb: drop mount size for hugetlbfs Li Zhijian (1): RDMA/rxe: Fix race condition in QP timer handlers Liang Jie (1): staging: rtl8723bs: fix missing status update on sdio_alloc_irq() fai= lure Lianqin Hu (1): ALSA: usb-audio: Add iface reset and delay quirk for AB13X USB Audio Linus Torvalds (1): Remove WARN_ALL_UNSEEDED_RANDOM kernel config option Linus Walleij (2): ata: pata_ftide010: Fix some DMA timings net: ethernet: xscale: Check for PTP support properly Longfang Liu (1): hisi_acc_vfio_pci: update status after RAS error Luca Ceresoli (1): drm: of: drm_of_panel_bridge_remove(): fix device_node leak Luca Weiss (1): pinctrl: qcom: sm8250-lpass-lpi: Fix i2s2_data_groups definition Ludovic Desroches (3): drm/atmel-hlcdc: fix memory leak from the atomic_destroy_state callba= ck drm/atmel-hlcdc: don't reject the commit if the src rect has fraction= al parts drm/atmel-hlcdc: fix use-after-free of drm_crtc_commit after release Luiz Augusto von Dentz (4): Bluetooth: L2CAP: Fix invalid response to L2CAP_ECRED_RECONF_REQ Bluetooth: L2CAP: Fix response to L2CAP_ECRED_CONN_REQ Bluetooth: L2CAP: Fix not checking output MTU is acceptable on L2CAP_= ECRED_CONN_REQ Bluetooth: L2CAP: Fix missing key size check for L2CAP_LE_CONN_REQ Maciej Grochowski (2): ntb: ntb_hw_switchtec: Fix array-index-out-of-bounds access ntb: ntb_hw_switchtec: Fix shift-out-of-bounds for 0 mw lut Mahadevan P (1): drm/msm/disp/dpu: add merge3d support for sc7280 Malaya Kumar Rout (1): tools/power/x86/intel-speed-select: Fix file descriptor leak in isola= te_cpus() Manikanta Maddireddy (1): PCI: endpoint: Fix swapped parameters in pci_{primary/secondary}_epc_= epf_unlink() functions Manivannan Sadhasivam (1): PCI: Enable ACS after configuring IOMMU for OF platforms Marc Zyngier (2): arm64: Force the use of CNTVCT_EL0 in __delay() arm64: Fix sampling the "stable" virtual counter in preemptible secti= on Marco Elver (1): arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=3Dy Marcus Folkesson (1): Revert "mfd: da9052-spi: Change read-mask to write-mask" Mario Kleiner (1): drm/amd/display: Use same max plane scaling limits for all 64 bpp for= mats Mario Limonciello (AMD) (3): crypto: ccp - Add an S4 restore flow crypto: ccp - Factor out ring destroy handling to a helper crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INI= T fails Mark Brown (1): mailbox: pcc: Remove spurious IRQF_ONESHOT usage Markus Perkins (1): misc: eeprom: Fix EWEN/EWDS/ERAL commands for 93xx56 and 93xx66 Martin Blumenstingl (1): clk: meson: gxbb: Limit the HDMI PLL OD to /4 on GXL/GXM SoCs Martin P\ufffd\ufffdlsson (1): net: usb: lan78xx: scan all MDIO addresses on LAN7801 Masami Hiramatsu (Google) (1): tracing: Fix to set write permission to per-cpu buffer_size_kb Matt Johnston (2): mctp i2c: initialise event handler read bytes ipmi: ipmb: initialise event handler read bytes Matt Whitlock (1): dm-unstripe: fix mapping bug when there are multiple targets in a tab= le Matthew Schwartz (1): mmc: rtsx_pci_sdmmc: increase power-on settling delay to 5ms Mauro Carvalho Chehab (3): EFI/CPER: don't dump the entire memory region APEI/GHES: ensure that won't go past CPER allocated record EFI/CPER: don't go past the ARM processor CPER record buffer Md Haris Iqbal (2): rnbd-srv: Zero the rsp buffer before using it RDMA/rtrs-clt: For conn rejection use actual err number Mehdi Djait (1): media: i2c: ov01a10: Fix digital gain range Miaoqian Lin (1): tracing: Properly process error handling in event_hist_trigger_parse() Michael Liang (1): dm: clear cloned request bio pointer when last clone bio completes Michael Thalmeier (1): net: nfc: nci: Fix parameter validation for packet data Mikulas Patocka (3): dm: use bio_clone_blkg_association dm-integrity: fix a typo in the code for write/discard race dm-integrity: fix recalculation in bitmap mode Ming Qian (1): media: amphion: Clear last_buffer_dequeued flag for DEC_CMD_START Mingj Ye (1): net: usb: r8152: fix transmit queue timeout Miquel Raynal (2): mtd: spinand: Fix kernel doc spi: spi-mem: Limit octal DTR constraints to octal DTR situations Miri Korenblit (2): wifi: cfg80211: stop NAN and P2P in cfg80211_leave wifi: iwlwifi: mvm: check the validity of noa_len Moteen Shah (1): serial: 8250: 8250_omap.c: Clear DMA RX running status only after DMA= termination is done Narayana Murty N (1): powerpc/eeh: fix recursive pci_lock_rescan_remove locking in EEH even= t handling Nicolas Cavallari (1): PCI: Add ACS quirk for Pericom PI7C9X2G404 switches [12d8:b404] Nicolas Dufresne (1): media: mediatek: vcodec: Don't try to decode 422/444 VP9 Niklas Schnelle (3): s390/pci: Handle futile config accesses of disabled devices directly Revert "PCI/IOV: Add PCI rescan-remove locking when enabling/disablin= g SR-IOV" PCI/IOV: Fix race between SR-IOV enable/disable and hotplug Niklas S\ufffd\ufffdderlund (1): clocksource/drivers/sh_tmu: Always leave device running after probe Nikolay Aleksandrov (1): net: bridge: mcast: always update mdb_n_entries for vlan contexts Nuno S\ufffd\ufffd (1): dma: dma-axi-dmac: fix SW cyclic transfers Oleksandr Suvorov (1): watchdog: imx7ulp_wdt: handle the nowayout option Olga Kornievskaia (1): pNFS: fix a missing wake up while waiting on NFS_LAYOUT_DRAIN Oliver Neukum (1): HID: hid-pl: handle probe errors Ondrej Mosnacek (2): ipc: don't audit capability check in ipc_permissions() ucount: check for CAP_SYS_RESOURCE using ns_capable_noaudit() Otto Pfl\ufffd\ufffdger (2): mailbox: sprd: mask interrupts that are not handled mailbox: sprd: clear delivery flag before handling TX done Pablo Neira Ayuso (2): netfilter: nft_set_rbtree: check for partial overlaps in anonymous se= ts net: remove WARN_ON_ONCE when accessing forward path array Paolo Abeni (1): mptcp: fix receive space timestamp initialization Paul Chaignon (1): bpf: Fix bpf_xdp_store_bytes proto for read-only arg Paulo Alcantara (1): smb: client: fix potential UAF and double free in smb2_open_file() Peng Fan (1): remoteproc: imx_rproc: Fix invalid loaded resource table detection Peter Ujfalusi (5): soundwire: dmi-quirks: add mapping for Avell B.ON (OEM rebranded of N= UC15) ASoC: SOF: ipc4-control: If there is no data do not send bytes update ASoC: SOF: ipc4-topology: Correct the allocation size for bytes contr= ols ASoC: SOF: ipc4-control: Use the correct size for scontrol->ipc_contr= ol_data ASoC: SOF: ipc4-control: Keep the payload size up to date Petr Hodina (1): clk: qcom: dispcc-sdm845: Enable parents for pixel clocks Petr Mladek (2): module: add helper function for reading module_buildid() kallsyms/ftrace: set module buildid in ftrace_mod_address_lookup() Petr Pavlu (2): tracing: Fix checking of freed trace_event_file for hist files tracing: Wake up poll waiters for hist files when removing an event Petre Rodan (1): iio: pressure: mprls0025pa: fix scan_type struct Phil Sutter (1): include: uapi: netfilter_bridge.h: Cover for musl libc Prashanth K (1): usb: dwc3: gadget: Move vbus draw to workqueue context Puranjay Mohan (1): selftests/bpf: veristat: fix printing order in output_stats() Purva Yeshi (1): Documentation: trace: Refactor toctree Qanux (1): ipv6: ioam: fix heap buffer overflow in __ioam6_fill_trace_data() Qi Tao (1): crypto: hisilicon/sec2 - support skcipher/aead fallback for hardware = queue unavailable Qing Wang (1): ovl: Fix uninit-value in ovl_fill_real Rafael J. Wysocki (1): cpuidle: governors: menu: Always check timers with tick stopped Randy Dunlap (2): serial: imx: change SERIAL_IMX_CONSOLE to bool serial: SH_SCI: improve "DMA support" prompt Renjiang Han (1): media: venus: vdec: fix error state assignment for zero bytesused Ren\ufffd\ufffd Rebe (4): net: sunhme: Fix sbus regression modpost: Amend ppc64 save/restfpr symnames for -Os build fix it87_wdt early reboot by reporting running timer fbdev: ffb: fix corrupted video output on Sun FFB1 Ricardo Ribalda (1): media: uvcvideo: Fix allocation for small frame sizes Robert Marko (1): mfd: simple-mfd-i2c: Add Delta TN48M CPLD support Robin Murphy (2): perf/arm-cmn: Support CMN-600AE perf/arm-cmn: Reject unsupported hardware configurations Roger Pau Monne (1): Partial revert "x86/xen: fix balloon target initialization for PVH do= m0" Romain Gantois (1): fpga: of-fpga-region: Fail if any bridge is missing Roman Penyaev (1): RDMA/rtrs-srv: fix SG mapping Roman Peshkichev (1): wifi: rtw88: fix DTIM period handling when conf->dtim_period is zero Ross Vandegrift (1): wifi: ath11k: add pm quirk for Thinkpad Z13/Z16 Gen1 Rui Wang (1): media: rkisp1: Fix filter mode register configuration Ruipeng Qi (1): pstore: ram_core: fix incorrect success return when vmap() fails Ruitong Liu (1): net/sched: act_skbedit: fix divide-by-zero in tcf_skbedit_hash() Ryan Lee (1): apparmor: return -ENOMEM in unpack_perms_table upon alloc failure Sagi Grimberg (1): fs/nfs: Fix readdir slow-start regression Sai Ritvik Tanksalkar (1): pstore/ram: fix buffer overflow in persistent_ram_save_old() Sakari Ailus (2): media: v4l2-async: Fix error handling on steps after finding a match media: ccs: Avoid possible division by zero Salah Triki (1): s390/cio: Fix device lifecycle handling in css_alloc_subchannel() Sam James (1): sparc: don't reference obsolete termio struct for TC* constants Samuel Wu (1): PM: wakeup: Handle empty list in wakeup_sources_walk_start() Sasha Levin (3): Linux 6.6.128 Revert "x86/kexec: add a sanity check on previous kernel's ima kexec = buffer" Linux 6.6.129 Sean Christopherson (1): KVM: nSVM: Remove a user-triggerable WARN on nested_svm_load_cr3() su= cceeding Sean V Kelley (1): ACPI: CPPC: Fix remaining for_each_possible_cpu() to use online CPUs Sebastian Andrzej Siewior (8): scsi: efct: Use IRQF_ONESHOT and default primary handler EDAC/altera: Remove IRQF_ONESHOT mfd: wm8350-core: Use IRQF_ONESHOT perf/cxlpmu: Replace IRQF_ONESHOT with IRQF_NO_THREAD mailbox: bcm-ferxrm-mailbox: Use default primary handler char: tpm: cr50: Remove IRQF_ONESHOT iio: Use IRQF_NO_THREAD iio: magnetometer: Remove IRQF_ONESHOT Sebastian Krzyszkowiak (2): ASoC: wm8962: Add WM8962_ADC_MONOMIX to "3D Coefficients" mask ASoC: wm8962: Don't report a microphone if it's shorted to ground on = plug Shardul Bankar (1): hfsplus: return error when node already exists in hfs_bnode_create Shaurya Rane (1): media: radio-keene: fix memory leak in error path Shawn Lin (1): PCI: dw-rockchip: Disable BAR 0 and BAR 1 for Root Port Shay Drory (3): net/mlx5: Fix multiport device check over light SFs net/mlx5: DR, Fix circular locking dependency in dump net/mlx5: Fix missing devlink lock in SRIOV enable error path Shell Chen (1): Bluetooth: btusb: Add new VID/PID for RTL8852CE Shengjiu Wang (3): ASoC: dt-bindings: asahi-kasei,ak4458: set unevaluatedProperties:false ASoC: dt-bindings: asahi-kasei,ak4458: Fix the supply names ASoC: dt-bindings: asahi-kasei,ak5558: Fix the supply names Shinas Rasheed (4): octeon_ep: support to fetch firmware info octeon_ep: restructured interrupt handlers octeon_ep: support Octeon CN10K devices octeon_ep: set backpressure watermark for RX queues Shuai Xue (1): Documentation: tracing: Add PCI tracepoint documentation Shyam Prasad N (2): cifs: Fix locking usage for tcon fields cifs: some missing initializations on replay Sri Jayaramappa (1): libsubcmd: Fix null intersection case in exclude_cmds() Srinivasan Shanmugam (2): drm/amdgpu: Use explicit VCN instance 0 in SR-IOV init drm/amdkfd: Fix watch_id bounds checking in debug address watch v2 Stanislav Fomichev (2): net: Add skb_dstref_steal and skb_dstref_restore net: Switch to skb_dstref_steal/skb_dstref_restore for ip_route_input= callers Stefan Metzmacher (1): smb: client: correct value for smbd_max_fragmented_recv_size Stefan S\ufffd\ufffdrensen (2): Bluetooth: hci_conn: Set link_policy on incoming ACL connections Bluetooth: hci_conn: use mod_delayed_work for active mode timeout Steven Rostedt (1): tracing: Remove duplicate ENABLE_EVENT_STR and DISABLE_EVENT_STR macr= os Sunday Clement (1): drm/amdkfd: Fix out-of-bounds write in kfd_event_page_set() Suraj Kandpal (1): drm/display/dp_mst: Add protection against 0 vcpi SurajSonawane2415 (1): docs: fix WARNING document not included in any toctree Svyatoslav Ryhel (1): drivers: iio: mpu3050: use dev_err_probe for regulator request Szymon Wilczek (2): media: pvrusb2: fix URB leak in pvr2_send_request_ex wifi: libertas: fix WARNING in usb_tx_block Takashi Iwai (2): ALSA: usb-audio: Update the number of packets properly at receiving ALSA: usb-audio: Add sanity check for OOB writes at silencing Taniya Das (1): clk: qcom: rcg2: compute 2d using duty fraction directly Teddy Astie (1): xen/virtio: Don't use grant-dma-ops when running as Dom0 Tetsuo Handa (2): hfsplus: pretend special inodes as regular files xfrm: always flush state and policy upon NETDEV_UNREGISTER event Thadeu Lima de Souza Cascardo (1): fpga: dfl: use subsys_initcall to allow built-in drivers to be added Thomas Bogendoerfer (1): bonding: only set speed/duplex to unknown, if getting speed failed Thomas Fourier (6): auxdisplay: arm-charlcd: fix release_mem_region() size crypto: cavium - fix dma_free_coherent() size crypto: octeontx - fix dma_free_coherent() size net: wan/fsl_ucc_hdlc: Fix dma_free_coherent() in uhdlc_memclean() fbdev: vt8500lcdfb: fix missing dma_free_coherent() net: ethernet: ec_bhf: Fix dma_free_coherent() dma handle Thomas Gleixner (1): hrtimer: Fix trace oddity Thomas Richter (2): perf test stat tests: Fix for virtualized machines s390/perf: Disable register readout on sampling events Thomas Weissschuh (1): ARM: 9467/1: mm: Don't use %pK through printk Thomas Wei\ufffd\ufffdschuh (4): ARM: VDSO: Patch out __vdso_clock_getres() if unavailable hyper-v: Mark inner union in hv_kvp_exchg_msg_value as packed virt: vbox: uapi: Mark inner unions in packed structs as packed binder: don't use %pK through printk Thomas Yen (1): scsi: ufs: core: Flush exception handling work when RPM level is zero Thomas Zimmermann (1): fbcon: Remove struct fbcon_display.inverse Thorsten Schmelzer (2): media: adv7180: fix frame interval in progressive mode HID: multitouch: add eGalaxTouch EXC3188 support Tiezhu Yang (2): LoongArch: Guard percpu handler under !CONFIG_PREEMPT_RT LoongArch: Disable instrumentation for setup_ptwalker() Tim Huang (1): drm/amdgpu: add support for HDP IP version 6.1.1 Tom Lendacky (1): crypto: ccp - Move direct access to some PSP registers out of TEE Tomas Melin (1): rtc: zynqmp: correct frequency value Tung Nguyen (1): tipc: fix duplicate publication key in tipc_service_insert_publ() Tuo Li (3): of: unittest: fix possible null-pointer dereferences in of_unittest_p= roperty_copy() ACPI: processor: Fix NULL-pointer dereference in acpi_processor_errat= a_piix4() misc: bcm_vk: Fix possible null-pointer dereferences in bcm_vk_read() Tzung-Bi Shih (2): platform/chrome: cros_ec_lightbar: Fix response size initialization remoteproc: mediatek: Break lock dependency to `prepare_lock` Uwe Kleine-K\ufffd\ufffdnig (2): PCI/portdrv: Fix potential resource leak dmaengine: fsl-edma-main: Convert to platform remove callback returni= ng void Vahagn Vardanian (1): netfilter: nf_conntrack_h323: fix OOB read in decode_choice() Val Packett (1): power: supply: qcom_battmgr: Recognize "LiP" as lithium-polymer Varun R Mallya (1): libbpf: Fix OOB read in btf_dump_get_bitfield_value Vasiliy Kovalev (1): KVM: x86: Add SRCU protection for reading PDPTRs in __get_sregs2() Viacheslav Dubeyko (1): hfsplus: fix volume corruption issue for generic/498 Vimlesh Kumar (2): octeon_ep: disable per ring interrupts octeon_ep: ensure dbell BADDR updation Vincent Donnefort (1): Documentation: tracing: Add ring-buffer mapping Vladimir Oltean (1): net: ixp4xx_eth: convert to ndo_hwtstamp_get() and ndo_hwtstamp_set() Vladimir Zapolskiy (3): ARM: dts: lpc32xx: Set motor PWM #pwm-cells property value to 3 cells arm: dts: lpc32xx: add clocks property to Motor Control PWM device tr= ee node clk: qcom: gcc-sm8550: Use floor ops for SDCC RCGs Vlastimil Babka (1): mm, page_alloc, thp: prevent reclaim for __GFP_THISNODE THP allocatio= ns Votokina Victoria (1): nfc: hci: shdlc: Stop timers and work before freeing context Waqar Hameed (9): power: supply: ab8500: Fix use-after-free in power_supply_changed() power: supply: act8945a: Fix use-after-free in power_supply_changed() power: supply: bq256xx: Fix use-after-free in power_supply_changed() power: supply: bq25980: Fix use-after-free in power_supply_changed() power: supply: cpcap-battery: Fix use-after-free in power_supply_chan= ged() power: supply: goldfish: Fix use-after-free in power_supply_changed() power: supply: rt9455: Fix use-after-free in power_supply_changed() power: supply: sbs-battery: Fix use-after-free in power_supply_change= d() power: supply: wm97xx: Fix NULL pointer dereference in power_supply_c= hanged() Wayne Lin (1): drm/amd/display: Avoid updating surface with the same surface under M= PO Wei Li (1): pinctrl: single: fix refcount leak in pcs_add_gpio_func() Weigang He (2): mtd: parsers: ofpart: fix OF node refcount leak in parse_fixed_partit= ions() fbdev: of: display_timing: fix refcount leak in of_get_display_timing= s() Weili Qian (1): crypto: hisilicon/trng - support tfms sharing the device Wentao Liang (2): ARM: omap2: Fix reference count leaks in omap_control_init() soc: ti: pruss: Fix double free in pruss_clk_mux_setup() William Tambe (1): mm/highmem: fix __kmap_to_page() build error Xiao Kan (1): drm: Account property blob allocations to memcg Xiaolei Wang (2): drm/v3d: Set DMA segment size to avoid debug warnings media: i2c: ov5647: use our own mutex for the ctrl lock Xu Yang (1): phy: fsl-imx8mq-usb: disable bind/unbind platform driver feature Yang Shen (2): crypto: hisilicon/zip - support deflate algorithm crypto: hisilicon/zip - remove zlib and gzip Yao Kai (1): rcu: Fix rcu_read_unlock() deadloop due to softirq Yao Zi (1): MIPS: Work around LLVM bug when gp is used as global register variable Yi Liu (2): RDMA/uverbs: Validate wqe_size before using it in ib_uverbs_post_send RDMA/uverbs: Add __GFP_NOWARN to ib_uverbs_unmarshall_recv() kmalloc Yoshihiro Shimoda (1): PCI: Add PCIE_MSG_CODE_ASSERT_INTx message macros Yosry Ahmed (1): KVM: nSVM: Always use vmcb01 in VMLOAD/VMSAVE emulation Yu Kuai (1): blk-mq-debugfs: add missing debugfs_mutex in blk_mq_debugfs_register_= hctxs() YunJe Shin (2): RDMA/siw: Fix potential NULL pointer dereference in header processing RDMA/umad: Reject negative data_len in ib_umad_write Yuto Hamaguchi (1): netfilter: nf_conntrack: Add allow_clash to generic protocol handler Yuxiong Wang (1): cxl: Fix premature commit_end increment on decoder commit failure Zhai Can (1): ACPI: PM: Add unused power resource quirk for THUNDEROBOT ZERO Zhang Yi (1): ext4: don't cache extent during splitting extent Zhiyu Zhang (1): fat: avoid parent link count underflow in rmdir Zilin Guan (6): soc: mediatek: svs: Fix memory leak in svs_enable_debug_write() mtd: parsers: Fix memory leak in mtd_parser_tplink_safeloader_parse() scsi: smartpqi: Fix memory leak in pqi_report_phys_luns() drm/amdgpu: Fix memory leak in amdgpu_acpi_enumerate_xcc() drm/amdgpu: Fix memory leak in amdgpu_ras_init() ext4: fix memory leak in ext4_ext_shift_extents() Ziyi Guo (12): wifi: ath10k: sdio: add missing lock protection in ath10k_sdio_fw_cra= shed_dump() net: mscc: ocelot: extract ocelot_xmit_timestamp() helper net: mscc: ocelot: split xmit into FDMA and register injection paths net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_in= j() net: usb: catc: enable basic endpoint checking xen-netback: reject zero-queue configuration from guest ASoC: fsl_xcvr: Revert fix missing lock in fsl_xcvr_mode_put() wifi: iwlegacy: add missing mutex protection in il4965_store_tx_power= () wifi: iwlegacy: add missing mutex protection in il3945_store_measurem= ent() wifi: ath10k: fix lock protection in ath10k_wmi_event_peer_sta_ps_sta= te_chg() net: usb: kaweth: remove TX queue manipulation in kaweth_set_rx_mode net: usb: pegasus: enable basic endpoint checking Zqiang (1): rcu: Remove local_irq_save/restore() in rcu_preempt_deferred_qs_handl= er() decce6 (2): drm/amdgpu: Add HAINAN clock adjustment drm/radeon: Add HAINAN clock adjustment ethanwu (2): ceph: supply snapshot context in ceph_uninline_data() ceph: supply snapshot context in ceph_zero_partial_object() gongqi (1): ALSA: hda/conexant: Add headset mic fix for MECHREVO Wujie 15X Pro jinbaohong (2): btrfs: handle user interrupt properly in btrfs_trim_fs() btrfs: continue trimming remaining devices on failure --- Documentation/PCI/endpoint/pci-vntb-howto.rst | 14 +- .../bindings/sound/asahi-kasei,ak4458.yaml | 6 +- .../bindings/sound/asahi-kasei,ak5558.yaml | 4 +- .../device_drivers/ethernet/marvell/octeon_ep.rst | 4 + Documentation/networking/ip-sysctl.rst | 20 + Documentation/trace/events-pci.rst | 74 ++ Documentation/trace/index.rst | 95 ++- Documentation/trace/ring-buffer-map.rst | 106 +++ Makefile | 13 +- arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts | 1 + arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi | 3 +- arch/arm/kernel/vdso.c | 1 + arch/arm/mach-omap2/control.c | 14 +- arch/arm/mm/physaddr.c | 2 +- arch/arm64/Kbuild | 4 + arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 6 + arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 9 + arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 + arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 9 + arch/arm64/boot/dts/apple/t8112-j473.dts | 19 + .../dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts | 2 +- arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 2 + arch/arm64/boot/dts/qcom/sdm630.dtsi | 4 +- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 8 +- .../arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi | 2 +- arch/arm64/boot/dts/qcom/sm6115.dtsi | 8 +- .../boot/dts/rockchip/rk3399-pinebook-pro.dts | 4 - arch/arm64/include/asm/rwonce.h | 2 +- arch/arm64/kernel/proton-pack.c | 1 + arch/arm64/lib/delay.c | 23 +- arch/loongarch/include/asm/topology.h | 2 +- arch/loongarch/kernel/setup.c | 1 + arch/loongarch/kernel/unwind_prologue.c | 2 +- arch/loongarch/mm/tlb.c | 2 +- arch/m68k/lib/memmove.c | 18 + arch/mips/include/asm/mach-loongson64/topology.h | 2 +- arch/mips/kernel/relocate.c | 13 + arch/mips/rb532/devices.c | 5 +- arch/openrisc/include/asm/barrier.h | 2 + arch/parisc/kernel/drivers.c | 2 +- arch/parisc/kernel/process.c | 3 + arch/powerpc/include/asm/eeh.h | 2 + arch/powerpc/include/asm/kup.h | 2 - arch/powerpc/include/asm/uaccess.h | 4 + arch/powerpc/kernel/eeh_driver.c | 11 +- arch/powerpc/kernel/eeh_pe.c | 74 +- arch/powerpc/kernel/smp.c | 2 + arch/s390/Kconfig | 3 +- arch/s390/kernel/perf_cpum_sf.c | 2 +- arch/s390/pci/pci.c | 25 +- arch/s390/purgatory/Makefile | 1 + arch/sparc/include/uapi/asm/ioctls.h | 8 +- arch/sparc/kernel/process.c | 38 +- arch/x86/hyperv/hv_vtl.c | 8 +- arch/x86/kernel/kexec-bzimage64.c | 7 + arch/x86/kvm/svm/nested.c | 3 +- arch/x86/kvm/svm/svm.c | 5 +- arch/x86/kvm/x86.c | 2 + arch/x86/platform/pvh/head.S | 2 + arch/x86/xen/enlighten.c | 2 +- arch/x86/xen/mmu.h | 4 - arch/x86/xen/mmu_pv.c | 11 +- arch/x86/xen/xen-ops.h | 1 - block/blk-mq-debugfs.c | 2 + drivers/acpi/acpi_processor.c | 28 +- drivers/acpi/acpica/evregion.c | 4 +- drivers/acpi/acpica/exoparg3.c | 46 +- drivers/acpi/apei/ghes.c | 6 +- drivers/acpi/cppc_acpi.c | 4 +- drivers/acpi/power.c | 13 + drivers/android/binder.c | 2 +- drivers/android/binder_alloc.c | 6 +- drivers/ata/libata-core.c | 24 + drivers/ata/libata-eh.c | 3 +- drivers/ata/libata-scsi.c | 84 +- drivers/ata/libata.h | 1 + drivers/ata/pata_ftide010.c | 6 +- drivers/atm/fore200e.c | 4 + drivers/auxdisplay/arm-charlcd.c | 2 +- drivers/base/power/wakeirq.c | 9 +- drivers/base/power/wakeup.c | 4 +- drivers/block/rnbd/rnbd-srv.c | 3 + drivers/block/ublk_drv.c | 6 +- drivers/bluetooth/btusb.c | 3 + drivers/bluetooth/hci_qca.c | 24 +- drivers/bus/fsl-mc/fsl-mc-bus.c | 6 +- drivers/char/ipmi/ipmi_ipmb.c | 5 + drivers/char/random.c | 12 +- drivers/char/tpm/st33zp24/st33zp24.c | 6 +- drivers/char/tpm/tpm_i2c_infineon.c | 6 +- drivers/char/tpm/tpm_tis_i2c_cr50.c | 3 +- drivers/char/tpm/tpm_tis_spi_cr50.c | 2 +- drivers/clk/clk-apple-nco.c | 1 + drivers/clk/mediatek/clk-mtk.c | 12 +- drivers/clk/meson/gxbb.c | 17 +- drivers/clk/microchip/clk-core.c | 25 +- drivers/clk/qcom/clk-rcg2.c | 7 +- drivers/clk/qcom/common.c | 2 +- drivers/clk/qcom/dispcc-sdm845.c | 4 +- drivers/clk/qcom/gcc-ipq5018.c | 1 + drivers/clk/qcom/gcc-msm8917.c | 1 - drivers/clk/qcom/gcc-msm8953.c | 1 - drivers/clk/qcom/gcc-qdu1000.c | 4 +- drivers/clk/qcom/gcc-sdx75.c | 4 +- drivers/clk/qcom/gcc-sm8450.c | 4 +- drivers/clk/qcom/gcc-sm8550.c | 4 +- drivers/clk/renesas/rzg2l-cpg.c | 6 +- drivers/clk/tegra/clk-tegra124-emc.c | 4 +- drivers/clocksource/Kconfig | 1 + drivers/clocksource/sh_tmu.c | 18 - drivers/cpufreq/cpufreq-dt-platdev.c | 3 + drivers/cpuidle/cpuidle.c | 10 + drivers/cpuidle/governors/menu.c | 39 +- drivers/crypto/cavium/cpt/cptvf_main.c | 3 +- drivers/crypto/ccp/psp-dev.c | 71 ++ drivers/crypto/ccp/psp-dev.h | 18 + drivers/crypto/ccp/sp-dev.c | 12 + drivers/crypto/ccp/sp-dev.h | 6 + drivers/crypto/ccp/sp-pci.c | 34 +- drivers/crypto/ccp/tee-dev.c | 95 +-- drivers/crypto/ccp/tee-dev.h | 16 +- drivers/crypto/hisilicon/qm.c | 6 +- drivers/crypto/hisilicon/sec2/sec_crypto.c | 62 +- drivers/crypto/hisilicon/trng/trng.c | 123 ++- drivers/crypto/hisilicon/zip/zip_crypto.c | 302 +------ drivers/crypto/hisilicon/zip/zip_main.c | 4 +- .../intel/qat/qat_common/adf_pfvf_pf_proto.c | 10 + drivers/crypto/marvell/octeontx/otx_cptvf_main.c | 3 +- drivers/cxl/core/hdm.c | 3 +- drivers/dma/dma-axi-dmac.c | 3 +- drivers/dma/fsl-edma-main.c | 7 +- drivers/dma/mediatek/mtk-uart-apdma.c | 10 +- drivers/dma/stm32-mdma.c | 2 +- drivers/dma/sun6i-dma.c | 26 +- drivers/edac/altera_edac.c | 11 +- drivers/edac/i5000_edac.c | 1 + drivers/edac/i5400_edac.c | 2 +- drivers/firmware/efi/cper-arm.c | 12 +- drivers/firmware/efi/cper.c | 8 +- drivers/firmware/efi/efi.c | 8 +- drivers/fpga/dfl.c | 2 +- drivers/fpga/of-fpga-region.c | 8 +- drivers/gpio/gpio-aspeed-sgpio.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 45 +- drivers/gpu/drm/amd/amdkfd/kfd_debug.c | 38 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 6 + drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 8 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 5 + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 3 +- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 5 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 25 +- drivers/gpu/drm/display/drm_dp_mst_topology.c | 3 +- drivers/gpu/drm/drm_property.c | 2 +- drivers/gpu/drm/i915/display/intel_acpi.c | 1 + drivers/gpu/drm/i915/intel_wakeref.c | 2 +- drivers/gpu/drm/i915/intel_wakeref.h | 14 +- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 5 +- .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h | 14 +- .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 7 +- drivers/gpu/drm/radeon/si_dpm.c | 5 + drivers/gpu/drm/v3d/v3d_drv.c | 2 + drivers/hid/Kconfig | 1 + drivers/hid/hid-apple.c | 1 + drivers/hid/hid-elecom.c | 16 + drivers/hid/hid-ids.h | 4 + drivers/hid/hid-logitech-hidpp.c | 2 +- drivers/hid/hid-magicmouse.c | 5 + drivers/hid/hid-multitouch.c | 3 + drivers/hid/hid-pl.c | 7 +- drivers/hid/hid-playstation.c | 4 +- drivers/hid/hid-prodikeys.c | 4 + drivers/hid/hid-quirks.c | 3 + drivers/hwmon/f71882fg.c | 6 +- drivers/hwmon/ibmpex.c | 9 +- drivers/hwmon/nct6775-platform.c | 1 + drivers/hwtracing/coresight/coresight-etm3x-core.c | 12 +- drivers/i3c/master.c | 6 +- drivers/i3c/master/dw-i3c-master.c | 2 + drivers/i3c/master/svc-i3c-master.c | 4 +- drivers/iio/accel/bma180.c | 5 +- drivers/iio/accel/sca3000.c | 6 +- drivers/iio/adc/ad7766.c | 2 +- drivers/iio/gyro/itg3200_buffer.c | 8 +- drivers/iio/gyro/itg3200_core.c | 2 + drivers/iio/gyro/mpu3050-core.c | 6 +- drivers/iio/light/si1145.c | 2 +- drivers/iio/magnetometer/ak8975.c | 2 +- drivers/iio/pressure/mprls0025pa.c | 4 +- drivers/infiniband/core/cache.c | 16 +- drivers/infiniband/core/core_priv.h | 3 + drivers/infiniband/core/device.c | 34 +- drivers/infiniband/core/rw.c | 53 +- drivers/infiniband/core/umem_dmabuf.c | 4 +- drivers/infiniband/core/user_mad.c | 8 +- drivers/infiniband/core/uverbs_cmd.c | 7 +- drivers/infiniband/hw/efa/efa_verbs.c | 2 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 26 +- drivers/infiniband/sw/rxe/rxe_comp.c | 3 + drivers/infiniband/sw/rxe/rxe_req.c | 3 + drivers/infiniband/sw/rxe/rxe_srq.c | 6 +- drivers/infiniband/sw/siw/siw_qp_rx.c | 3 +- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 4 +- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 33 +- drivers/iommu/amd/iommu.c | 25 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 31 +- drivers/iommu/intel/pasid.c | 9 +- drivers/leds/rgb/leds-qcom-lpg.c | 8 +- drivers/mailbox/bcm-flexrm-mailbox.c | 14 +- drivers/mailbox/imx-mailbox.c | 8 +- drivers/mailbox/pcc.c | 2 +- drivers/mailbox/sprd-mailbox.c | 20 +- drivers/md/dm-exception-store.c | 2 +- drivers/md/dm-integrity.c | 15 +- drivers/md/dm-log.c | 2 +- drivers/md/dm-mpath.c | 2 +- drivers/md/dm-path-selector.c | 2 +- drivers/md/dm-rq.c | 16 +- drivers/md/dm-target.c | 2 +- drivers/md/dm-unstripe.c | 2 +- drivers/md/dm-verity-fec.c | 4 +- drivers/md/dm.c | 2 + drivers/md/md-bitmap.c | 3 +- drivers/md/md-cluster.c | 7 +- drivers/md/raid10.c | 2 +- drivers/media/dvb-core/dmxdev.c | 8 +- drivers/media/dvb-core/dvb_vb2.c | 5 +- drivers/media/i2c/adv7180.c | 7 + drivers/media/i2c/ccs/ccs-core.c | 18 +- drivers/media/i2c/ov01a10.c | 44 +- drivers/media/i2c/ov5647.c | 24 +- drivers/media/i2c/tw9903.c | 1 + drivers/media/i2c/tw9906.c | 1 + drivers/media/pci/cx23885/cx23885-alsa.c | 4 +- drivers/media/pci/cx25821/cx25821-alsa.c | 1 + drivers/media/pci/cx25821/cx25821-core.c | 1 + drivers/media/pci/cx88/cx88-alsa.c | 4 +- drivers/media/pci/solo6x10/solo6x10-tw28.c | 8 +- drivers/media/platform/amphion/vdec.c | 1 + drivers/media/platform/mediatek/mdp/mtk_mdp_core.c | 17 +- .../vcodec/decoder/mtk_vcodec_dec_stateless.c | 6 + .../mediatek/vcodec/encoder/mtk_vcodec_enc.c | 6 +- drivers/media/platform/qcom/camss/camss-vfe-480.c | 6 +- drivers/media/platform/qcom/venus/vdec.c | 14 +- .../media/platform/rockchip/rkisp1/rkisp1-params.c | 6 - drivers/media/platform/ti/omap3isp/isppreview.c | 21 +- drivers/media/platform/ti/omap3isp/ispvideo.c | 14 +- .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 43 +- drivers/media/radio/radio-keene.c | 2 +- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 5 + drivers/media/usb/uvc/uvc_video.c | 3 +- drivers/media/v4l2-core/v4l2-async.c | 45 +- drivers/mfd/Kconfig | 24 + drivers/mfd/arizona-core.c | 2 +- drivers/mfd/da9052-spi.c | 2 +- drivers/mfd/mfd-core.c | 36 +- drivers/mfd/simple-mfd-i2c.c | 33 +- drivers/misc/bcm-vk/bcm_vk_msg.c | 12 +- drivers/misc/eeprom/eeprom_93xx46.c | 11 +- drivers/mtd/nand/raw/cadence-nand-controller.c | 2 +- drivers/mtd/nand/raw/pl35x-nand-controller.c | 1 + drivers/mtd/parsers/ofpart_core.c | 16 +- drivers/mtd/parsers/tplink_safeloader.c | 1 + drivers/net/bonding/bond_main.c | 21 +- drivers/net/caif/caif_serial.c | 5 +- drivers/net/ethernet/cadence/macb_main.c | 11 +- drivers/net/ethernet/ec_bhf.c | 2 +- .../net/ethernet/freescale/dpaa2/dpaa2-switch.c | 7 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 11 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 5 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +- drivers/net/ethernet/marvell/octeon_ep/Makefile | 3 +- .../net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c | 189 +++-- .../net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c | 935 +++++++++++++++++= ++++ .../net/ethernet/marvell/octeon_ep/octep_config.h | 32 +- .../ethernet/marvell/octeon_ep/octep_ctrl_net.c | 24 +- .../ethernet/marvell/octeon_ep/octep_ctrl_net.h | 18 + .../net/ethernet/marvell/octeon_ep/octep_main.c | 233 ++++- .../net/ethernet/marvell/octeon_ep/octep_main.h | 21 +- .../marvell/octeon_ep/octep_regs_cn9k_pf.h | 5 + .../marvell/octeon_ep/octep_regs_cnxk_pf.h | 404 +++++++++ drivers/net/ethernet/marvell/octeon_ep/octep_rx.c | 8 +- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 2 + drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 11 + .../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 12 +- .../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 41 +- .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 1 + drivers/net/ethernet/marvell/skge.c | 1 - drivers/net/ethernet/mellanox/mlx5/core/sriov.c | 2 + .../ethernet/mellanox/mlx5/core/steering/dr_dbg.c | 4 +- drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c | 2 +- drivers/net/ethernet/microchip/sparx5/sparx5_qos.h | 2 +- drivers/net/ethernet/mscc/ocelot_net.c | 75 +- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 28 +- .../net/ethernet/pensando/ionic/ionic_ethtool.c | 7 +- drivers/net/ethernet/sun/sunhme.c | 3 + drivers/net/ethernet/ti/cpsw_new.c | 12 +- drivers/net/ethernet/xscale/ixp4xx_eth.c | 60 +- drivers/net/ethernet/xscale/ptp_ixp46x.c | 3 + drivers/net/macvlan.c | 5 + drivers/net/mctp/mctp-i2c.c | 9 + drivers/net/usb/Kconfig | 1 - drivers/net/usb/catc.c | 37 +- drivers/net/usb/kaweth.c | 2 - drivers/net/usb/lan78xx.c | 2 - drivers/net/usb/pegasus.c | 35 +- drivers/net/usb/r8152.c | 2 + drivers/net/usb/sr9700.c | 25 +- drivers/net/usb/sr9700.h | 7 +- drivers/net/wan/farsync.c | 2 + drivers/net/wan/fsl_ucc_hdlc.c | 8 +- drivers/net/wireless/ath/ath10k/sdio.c | 6 + drivers/net/wireless/ath/ath10k/wmi.c | 4 +- drivers/net/wireless/ath/ath11k/core.c | 28 + drivers/net/wireless/ath/ath12k/wmi.c | 2 +- drivers/net/wireless/intel/ipw2x00/ipw2200.c | 8 +- drivers/net/wireless/intel/iwlegacy/3945-mac.c | 2 + drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 14 + drivers/net/wireless/marvell/libertas/if_usb.c | 2 + drivers/net/wireless/realtek/rtw88/main.c | 4 +- drivers/net/wireless/realtek/rtw88/main.h | 2 +- drivers/net/wireless/realtek/rtw88/rtw8821cu.c | 2 + drivers/net/wireless/realtek/rtw88/rtw8822b.c | 3 +- drivers/net/wireless/realtek/rtw89/pci.c | 1 + drivers/net/wireless/realtek/rtw89/wow.c | 4 + drivers/net/wireless/realtek/rtw89/wow.h | 1 + drivers/net/xen-netback/xenbus.c | 5 +- drivers/nfc/nxp-nci/i2c.c | 2 +- drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 12 +- drivers/ntb/ntb_transport.c | 4 +- drivers/nvdimm/nd_virtio.c | 3 +- drivers/nvdimm/virtio_pmem.c | 1 + drivers/nvdimm/virtio_pmem.h | 4 + drivers/nvmem/core.c | 1 + drivers/of/unittest.c | 6 +- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 8 + drivers/pci/controller/pcie-mediatek.c | 4 +- drivers/pci/endpoint/pci-ep-cfs.c | 8 +- drivers/pci/iov.c | 9 +- drivers/pci/msi/msi.c | 4 +- drivers/pci/p2pdma.c | 1 + drivers/pci/pci-acpi.c | 59 +- drivers/pci/pci-driver.c | 8 + drivers/pci/pci.c | 40 +- drivers/pci/pci.h | 26 + drivers/pci/pcie/aer.c | 3 - drivers/pci/pcie/portdrv.c | 6 +- drivers/pci/probe.c | 189 +++-- drivers/pci/quirks.c | 27 + drivers/perf/arm-cmn.c | 19 +- drivers/perf/arm_spe_pmu.c | 18 +- drivers/perf/cxl_pmu.c | 2 +- drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 1 + drivers/phy/marvell/phy-mvebu-cp110-utmi.c | 2 +- drivers/pinctrl/pinctrl-equilibrium.c | 1 + drivers/pinctrl/pinctrl-single.c | 2 + drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c | 2 +- drivers/platform/chrome/cros_ec_lightbar.c | 2 +- drivers/platform/chrome/cros_typec_switch.c | 6 +- drivers/power/reset/nvmem-reboot-mode.c | 15 +- drivers/power/supply/ab8500_charger.c | 40 +- drivers/power/supply/act8945a_charger.c | 16 +- drivers/power/supply/bq256xx_charger.c | 12 +- drivers/power/supply/bq25980_charger.c | 12 +- drivers/power/supply/bq27xxx_battery.c | 6 +- drivers/power/supply/cpcap-battery.c | 8 +- drivers/power/supply/goldfish_battery.c | 12 +- drivers/power/supply/qcom_battmgr.c | 3 +- drivers/power/supply/rt9455_charger.c | 17 +- drivers/power/supply/sbs-battery.c | 36 +- drivers/power/supply/wm97xx_battery.c | 34 +- drivers/powercap/intel_rapl_tpmi.c | 2 +- drivers/rapidio/rio-scan.c | 3 +- drivers/regulator/core.c | 55 +- drivers/remoteproc/imx_dsp_rproc.c | 9 + drivers/remoteproc/imx_rproc.c | 4 + drivers/remoteproc/mtk_scp.c | 39 +- drivers/remoteproc/mtk_scp_ipi.c | 4 +- drivers/rpmsg/rpmsg_core.c | 66 +- drivers/rtc/interface.c | 2 +- drivers/rtc/rtc-zynqmp.c | 3 + drivers/s390/cio/css.c | 2 +- drivers/scsi/BusLogic.c | 6 +- drivers/scsi/csiostor/csio_scsi.c | 3 +- drivers/scsi/elx/efct/efct_driver.c | 8 +- drivers/scsi/smartpqi/smartpqi_init.c | 13 +- drivers/soc/mediatek/mtk-svs.c | 5 +- drivers/soc/qcom/cmd-db.c | 7 +- drivers/soc/qcom/smem.c | 4 +- drivers/soc/ti/k3-socinfo.c | 2 +- drivers/soc/ti/pruss.c | 6 +- drivers/soundwire/dmi-quirks.c | 11 + drivers/spi/spi-geni-qcom.c | 14 +- drivers/spi/spi-mem.c | 26 +- drivers/spi/spi-stm32.c | 9 +- drivers/spi/spi-wpcm-fiu.c | 19 +- drivers/staging/greybus/light.c | 8 +- drivers/staging/rtl8723bs/core/rtw_mlme.c | 6 +- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 3 +- drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 3 +- .../intel/int340x_thermal/processor_thermal_rfim.c | 5 +- drivers/tty/serial/8250/8250_dw.c | 11 +- drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/Kconfig | 8 +- drivers/ufs/core/ufshcd.c | 2 + drivers/ufs/host/Kconfig | 1 + drivers/ufs/host/ufs-mediatek.c | 12 +- drivers/usb/dwc2/core.c | 1 + drivers/usb/dwc3/core.c | 19 +- drivers/usb/dwc3/core.h | 4 + drivers/usb/dwc3/gadget.c | 8 +- drivers/usb/gadget/udc/bdc/bdc_core.c | 4 +- drivers/usb/gadget/udc/tegra-xudc.c | 12 +- drivers/usb/typec/ucsi/psy.c | 30 +- drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 3 +- drivers/vhost/vdpa.c | 1 + drivers/video/backlight/qcom-wled.c | 42 +- drivers/video/fbdev/au1200fb.c | 6 +- drivers/video/fbdev/core/fbcon.c | 3 +- drivers/video/fbdev/core/fbcon.h | 1 - drivers/video/fbdev/ffb.c | 14 +- drivers/video/fbdev/vt8500lcdfb.c | 5 +- drivers/video/of_display_timing.c | 10 +- drivers/watchdog/imx7ulp_wdt.c | 1 + drivers/watchdog/it87_wdt.c | 12 + drivers/watchdog/starfive-wdt.c | 2 +- drivers/xen/balloon.c | 19 +- drivers/xen/grant-dma-ops.c | 3 +- drivers/xen/unpopulated-alloc.c | 3 + drivers/xen/xenbus/xenbus_probe_frontend.c | 4 +- fs/btrfs/extent-tree.c | 13 +- fs/btrfs/qgroup.c | 15 +- fs/btrfs/transaction.c | 7 - fs/btrfs/volumes.c | 10 +- fs/buffer.c | 4 + fs/ceph/addr.c | 24 +- fs/ceph/file.c | 17 +- fs/ext4/extents.c | 9 +- fs/ext4/ioctl.c | 3 + fs/ext4/mballoc.c | 2 - fs/ext4/super.c | 10 +- fs/fat/namei_msdos.c | 7 +- fs/fat/namei_vfat.c | 7 +- fs/fs_struct.c | 1 + fs/gfs2/bmap.c | 21 +- fs/gfs2/glock.c | 36 +- fs/gfs2/glock.h | 3 +- fs/gfs2/inode.c | 34 +- fs/hfsplus/bnode.c | 2 +- fs/hfsplus/inode.c | 12 +- fs/hfsplus/super.c | 6 + fs/iomap/direct-io.c | 10 +- fs/jfs/jfs_logmgr.c | 1 + fs/jfs/namei.c | 6 +- fs/minix/inode.c | 50 +- fs/nfs/dir.c | 4 +- fs/nfs/pnfs.c | 3 +- fs/nfsd/nfs4idmap.c | 52 +- fs/nfsd/nfs4proc.c | 2 - fs/nfsd/nfs4xdr.c | 16 + fs/ntfs3/attrib.c | 19 +- fs/ntfs3/attrlist.c | 9 + fs/ntfs3/file.c | 8 +- fs/ntfs3/fslog.c | 3 + fs/ntfs3/fsntfs.c | 6 + fs/ntfs3/index.c | 7 +- fs/ocfs2/xattr.c | 4 + fs/overlayfs/readdir.c | 2 +- fs/proc/array.c | 2 +- fs/pstore/ram_core.c | 18 + fs/quota/quota.c | 1 + fs/smb/client/cached_dir.c | 4 +- fs/smb/client/connect.c | 2 + fs/smb/client/smb2file.c | 2 + fs/smb/client/smb2misc.c | 6 +- fs/smb/client/smb2ops.c | 29 +- fs/smb/client/smb2pdu.c | 3 + fs/smb/client/smbdirect.c | 19 +- fs/smb/client/trace.h | 1 + fs/xfs/libxfs/xfs_attr_leaf.c | 49 +- fs/xfs/scrub/attr.c | 5 +- fs/xfs/scrub/btree.c | 2 + fs/xfs/scrub/common.c | 4 + fs/xfs/scrub/dabtree.c | 2 + include/acpi/ghes.h | 1 + include/asm-generic/audit_change_attr.h | 3 + include/asm-generic/audit_read.h | 6 + include/drm/drm_of.h | 3 + include/linux/audit.h | 6 - include/linux/audit_arch.h | 7 + include/linux/cache.h | 84 ++ include/linux/capability.h | 6 + include/linux/clk.h | 48 +- include/linux/cper.h | 3 +- include/linux/ftrace.h | 6 +- include/linux/inetdevice.h | 2 +- include/linux/mfd/wm8350/core.h | 2 +- include/linux/mlx5/driver.h | 4 +- include/linux/module.h | 9 + include/linux/mtd/spinand.h | 2 +- include/linux/psp.h | 1 + include/linux/skbuff.h | 32 + include/linux/skmsg.h | 70 +- include/linux/tcp.h | 14 +- include/linux/trace_events.h | 5 + include/linux/u64_stats_sync.h | 10 + include/media/dvb_vb2.h | 6 +- include/net/bluetooth/l2cap.h | 2 + include/net/inet_connection_sock.h | 16 +- include/net/ioam6.h | 2 + include/net/ip.h | 7 +- include/net/ipv6.h | 15 +- include/net/netfilter/nf_conntrack_count.h | 1 + include/net/netns/ipv4.h | 58 +- include/rdma/ib_verbs.h | 2 +- include/rdma/rw.h | 2 + include/uapi/linux/hyperv.h | 2 +- include/uapi/linux/netfilter_bridge.h | 4 + include/uapi/linux/vbox_vmmdev_types.h | 4 +- include/ufs/ufshcd.h | 4 - include/xen/xen.h | 2 + io_uring/cancel.h | 6 +- io_uring/filetable.c | 4 + io_uring/sync.c | 2 + ipc/ipc_sysctl.c | 2 +- kernel/bpf/verifier.c | 18 +- kernel/configs/debug.config | 1 - kernel/kallsyms.c | 4 +- kernel/kexec_file.c | 131 +-- kernel/module/kallsyms.c | 9 +- kernel/rcu/tree.c | 98 +-- kernel/rcu/tree.h | 4 +- kernel/rcu/tree_plugin.h | 109 ++- kernel/sched/rt.c | 5 + kernel/time/hrtimer.c | 2 +- kernel/trace/ftrace.c | 5 +- kernel/trace/trace.c | 2 +- kernel/trace/trace_events.c | 8 +- kernel/trace/trace_events_hist.c | 6 +- kernel/trace/trace_hwlat.c | 15 +- kernel/ucount.c | 2 +- kernel/workqueue.c | 92 +- lib/Kconfig.debug | 27 - localversion-rt | 2 +- mm/highmem.c | 3 +- mm/page_alloc.c | 14 + net/atm/signaling.c | 56 +- net/bluetooth/hci_conn.c | 5 +- net/bluetooth/hci_sync.c | 2 - net/bluetooth/l2cap_core.c | 81 +- net/bluetooth/l2cap_sock.c | 15 +- net/bridge/br_multicast.c | 45 +- net/ceph/crypto.c | 8 +- net/ceph/crypto.h | 2 +- net/ceph/messenger_v2.c | 2 +- net/core/dev.c | 25 +- net/core/filter.c | 2 +- net/core/gro.c | 2 +- net/core/net_namespace.c | 45 + net/core/skmsg.c | 30 +- net/ipv4/fib_lookup.h | 6 +- net/ipv4/fib_trie.c | 4 +- net/ipv4/icmp.c | 72 +- net/ipv4/igmp.c | 4 +- net/ipv4/ip_options.c | 5 +- net/ipv4/ping.c | 31 +- net/ipv4/sysctl_net_ipv4.c | 49 +- net/ipv4/tcp.c | 3 + net/ipv4/tcp_bpf.c | 25 +- net/ipv4/tcp_input.c | 8 + net/ipv4/tcp_ipv4.c | 3 + net/ipv4/tcp_output.c | 9 +- net/ipv4/udp_bpf.c | 23 +- net/ipv6/exthdrs.c | 15 +- net/ipv6/icmp.c | 10 +- net/ipv6/ioam6.c | 14 + net/ipv6/ioam6_iptunnel.c | 10 +- net/ipv6/ip6_fib.c | 2 +- net/ipv6/xfrm6_policy.c | 7 +- net/mptcp/protocol.c | 8 +- net/mptcp/protocol.h | 5 + net/netfilter/nf_conncount.c | 54 +- net/netfilter/nf_conntrack_h323_asn1.c | 2 +- net/netfilter/nf_conntrack_h323_main.c | 10 +- net/netfilter/nf_conntrack_proto_generic.c | 1 + net/netfilter/nf_tables_api.c | 8 + net/netfilter/nft_compat.c | 13 +- net/netfilter/nft_connlimit.c | 7 +- net/netfilter/nft_counter.c | 4 +- net/netfilter/nft_set_hash.c | 9 +- net/netfilter/nft_set_rbtree.c | 30 +- net/netfilter/xt_tcpmss.c | 2 +- net/nfc/hci/llc_shdlc.c | 8 + net/nfc/nci/ntf.c | 159 +++- net/rds/connection.c | 4 + net/rds/send.c | 6 +- net/rds/tcp_listen.c | 5 - net/sched/act_skbedit.c | 6 +- net/sunrpc/auth_gss/auth_gss.c | 3 + net/sunrpc/auth_gss/gss_rpc_xdr.c | 82 +- net/sunrpc/xprtrdma/svc_rdma_transport.c | 43 +- net/tipc/crypto.c | 2 +- net/tipc/name_table.c | 6 +- net/vmw_vsock/vmci_transport.c | 2 +- net/wireless/core.c | 4 +- net/wireless/wext-compat.c | 2 +- net/xfrm/xfrm_device.c | 12 +- net/xfrm/xfrm_policy.c | 11 +- scripts/kernel-doc | 5 + scripts/mod/modpost.c | 4 + security/apparmor/apparmorfs.c | 27 +- security/apparmor/domain.c | 60 +- security/apparmor/file.c | 12 +- security/apparmor/include/lib.h | 2 + security/apparmor/include/match.h | 6 - security/apparmor/include/policy.h | 49 +- security/apparmor/ipc.c | 4 +- security/apparmor/label.c | 51 +- security/apparmor/lib.c | 4 +- security/apparmor/lsm.c | 63 ++ security/apparmor/match.c | 44 - security/apparmor/mount.c | 20 +- security/apparmor/net.c | 10 +- security/apparmor/policy.c | 58 +- security/apparmor/policy_unpack.c | 122 ++- security/apparmor/resource.c | 5 + security/smack/smackfs.c | 79 +- sound/pci/hda/patch_conexant.c | 1 + sound/soc/amd/yc/acp6x-mach.c | 8 +- sound/soc/codecs/aw88261.c | 3 +- sound/soc/codecs/es8328.c | 10 +- sound/soc/codecs/max98390.c | 3 + sound/soc/codecs/nau8821.c | 85 +- sound/soc/codecs/nau8821.h | 3 +- sound/soc/codecs/wm8962.c | 12 +- sound/soc/fsl/fsl_xcvr.c | 3 - sound/soc/rockchip/rockchip_i2s_tdm.c | 10 + sound/soc/sof/ipc4-control.c | 41 +- sound/soc/sof/ipc4-topology.c | 35 +- sound/soc/sunxi/sun50i-dmic.c | 3 + sound/usb/endpoint.c | 40 +- sound/usb/quirks.c | 2 + tools/bpf/bpftool/net.c | 5 +- tools/include/linux/bitfield.h | 1 + tools/lib/bpf/btf_dump.c | 9 + tools/lib/bpf/netlink.c | 4 +- tools/lib/perf/Makefile | 14 +- tools/lib/subcmd/help.c | 10 +- tools/objtool/Makefile | 2 + tools/perf/tests/shell/stat.sh | 6 +- tools/perf/util/evsel_fprintf.c | 8 +- tools/perf/util/unwind-libdw.c | 7 +- tools/power/cpupower/lib/cpuidle.c | 1 + tools/power/x86/intel-speed-select/isst-config.c | 2 + tools/spi/.gitignore | 1 + tools/testing/selftests/bpf/veristat.c | 2 +- .../selftests/drivers/net/mlxsw/tc_restrictions.sh | 4 +- tools/testing/selftests/memfd/memfd_test.c | 123 ++- .../selftests/mm/charge_reserved_hugetlb.sh | 4 +- .../selftests/net/forwarding/vxlan_bridge_1d.sh | 26 +- .../net/forwarding/vxlan_bridge_1d_ipv6.sh | 2 +- 670 files changed, 7930 insertions(+), 2926 deletions(-) --- diff --git a/Documentation/PCI/endpoint/pci-vntb-howto.rst b/Documentation/= PCI/endpoint/pci-vntb-howto.rst index 70d3bc90893f..949c0d35694c 100644 --- a/Documentation/PCI/endpoint/pci-vntb-howto.rst +++ b/Documentation/PCI/endpoint/pci-vntb-howto.rst @@ -52,14 +52,14 @@ PCI endpoint function device can be created using the c= onfigfs. To create # cd /sys/kernel/config/pci_ep/ # mkdir functions/pci_epf_vntb/func1 =20 -The "mkdir func1" above creates the pci-epf-ntb function device that will +The "mkdir func1" above creates the pci-epf-vntb function device that will be probed by pci_epf_vntb driver. =20 The PCI endpoint framework populates the directory with the following configurable fields:: =20 - # ls functions/pci_epf_ntb/func1 - baseclass_code deviceid msi_interrupts pci-epf-ntb.0 + # ls functions/pci_epf_vntb/func1 + baseclass_code deviceid msi_interrupts pci-epf-vntb.0 progif_code secondary subsys_id vendorid cache_line_size interrupt_pin msix_interrupts primary revid subclass_code subsys_vendor_id @@ -106,13 +106,13 @@ of the function device and is populated with the foll= owing NTB specific # echo 0x080A > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_pid # echo 0x10 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vbus_number =20 -Binding pci-epf-ntb Device to EP Controller +Binding pci-epf-vntb Device to EP Controller -------------------------------------------- =20 NTB function device should be attached to PCI endpoint controllers connected to the host. =20 - # ln -s controllers/5f010000.pcie_ep functions/pci-epf-ntb/func1/primary + # ln -s controllers/5f010000.pcie_ep functions/pci_epf_vntb/func1/primary =20 Once the above step is completed, the PCI endpoint controllers are ready to establish a link with the host. @@ -134,7 +134,7 @@ lspci Output at Host side ------------------------- =20 Note that the devices listed here correspond to the values populated in -"Creating pci-epf-ntb Device" section above:: +"Creating pci-epf-vntb Device" section above:: =20 # lspci 00:00.0 PCI bridge: Freescale Semiconductor Inc Device 0000 (rev 0= 1) @@ -147,7 +147,7 @@ lspci Output at EP Side / Virtual PCI bus ----------------------------------------- =20 Note that the devices listed here correspond to the values populated in -"Creating pci-epf-ntb Device" section above:: +"Creating pci-epf-vntb Device" section above:: =20 # lspci 10:00.0 Unassigned class [ffff]: Dawicontrol Computersysteme GmbH = Device 1234 (rev ff) diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yam= l b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml index 4477f84b7acc..e44801ddbd2a 100644 --- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml @@ -18,10 +18,10 @@ title: AK4458 audio DAC reg: maxItems: 1 =20 - avdd-supply: + AVDD-supply: description: Analog power supply =20 - dvdd-supply: + DVDD-supply: description: Digital power supply =20 reset-gpios: @@ -56,7 +56,7 @@ title: AK4458 audio DAC properties: dsd-path: false =20 -additionalProperties: false +unevaluatedProperties: false =20 examples: - | diff --git a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yam= l b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml index d3d494ae8abf..dc8f85f266bf 100644 --- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml +++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml @@ -19,10 +19,10 @@ title: AK5558 8 channel differential 32-bit delta-sigma= ADC reg: maxItems: 1 =20 - avdd-supply: + AVDD-supply: description: A 1.8V supply that powers up the AVDD pin. =20 - dvdd-supply: + DVDD-supply: description: A 1.2V supply that powers up the DVDD pin. =20 reset-gpios: diff --git a/Documentation/networking/device_drivers/ethernet/marvell/octeo= n_ep.rst b/Documentation/networking/device_drivers/ethernet/marvell/octeon_= ep.rst index cad96c8d1f97..613a818d5db6 100644 --- a/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst +++ b/Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst @@ -24,6 +24,10 @@ Supported Devices Currently, this driver support following devices: * Network controller: Cavium, Inc. Device b200 * Network controller: Cavium, Inc. Device b400 + * Network controller: Cavium, Inc. Device b900 + * Network controller: Cavium, Inc. Device ba00 + * Network controller: Cavium, Inc. Device bc00 + * Network controller: Cavium, Inc. Device bd00 =20 Interface Control =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/network= ing/ip-sysctl.rst index a66054d0763a..531a070df2a6 100644 --- a/Documentation/networking/ip-sysctl.rst +++ b/Documentation/networking/ip-sysctl.rst @@ -745,6 +745,13 @@ tcp_comp_sack_nr - INTEGER =20 Default : 44 =20 +tcp_backlog_ack_defer - BOOLEAN + If set, user thread processing socket backlog tries sending + one ACK for the whole queue. This helps to avoid potential + long latencies at end of a TCP socket syscall. + + Default : true + tcp_slow_start_after_idle - BOOLEAN If set, provide RFC2861 behavior and time out the congestion window after an idle period. An idle period is defined at @@ -1176,6 +1183,19 @@ tcp_plb_cong_thresh - INTEGER =20 Default: 128 =20 +tcp_pingpong_thresh - INTEGER + The number of estimated data replies sent for estimated incoming data + requests that must happen before TCP considers that a connection is a + "ping-pong" (request-response) connection for which delayed + acknowledgments can provide benefits. + + This threshold is 1 by default, but some applications may need a higher + threshold for optimal performance. + + Possible Values: 1 - 255 + + Default: 1 + UDP variables =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/Documentation/trace/events-pci.rst b/Documentation/trace/event= s-pci.rst new file mode 100644 index 000000000000..03ff4ad30ddf --- /dev/null +++ b/Documentation/trace/events-pci.rst @@ -0,0 +1,74 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +Subsystem Trace Points: PCI +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +Overview +=3D=3D=3D=3D=3D=3D=3D=3D +The PCI tracing system provides tracepoints to monitor critical hardware e= vents +that can impact system performance and reliability. These events normally = show +up here: + + /sys/kernel/tracing/events/pci + +Cf. include/trace/events/pci.h for the events definitions. + +Available Tracepoints +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +pci_hp_event +------------ + +Monitors PCI hotplug events including card insertion/removal and link +state changes. +:: + + pci_hp_event "%s slot:%s, event:%s\n" + +**Event Types**: + +* ``LINK_UP`` - PCIe link established +* ``LINK_DOWN`` - PCIe link lost +* ``CARD_PRESENT`` - Card detected in slot +* ``CARD_NOT_PRESENT`` - Card removed from slot + +**Example Usage**:: + + # Enable the tracepoint + echo 1 > /sys/kernel/debug/tracing/events/pci/pci_hp_event/enable + + # Monitor events (the following output is generated when a device is h= otplugged) + cat /sys/kernel/debug/tracing/trace_pipe + irq/51-pciehp-88 [001] ..... 1311.177459: pci_hp_event: 0000:= 00:02.0 slot:10, event:CARD_PRESENT + + irq/51-pciehp-88 [001] ..... 1311.177566: pci_hp_event: 0000:= 00:02.0 slot:10, event:LINK_UP + +pcie_link_event +--------------- + +Monitors PCIe link speed changes and provides detailed link status informa= tion. +:: + + pcie_link_event "%s type:%d, reason:%d, cur_bus_speed:%d, max_bus_spe= ed:%d, width:%u, flit_mode:%u, status:%s\n" + +**Parameters**: + +* ``type`` - PCIe device type (4=3DRoot Port, etc.) +* ``reason`` - Reason for link change: + + - ``0`` - Link retrain + - ``1`` - Bus enumeration + - ``2`` - Bandwidth notification enable + - ``3`` - Bandwidth notification IRQ + - ``4`` - Hotplug event + + +**Example Usage**:: + + # Enable the tracepoint + echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_link_event/enable + + # Monitor events (the following output is generated when a device is h= otplugged) + cat /sys/kernel/debug/tracing/trace_pipe + irq/51-pciehp-88 [001] ..... 381.545386: pcie_link_event: 00= 00:00:02.0 type:4, reason:4, cur_bus_speed:20, max_bus_speed:23, width:1, f= lit_mode:0, status:DLLLA diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 5092d6c13af5..e9bcb9d9f7f3 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst @@ -1,37 +1,104 @@ -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D -Linux Tracing Technologies -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D +Linux Tracing Technologies Guide +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D + +Tracing in the Linux kernel is a powerful mechanism that allows +developers and system administrators to analyze and debug system +behavior. This guide provides documentation on various tracing +frameworks and tools available in the Linux kernel. + +Introduction to Tracing +----------------------- + +This section provides an overview of Linux tracing mechanisms +and debugging approaches. =20 .. toctree:: :maxdepth: 2 =20 - ftrace-design + debugging + tracepoints tracepoint-analysis + ring-buffer-map + +Core Tracing Frameworks +----------------------- + +The following are the primary tracing frameworks integrated into +the Linux kernel. + +.. toctree:: + :maxdepth: 1 + ftrace + ftrace-design ftrace-uses - fprobe kprobes kprobetrace - uprobetracer fprobetrace - tracepoints + fprobe + ring-buffer-design + +Event Tracing and Analysis +-------------------------- + +A detailed explanation of event tracing mechanisms and their +applications. + +.. toctree:: + :maxdepth: 1 + events events-kmem events-power events-nmi events-msr - mmiotrace + events-pci + boottime-trace histogram histogram-design - boottime-trace - hwlat_detector - osnoise-tracer - timerlat-tracer + +Hardware and Performance Tracing +-------------------------------- + +This section covers tracing features that monitor hardware +interactions and system performance. + +.. toctree:: + :maxdepth: 1 + intel_th - ring-buffer-design stm sys-t coresight/index - user_events rv/index hisi-ptt + mmiotrace + hwlat_detector + osnoise-tracer + timerlat-tracer + +User-Space Tracing +------------------ + +These tools allow tracing user-space applications and +interactions. + +.. toctree:: + :maxdepth: 1 + + user_events + uprobetracer + +Additional Resources +-------------------- + +For more details, refer to the respective documentation of each +tracing tool and framework. + +.. only:: subproject and html + + Indices + =3D=3D=3D=3D=3D=3D=3D + + * :ref:`genindex` diff --git a/Documentation/trace/ring-buffer-map.rst b/Documentation/trace/= ring-buffer-map.rst new file mode 100644 index 000000000000..8e296bcc0d7f --- /dev/null +++ b/Documentation/trace/ring-buffer-map.rst @@ -0,0 +1,106 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Tracefs ring-buffer memory mapping +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +:Author: Vincent Donnefort + +Overview +=3D=3D=3D=3D=3D=3D=3D=3D +Tracefs ring-buffer memory map provides an efficient method to stream data +as no memory copy is necessary. The application mapping the ring-buffer be= comes +then a consumer for that ring-buffer, in a similar fashion to trace_pipe. + +Memory mapping setup +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The mapping works with a mmap() of the trace_pipe_raw interface. + +The first system page of the mapping contains ring-buffer statistics and +description. It is referred to as the meta-page. One of the most important +fields of the meta-page is the reader. It contains the sub-buffer ID which= can +be safely read by the mapper (see ring-buffer-design.rst). + +The meta-page is followed by all the sub-buffers, ordered by ascending ID.= It is +therefore effortless to know where the reader starts in the mapping: + +.. code-block:: c + + reader_id =3D meta->reader->id; + reader_offset =3D meta->meta_page_size + reader_id * meta->subbuf_= size; + +When the application is done with the current reader, it can get a new one= using +the trace_pipe_raw ioctl() TRACE_MMAP_IOCTL_GET_READER. This ioctl also up= dates +the meta-page fields. + +Limitations +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +When a mapping is in place on a Tracefs ring-buffer, it is not possible to +either resize it (either by increasing the entire size of the ring-buffer = or +each subbuf). It is also not possible to use snapshot and causes splice to= copy +the ring buffer data instead of using the copyless swap from the ring buff= er. + +Concurrent readers (either another application mapping that ring-buffer or= the +kernel with trace_pipe) are allowed but not recommended. They will compete= for +the ring-buffer and the output is unpredictable, just like concurrent read= ers on +trace_pipe would be. + +Example +=3D=3D=3D=3D=3D=3D=3D + +.. code-block:: c + + #include + #include + #include + #include + + #include + + #include + #include + + #define TRACE_PIPE_RAW "/sys/kernel/tracing/per_cpu/cpu0/trace_pip= e_raw" + + int main(void) + { + int page_size =3D getpagesize(), fd, reader_id; + unsigned long meta_len, data_len; + struct trace_buffer_meta *meta; + void *map, *reader, *data; + + fd =3D open(TRACE_PIPE_RAW, O_RDONLY | O_NONBLOCK); + if (fd < 0) + exit(EXIT_FAILURE); + + map =3D mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0= ); + if (map =3D=3D MAP_FAILED) + exit(EXIT_FAILURE); + + meta =3D (struct trace_buffer_meta *)map; + meta_len =3D meta->meta_page_size; + + printf("entries: %llu\n", meta->entries); + printf("overrun: %llu\n", meta->overrun); + printf("read: %llu\n", meta->read); + printf("nr_subbufs: %u\n", meta->nr_subbufs); + + data_len =3D meta->subbuf_size * meta->nr_subbufs; + data =3D mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, m= eta_len); + if (data =3D=3D MAP_FAILED) + exit(EXIT_FAILURE); + + if (ioctl(fd, TRACE_MMAP_IOCTL_GET_READER) < 0) + exit(EXIT_FAILURE); + + reader_id =3D meta->reader.id; + reader =3D data + meta->subbuf_size * reader_id; + + printf("Current reader address: %p\n", reader); + + munmap(data, data_len); + munmap(meta, meta_len); + close (fd); + + return 0; + } diff --git a/Makefile b/Makefile index b9c04d8271b9..022aed903173 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION =3D 6 PATCHLEVEL =3D 6 -SUBLEVEL =3D 127 +SUBLEVEL =3D 129 EXTRAVERSION =3D NAME =3D Pingu\ufffd\ufffdn Aangedreven =20 @@ -1356,6 +1356,15 @@ ifneq ($(wildcard $(resolve_btfids_O)),) $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=3D$(resolve_btfids_= O) clean endif =20 +PHONY +=3D objtool_clean + +objtool_O =3D $(abspath $(objtree))/tools/objtool + +objtool_clean: +ifneq ($(wildcard $(objtool_O)),) + $(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=3D$(objtool_O) srctree=3D$= (abs_srctree) clean +endif + tools/: FORCE $(Q)mkdir -p $(objtree)/tools $(Q)$(MAKE) O=3D$(abspath $(objtree)) subdir=3Dtools -C $(srctree)/tools/ @@ -1509,7 +1518,7 @@ PHONY +=3D archclean vmlinuxclean $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean $(Q)$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) clean) =20 -clean: archclean vmlinuxclean resolve_btfids_clean +clean: archclean vmlinuxclean resolve_btfids_clean objtool_clean =20 # mrproper - Delete all generated files, including .config # diff --git a/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts b/arch/arm/= boot/dts/allwinner/sun5i-a13-utoo-p66.dts index be486d28d04f..428cab5a0e90 100644 --- a/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts +++ b/arch/arm/boot/dts/allwinner/sun5i-a13-utoo-p66.dts @@ -102,6 +102,7 @@ &touchscreen { /* The P66 uses a different EINT then the reference design */ interrupts =3D <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */ /* The icn8318 binding expects wake-gpios instead of power-gpios */ + /delete-property/ power-gpios; wake-gpios =3D <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ touchscreen-size-x =3D <800>; touchscreen-size-y =3D <480>; diff --git a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi b/arch/arm/boot/dts/nxp= /lpc/lpc32xx.dtsi index 974410918f35..7503074d2877 100644 --- a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi +++ b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi @@ -301,8 +301,9 @@ i2c2: i2c@400a8000 { mpwm: mpwm@400e8000 { compatible =3D "nxp,lpc3220-motor-pwm"; reg =3D <0x400e8000 0x78>; + clocks =3D <&clk LPC32XX_CLK_MCPWM>; + #pwm-cells =3D <3>; status =3D "disabled"; - #pwm-cells =3D <2>; }; }; =20 diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c index f297d66a8a76..32b6683b4595 100644 --- a/arch/arm/kernel/vdso.c +++ b/arch/arm/kernel/vdso.c @@ -176,6 +176,7 @@ static void __init patch_vdso(void *ehdr) vdso_nullpatch_one(&einfo, "__vdso_gettimeofday"); vdso_nullpatch_one(&einfo, "__vdso_clock_gettime"); vdso_nullpatch_one(&einfo, "__vdso_clock_gettime64"); + vdso_nullpatch_one(&einfo, "__vdso_clock_getres"); } } =20 diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 79860b23030d..eb6fc7c61b6e 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -732,7 +732,7 @@ int __init omap2_control_base_init(void) */ int __init omap_control_init(void) { - struct device_node *np, *scm_conf; + struct device_node *np, *scm_conf, *clocks_node; const struct of_device_id *match; const struct omap_prcm_init_data *data; int ret; @@ -753,16 +753,19 @@ int __init omap_control_init(void) =20 if (IS_ERR(syscon)) { ret =3D PTR_ERR(syscon); - goto of_node_put; + goto err_put_scm_conf; } =20 - if (of_get_child_by_name(scm_conf, "clocks")) { + clocks_node =3D of_get_child_by_name(scm_conf, "clocks"); + if (clocks_node) { + of_node_put(clocks_node); ret =3D omap2_clk_provider_init(scm_conf, data->index, syscon, NULL); if (ret) - goto of_node_put; + goto err_put_scm_conf; } + of_node_put(scm_conf); } else { /* No scm_conf found, direct access */ ret =3D omap2_clk_provider_init(np, data->index, NULL, @@ -780,6 +783,9 @@ int __init omap_control_init(void) =20 return 0; =20 +err_put_scm_conf: + if (scm_conf) + of_node_put(scm_conf); of_node_put: of_node_put(np); return ret; diff --git a/arch/arm/mm/physaddr.c b/arch/arm/mm/physaddr.c index 3f263c840ebc..1a37ebfacbba 100644 --- a/arch/arm/mm/physaddr.c +++ b/arch/arm/mm/physaddr.c @@ -38,7 +38,7 @@ static inline bool __virt_addr_valid(unsigned long x) phys_addr_t __virt_to_phys(unsigned long x) { WARN(!__virt_addr_valid(x), - "virt_to_phys used for non-linear address: %pK (%pS)\n", + "virt_to_phys used for non-linear address: %px (%pS)\n", (void *)x, (void *)x); =20 return __virt_to_phys_nodebug(x); diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild index 5bfbf7d79c99..d876bc0e5421 100644 --- a/arch/arm64/Kbuild +++ b/arch/arm64/Kbuild @@ -1,4 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only + +# Branch profiling isn't noinstr-safe +subdir-ccflags-$(CONFIG_TRACE_BRANCH_PROFILING) +=3D -DDISABLE_BRANCH_PROF= ILING + obj-y +=3D kernel/ mm/ net/ obj-$(CONFIG_KVM) +=3D kvm/ obj-$(CONFIG_XEN) +=3D xen/ diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/d= ts/amlogic/meson-axg.dtsi index 768d0ed78dbe..16af71d84a13 100644 --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi @@ -1894,6 +1894,9 @@ sd_emmc_b: mmc@5000 { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_B>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_B_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 sd_emmc_c: mmc@7000 { @@ -1906,6 +1909,9 @@ sd_emmc_c: mmc@7000 { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_C>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_C_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 usb2_phy1: phy@9020 { diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64= /boot/dts/amlogic/meson-g12-common.dtsi index 0ff0d090548d..c5848363df37 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi @@ -2341,6 +2341,9 @@ sd_emmc_a: mmc@ffe03000 { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_A>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_A_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 sd_emmc_b: mmc@ffe05000 { @@ -2353,6 +2356,9 @@ sd_emmc_b: mmc@ffe05000 { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_B>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_B_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 sd_emmc_c: mmc@ffe07000 { @@ -2365,6 +2371,9 @@ sd_emmc_c: mmc@ffe07000 { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_C>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_C_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 usb: usb@ffe09000 { diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/= dts/amlogic/meson-gxbb.dtsi index ed00e67e6923..851ae89dd17f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -799,6 +799,9 @@ &sd_emmc_a { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_A>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_A_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &sd_emmc_b { @@ -807,6 +810,9 @@ &sd_emmc_b { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_B>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_B_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &sd_emmc_c { @@ -815,6 +821,9 @@ &sd_emmc_c { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_C>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_C_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &simplefb_hdmi { diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/d= ts/amlogic/meson-gxl.dtsi index f58d1790de1c..f7fafebafd80 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi @@ -869,6 +869,9 @@ &sd_emmc_a { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_A>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_A_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &sd_emmc_b { @@ -877,6 +880,9 @@ &sd_emmc_b { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_B>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_B_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &sd_emmc_c { @@ -885,6 +891,9 @@ &sd_emmc_c { <&clkc CLKID_FCLK_DIV2>; clock-names =3D "core", "clkin0", "clkin1"; resets =3D <&reset RESET_SD_EMMC_C>; + + assigned-clocks =3D <&clkc CLKID_SD_EMMC_C_CLK0>; + assigned-clock-rates =3D <24000000>; }; =20 &simplefb_hdmi { diff --git a/arch/arm64/boot/dts/apple/t8112-j473.dts b/arch/arm64/boot/dts= /apple/t8112-j473.dts index 06fe257f08be..4ae1ce919daf 100644 --- a/arch/arm64/boot/dts/apple/t8112-j473.dts +++ b/arch/arm64/boot/dts/apple/t8112-j473.dts @@ -21,6 +21,25 @@ aliases { }; }; =20 +/* + * Keep the power-domains used for the HDMI port on. + */ +&framebuffer0 { + power-domains =3D <&ps_dispext_cpu0>, <&ps_dptx_ext_phy>; +}; + +/* + * The M2 Mac mini uses dispext for the HDMI output so it's not necessary = to + * keep disp0 power-domains always-on. + */ +&ps_disp0_sys { + /delete-property/ apple,always-on; +}; + +&ps_disp0_fe { + /delete-property/ apple,always-on; +}; + /* * Force the bus number assignments so that we can declare some of the * on-board devices and properties that are populated by the bootloader diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/= arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts index 258e90cc16ff..5430b62a3b28 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts @@ -810,7 +810,7 @@ pinctrl_hdmi: hdmigrp { fsl,pins =3D , , , - ; + ; }; =20 pinctrl_hoggpio2: hoggpio2grp { diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boo= t/dts/nvidia/tegra210-smaug.dts index 53805555dd2d..a75c6c1928a4 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -1724,6 +1724,8 @@ usb2-0 { status =3D "okay"; vbus-supply =3D <&usbc_vbus>; mode =3D "otg"; + usb-role-switch; + role-switch-default-mode =3D "host"; }; =20 usb3-0 { diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qco= m/sdm630.dtsi index 0f3f57fb860e..74b36cb8bffa 100644 --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi @@ -589,8 +589,8 @@ qusb2_hstx_trim: hstx-trim@240 { }; =20 gpu_speed_bin: gpu-speed-bin@41a0 { - reg =3D <0x41a2 0x1>; - bits =3D <5 7>; + reg =3D <0x41a2 0x2>; + bits =3D <5 8>; }; }; =20 diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/d= ts/qcom/sdm845-db845c.dts index 0a891a012244..1164f2cf5bc9 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -372,6 +372,12 @@ vreg_l21a_2p95: ldo21 { regulator-initial-mode =3D ; }; =20 + vreg_l23a_3p3: ldo23 { + regulator-min-microvolt =3D <3300000>; + regulator-max-microvolt =3D <3312000>; + regulator-initial-mode =3D ; + }; + vreg_l24a_3p075: ldo24 { regulator-min-microvolt =3D <3088000>; regulator-max-microvolt =3D <3088000>; @@ -852,7 +858,6 @@ &spi0 { status =3D "okay"; pinctrl-names =3D "default"; pinctrl-0 =3D <&qup_spi0_default>; - cs-gpios =3D <&tlmm 3 GPIO_ACTIVE_LOW>; =20 can@0 { compatible =3D "microchip,mcp2517fd"; @@ -1158,6 +1163,7 @@ &wifi { vdd-1.8-xo-supply =3D <&vreg_l7a_1p8>; vdd-1.3-rfa-supply =3D <&vreg_l17a_1p3>; vdd-3.3-ch0-supply =3D <&vreg_l25a_3p3>; + vdd-3.3-ch1-supply =3D <&vreg_l23a_3p3>; =20 qcom,snoc-host-cap-8bit-quirk; qcom,ath10k-calibration-variant =3D "Thundercomm_DB845C"; diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm= 64/boot/dts/qcom/sdm845-oneplus-common.dtsi index bccc52e01da3..e028b58a30f3 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi @@ -155,7 +155,6 @@ ts_1p8_supply: ts-1p8-regulator { =20 gpio =3D <&tlmm 88 0>; enable-active-high; - regulator-boot-on; }; }; =20 @@ -246,6 +245,7 @@ vreg_l12a_1p8: ldo12 { regulator-min-microvolt =3D <1800000>; regulator-max-microvolt =3D <1800000>; regulator-initial-mode =3D ; + regulator-boot-on; }; =20 vreg_l14a_1p88: ldo14 { diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qco= m/sm6115.dtsi index 5c6fcf725473..4c6d30404ff1 100644 --- a/arch/arm64/boot/dts/qcom/sm6115.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi @@ -1336,8 +1336,12 @@ usb_dwc3: usb@4e00000 { =20 gpu: gpu@5900000 { compatible =3D "qcom,adreno-610.0", "qcom,adreno"; - reg =3D <0x0 0x05900000 0x0 0x40000>; - reg-names =3D "kgsl_3d0_reg_memory"; + reg =3D <0x0 0x05900000 0x0 0x40000>, + <0x0 0x0599e000 0x0 0x1000>, + <0x0 0x05961000 0x0 0x800>; + reg-names =3D "kgsl_3d0_reg_memory", + "cx_mem", + "cx_dbgc"; =20 /* There's no (real) GMU, so we have to handle quite a bunch of clocks!= */ clocks =3D <&gpucc GPU_CC_GX_GFX3D_CLK>, diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/ar= m64/boot/dts/rockchip/rk3399-pinebook-pro.dts index fb3012a6c9fc..a1594a436eca 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts @@ -429,10 +429,6 @@ &gpu { status =3D "okay"; }; =20 -&hdmi_sound { - status =3D "okay"; -}; - &i2c0 { clock-frequency =3D <400000>; i2c-scl-falling-time-ns =3D <4>; diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonc= e.h index 56f7b1d4d54b..bd5fc880b909 100644 --- a/arch/arm64/include/asm/rwonce.h +++ b/arch/arm64/include/asm/rwonce.h @@ -62,7 +62,7 @@ default: \ atomic =3D 0; \ } \ - atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(__x))__x);\ + atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\ }) =20 #endif /* !BUILD_VDSO */ diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pac= k.c index 2c81e0efaf37..19518a9da53f 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -896,6 +896,7 @@ static u8 spectre_bhb_loop_affected(void) MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), + MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), {}, }; static const struct midr_range spectre_bhb_k24_list[] =3D { diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c index 5b7890139bc2..15a953ac6f0f 100644 --- a/arch/arm64/lib/delay.c +++ b/arch/arm64/lib/delay.c @@ -23,9 +23,24 @@ static inline unsigned long xloops_to_cycles(unsigned lo= ng xloops) return (xloops * loops_per_jiffy * HZ) >> 32; } =20 +/* + * Force the use of CNTVCT_EL0 in order to have the same base as WFxT. + * This avoids some annoying issues when CNTVOFF_EL2 is not reset 0 on a + * KVM host running at EL1 until we do a vcpu_put() on the vcpu. When + * running at EL2, the effective offset is always 0. + * + * Note that userspace cannot change the offset behind our back either, + * as the vcpu mutex is held as long as KVM_RUN is in progress. + */ +static cycles_t notrace __delay_cycles(void) +{ + guard(preempt_notrace)(); + return __arch_counter_get_cntvct_stable(); +} + void __delay(unsigned long cycles) { - cycles_t start =3D get_cycles(); + cycles_t start =3D __delay_cycles(); =20 if (cpus_have_const_cap(ARM64_HAS_WFXT)) { u64 end =3D start + cycles; @@ -35,17 +50,17 @@ void __delay(unsigned long cycles) * early, use a WFET loop to complete the delay. */ wfit(end); - while ((get_cycles() - start) < cycles) + while ((__delay_cycles() - start) < cycles) wfet(end); } else if (arch_timer_evtstrm_available()) { const cycles_t timer_evt_period =3D USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US); =20 - while ((get_cycles() - start + timer_evt_period) < cycles) + while ((__delay_cycles() - start + timer_evt_period) < cycles) wfe(); } =20 - while ((get_cycles() - start) < cycles) + while ((__delay_cycles() - start) < cycles) cpu_relax(); } EXPORT_SYMBOL(__delay); diff --git a/arch/loongarch/include/asm/topology.h b/arch/loongarch/include= /asm/topology.h index 66128dec0bf6..6ff4cdc3d186 100644 --- a/arch/loongarch/include/asm/topology.h +++ b/arch/loongarch/include/asm/topology.h @@ -11,7 +11,7 @@ =20 extern cpumask_t cpus_on_node[]; =20 -#define cpumask_of_node(node) (&cpus_on_node[node]) +#define cpumask_of_node(node) ((node) =3D=3D NUMA_NO_NODE ? cpu_all_mask = : &cpus_on_node[node]) =20 struct pci_bus; extern int pcibus_to_node(struct pci_bus *); diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 5dfd5d8dfca2..2e34ece474ee 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -432,6 +432,7 @@ static void __init arch_mem_init(char **cmdline_p) PFN_UP(__pa_symbol(&__nosave_end))); =20 memblock_dump_all(); + memblock_set_bottom_up(false); =20 early_memtest(PFN_PHYS(ARCH_PFN_OFFSET), PFN_PHYS(max_low_pfn)); } diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kerne= l/unwind_prologue.c index 929ae240280a..c9ee6892d81c 100644 --- a/arch/loongarch/kernel/unwind_prologue.c +++ b/arch/loongarch/kernel/unwind_prologue.c @@ -64,7 +64,7 @@ static inline bool scan_handlers(unsigned long entry_offs= et) =20 static inline bool fix_exception(unsigned long pc) { -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && !defined(CONFIG_PREEMPT_RT) int cpu; =20 for_each_possible_cpu(cpu) { diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c index 526310ec73c7..885c9fa447ca 100644 --- a/arch/loongarch/mm/tlb.c +++ b/arch/loongarch/mm/tlb.c @@ -201,7 +201,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned = long address, pte_t *ptep local_irq_restore(flags); } =20 -static void setup_ptwalker(void) +static void __no_sanitize_address setup_ptwalker(void) { unsigned long pwctl0, pwctl1; unsigned long pgd_i =3D 0, pgd_w =3D 0; diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c index 6519f7f349f6..e33f00b02e4c 100644 --- a/arch/m68k/lib/memmove.c +++ b/arch/m68k/lib/memmove.c @@ -24,6 +24,15 @@ void *memmove(void *dest, const void *src, size_t n) src =3D csrc; n--; } +#if defined(CONFIG_M68000) + if ((long)src & 1) { + char *cdest =3D dest; + const char *csrc =3D src; + for (; n; n--) + *cdest++ =3D *csrc++; + return xdest; + } +#endif if (n > 2 && (long)dest & 2) { short *sdest =3D dest; const short *ssrc =3D src; @@ -66,6 +75,15 @@ void *memmove(void *dest, const void *src, size_t n) src =3D csrc; n--; } +#if defined(CONFIG_M68000) + if ((long)src & 1) { + char *cdest =3D dest; + const char *csrc =3D src; + for (; n; n--) + *--cdest =3D *--csrc; + return xdest; + } +#endif if (n > 2 && (long)dest & 2) { short *sdest =3D dest; const short *ssrc =3D src; diff --git a/arch/mips/include/asm/mach-loongson64/topology.h b/arch/mips/i= nclude/asm/mach-loongson64/topology.h index 3414a1fd1783..89bb4deab98a 100644 --- a/arch/mips/include/asm/mach-loongson64/topology.h +++ b/arch/mips/include/asm/mach-loongson64/topology.h @@ -7,7 +7,7 @@ #define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2) =20 extern cpumask_t __node_cpumask[]; -#define cpumask_of_node(node) (&__node_cpumask[node]) +#define cpumask_of_node(node) ((node) =3D=3D NUMA_NO_NODE ? cpu_all_mask= : &__node_cpumask[node]) =20 struct pci_bus; extern int pcibus_to_node(struct pci_bus *); diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 6d35d4f7ebe1..55fe0e829549 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -420,7 +420,20 @@ void *__init relocate_kernel(void) goto out; =20 /* The current thread is now within the relocated image */ +#ifndef CONFIG_CC_IS_CLANG __current_thread_info =3D RELOCATED(&init_thread_union); +#else + /* + * LLVM may wrongly restore $gp ($28) in epilog even if it's + * intentionally modified. Work around this by using inline + * assembly to assign $gp. $gp couldn't be listed as output or + * clobber, or LLVM will still restore its original value. + * See also LLVM upstream issue + * https://github.com/llvm/llvm-project/issues/176546 + */ + asm volatile("move $28, %0" : : + "r" (RELOCATED(&init_thread_union))); +#endif =20 /* Return the new kernel's entry point */ kernel_entry =3D RELOCATED(start_kernel); diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index b7f6f782d9a1..ffa4d38ca95d 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -212,11 +212,12 @@ static struct platform_device rb532_wdt =3D { static struct plat_serial8250_port rb532_uart_res[] =3D { { .type =3D PORT_16550A, - .membase =3D (char *)KSEG1ADDR(REGBASE + UART0BASE), + .mapbase =3D REGBASE + UART0BASE, + .mapsize =3D 0x1000, .irq =3D UART0_IRQ, .regshift =3D 2, .iotype =3D UPIO_MEM, - .flags =3D UPF_BOOT_AUTOCONF, + .flags =3D UPF_BOOT_AUTOCONF | UPF_IOREMAP, }, { .flags =3D 0, diff --git a/arch/openrisc/include/asm/barrier.h b/arch/openrisc/include/as= m/barrier.h index 7538294721be..8e592c990902 100644 --- a/arch/openrisc/include/asm/barrier.h +++ b/arch/openrisc/include/asm/barrier.h @@ -4,6 +4,8 @@ =20 #define mb() asm volatile ("l.msync" ::: "memory") =20 +#define nop() asm volatile ("l.nop") + #include =20 #endif /* __ASM_BARRIER_H */ diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 8be4558ef33c..3cfd81c7e112 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -435,7 +435,7 @@ static struct parisc_device * __init create_tree_node(c= har id, dev->dev.dma_mask =3D &dev->dma_mask; dev->dev.coherent_dma_mask =3D dev->dma_mask; if (device_register(&dev->dev)) { - kfree(dev); + put_device(&dev->dev); return NULL; } =20 diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index ed93bd8c1545..d7b0f233f2cc 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -85,6 +85,9 @@ void machine_restart(char *cmd) #endif /* set up a new led state on systems shipped with a LED State panel */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); + + /* prevent interrupts during reboot */ + set_eiem(0); =09 /* "Normal" system reset */ pdc_do_reset(); diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 514dd056c2c8..b5709b9aed23 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -289,6 +289,8 @@ void eeh_pe_dev_traverse(struct eeh_pe *root, void eeh_pe_restore_bars(struct eeh_pe *pe); const char *eeh_pe_loc_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); +const char *eeh_pe_loc_get_bus(struct pci_bus *bus); +struct pci_bus *eeh_pe_bus_get_nolock(struct eeh_pe *pe); =20 void eeh_show_enabled(void); int __init eeh_init(struct eeh_ops *ops); diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index ad7e8c5aec3f..63223b7e520f 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -134,7 +134,6 @@ static __always_inline void kuap_assert_locked(void) =20 static __always_inline void allow_read_from_user(const void __user *from, = unsigned long size) { - barrier_nospec(); allow_user_access(NULL, from, size, KUAP_READ); } =20 @@ -146,7 +145,6 @@ static __always_inline void allow_write_to_user(void __= user *to, unsigned long s static __always_inline void allow_read_write_user(void __user *to, const v= oid __user *from, unsigned long size) { - barrier_nospec(); allow_user_access(to, from, size, KUAP_READ_WRITE); } =20 diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/= uaccess.h index a81bd825087c..ec7f001d03d0 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -290,6 +290,7 @@ do { \ __typeof__(sizeof(*(ptr))) __gu_size =3D sizeof(*(ptr)); \ \ might_fault(); \ + barrier_nospec(); \ allow_read_from_user(__gu_addr, __gu_size); \ __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \ prevent_read_from_user(__gu_addr, __gu_size); \ @@ -318,6 +319,7 @@ raw_copy_in_user(void __user *to, const void __user *fr= om, unsigned long n) { unsigned long ret; =20 + barrier_nospec(); allow_read_write_user(to, from, n); ret =3D __copy_tofrom_user(to, from, n); prevent_read_write_user(to, from, n); @@ -404,6 +406,7 @@ static __must_check __always_inline bool user_access_be= gin(const void __user *pt =20 might_fault(); =20 + barrier_nospec(); allow_read_write_user((void __user *)ptr, ptr, len); return true; } @@ -420,6 +423,7 @@ user_read_access_begin(const void __user *ptr, size_t l= en) =20 might_fault(); =20 + barrier_nospec(); allow_read_from_user(ptr, len); return true; } diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_dri= ver.c index cc8bedf410ea..632bf157636e 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -846,7 +846,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) =20 pci_lock_rescan_remove(); =20 - bus =3D eeh_pe_bus_get(pe); + bus =3D eeh_pe_bus_get_nolock(pe); if (!bus) { pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n", __func__, pe->phb->global_number, pe->addr); @@ -877,14 +877,15 @@ void eeh_handle_normal_event(struct eeh_pe *pe) /* Log the event */ if (pe->type & EEH_PE_PHB) { pr_err("EEH: Recovering PHB#%x, location: %s\n", - pe->phb->global_number, eeh_pe_loc_get(pe)); + pe->phb->global_number, eeh_pe_loc_get_bus(bus)); } else { struct eeh_pe *phb_pe =3D eeh_phb_pe_get(pe->phb); =20 pr_err("EEH: Recovering PHB#%x-PE#%x\n", pe->phb->global_number, pe->addr); pr_err("EEH: PE location: %s, PHB location: %s\n", - eeh_pe_loc_get(pe), eeh_pe_loc_get(phb_pe)); + eeh_pe_loc_get_bus(bus), + eeh_pe_loc_get_bus(eeh_pe_bus_get_nolock(phb_pe))); } =20 #ifdef CONFIG_STACKTRACE @@ -1089,7 +1090,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true); eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); =20 - bus =3D eeh_pe_bus_get(pe); + bus =3D eeh_pe_bus_get_nolock(pe); if (bus) pci_hp_remove_devices(bus); else @@ -1213,7 +1214,7 @@ void eeh_handle_special_event(void) (phb_pe->state & EEH_PE_RECOVERING)) continue; =20 - bus =3D eeh_pe_bus_get(phb_pe); + bus =3D eeh_pe_bus_get_nolock(phb_pe); if (!bus) { pr_err("%s: Cannot find PCI bus for " "PHB#%x-PE#%x\n", diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 08095aeba5c9..b10fcca52040 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -812,6 +812,24 @@ void eeh_pe_restore_bars(struct eeh_pe *pe) const char *eeh_pe_loc_get(struct eeh_pe *pe) { struct pci_bus *bus =3D eeh_pe_bus_get(pe); + return eeh_pe_loc_get_bus(bus); +} + +/** + * eeh_pe_loc_get_bus - Retrieve location code binding to the given PCI bus + * @bus: PCI bus + * + * Retrieve the location code associated with the given PCI bus. If the bus + * is a root bus, the location code is fetched from the PHB device tree no= de + * or root port. Otherwise, the location code is obtained from the device + * tree node of the upstream bridge of the bus. The function walks up the + * bus hierarchy if necessary, checking each node for the appropriate + * location code property ("ibm,io-base-loc-code" for root buses, + * "ibm,slot-location-code" for others). If no location code is found, + * returns "N/A". + */ +const char *eeh_pe_loc_get_bus(struct pci_bus *bus) +{ struct device_node *dn; const char *loc =3D NULL; =20 @@ -838,8 +856,9 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe) } =20 /** - * eeh_pe_bus_get - Retrieve PCI bus according to the given PE + * _eeh_pe_bus_get - Retrieve PCI bus according to the given PE * @pe: EEH PE + * @do_lock: Is the caller already held the pci_lock_rescan_remove? * * Retrieve the PCI bus according to the given PE. Basically, * there're 3 types of PEs: PHB/Bus/Device. For PHB PE, the @@ -847,7 +866,7 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe) * returned for BUS PE. However, we don't have associated PCI * bus for DEVICE PE. */ -struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) +static struct pci_bus *_eeh_pe_bus_get(struct eeh_pe *pe, bool do_lock) { struct eeh_dev *edev; struct pci_dev *pdev; @@ -862,11 +881,58 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) =20 /* Retrieve the parent PCI bus of first (top) PCI device */ edev =3D list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); - pci_lock_rescan_remove(); + if (do_lock) + pci_lock_rescan_remove(); pdev =3D eeh_dev_to_pci_dev(edev); if (pdev) bus =3D pdev->bus; - pci_unlock_rescan_remove(); + if (do_lock) + pci_unlock_rescan_remove(); =20 return bus; } + +/** + * eeh_pe_bus_get - Retrieve PCI bus associated with the given EEH PE, loc= king + * if needed + * @pe: Pointer to the EEH PE + * + * This function is a wrapper around _eeh_pe_bus_get(), which retrieves th= e PCI + * bus associated with the provided EEH PE structure. It acquires the PCI + * rescans lock to ensure safe access to shared data during the retrieval + * process. This function should be used when the caller requires the PCI = bus + * while holding the rescan/remove lock, typically during operations that = modify + * or inspect PCIe device state in a safe manner. + * + * RETURNS: + * A pointer to the PCI bus associated with the EEH PE, or NULL if none fo= und. + */ + +struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) +{ + return _eeh_pe_bus_get(pe, true); +} + +/** + * eeh_pe_bus_get_nolock - Retrieve PCI bus associated with the given EEH = PE + * without locking + * @pe: Pointer to the EEH PE + * + * This function is a variant of _eeh_pe_bus_get() that retrieves the PCI = bus + * associated with the specified EEH PE without acquiring the + * pci_lock_rescan_remove lock. It should only be used when the caller can + * guarantee safe access to PE structures without the need for that lock, + * typically in contexts where the lock is already held locking is otherwi= se + * managed. + * + * RETURNS: + * pointer to the PCI bus associated with the EEH PE, or NULL if none is f= ound. + * + * NOTE: + * Use this function carefully to avoid race conditions and data corruptio= n. + */ + +struct pci_bus *eeh_pe_bus_get_nolock(struct eeh_pe *pe) +{ + return _eeh_pe_bus_get(pe, false); +} diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 4e4870031265..ab99a3e7f997 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -830,6 +830,8 @@ static int parse_thread_groups(struct device_node *dn, =20 count =3D of_property_count_u32_elems(dn, "ibm,thread-groups"); thread_group_array =3D kcalloc(count, sizeof(u32), GFP_KERNEL); + if (!thread_group_array) + return -ENOMEM; ret =3D of_property_read_u32_array(dn, "ibm,thread-groups", thread_group_array, count); if (ret) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e99dae26500d..3b2625eb34c5 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -231,6 +231,7 @@ config S390 select SPARSE_IRQ select SWIOTLB select SYSCTL_EXCEPTION_TRACE + select SYSTEM_DATA_VERIFICATION if KEXEC_SIG select THREAD_INFO_IN_TASK select TRACE_IRQFLAGS_SUPPORT select TTY @@ -254,7 +255,7 @@ config ARCH_SUPPORTS_KEXEC_FILE def_bool y =20 config ARCH_SUPPORTS_KEXEC_SIG - def_bool MODULE_SIG_FORMAT + def_bool y =20 config ARCH_SUPPORTS_KEXEC_PURGATORY def_bool y diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_s= f.c index e52c89739bc9..c6cac49f3ae7 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -925,7 +925,7 @@ static bool is_callchain_event(struct perf_event *event) u64 sample_type =3D event->attr.sample_type; =20 return sample_type & (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | - PERF_SAMPLE_STACK_USER); + PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_STACK_USER); } =20 static int cpumsf_pmu_event_init(struct perf_event *event) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 777362cb4ea8..d4c7c4ef102d 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -206,24 +206,33 @@ int zpci_fmb_disable_device(struct zpci_dev *zdev) static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 l= en) { u64 req =3D ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); + int rc =3D -ENODEV; u64 data; - int rc; + + if (!zdev_enabled(zdev)) + goto out_err; =20 rc =3D __zpci_load(&data, req, offset); - if (!rc) { - data =3D le64_to_cpu((__force __le64) data); - data >>=3D (8 - len) * 8; - *val =3D (u32) data; - } else - *val =3D 0xffffffff; + if (rc) + goto out_err; + data =3D le64_to_cpu((__force __le64)data); + data >>=3D (8 - len) * 8; + *val =3D (u32)data; + return 0; + +out_err: + PCI_SET_ERROR_RESPONSE(val); return rc; } =20 static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 l= en) { u64 req =3D ZPCI_CREATE_REQ(zdev->fh, ZPCI_PCIAS_CFGSPC, len); + int rc =3D -ENODEV; u64 data =3D val; - int rc; + + if (!zdev_enabled(zdev)) + return rc; =20 data <<=3D (8 - len) * 8; data =3D (__force u64) cpu_to_le64(data); diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index fe7e71f91711..0cbfa716a64a 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -29,6 +29,7 @@ KBUILD_CFLAGS +=3D -fno-stack-protector KBUILD_CFLAGS +=3D -DDISABLE_BRANCH_PROFILING KBUILD_CFLAGS +=3D $(CLANG_FLAGS) KBUILD_CFLAGS +=3D $(call cc-option,-fno-PIE) +KBUILD_CFLAGS +=3D $(call cc-option, -Wno-default-const-init-unsafe) KBUILD_AFLAGS :=3D $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS)) =20 # Since we link purgatory with -r unresolved symbols are not checked, so we diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi= /asm/ioctls.h index 7fd2f5873c9e..a8bbdf9877a4 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -5,10 +5,10 @@ #include =20 /* Big T */ -#define TCGETA _IOR('T', 1, struct termio) -#define TCSETA _IOW('T', 2, struct termio) -#define TCSETAW _IOW('T', 3, struct termio) -#define TCSETAF _IOW('T', 4, struct termio) +#define TCGETA 0x40125401 /* _IOR('T', 1, struct termio) */ +#define TCSETA 0x80125402 /* _IOW('T', 2, struct termio) */ +#define TCSETAW 0x80125403 /* _IOW('T', 3, struct termio) */ +#define TCSETAF 0x80125404 /* _IOW('T', 4, struct termio) */ #define TCSBRK _IO('T', 5) #define TCXONC _IO('T', 6) #define TCFLSH _IO('T', 7) diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 0442ab00518d..7d69877511fa 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -17,14 +17,18 @@ =20 asmlinkage long sparc_fork(struct pt_regs *regs) { - unsigned long orig_i1 =3D regs->u_regs[UREG_I1]; + unsigned long orig_i1; long ret; struct kernel_clone_args args =3D { .exit_signal =3D SIGCHLD, - /* Reuse the parent's stack for the child. */ - .stack =3D regs->u_regs[UREG_FP], }; =20 + synchronize_user_stack(); + + orig_i1 =3D regs->u_regs[UREG_I1]; + /* Reuse the parent's stack for the child. */ + args.stack =3D regs->u_regs[UREG_FP]; + ret =3D kernel_clone(&args); =20 /* If we get an error and potentially restart the system @@ -40,16 +44,19 @@ asmlinkage long sparc_fork(struct pt_regs *regs) =20 asmlinkage long sparc_vfork(struct pt_regs *regs) { - unsigned long orig_i1 =3D regs->u_regs[UREG_I1]; + unsigned long orig_i1; long ret; - struct kernel_clone_args args =3D { .flags =3D CLONE_VFORK | CLONE_VM, .exit_signal =3D SIGCHLD, - /* Reuse the parent's stack for the child. */ - .stack =3D regs->u_regs[UREG_FP], }; =20 + synchronize_user_stack(); + + orig_i1 =3D regs->u_regs[UREG_I1]; + /* Reuse the parent's stack for the child. */ + args.stack =3D regs->u_regs[UREG_FP]; + ret =3D kernel_clone(&args); =20 /* If we get an error and potentially restart the system @@ -65,15 +72,18 @@ asmlinkage long sparc_vfork(struct pt_regs *regs) =20 asmlinkage long sparc_clone(struct pt_regs *regs) { - unsigned long orig_i1 =3D regs->u_regs[UREG_I1]; - unsigned int flags =3D lower_32_bits(regs->u_regs[UREG_I0]); + unsigned long orig_i1; + unsigned int flags; long ret; + struct kernel_clone_args args =3D {0}; =20 - struct kernel_clone_args args =3D { - .flags =3D (flags & ~CSIGNAL), - .exit_signal =3D (flags & CSIGNAL), - .tls =3D regs->u_regs[UREG_I3], - }; + synchronize_user_stack(); + + orig_i1 =3D regs->u_regs[UREG_I1]; + flags =3D lower_32_bits(regs->u_regs[UREG_I0]); + args.flags =3D (flags & ~CSIGNAL); + args.exit_signal =3D (flags & CSIGNAL); + args.tls =3D regs->u_regs[UREG_I3]; =20 #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index b12bef0ff7bb..4b91b41df520 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -68,7 +68,7 @@ static void hv_vtl_ap_entry(void) =20 static int hv_vtl_bringup_vcpu(u32 target_vp_index, int cpu, u64 eip_ignor= ed) { - u64 status; + u64 status, rsp, rip; int ret =3D 0; struct hv_enable_vp_vtl *input; unsigned long irq_flags; @@ -81,9 +81,11 @@ static int hv_vtl_bringup_vcpu(u32 target_vp_index, int = cpu, u64 eip_ignored) struct desc_struct *gdt; =20 struct task_struct *idle =3D idle_thread_get(cpu); - u64 rsp =3D (unsigned long)idle->thread.sp; + if (IS_ERR(idle)) + return PTR_ERR(idle); =20 - u64 rip =3D (u64)&hv_vtl_ap_entry; + rsp =3D (unsigned long)idle->thread.sp; + rip =3D (u64)&hv_vtl_ap_entry; =20 native_store_gdt(&gdt_ptr); store_idt(&idt_ptr); diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzim= age64.c index a61c12c01270..b1f10084474a 100644 --- a/arch/x86/kernel/kexec-bzimage64.c +++ b/arch/x86/kernel/kexec-bzimage64.c @@ -184,6 +184,13 @@ setup_efi_state(struct boot_params *params, unsigned l= ong params_load_addr, struct efi_info *current_ei =3D &boot_params.efi_info; struct efi_info *ei =3D ¶ms->efi_info; =20 + if (!params->acpi_rsdp_addr) { + if (efi.acpi20 !=3D EFI_INVALID_TABLE_ADDR) + params->acpi_rsdp_addr =3D efi.acpi20; + else if (efi.acpi !=3D EFI_INVALID_TABLE_ADDR) + params->acpi_rsdp_addr =3D efi.acpi; + } + if (!efi_enabled(EFI_RUNTIME_SERVICES)) return 0; =20 diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 97ec7781eb67..eebfea132285 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1758,10 +1758,9 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, * thus MMU might not be initialized correctly. * Set it again to fix this. */ - ret =3D nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, nested_npt_enabled(svm), false); - if (WARN_ON_ONCE(ret)) + if (ret) goto out_free; =20 svm->nested.force_msr_bitmap_recalc =3D true; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index dd4236a6bd94..9ddd1ee5f312 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2299,12 +2299,13 @@ static int vmload_vmsave_interception(struct kvm_vc= pu *vcpu, bool vmload) =20 ret =3D kvm_skip_emulated_instruction(vcpu); =20 + /* KVM always performs VMLOAD/VMSAVE on VMCB01 (see __svm_vcpu_run()) */ if (vmload) { - svm_copy_vmloadsave_state(svm->vmcb, vmcb12); + svm_copy_vmloadsave_state(svm->vmcb01.ptr, vmcb12); svm->sysenter_eip_hi =3D 0; svm->sysenter_esp_hi =3D 0; } else { - svm_copy_vmloadsave_state(vmcb12, svm->vmcb); + svm_copy_vmloadsave_state(vmcb12, svm->vmcb01.ptr); } =20 kvm_vcpu_unmap(vcpu, &map, true); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 89df215ebf28..00bbee40dbec 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -11437,9 +11437,11 @@ static void __get_sregs2(struct kvm_vcpu *vcpu, st= ruct kvm_sregs2 *sregs2) return; =20 if (is_pae_paging(vcpu)) { + kvm_vcpu_srcu_read_lock(vcpu); for (i =3D 0 ; i < 4 ; i++) sregs2->pdptrs[i] =3D kvm_pdptr_read(vcpu, i); sregs2->flags |=3D KVM_SREGS2_FLAGS_PDPTRS_VALID; + kvm_vcpu_srcu_read_unlock(vcpu); } } =20 diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S index fc46b4dfbd74..10deae1a30c6 100644 --- a/arch/x86/platform/pvh/head.S +++ b/arch/x86/platform/pvh/head.S @@ -70,10 +70,12 @@ SYM_CODE_START_LOCAL(pvh_start_xen) =20 mov $_pa(early_stack_end), %esp =20 +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) /* Enable PAE mode. */ mov %cr4, %eax orl $X86_CR4_PAE, %eax mov %eax, %cr4 +#endif =20 #ifdef CONFIG_X86_64 /* Enable Long mode. */ diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 638de313fc4e..03fb16dc0b92 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -480,7 +480,7 @@ int __init arch_xen_unpopulated_init(struct resource **= res) * driver to know how much of the physmap is unpopulated and * set an accurate initial memory target. */ - xen_released_pages +=3D xen_extra_mem[i].n_pfns; + xen_unpopulated_pages +=3D xen_extra_mem[i].n_pfns; /* Zero so region is not also added to the balloon driver. */ xen_extra_mem[i].n_pfns =3D 0; } diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 6e4c6bd62203..11fa577af6b4 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -17,10 +17,6 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned l= ong mfn); =20 void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); =20 -pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long= addr, pte_t *ptep); -void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned lon= g addr, - pte_t *ptep, pte_t pte); - unsigned long xen_read_cr2_direct(void); =20 extern void xen_init_mmu_ops(void); diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 88a722954f3f..23f30ca52816 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -173,7 +173,7 @@ static int alloc_discontig_frames(unsigned int order) * looking at another vcpu's cr3 value, it should use this variable. */ DEFINE_PER_CPU(unsigned long, xen_cr3); /* cr3 stored as physaddr */ -DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ +static DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 = */ =20 static phys_addr_t xen_pt_base, xen_pt_size __initdata; =20 @@ -350,16 +350,17 @@ static void xen_set_pte(pte_t *ptep, pte_t pteval) __xen_set_pte(ptep, pteval); } =20 -pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep) +static pte_t xen_ptep_modify_prot_start(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) { /* Just return the pte as-is. We preserve the bits on commit */ trace_xen_mmu_ptep_modify_prot_start(vma->vm_mm, addr, ptep, *ptep); return *ptep; } =20 -void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long= addr, - pte_t *ptep, pte_t pte) +static void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, + unsigned long addr, + pte_t *ptep, pte_t pte) { struct mmu_update u; =20 diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 607f3a42fe3b..af418489335c 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -23,7 +23,6 @@ void xen_copy_trap_info(struct trap_info *traps); =20 DECLARE_PER_CPU_ALIGNED(struct vcpu_info, xen_vcpu_info); DECLARE_PER_CPU(unsigned long, xen_cr3); -DECLARE_PER_CPU(unsigned long, xen_current_cr3); =20 extern struct start_info *xen_start_info; extern struct shared_info xen_dummy_shared_info; diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c index c3b5930106b2..e0677043f00d 100644 --- a/block/blk-mq-debugfs.c +++ b/block/blk-mq-debugfs.c @@ -730,8 +730,10 @@ void blk_mq_debugfs_register_hctxs(struct request_queu= e *q) struct blk_mq_hw_ctx *hctx; unsigned long i; =20 + mutex_lock(&q->debugfs_mutex); queue_for_each_hw_ctx(q, hctx, i) blk_mq_debugfs_register_hctx(q, hctx); + mutex_unlock(&q->debugfs_mutex); } =20 void blk_mq_debugfs_unregister_hctxs(struct request_queue *q) diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index c0f9cf9768ea..5e409f86f070 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -39,6 +39,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *de= v) { u8 value1 =3D 0; u8 value2 =3D 0; + struct pci_dev *ide_dev =3D NULL, *isa_dev =3D NULL; =20 =20 if (!dev) @@ -96,12 +97,12 @@ static int acpi_processor_errata_piix4(struct pci_dev *= dev) * each IDE controller's DMA status to make sure we catch all * DMA activity. */ - dev =3D pci_get_subsys(PCI_VENDOR_ID_INTEL, + ide_dev =3D pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - errata.piix4.bmisx =3D pci_resource_start(dev, 4); - pci_dev_put(dev); + if (ide_dev) { + errata.piix4.bmisx =3D pci_resource_start(ide_dev, 4); + pci_dev_put(ide_dev); } =20 /* @@ -113,24 +114,25 @@ static int acpi_processor_errata_piix4(struct pci_dev= *dev) * disable C3 support if this is enabled, as some legacy * devices won't operate well if fast DMA is disabled. */ - dev =3D pci_get_subsys(PCI_VENDOR_ID_INTEL, + isa_dev =3D pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - pci_read_config_byte(dev, 0x76, &value1); - pci_read_config_byte(dev, 0x77, &value2); + if (isa_dev) { + pci_read_config_byte(isa_dev, 0x76, &value1); + pci_read_config_byte(isa_dev, 0x77, &value2); if ((value1 & 0x80) || (value2 & 0x80)) errata.piix4.fdma =3D 1; - pci_dev_put(dev); + pci_dev_put(isa_dev); } =20 break; } =20 - if (errata.piix4.bmisx) - dev_dbg(&dev->dev, "Bus master activity detection (BM-IDE) erratum enabl= ed\n"); - if (errata.piix4.fdma) - dev_dbg(&dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); + if (ide_dev) + dev_dbg(&ide_dev->dev, "Bus master activity detection (BM-IDE) erratum e= nabled\n"); + + if (isa_dev) + dev_dbg(&isa_dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); =20 return 0; } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index cf53b9535f18..7788c27ccf46 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -163,7 +163,9 @@ acpi_ev_address_space_dispatch(union acpi_operand_objec= t *region_obj, return_ACPI_STATUS(AE_NOT_EXIST); } =20 - if (region_obj->region.space_id =3D=3D ACPI_ADR_SPACE_PLATFORM_COMM) { + if (field_obj + && region_obj->region.space_id =3D=3D + ACPI_ADR_SPACE_PLATFORM_COMM) { struct acpi_pcc_info *ctx =3D handler_desc->address_space.context; =20 diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index d3091f619909..41758343657d 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -10,6 +10,7 @@ #include #include "accommon.h" #include "acinterp.h" +#include #include "acparser.h" #include "amlcode.h" =20 @@ -51,8 +52,7 @@ ACPI_MODULE_NAME("exoparg3") acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) { union acpi_operand_object **operand =3D &walk_state->operands[0]; - struct acpi_signal_fatal_info *fatal; - acpi_status status =3D AE_OK; + struct acpi_signal_fatal_info fatal; =20 ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); @@ -60,28 +60,23 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_st= ate *walk_state) switch (walk_state->opcode) { case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ =20 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "FatalOp: Type %X Code %X Arg %X " - "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", - (u32)operand[0]->integer.value, - (u32)operand[1]->integer.value, - (u32)operand[2]->integer.value)); - - fatal =3D ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); - if (fatal) { - fatal->type =3D (u32) operand[0]->integer.value; - fatal->code =3D (u32) operand[1]->integer.value; - fatal->argument =3D (u32) operand[2]->integer.value; - } + fatal.type =3D (u32)operand[0]->integer.value; + fatal.code =3D (u32)operand[1]->integer.value; + fatal.argument =3D (u32)operand[2]->integer.value; =20 - /* Always signal the OS! */ + ACPI_BIOS_ERROR((AE_INFO, + "Fatal ACPI BIOS error (Type 0x%X Code 0x%X Arg 0x%X)\n", + fatal.type, fatal.code, fatal.argument)); =20 - status =3D acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); + /* Always signal the OS! */ =20 - /* Might return while OS is shutting down, just continue */ + acpi_os_signal(ACPI_SIGNAL_FATAL, &fatal); =20 - ACPI_FREE(fatal); - goto cleanup; + /* + * Might return while OS is shutting down, so abort the AML execution + * by returning an error. + */ + return_ACPI_STATUS(AE_ERROR); =20 case AML_EXTERNAL_OP: /* @@ -93,21 +88,16 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_st= ate *walk_state) * wrong if an external opcode ever gets here. */ ACPI_ERROR((AE_INFO, "Executed External Op")); - status =3D AE_OK; - goto cleanup; + + return_ACPI_STATUS(AE_OK); =20 default: =20 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); =20 - status =3D AE_AML_BAD_OPCODE; - goto cleanup; + return_ACPI_STATUS(AE_AML_BAD_OPCODE); } - -cleanup: - - return_ACPI_STATUS(status); } =20 /*************************************************************************= ****** diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index e768dfd345fb..9c0d256fc72b 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -290,6 +291,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *= generic) error_block_length =3D GHES_ESTATUS_MAX_SIZE; } ghes->estatus =3D kmalloc(error_block_length, GFP_KERNEL); + ghes->estatus_length =3D error_block_length; if (!ghes->estatus) { rc =3D -ENOMEM; goto err_unmap_status_addr; @@ -361,13 +363,15 @@ static int __ghes_check_estatus(struct ghes *ghes, struct acpi_hest_generic_status *estatus) { u32 len =3D cper_estatus_len(estatus); + u32 max_len =3D min(ghes->generic->error_block_length, + ghes->estatus_length); =20 if (len < sizeof(*estatus)) { pr_warn_ratelimited(FW_WARN GHES_PFX "Truncated error status block!\n"); return -EIO; } =20 - if (len > ghes->generic->error_block_length) { + if (!len || len > max_len) { pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid error status block length!= \n"); return -EIO; } diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 16ac219ae6fe..0bf3861cf79b 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -347,7 +347,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd) end: if (cmd =3D=3D CMD_WRITE) { if (unlikely(ret)) { - for_each_possible_cpu(i) { + for_each_online_cpu(i) { struct cpc_desc *desc =3D per_cpu(cpc_desc_ptr, i); =20 if (!desc) @@ -509,7 +509,7 @@ int acpi_get_psd_map(unsigned int cpu, struct cppc_cpud= ata *cpu_data) else if (pdomain->coord_type =3D=3D DOMAIN_COORD_TYPE_SW_ANY) cpu_data->shared_type =3D CPUFREQ_SHARED_TYPE_ANY; =20 - for_each_possible_cpu(i) { + for_each_online_cpu(i) { if (i =3D=3D cpu) continue; =20 diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c2c70139c4f1..ff5fcd541e50 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1035,6 +1035,19 @@ static const struct dmi_system_id dmi_leave_unused_p= ower_resources_on[] =3D { DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), }, }, + { + /* + * THUNDEROBOT ZERO laptop: Due to its SSDT table bug, power + * resource 'PXP' will be shut down on initialization, making + * the NVMe #2 and the NVIDIA dGPU both unavailable (they're + * both controlled by 'PXP'). + */ + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "THUNDEROBOT"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZERO"), + } + + }, {} }; =20 diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 43f11f66970b..73408a5b45b3 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -4211,7 +4211,7 @@ static int binder_thread_write(struct binder_proc *pr= oc, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", + "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", proc->pid, thread->pid, (u64)cookie, death); if (death =3D=3D NULL) { diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 34c27223cb7d..6a4be6087ae6 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -79,7 +79,7 @@ static void binder_insert_free_buffer(struct binder_alloc= *alloc, new_buffer_size =3D binder_alloc_buffer_size(alloc, new_buffer); =20 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: add free buffer, size %zd, at %pK\n", + "%d: add free buffer, size %zd, at %p\n", alloc->pid, new_buffer_size, new_buffer); =20 while (*p) { @@ -474,7 +474,7 @@ static struct binder_buffer *binder_alloc_new_buf_locke= d( } =20 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", + "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", alloc->pid, size, buffer, buffer_size); =20 has_page_addr =3D (void __user *) @@ -646,7 +646,7 @@ static void binder_free_buf_locked(struct binder_alloc = *alloc, ALIGN(buffer->extra_buffers_size, sizeof(void *)); =20 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, - "%d: binder_free_buf %pK size %zd buffer_size %zd\n", + "%d: binder_free_buf %p size %zd buffer_size %zd\n", alloc->pid, buffer, size, buffer_size); =20 BUG_ON(buffer->free); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d5e713f284b7..91c6291b01f4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2318,6 +2318,24 @@ static bool ata_dev_check_adapter(struct ata_device = *dev, return false; } =20 +bool ata_adapter_is_online(struct ata_port *ap) +{ + struct device *dev; + + if (!ap || !ap->host) + return false; + + dev =3D ap->host->dev; + if (!dev) + return false; + + if (dev_is_pci(dev) && + pci_channel_offline(to_pci_dev(dev))) + return false; + + return true; +} + static int ata_dev_config_ncq(struct ata_device *dev, char *desc, size_t desc_sz) { @@ -5023,6 +5041,12 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags |=3D ATA_QCFLAG_ACTIVE; ap->qc_active |=3D 1ULL << qc->tag; =20 + /* Make sure the device is still accessible. */ + if (!ata_adapter_is_online(ap)) { + qc->err_mask |=3D AC_ERR_HOST_BUS; + goto sys_err; + } + /* * We guarantee to LLDs that they will have at least one * non-zero sg if the command is a data command. diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 3263fc13491e..fc2c508c41bd 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -723,7 +723,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host= , struct ata_port *ap) spin_unlock_irqrestore(ap->lock, flags); =20 /* invoke EH, skip if unloading or suspended */ - if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) + if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)) && + ata_adapter_is_online(ap)) ap->ops->error_handler(ap); else { /* if unloading, commence suicide */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8f6a7acf770e..300818cb1478 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1736,6 +1736,42 @@ static void ata_scsi_qc_complete(struct ata_queued_c= md *qc) ata_qc_done(qc); } =20 +static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *q= c) +{ + int ret; + + if (!ap->ops->qc_defer) + goto issue; + + /* Check if the command needs to be deferred. */ + ret =3D ap->ops->qc_defer(qc); + switch (ret) { + case 0: + break; + case ATA_DEFER_LINK: + ret =3D SCSI_MLQUEUE_DEVICE_BUSY; + break; + case ATA_DEFER_PORT: + ret =3D SCSI_MLQUEUE_HOST_BUSY; + break; + default: + WARN_ON_ONCE(1); + ret =3D SCSI_MLQUEUE_HOST_BUSY; + break; + } + + if (ret) { + /* Force a requeue of the command to defer its execution. */ + ata_qc_free(qc); + return ret; + } + +issue: + ata_qc_issue(qc); + + return 0; +} + /** * ata_scsi_translate - Translate then issue SCSI command to ATA device * @dev: ATA device to which the command is addressed @@ -1759,66 +1795,49 @@ static void ata_scsi_qc_complete(struct ata_queued_= cmd *qc) * spin_lock_irqsave(host lock) * * RETURNS: - * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command - * needs to be deferred. + * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY or SCSI_MLQUEUE_HOST_BUSY if the + * command needs to be deferred. */ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cm= d, ata_xlat_func_t xlat_func) { struct ata_port *ap =3D dev->link->ap; struct ata_queued_cmd *qc; - int rc; =20 + lockdep_assert_held(ap->lock); + + /* + * ata_scsi_qc_new() calls scsi_done(cmd) in case of failure. So we + * have nothing further to do when allocating a qc fails. + */ qc =3D ata_scsi_qc_new(dev, cmd); if (!qc) - goto err_mem; + return 0; =20 /* data is present; dma-map it */ if (cmd->sc_data_direction =3D=3D DMA_FROM_DEVICE || cmd->sc_data_direction =3D=3D DMA_TO_DEVICE) { if (unlikely(scsi_bufflen(cmd) < 1)) { ata_dev_warn(dev, "WARNING: zero len r/w req\n"); - goto err_did; + cmd->result =3D (DID_ERROR << 16); + goto done; } =20 ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd)); - qc->dma_dir =3D cmd->sc_data_direction; } =20 qc->complete_fn =3D ata_scsi_qc_complete; =20 if (xlat_func(qc)) - goto early_finish; - - if (ap->ops->qc_defer) { - if ((rc =3D ap->ops->qc_defer(qc))) - goto defer; - } + goto done; =20 - /* select device, send command to hardware */ - ata_qc_issue(qc); + return ata_scsi_qc_issue(ap, qc); =20 - return 0; - -early_finish: +done: ata_qc_free(qc); scsi_done(cmd); return 0; - -err_did: - ata_qc_free(qc); - cmd->result =3D (DID_ERROR << 16); - scsi_done(cmd); -err_mem: - return 0; - -defer: - ata_qc_free(qc); - if (rc =3D=3D ATA_DEFER_LINK) - return SCSI_MLQUEUE_DEVICE_BUSY; - else - return SCSI_MLQUEUE_HOST_BUSY; } =20 struct ata_scsi_args { @@ -2867,6 +2886,9 @@ ata_scsi_find_dev(struct ata_port *ap, const struct s= csi_device *scsidev) { struct ata_device *dev =3D __ata_scsi_find_dev(ap, scsidev); =20 + if (!ata_adapter_is_online(ap)) + return NULL; + if (unlikely(!dev || !ata_dev_enabled(dev))) return NULL; =20 diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 05ac80da8ebc..9927d79e5587 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -75,6 +75,7 @@ extern int atapi_check_dma(struct ata_queued_cmd *qc); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); extern bool ata_phys_link_online(struct ata_link *link); extern bool ata_phys_link_offline(struct ata_link *link); +bool ata_adapter_is_online(struct ata_port *ap); extern void ata_dev_init(struct ata_device *dev); extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int = pmp); extern int sata_link_init_spd(struct ata_link *link); diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c index 4d6ef90ccc77..3e6c82f68ab9 100644 --- a/drivers/ata/pata_ftide010.c +++ b/drivers/ata/pata_ftide010.c @@ -122,10 +122,10 @@ static const u8 mwdma_50_active_time[3] =3D {6, 2, 2}; static const u8 mwdma_50_recovery_time[3] =3D {6, 2, 1}; static const u8 mwdma_66_active_time[3] =3D {8, 3, 3}; static const u8 mwdma_66_recovery_time[3] =3D {8, 2, 1}; -static const u8 udma_50_setup_time[6] =3D {3, 3, 2, 2, 1, 1}; +static const u8 udma_50_setup_time[6] =3D {3, 3, 2, 2, 1, 9}; static const u8 udma_50_hold_time[6] =3D {3, 1, 1, 1, 1, 1}; -static const u8 udma_66_setup_time[7] =3D {4, 4, 3, 2, }; -static const u8 udma_66_hold_time[7] =3D {}; +static const u8 udma_66_setup_time[7] =3D {4, 4, 3, 2, 1, 9, 9}; +static const u8 udma_66_hold_time[7] =3D {4, 2, 1, 1, 1, 1, 1}; =20 /* * We set 66 MHz for all MWDMA modes diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b57faf6dc327..ca3051e0023e 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -376,6 +376,10 @@ fore200e_shutdown(struct fore200e* fore200e) fallthrough; case FORE200E_STATE_IRQ: free_irq(fore200e->irq, fore200e->atm_dev); +#ifdef FORE200E_USE_TASKLET + tasklet_kill(&fore200e->tx_tasklet); + tasklet_kill(&fore200e->rx_tasklet); +#endif =20 fallthrough; case FORE200E_STATE_ALLOC_BUF: diff --git a/drivers/auxdisplay/arm-charlcd.c b/drivers/auxdisplay/arm-char= lcd.c index 0b1c99cca733..f418b133ee75 100644 --- a/drivers/auxdisplay/arm-charlcd.c +++ b/drivers/auxdisplay/arm-charlcd.c @@ -323,7 +323,7 @@ static int __init charlcd_probe(struct platform_device = *pdev) out_no_irq: iounmap(lcd->virtbase); out_no_memregion: - release_mem_region(lcd->phybase, SZ_4K); + release_mem_region(lcd->phybase, lcd->physize); out_no_resource: kfree(lcd); return ret; diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index 5a5a9e978e85..ddbe9cc91d23 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -83,13 +83,16 @@ EXPORT_SYMBOL_GPL(dev_pm_set_wake_irq); */ void dev_pm_clear_wake_irq(struct device *dev) { - struct wake_irq *wirq =3D dev->power.wakeirq; + struct wake_irq *wirq; unsigned long flags; =20 - if (!wirq) + spin_lock_irqsave(&dev->power.lock, flags); + wirq =3D dev->power.wakeirq; + if (!wirq) { + spin_unlock_irqrestore(&dev->power.lock, flags); return; + } =20 - spin_lock_irqsave(&dev->power.lock, flags); device_wakeup_detach_irq(dev); dev->power.wakeirq =3D NULL; spin_unlock_irqrestore(&dev->power.lock, flags); diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index a917219feea6..eae81def0902 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -280,9 +280,7 @@ EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock); */ struct wakeup_source *wakeup_sources_walk_start(void) { - struct list_head *ws_head =3D &wakeup_sources; - - return list_entry_rcu(ws_head->next, struct wakeup_source, entry); + return list_first_or_null_rcu(&wakeup_sources, struct wakeup_source, entr= y); } EXPORT_SYMBOL_GPL(wakeup_sources_walk_start); =20 diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c index b67e39a34010..ebc0f4c09105 100644 --- a/drivers/block/rnbd/rnbd-srv.c +++ b/drivers/block/rnbd/rnbd-srv.c @@ -536,6 +536,8 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_= open_rsp *rsp, { struct block_device *bdev =3D sess_dev->bdev; =20 + memset(rsp, 0, sizeof(*rsp)); + rsp->hdr.type =3D cpu_to_le16(RNBD_MSG_OPEN_RSP); rsp->device_id =3D cpu_to_le32(sess_dev->device_id); rsp->nsectors =3D cpu_to_le64(bdev_nr_sectors(bdev)); @@ -641,6 +643,7 @@ static void process_msg_sess_info(struct rnbd_srv_sessi= on *srv_sess, =20 trace_process_msg_sess_info(srv_sess, sess_info_msg); =20 + memset(rsp, 0, sizeof(*rsp)); rsp->hdr.type =3D cpu_to_le16(RNBD_MSG_SESS_INFO_RSP); rsp->ver =3D srv_sess->ver; } diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 44f630a3f610..89c1d6ec7ada 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -2908,10 +2908,10 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd = *cmd, if (issue_flags & IO_URING_F_NONBLOCK) return -EAGAIN; =20 - ublk_ctrl_cmd_dump(cmd); - if (!(issue_flags & IO_URING_F_SQE128)) - goto out; + return -EINVAL; + + ublk_ctrl_cmd_dump(cmd); =20 ret =3D ublk_check_cmd_op(cmd_op); if (ret) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index eaeacdadb202..168e46ce5997 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -548,6 +548,8 @@ static const struct usb_device_id quirks_table[] =3D { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3592), .driver_info =3D BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3612), .driver_info =3D BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe122), .driver_info =3D BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, =20 @@ -719,6 +721,7 @@ static const struct usb_device_id quirks_table[] =3D { =20 /* Additional Realtek 8723BU Bluetooth devices */ { USB_DEVICE(0x7392, 0xa611), .driver_info =3D BTUSB_REALTEK }, + { USB_DEVICE(0x2c0a, 0x8761), .driver_info =3D BTUSB_REALTEK }, =20 /* Additional Realtek 8723DE Bluetooth devices */ { USB_DEVICE(0x0bda, 0xb009), .driver_info =3D BTUSB_REALTEK }, diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 9c6f79d86053..cdad817e632c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1959,19 +1959,23 @@ static int qca_setup(struct hci_uart *hu) } =20 out: - if (ret && retries < MAX_INIT_RETRIES) { - bt_dev_warn(hdev, "Retry BT power ON:%d", retries); + if (ret) { qca_power_shutdown(hu); - if (hu->serdev) { - serdev_device_close(hu->serdev); - ret =3D serdev_device_open(hu->serdev); - if (ret) { - bt_dev_err(hdev, "failed to open port"); - return ret; + + if (retries < MAX_INIT_RETRIES) { + bt_dev_warn(hdev, "Retry BT power ON:%d", retries); + if (hu->serdev) { + serdev_device_close(hu->serdev); + ret =3D serdev_device_open(hu->serdev); + if (ret) { + bt_dev_err(hdev, "failed to open port"); + return ret; + } } + retries++; + goto retry; } - retries++; - goto retry; + return ret; } =20 /* Setup bdaddr */ diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bu= s.c index 8b421ef0580a..56f5c24c367c 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -908,11 +908,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc, return 0; =20 error_cleanup_dev: - kfree(mc_dev->regions); - if (mc_bus) - kfree(mc_bus); - else - kfree(mc_dev); + put_device(&mc_dev->dev); =20 return error; } diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index 4e335832fc26..2b7f6d9aa739 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -202,11 +202,16 @@ static int ipmi_ipmb_slave_cb(struct i2c_client *clie= nt, break; =20 case I2C_SLAVE_READ_REQUESTED: + *val =3D 0xff; + ipmi_ipmb_check_msg_done(iidev); + break; + case I2C_SLAVE_STOP: ipmi_ipmb_check_msg_done(iidev); break; =20 case I2C_SLAVE_READ_PROCESSED: + *val =3D 0xff; break; } =20 diff --git a/drivers/char/random.c b/drivers/char/random.c index 7b5d4822fa3a..c66aecb56164 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -91,8 +91,7 @@ static ATOMIC_NOTIFIER_HEAD(random_ready_notifier); /* Control how we warn userspace. */ static struct ratelimit_state urandom_warning =3D RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_REL= EASE); -static int ratelimit_disable __read_mostly =3D - IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM); +static int ratelimit_disable __read_mostly =3D 0; module_param_named(ratelimit_disable, ratelimit_disable, int, 0644); MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression"= ); =20 @@ -163,12 +162,6 @@ int __cold execute_with_initialized_rng(struct notifie= r_block *nb) return ret; } =20 -#define warn_unseeded_randomness() \ - if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \ - printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init= =3D%d\n", \ - __func__, (void *)_RET_IP_, crng_init) - - /********************************************************************* * * Fast key erasure RNG, the "crng". @@ -413,7 +406,6 @@ static void _get_random_bytes(void *buf, size_t len) */ void get_random_bytes(void *buf, size_t len) { - warn_unseeded_randomness(); _get_random_bytes(buf, len); } EXPORT_SYMBOL(get_random_bytes); @@ -501,8 +493,6 @@ type get_random_ ##type(void) \ struct batch_ ##type *batch; \ unsigned long next_gen; \ \ - warn_unseeded_randomness(); \ - \ if (!crng_ready()) { \ _get_random_bytes(&ret, sizeof(ret)); \ return ret; \ diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp= 24/st33zp24.c index a5b554cd4778..f78c61f4163d 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -328,8 +328,10 @@ static int st33zp24_send(struct tpm_chip *chip, unsign= ed char *buf, =20 for (i =3D 0; i < len - 1;) { burstcnt =3D get_burstcount(chip); - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + ret =3D burstcnt; + goto out_err; + } size =3D min_t(int, len - i - 1, burstcnt); ret =3D tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, buf + i, size); diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c= _infineon.c index 81d8a78dc655..3675faa4a00c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 = *buf, size_t len) burstcnt =3D get_burstcount(chip); =20 /* burstcnt < 0 =3D TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc =3D burstcnt; + goto out_err; + } =20 if (burstcnt > (len - 1 - count)) burstcnt =3D len - 1 - count; diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis= _i2c_cr50.c index e70abd69e1ae..0f589f301e5b 100644 --- a/drivers/char/tpm/tpm_tis_i2c_cr50.c +++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c @@ -713,8 +713,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client) =20 if (client->irq > 0) { rc =3D devm_request_irq(dev, client->irq, tpm_cr50_i2c_int_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | - IRQF_NO_AUTOEN, + IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, dev->driver->name, chip); if (rc < 0) { dev_err(dev, "Failed to probe IRQ %d\n", client->irq); diff --git a/drivers/char/tpm/tpm_tis_spi_cr50.c b/drivers/char/tpm/tpm_tis= _spi_cr50.c index f4937280e940..32920b4cecfb 100644 --- a/drivers/char/tpm/tpm_tis_spi_cr50.c +++ b/drivers/char/tpm/tpm_tis_spi_cr50.c @@ -287,7 +287,7 @@ int cr50_spi_probe(struct spi_device *spi) if (spi->irq > 0) { ret =3D devm_request_irq(&spi->dev, spi->irq, cr50_spi_irq_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_RISING, "cr50_spi", cr50_phy); if (ret < 0) { if (ret =3D=3D -EPROBE_DEFER) diff --git a/drivers/clk/clk-apple-nco.c b/drivers/clk/clk-apple-nco.c index 457a48d48941..c205b7f1dade 100644 --- a/drivers/clk/clk-apple-nco.c +++ b/drivers/clk/clk-apple-nco.c @@ -318,6 +318,7 @@ static int applnco_probe(struct platform_device *pdev) } =20 static const struct of_device_id applnco_ids[] =3D { + { .compatible =3D "apple,t8103-nco" }, { .compatible =3D "apple,nco" }, { } }; diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index ba1d1c495bc2..644e5a854f2b 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -497,14 +497,16 @@ static int __mtk_clk_simple_probe(struct platform_dev= ice *pdev, =20 =20 if (mcd->need_runtime_pm) { - devm_pm_runtime_enable(&pdev->dev); + r =3D devm_pm_runtime_enable(&pdev->dev); + if (r) + goto unmap_io; /* * Do a pm_runtime_resume_and_get() to workaround a possible * deadlock between clk_register() and the genpd framework. */ r =3D pm_runtime_resume_and_get(&pdev->dev); if (r) - return r; + goto unmap_io; } =20 /* Calculate how many clk_hw_onecell_data entries to allocate */ @@ -618,11 +620,11 @@ static int __mtk_clk_simple_probe(struct platform_dev= ice *pdev, free_data: mtk_free_clk_data(clk_data); free_base: - if (mcd->shared_io && base) - iounmap(base); - if (mcd->need_runtime_pm) pm_runtime_put(&pdev->dev); +unmap_io: + if (mcd->shared_io && base) + iounmap(base); return r; } =20 diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index a133013356b6..00eaca92b388 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -318,12 +318,23 @@ static struct clk_regmap gxbb_hdmi_pll =3D { }, }; =20 +/* + * GXL hdmi OD dividers are POWER_OF_TWO dividers but limited to /4. + * A divider value of 3 should map to /8 but instead map /4 so ignore it. + */ +static const struct clk_div_table gxl_hdmi_pll_od_div_table[] =3D { + { .val =3D 0, .div =3D 1 }, + { .val =3D 1, .div =3D 2 }, + { .val =3D 2, .div =3D 4 }, + { /* sentinel */ } +}; + static struct clk_regmap gxl_hdmi_pll_od =3D { .data =3D &(struct clk_regmap_div_data){ .offset =3D HHI_HDMI_PLL_CNTL + 8, .shift =3D 21, .width =3D 2, - .flags =3D CLK_DIVIDER_POWER_OF_TWO, + .table =3D gxl_hdmi_pll_od_div_table, }, .hw.init =3D &(struct clk_init_data){ .name =3D "hdmi_pll_od", @@ -341,7 +352,7 @@ static struct clk_regmap gxl_hdmi_pll_od2 =3D { .offset =3D HHI_HDMI_PLL_CNTL + 8, .shift =3D 23, .width =3D 2, - .flags =3D CLK_DIVIDER_POWER_OF_TWO, + .table =3D gxl_hdmi_pll_od_div_table, }, .hw.init =3D &(struct clk_init_data){ .name =3D "hdmi_pll_od2", @@ -359,7 +370,7 @@ static struct clk_regmap gxl_hdmi_pll =3D { .offset =3D HHI_HDMI_PLL_CNTL + 8, .shift =3D 19, .width =3D 2, - .flags =3D CLK_DIVIDER_POWER_OF_TWO, + .table =3D gxl_hdmi_pll_od_div_table, }, .hw.init =3D &(struct clk_init_data){ .name =3D "hdmi_pll", diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-c= ore.c index 1b4f023cdc8b..71fbaf8318f2 100644 --- a/drivers/clk/microchip/clk-core.c +++ b/drivers/clk/microchip/clk-core.c @@ -281,14 +281,13 @@ static u8 roclk_get_parent(struct clk_hw *hw) =20 v =3D (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK; =20 - if (!refo->parent_map) - return v; - - for (i =3D 0; i < clk_hw_get_num_parents(hw); i++) - if (refo->parent_map[i] =3D=3D v) - return i; + if (refo->parent_map) { + for (i =3D 0; i < clk_hw_get_num_parents(hw); i++) + if (refo->parent_map[i] =3D=3D v) + return i; + } =20 - return -EINVAL; + return v; } =20 static unsigned long roclk_calc_rate(unsigned long parent_rate, @@ -823,13 +822,13 @@ static u8 sclk_get_parent(struct clk_hw *hw) =20 v =3D (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; =20 - if (!sclk->parent_map) - return v; + if (sclk->parent_map) { + for (i =3D 0; i < clk_hw_get_num_parents(hw); i++) + if (sclk->parent_map[i] =3D=3D v) + return i; + } =20 - for (i =3D 0; i < clk_hw_get_num_parents(hw); i++) - if (sclk->parent_map[i] =3D=3D v) - return i; - return -EINVAL; + return v; } =20 static int sclk_set_parent(struct clk_hw *hw, u8 index) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index fae1c07982ab..20bb72565f0e 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -434,7 +434,7 @@ static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, s= truct clk_duty *duty) static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *dut= y) { struct clk_rcg2 *rcg =3D to_clk_rcg2(hw); - u32 notn_m, n, m, d, not2d, mask, duty_per, cfg; + u32 notn_m, n, m, d, not2d, mask, cfg; int ret; =20 /* Duty-cycle cannot be modified for non-MND RCGs */ @@ -453,10 +453,8 @@ static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, = struct clk_duty *duty) =20 n =3D (~(notn_m) + m) & mask; =20 - duty_per =3D (duty->num * 100) / duty->den; - /* Calculate 2d value */ - d =3D DIV_ROUND_CLOSEST(n * duty_per * 2, 100); + d =3D DIV_ROUND_CLOSEST(n * duty->num * 2, duty->den); =20 /* * Check bit widths of 2d. If D is too big reduce duty cycle. @@ -920,6 +918,7 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw, if (req->max_rate < parent_req.max_rate) parent_req.max_rate =3D req->max_rate; =20 + parent_req.best_parent_hw =3D req->best_parent_hw; ret =3D __clk_determine_rate(req->best_parent_hw, &parent_req); if (ret) return ret; diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 35bd987f2e52..3d6e87872ddc 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -325,7 +325,7 @@ int qcom_cc_probe_by_index(struct platform_device *pdev= , int index, =20 base =3D devm_platform_ioremap_resource(pdev, index); if (IS_ERR(base)) - return -ENOMEM; + return PTR_ERR(base); =20 regmap =3D devm_regmap_init_mmio(&pdev->dev, base, desc->config); if (IS_ERR(regmap)) diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm= 845.c index e792e0b130d3..eae6dcff18da 100644 --- a/drivers/clk/qcom/dispcc-sdm845.c +++ b/drivers/clk/qcom/dispcc-sdm845.c @@ -280,7 +280,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src =3D { .name =3D "disp_cc_mdss_pclk0_clk_src", .parent_data =3D disp_cc_parent_data_4, .num_parents =3D ARRAY_SIZE(disp_cc_parent_data_4), - .flags =3D CLK_SET_RATE_PARENT, + .flags =3D CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, .ops =3D &clk_pixel_ops, }, }; @@ -295,7 +295,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src =3D { .name =3D "disp_cc_mdss_pclk1_clk_src", .parent_data =3D disp_cc_parent_data_4, .num_parents =3D ARRAY_SIZE(disp_cc_parent_data_4), - .flags =3D CLK_SET_RATE_PARENT, + .flags =3D CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, .ops =3D &clk_pixel_ops, }, }; diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c index 915e84db3c97..292eaa154737 100644 --- a/drivers/clk/qcom/gcc-ipq5018.c +++ b/drivers/clk/qcom/gcc-ipq5018.c @@ -1339,6 +1339,7 @@ static struct clk_branch gcc_sleep_clk_src =3D { .name =3D "gcc_sleep_clk_src", .parent_data =3D gcc_sleep_clk_data, .num_parents =3D ARRAY_SIZE(gcc_sleep_clk_data), + .flags =3D CLK_IS_CRITICAL, .ops =3D &clk_branch2_ops, }, }, diff --git a/drivers/clk/qcom/gcc-msm8917.c b/drivers/clk/qcom/gcc-msm8917.c index f2dd132e2fb1..0be62cb7a622 100644 --- a/drivers/clk/qcom/gcc-msm8917.c +++ b/drivers/clk/qcom/gcc-msm8917.c @@ -3034,7 +3034,6 @@ static struct gdsc cpp_gdsc =3D { .pd =3D { .name =3D "cpp_gdsc", }, - .flags =3D ALWAYS_ON, .pwrsts =3D PWRSTS_OFF_ON, }; =20 diff --git a/drivers/clk/qcom/gcc-msm8953.c b/drivers/clk/qcom/gcc-msm8953.c index e6e2ab1380f2..1689f0881406 100644 --- a/drivers/clk/qcom/gcc-msm8953.c +++ b/drivers/clk/qcom/gcc-msm8953.c @@ -3946,7 +3946,6 @@ static struct gdsc cpp_gdsc =3D { .pd =3D { .name =3D "cpp_gdsc", }, - .flags =3D ALWAYS_ON, .pwrsts =3D PWRSTS_OFF_ON, }; =20 diff --git a/drivers/clk/qcom/gcc-qdu1000.c b/drivers/clk/qcom/gcc-qdu1000.c index 9f42d2601464..84643f9ffb02 100644 --- a/drivers/clk/qcom/gcc-qdu1000.c +++ b/drivers/clk/qcom/gcc-qdu1000.c @@ -904,7 +904,7 @@ static struct clk_rcg2 gcc_sdcc5_apps_clk_src =3D { .name =3D "gcc_sdcc5_apps_clk_src", .parent_data =3D gcc_parent_data_8, .num_parents =3D ARRAY_SIZE(gcc_parent_data_8), - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 @@ -923,7 +923,7 @@ static struct clk_rcg2 gcc_sdcc5_ice_core_clk_src =3D { .name =3D "gcc_sdcc5_ice_core_clk_src", .parent_data =3D gcc_parent_data_2, .num_parents =3D ARRAY_SIZE(gcc_parent_data_2), - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 diff --git a/drivers/clk/qcom/gcc-sdx75.c b/drivers/clk/qcom/gcc-sdx75.c index 573af17bd24c..314bacd03374 100644 --- a/drivers/clk/qcom/gcc-sdx75.c +++ b/drivers/clk/qcom/gcc-sdx75.c @@ -1033,7 +1033,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src =3D { .name =3D "gcc_sdcc1_apps_clk_src", .parent_data =3D gcc_parent_data_17, .num_parents =3D ARRAY_SIZE(gcc_parent_data_17), - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 @@ -1057,7 +1057,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src =3D { .name =3D "gcc_sdcc2_apps_clk_src", .parent_data =3D gcc_parent_data_18, .num_parents =3D ARRAY_SIZE(gcc_parent_data_18), - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 diff --git a/drivers/clk/qcom/gcc-sm8450.c b/drivers/clk/qcom/gcc-sm8450.c index 4c55df89ddca..ef02d1003cb4 100644 --- a/drivers/clk/qcom/gcc-sm8450.c +++ b/drivers/clk/qcom/gcc-sm8450.c @@ -936,7 +936,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src =3D { .parent_data =3D gcc_parent_data_7, .num_parents =3D ARRAY_SIZE(gcc_parent_data_7), .flags =3D CLK_SET_RATE_PARENT, - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 @@ -959,7 +959,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src =3D { .parent_data =3D gcc_parent_data_0, .num_parents =3D ARRAY_SIZE(gcc_parent_data_0), .flags =3D CLK_SET_RATE_PARENT, - .ops =3D &clk_rcg2_floor_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 diff --git a/drivers/clk/qcom/gcc-sm8550.c b/drivers/clk/qcom/gcc-sm8550.c index b30ece62216f..3e5ce6fa6805 100644 --- a/drivers/clk/qcom/gcc-sm8550.c +++ b/drivers/clk/qcom/gcc-sm8550.c @@ -1025,7 +1025,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src =3D { .parent_data =3D gcc_parent_data_9, .num_parents =3D ARRAY_SIZE(gcc_parent_data_9), .flags =3D CLK_SET_RATE_PARENT, - .ops =3D &clk_rcg2_shared_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 @@ -1048,7 +1048,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src =3D { .parent_data =3D gcc_parent_data_0, .num_parents =3D ARRAY_SIZE(gcc_parent_data_0), .flags =3D CLK_SET_RATE_PARENT, - .ops =3D &clk_rcg2_shared_ops, + .ops =3D &clk_rcg2_shared_floor_ops, }, }; =20 diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cp= g.c index 4bba49215c71..2dea5fb8b858 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -91,8 +91,8 @@ struct sd_mux_hw_data { =20 struct rzg2l_pll5_param { u32 pl5_fracin; + u16 pl5_intin; u8 pl5_refdiv; - u8 pl5_intin; u8 pl5_postdiv1; u8 pl5_postdiv2; u8 pl5_spread; @@ -380,8 +380,8 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param = *params, foutvco_rate =3D div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA, (params->pl5_intin << 24) + params->pl5_fracin), params->pl5_refdiv) >> 24; - foutpostdiv_rate =3D DIV_ROUND_CLOSEST_ULL(foutvco_rate, - params->pl5_postdiv1 * params->pl5_postdiv2); + foutpostdiv_rate =3D DIV_ROUND_CLOSEST(foutvco_rate, + params->pl5_postdiv1 * params->pl5_postdiv2); =20 return foutpostdiv_rate; } diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-t= egra124-emc.c index 2a6db0434281..0f6fb776b229 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -538,8 +538,10 @@ struct clk *tegra124_clk_register_emc(void __iomem *ba= se, struct device_node *np tegra->hw.init =3D &init; =20 clk =3D clk_register(NULL, &tegra->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + kfree(tegra); return clk; + } =20 tegra->prev_parent =3D clk_hw_get_parent_by_index( &tegra->hw, emc_get_parent(&tegra->hw))->clk; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 8208a3d89563..5b526b74e5de 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -236,6 +236,7 @@ config KEYSTONE_TIMER =20 config INTEGRATOR_AP_TIMER bool "Integrator-AP timer driver" if COMPILE_TEST + depends on OF select CLKSRC_MMIO help Enables support for the Integrator-AP timer. diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index beffff81c00f..3fc6ed9b5630 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -143,16 +143,6 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel= *ch, int start) =20 static int __sh_tmu_enable(struct sh_tmu_channel *ch) { - int ret; - - /* enable clock */ - ret =3D clk_enable(ch->tmu->clk); - if (ret) { - dev_err(&ch->tmu->pdev->dev, "ch%u: cannot enable clock\n", - ch->index); - return ret; - } - /* make sure channel is disabled */ sh_tmu_start_stop_ch(ch, 0); =20 @@ -174,7 +164,6 @@ static int sh_tmu_enable(struct sh_tmu_channel *ch) if (ch->enable_count++ > 0) return 0; =20 - pm_runtime_get_sync(&ch->tmu->pdev->dev); dev_pm_syscore_device(&ch->tmu->pdev->dev, true); =20 return __sh_tmu_enable(ch); @@ -187,9 +176,6 @@ static void __sh_tmu_disable(struct sh_tmu_channel *ch) =20 /* disable interrupts in TMU block */ sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); - - /* stop clock */ - clk_disable(ch->tmu->clk); } =20 static void sh_tmu_disable(struct sh_tmu_channel *ch) @@ -203,7 +189,6 @@ static void sh_tmu_disable(struct sh_tmu_channel *ch) __sh_tmu_disable(ch); =20 dev_pm_syscore_device(&ch->tmu->pdev->dev, false); - pm_runtime_put(&ch->tmu->pdev->dev); } =20 static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta, @@ -552,7 +537,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, stru= ct platform_device *pdev) goto err_clk_unprepare; =20 tmu->rate =3D clk_get_rate(tmu->clk) / 4; - clk_disable(tmu->clk); =20 /* Map the memory resource. */ ret =3D sh_tmu_map_memory(tmu); @@ -626,8 +610,6 @@ static int sh_tmu_probe(struct platform_device *pdev) out: if (tmu->has_clockevent || tmu->has_clocksource) pm_runtime_irq_safe(&pdev->dev); - else - pm_runtime_idle(&pdev->dev); =20 return 0; } diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq= -dt-platdev.c index 8b53388280d7..ad4f23e2158b 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -158,8 +158,11 @@ static const struct of_device_id blocklist[] __initcon= st =3D { { .compatible =3D "qcom,sdm845", }, { .compatible =3D "qcom,sdx75", }, { .compatible =3D "qcom,sm6115", }, + { .compatible =3D "qcom,sm6125", }, + { .compatible =3D "qcom,sm6150", }, { .compatible =3D "qcom,sm6350", }, { .compatible =3D "qcom,sm6375", }, + { .compatible =3D "qcom,sm7125", }, { .compatible =3D "qcom,sm7225", }, { .compatible =3D "qcom,sm8150", }, { .compatible =3D "qcom,sm8250", }, diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 6704d610573a..aa117f2967fd 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -356,6 +356,16 @@ noinstr int cpuidle_enter_state(struct cpuidle_device = *dev, int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, bool *stop_tick) { + /* + * If there is only a single idle state (or none), there is nothing + * meaningful for the governor to choose. Skip the governor and + * always use state 0 with the tick running. + */ + if (drv->state_count <=3D 1) { + *stop_tick =3D false; + return 0; + } + return cpuidle_curr_governor->select(drv, dev, stop_tick); } =20 diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/m= enu.c index 27010eee6d1b..bedf6c4b8d1b 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include =20 @@ -94,16 +92,11 @@ * state, and thus the less likely a busy CPU will hit such a deep * C state. * - * Two factors are used in determing this multiplier: - * a value of 10 is added for each point of "per cpu load average" we have. - * a value of 5 points is added for each process that is waiting for - * IO on this CPU. - * (these values are experimentally determined) - * - * The load average factor gives a longer term (few seconds) input to the - * decision, while the iowait value gives a cpu local instantanious input. - * The iowait factor may look low, but realize that this is also already - * represented in the system load average. + * Currently there is only one value determining the factor: + * 10 points are added for each process that is waiting for IO on this CPU. + * (This value was experimentally determined.) + * Utilization is no longer a factor as it was shown that it never contrib= uted + * significantly to the performance multiplier in the first place. * */ =20 @@ -276,7 +269,7 @@ static int menu_select(struct cpuidle_driver *drv, stru= ct cpuidle_device *dev, =20 /* Find the shortest expected idle interval. */ predicted_ns =3D get_typical_interval(data) * NSEC_PER_USEC; - if (predicted_ns > RESIDENCY_THRESHOLD_NS) { + if (predicted_ns > RESIDENCY_THRESHOLD_NS || tick_nohz_tick_stopped()) { unsigned int timer_us; =20 /* Determine the time till the closest timer. */ @@ -296,6 +289,16 @@ static int menu_select(struct cpuidle_driver *drv, str= uct cpuidle_device *dev, RESOLUTION * DECAY * NSEC_PER_USEC); /* Use the lowest expected idle interval to pick the idle state. */ predicted_ns =3D min((u64)timer_us * NSEC_PER_USEC, predicted_ns); + /* + * If the tick is already stopped, the cost of possible short + * idle duration misprediction is much higher, because the CPU + * may be stuck in a shallow idle state for a long time as a + * result of it. In that case, say we might mispredict and use + * the known time till the closest timer event for the idle + * state selection. + */ + if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) + predicted_ns =3D data->next_timer_ns; } else { /* * Because the next timer event is not going to be determined @@ -321,16 +324,6 @@ static int menu_select(struct cpuidle_driver *drv, str= uct cpuidle_device *dev, return 0; } =20 - /* - * If the tick is already stopped, the cost of possible short idle - * duration misprediction is much higher, because the CPU may be stuck - * in a shallow idle state for a long time as a result of it. In that - * case, say we might mispredict and use the known time till the closest - * timer event for the idle state selection. - */ - if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) - predicted_ns =3D data->next_timer_ns; - /* * Find the idle state with the lowest power while satisfying * our constraints. diff --git a/drivers/crypto/cavium/cpt/cptvf_main.c b/drivers/crypto/cavium= /cpt/cptvf_main.c index c246920e6f54..bccd680c7f7e 100644 --- a/drivers/crypto/cavium/cpt/cptvf_main.c +++ b/drivers/crypto/cavium/cpt/cptvf_main.c @@ -180,7 +180,8 @@ static void free_command_queues(struct cpt_vf *cptvf, =20 hlist_for_each_entry_safe(chunk, node, &cqinfo->queue[i].chead, nextchunk) { - dma_free_coherent(&pdev->dev, chunk->size, + dma_free_coherent(&pdev->dev, + chunk->size + CPT_NEXT_CHUNK_PTR_SIZE, chunk->head, chunk->dma_addr); chunk->head =3D NULL; diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c index d42d7bc62352..5f591bce0952 100644 --- a/drivers/crypto/ccp/psp-dev.c +++ b/drivers/crypto/ccp/psp-dev.c @@ -9,6 +9,9 @@ =20 #include #include +#include +#include +#include =20 #include "sp-dev.h" #include "psp-dev.h" @@ -19,6 +22,62 @@ =20 struct psp_device *psp_master; =20 +#define PSP_C2PMSG_17_CMDRESP_CMD GENMASK(19, 16) + +static int psp_mailbox_poll(const void __iomem *cmdresp_reg, unsigned int = *cmdresp, + unsigned int timeout_msecs) +{ + while (true) { + *cmdresp =3D ioread32(cmdresp_reg); + if (FIELD_GET(PSP_CMDRESP_RESP, *cmdresp)) + return 0; + + if (!timeout_msecs--) + break; + + usleep_range(1000, 1100); + } + + return -ETIMEDOUT; +} + +int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cm= dbuff, + unsigned int timeout_msecs, unsigned int *cmdresp) +{ + void __iomem *cmdresp_reg, *cmdbuff_lo_reg, *cmdbuff_hi_reg; + int ret; + + if (!psp || !psp->vdata || !psp->vdata->cmdresp_reg || + !psp->vdata->cmdbuff_addr_lo_reg || !psp->vdata->cmdbuff_addr_hi_reg) + return -ENODEV; + + cmdresp_reg =3D psp->io_regs + psp->vdata->cmdresp_reg; + cmdbuff_lo_reg =3D psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg; + cmdbuff_hi_reg =3D psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg; + + mutex_lock(&psp->mailbox_mutex); + + /* Ensure mailbox is ready for a command */ + ret =3D -EBUSY; + if (psp_mailbox_poll(cmdresp_reg, cmdresp, 0)) + goto unlock; + + if (cmdbuff) { + iowrite32(lower_32_bits(__psp_pa(cmdbuff)), cmdbuff_lo_reg); + iowrite32(upper_32_bits(__psp_pa(cmdbuff)), cmdbuff_hi_reg); + } + + *cmdresp =3D FIELD_PREP(PSP_C2PMSG_17_CMDRESP_CMD, cmd); + iowrite32(*cmdresp, cmdresp_reg); + + ret =3D psp_mailbox_poll(cmdresp_reg, cmdresp, timeout_msecs); + +unlock: + mutex_unlock(&psp->mailbox_mutex); + + return ret; +} + static struct psp_device *psp_alloc_struct(struct sp_device *sp) { struct device *dev =3D sp->dev; @@ -164,6 +223,7 @@ int psp_dev_init(struct sp_device *sp) } =20 psp->io_regs =3D sp->io_map; + mutex_init(&psp->mailbox_mutex); =20 ret =3D psp_get_capability(psp); if (ret) @@ -253,6 +313,17 @@ struct psp_device *psp_get_master_device(void) return sp ? sp->psp_data : NULL; } =20 +int psp_restore(struct sp_device *sp) +{ + struct psp_device *psp =3D sp->psp_data; + int ret =3D 0; + + if (psp->tee_data) + ret =3D tee_restore(psp); + + return ret; +} + void psp_pci_init(void) { psp_master =3D psp_get_master_device(); diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h index 8a4de69399c5..d917657c6085 100644 --- a/drivers/crypto/ccp/psp-dev.h +++ b/drivers/crypto/ccp/psp-dev.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include =20 #include "sp-dev.h" =20 @@ -33,6 +35,7 @@ struct psp_device { struct sp_device *sp; =20 void __iomem *io_regs; + struct mutex mailbox_mutex; =20 psp_irq_handler_t sev_irq_handler; void *sev_irq_data; @@ -71,4 +74,19 @@ struct psp_device *psp_get_master_device(void); #define PSP_SECURITY_HSP_TPM_AVAILABLE BIT(10) #define PSP_SECURITY_ROM_ARMOR_ENFORCED BIT(11) =20 +/** + * enum psp_cmd - PSP mailbox commands + * @PSP_CMD_TEE_RING_INIT: Initialize TEE ring buffer + * @PSP_CMD_TEE_RING_DESTROY: Destroy TEE ring buffer + * @PSP_CMD_MAX: Maximum command id + */ +enum psp_cmd { + PSP_CMD_TEE_RING_INIT =3D 1, + PSP_CMD_TEE_RING_DESTROY =3D 2, + PSP_CMD_MAX =3D 15, +}; + +int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cm= dbuff, + unsigned int timeout_msecs, unsigned int *cmdresp); + #endif /* __PSP_DEV_H */ diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c index 7eb3e4668286..ccbe009ad6e5 100644 --- a/drivers/crypto/ccp/sp-dev.c +++ b/drivers/crypto/ccp/sp-dev.c @@ -229,6 +229,18 @@ int sp_resume(struct sp_device *sp) return 0; } =20 +int sp_restore(struct sp_device *sp) +{ + if (sp->psp_data) { + int ret =3D psp_restore(sp); + + if (ret) + return ret; + } + + return sp_resume(sp); +} + struct sp_device *sp_get_psp_master_device(void) { struct sp_device *i, *ret =3D NULL; diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h index 2329ad524b49..2efe4a6ef544 100644 --- a/drivers/crypto/ccp/sp-dev.h +++ b/drivers/crypto/ccp/sp-dev.h @@ -71,6 +71,9 @@ struct psp_vdata { const struct sev_vdata *sev; const struct tee_vdata *tee; const struct platform_access_vdata *platform_access; + const unsigned int cmdresp_reg; + const unsigned int cmdbuff_addr_lo_reg; + const unsigned int cmdbuff_addr_hi_reg; const unsigned int feature_reg; const unsigned int inten_reg; const unsigned int intsts_reg; @@ -138,6 +141,7 @@ struct sp_device *sp_get_master(void); =20 int sp_suspend(struct sp_device *sp); int sp_resume(struct sp_device *sp); +int sp_restore(struct sp_device *sp); int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler, const char *name, void *data); void sp_free_ccp_irq(struct sp_device *sp, void *data); @@ -171,6 +175,7 @@ int psp_dev_init(struct sp_device *sp); void psp_pci_init(void); void psp_dev_destroy(struct sp_device *sp); void psp_pci_exit(void); +int psp_restore(struct sp_device *sp); =20 #else /* !CONFIG_CRYPTO_DEV_SP_PSP */ =20 @@ -178,6 +183,7 @@ static inline int psp_dev_init(struct sp_device *sp) { = return 0; } static inline void psp_pci_init(void) { } static inline void psp_dev_destroy(struct sp_device *sp) { } static inline void psp_pci_exit(void) { } +static inline int psp_restore(struct sp_device *sp) { return 0; } =20 #endif /* CONFIG_CRYPTO_DEV_SP_PSP */ =20 diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index b1e60542351a..86517bb4c195 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -407,6 +407,13 @@ static int __maybe_unused sp_pci_resume(struct device = *dev) return sp_resume(sp); } =20 +static int __maybe_unused sp_pci_restore(struct device *dev) +{ + struct sp_device *sp =3D dev_get_drvdata(dev); + + return sp_restore(sp); +} + #ifdef CONFIG_CRYPTO_DEV_SP_PSP static const struct sev_vdata sevv1 =3D { .cmdresp_reg =3D 0x10580, /* C2PMSG_32 */ @@ -421,18 +428,12 @@ static const struct sev_vdata sevv2 =3D { }; =20 static const struct tee_vdata teev1 =3D { - .cmdresp_reg =3D 0x10544, /* C2PMSG_17 */ - .cmdbuff_addr_lo_reg =3D 0x10548, /* C2PMSG_18 */ - .cmdbuff_addr_hi_reg =3D 0x1054c, /* C2PMSG_19 */ .ring_wptr_reg =3D 0x10550, /* C2PMSG_20 */ .ring_rptr_reg =3D 0x10554, /* C2PMSG_21 */ .info_reg =3D 0x109e8, /* C2PMSG_58 */ }; =20 static const struct tee_vdata teev2 =3D { - .cmdresp_reg =3D 0x10944, /* C2PMSG_17 */ - .cmdbuff_addr_lo_reg =3D 0x10948, /* C2PMSG_18 */ - .cmdbuff_addr_hi_reg =3D 0x1094c, /* C2PMSG_19 */ .ring_wptr_reg =3D 0x10950, /* C2PMSG_20 */ .ring_rptr_reg =3D 0x10954, /* C2PMSG_21 */ }; @@ -469,6 +470,9 @@ static const struct psp_vdata pspv2 =3D { static const struct psp_vdata pspv3 =3D { .tee =3D &teev1, .platform_access =3D &pa_v1, + .cmdresp_reg =3D 0x10544, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg =3D 0x10548, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg =3D 0x1054c, /* C2PMSG_19 */ .bootloader_info_reg =3D 0x109ec, /* C2PMSG_59 */ .feature_reg =3D 0x109fc, /* C2PMSG_63 */ .inten_reg =3D 0x10690, /* P2CMSG_INTEN */ @@ -479,6 +483,9 @@ static const struct psp_vdata pspv3 =3D { static const struct psp_vdata pspv4 =3D { .sev =3D &sevv2, .tee =3D &teev1, + .cmdresp_reg =3D 0x10544, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg =3D 0x10548, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg =3D 0x1054c, /* C2PMSG_19 */ .bootloader_info_reg =3D 0x109ec, /* C2PMSG_59 */ .feature_reg =3D 0x109fc, /* C2PMSG_63 */ .inten_reg =3D 0x10690, /* P2CMSG_INTEN */ @@ -488,6 +495,9 @@ static const struct psp_vdata pspv4 =3D { static const struct psp_vdata pspv5 =3D { .tee =3D &teev2, .platform_access =3D &pa_v2, + .cmdresp_reg =3D 0x10944, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg =3D 0x10948, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg =3D 0x1094c, /* C2PMSG_19 */ .feature_reg =3D 0x109fc, /* C2PMSG_63 */ .inten_reg =3D 0x10510, /* P2CMSG_INTEN */ .intsts_reg =3D 0x10514, /* P2CMSG_INTSTS */ @@ -496,6 +506,9 @@ static const struct psp_vdata pspv5 =3D { static const struct psp_vdata pspv6 =3D { .sev =3D &sevv2, .tee =3D &teev2, + .cmdresp_reg =3D 0x10944, /* C2PMSG_17 */ + .cmdbuff_addr_lo_reg =3D 0x10948, /* C2PMSG_18 */ + .cmdbuff_addr_hi_reg =3D 0x1094c, /* C2PMSG_19 */ .feature_reg =3D 0x109fc, /* C2PMSG_63 */ .inten_reg =3D 0x10510, /* P2CMSG_INTEN */ .intsts_reg =3D 0x10514, /* P2CMSG_INTSTS */ @@ -585,7 +598,14 @@ static const struct pci_device_id sp_pci_table[] =3D { }; MODULE_DEVICE_TABLE(pci, sp_pci_table); =20 -static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume); +static const struct dev_pm_ops sp_pci_pm_ops =3D { + .suspend =3D pm_sleep_ptr(sp_pci_suspend), + .resume =3D pm_sleep_ptr(sp_pci_resume), + .freeze =3D pm_sleep_ptr(sp_pci_suspend), + .thaw =3D pm_sleep_ptr(sp_pci_resume), + .poweroff =3D pm_sleep_ptr(sp_pci_suspend), + .restore_early =3D pm_sleep_ptr(sp_pci_restore), +}; =20 static struct pci_driver sp_pci_driver =3D { .name =3D "ccp", diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c index 5560bf8329a1..01d7dcb9cfee 100644 --- a/drivers/crypto/ccp/tee-dev.c +++ b/drivers/crypto/ccp/tee-dev.c @@ -62,26 +62,6 @@ static void tee_free_ring(struct psp_tee_device *tee) mutex_destroy(&rb_mgr->mutex); } =20 -static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int time= out, - unsigned int *reg) -{ - /* ~10ms sleep per loop =3D> nloop =3D timeout * 100 */ - int nloop =3D timeout * 100; - - while (--nloop) { - *reg =3D ioread32(tee->io_regs + tee->vdata->cmdresp_reg); - if (FIELD_GET(PSP_CMDRESP_RESP, *reg)) - return 0; - - usleep_range(10000, 10100); - } - - dev_err(tee->dev, "tee: command timed out, disabling PSP\n"); - psp_dead =3D true; - - return -ETIMEDOUT; -} - static struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee) { @@ -106,11 +86,34 @@ static inline void tee_free_cmd_buffer(struct tee_init= _ring_cmd *cmd) kfree(cmd); } =20 +static bool tee_send_destroy_cmd(struct psp_tee_device *tee) +{ + unsigned int reg; + int ret; + + ret =3D psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL, + TEE_DEFAULT_CMD_TIMEOUT, ®); + if (ret) { + dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE su= pport\n"); + psp_dead =3D true; + return false; + } + + if (FIELD_GET(PSP_CMDRESP_STS, reg)) { + dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", + FIELD_GET(PSP_CMDRESP_STS, reg)); + psp_dead =3D true; + return false; + } + + return true; +} + static int tee_init_ring(struct psp_tee_device *tee) { int ring_size =3D MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd); struct tee_init_ring_cmd *cmd; - phys_addr_t cmd_buffer; + bool retry =3D false; unsigned int reg; int ret; =20 @@ -130,27 +133,32 @@ static int tee_init_ring(struct psp_tee_device *tee) return -ENOMEM; } =20 - cmd_buffer =3D __psp_pa((void *)cmd); - /* Send command buffer details to Trusted OS by writing to * CPU-PSP message registers */ - - iowrite32(lower_32_bits(cmd_buffer), - tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg); - iowrite32(upper_32_bits(cmd_buffer), - tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg); - iowrite32(TEE_RING_INIT_CMD, - tee->io_regs + tee->vdata->cmdresp_reg); - - ret =3D tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); +retry_init: + ret =3D psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd, + TEE_DEFAULT_CMD_TIMEOUT, ®); if (ret) { - dev_err(tee->dev, "tee: ring init command timed out\n"); + dev_err(tee->dev, "tee: ring init command timed out, disabling TEE suppo= rt\n"); tee_free_ring(tee); + psp_dead =3D true; goto free_buf; } =20 if (FIELD_GET(PSP_CMDRESP_STS, reg)) { + /* + * During the hibernate resume sequence driver may have gotten loaded + * but the ring not properly destroyed. If the ring doesn't work, try + * to destroy and re-init once. + */ + if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) =3D=3D PSP_TEE_STS_RING_BU= SY) { + dev_info(tee->dev, "tee: ring init command failed with busy status, ret= rying\n"); + if (tee_send_destroy_cmd(tee)) { + retry =3D true; + goto retry_init; + } + } dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n", FIELD_GET(PSP_CMDRESP_STS, reg)); tee_free_ring(tee); @@ -165,25 +173,13 @@ static int tee_init_ring(struct psp_tee_device *tee) =20 static void tee_destroy_ring(struct psp_tee_device *tee) { - unsigned int reg; - int ret; - if (!tee->rb_mgr.ring_start) return; =20 if (psp_dead) goto free_ring; =20 - iowrite32(TEE_RING_DESTROY_CMD, - tee->io_regs + tee->vdata->cmdresp_reg); - - ret =3D tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, ®); - if (ret) { - dev_err(tee->dev, "tee: ring destroy command timed out\n"); - } else if (FIELD_GET(PSP_CMDRESP_STS, reg)) { - dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n", - FIELD_GET(PSP_CMDRESP_STS, reg)); - } + tee_send_destroy_cmd(tee); =20 free_ring: tee_free_ring(tee); @@ -370,7 +366,7 @@ int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *b= uf, size_t len, if (ret) return ret; =20 - ret =3D tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT); + ret =3D tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_RING_TIMEOUT); if (ret) { resp->flag =3D CMD_RESPONSE_TIMEDOUT; return ret; @@ -395,3 +391,8 @@ int psp_check_tee_status(void) return 0; } EXPORT_SYMBOL(psp_check_tee_status); + +int tee_restore(struct psp_device *psp) +{ + return tee_init_ring(psp->tee_data); +} diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h index 49d26158b71e..c23416cb7bb3 100644 --- a/drivers/crypto/ccp/tee-dev.h +++ b/drivers/crypto/ccp/tee-dev.h @@ -17,21 +17,10 @@ #include #include =20 -#define TEE_DEFAULT_TIMEOUT 10 +#define TEE_DEFAULT_CMD_TIMEOUT (10 * MSEC_PER_SEC) +#define TEE_DEFAULT_RING_TIMEOUT 10 #define MAX_BUFFER_SIZE 988 =20 -/** - * enum tee_ring_cmd_id - TEE interface commands for ring buffer configura= tion - * @TEE_RING_INIT_CMD: Initialize ring buffer - * @TEE_RING_DESTROY_CMD: Destroy ring buffer - * @TEE_RING_MAX_CMD: Maximum command id - */ -enum tee_ring_cmd_id { - TEE_RING_INIT_CMD =3D 0x00010000, - TEE_RING_DESTROY_CMD =3D 0x00020000, - TEE_RING_MAX_CMD =3D 0x000F0000, -}; - /** * struct tee_init_ring_cmd - Command to init TEE ring buffer * @low_addr: bits [31:0] of the physical address of ring buffer @@ -122,5 +111,6 @@ struct tee_ring_cmd { =20 int tee_dev_init(struct psp_device *psp); void tee_dev_destroy(struct psp_device *psp); +int tee_restore(struct psp_device *psp); =20 #endif /* __TEE_DEV_H__ */ diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 2c0ca68914e2..e09357fea057 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -633,9 +633,13 @@ static void qm_mb_write(struct hisi_qm *qm, const void= *src) } =20 #if IS_ENABLED(CONFIG_ARM64) + /* + * The dmb oshst instruction ensures that the data in the + * mailbox is written before it is sent to the hardware. + */ asm volatile("ldp %0, %1, %3\n" - "stp %0, %1, %2\n" "dmb oshst\n" + "stp %0, %1, %2\n" : "=3D&r" (tmp0), "=3D&r" (tmp1), "+Q" (*((char __iomem *)fun_base)) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hi= silicon/sec2/sec_crypto.c index d6727b8ff582..8db3d2990816 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -590,10 +590,8 @@ static int sec_ctx_base_init(struct sec_ctx *ctx) int i, ret; =20 ctx->qps =3D sec_create_qps(); - if (!ctx->qps) { - pr_err("Can not create sec qps!\n"); + if (!ctx->qps) return -ENODEV; - } =20 sec =3D container_of(ctx->qps[0]->qm, struct sec_dev, qm); ctx->sec =3D sec; @@ -632,6 +630,9 @@ static void sec_ctx_base_uninit(struct sec_ctx *ctx) { int i; =20 + if (!ctx->qps) + return; + for (i =3D 0; i < ctx->sec->ctx_q_num; i++) sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); =20 @@ -643,6 +644,9 @@ static int sec_cipher_init(struct sec_ctx *ctx) { struct sec_cipher_ctx *c_ctx =3D &ctx->c_ctx; =20 + if (!ctx->qps) + return 0; + c_ctx->c_key =3D dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE, &c_ctx->c_key_dma, GFP_KERNEL); if (!c_ctx->c_key) @@ -655,6 +659,9 @@ static void sec_cipher_uninit(struct sec_ctx *ctx) { struct sec_cipher_ctx *c_ctx =3D &ctx->c_ctx; =20 + if (!ctx->qps) + return; + memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE); dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE, c_ctx->c_key, c_ctx->c_key_dma); @@ -676,6 +683,9 @@ static void sec_auth_uninit(struct sec_ctx *ctx) { struct sec_auth_ctx *a_ctx =3D &ctx->a_ctx; =20 + if (!ctx->qps) + return; + memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE); dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, a_ctx->a_key, a_ctx->a_key_dma); @@ -713,7 +723,7 @@ static int sec_skcipher_init(struct crypto_skcipher *tf= m) } =20 ret =3D sec_ctx_base_init(ctx); - if (ret) + if (ret && ret !=3D -ENODEV) return ret; =20 ret =3D sec_cipher_init(ctx); @@ -824,6 +834,9 @@ static int sec_skcipher_setkey(struct crypto_skcipher *= tfm, const u8 *key, struct device *dev =3D ctx->dev; int ret; =20 + if (!ctx->qps) + goto set_soft_key; + if (c_mode =3D=3D SEC_CMODE_XTS) { ret =3D xts_verify_key(tfm, key, keylen); if (ret) { @@ -854,13 +867,14 @@ static int sec_skcipher_setkey(struct crypto_skcipher= *tfm, const u8 *key, } =20 memcpy(c_ctx->c_key, key, keylen); - if (c_ctx->fbtfm) { - ret =3D crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); - if (ret) { - dev_err(dev, "failed to set fallback skcipher key!\n"); - return ret; - } + +set_soft_key: + ret =3D crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); + if (ret) { + dev_err(dev, "failed to set fallback skcipher key!\n"); + return ret; } + return 0; } =20 @@ -1139,6 +1153,9 @@ static int sec_aead_setkey(struct crypto_aead *tfm, c= onst u8 *key, struct crypto_authenc_keys keys; int ret; =20 + if (!ctx->qps) + return sec_aead_fallback_setkey(a_ctx, tfm, key, keylen); + ctx->a_ctx.a_alg =3D a_alg; ctx->c_ctx.c_alg =3D c_alg; c_ctx->c_mode =3D c_mode; @@ -1833,6 +1850,9 @@ static int sec_skcipher_ctx_init(struct crypto_skciph= er *tfm) if (ret) return ret; =20 + if (!ctx->qps) + return 0; + if (ctx->sec->qm.ver < QM_HW_V3) { ctx->type_supported =3D SEC_BD_TYPE2; ctx->req_op =3D &sec_skcipher_req_ops; @@ -1841,7 +1861,7 @@ static int sec_skcipher_ctx_init(struct crypto_skciph= er *tfm) ctx->req_op =3D &sec_skcipher_req_ops_v3; } =20 - return ret; + return 0; } =20 static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm) @@ -1909,7 +1929,7 @@ static int sec_aead_ctx_init(struct crypto_aead *tfm,= const char *hash_name) int ret; =20 ret =3D sec_aead_init(tfm); - if (ret) { + if (ret && ret !=3D -ENODEV) { pr_err("hisi_sec2: aead init error!\n"); return ret; } @@ -1951,7 +1971,7 @@ static int sec_aead_xcm_ctx_init(struct crypto_aead *= tfm) int ret; =20 ret =3D sec_aead_init(tfm); - if (ret) { + if (ret && ret !=3D -ENODEV) { dev_err(ctx->dev, "hisi_sec2: aead xcm init error!\n"); return ret; } @@ -2098,6 +2118,9 @@ static int sec_skcipher_crypto(struct skcipher_reques= t *sk_req, bool encrypt) bool need_fallback =3D false; int ret; =20 + if (!ctx->qps) + goto soft_crypto; + if (!sk_req->cryptlen) { if (ctx->c_ctx.c_mode =3D=3D SEC_CMODE_XTS) return -EINVAL; @@ -2114,9 +2137,12 @@ static int sec_skcipher_crypto(struct skcipher_reque= st *sk_req, bool encrypt) return -EINVAL; =20 if (unlikely(ctx->c_ctx.fallback || need_fallback)) - return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); + goto soft_crypto; =20 return ctx->req_op->process(ctx, req); + +soft_crypto: + return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); } =20 static int sec_skcipher_encrypt(struct skcipher_request *sk_req) @@ -2346,6 +2372,9 @@ static int sec_aead_crypto(struct aead_request *a_req= , bool encrypt) bool need_fallback =3D false; int ret; =20 + if (!ctx->qps) + goto soft_crypto; + req->flag =3D a_req->base.flags; req->aead_req.aead_req =3D a_req; req->c_req.encrypt =3D encrypt; @@ -2355,11 +2384,14 @@ static int sec_aead_crypto(struct aead_request *a_r= eq, bool encrypt) ret =3D sec_aead_param_check(ctx, req, &need_fallback); if (unlikely(ret)) { if (need_fallback) - return sec_aead_soft_crypto(ctx, a_req, encrypt); + goto soft_crypto; return -EINVAL; } =20 return ctx->req_op->process(ctx, req); + +soft_crypto: + return sec_aead_soft_crypto(ctx, a_req, encrypt); } =20 static int sec_aead_encrypt(struct aead_request *a_req) diff --git a/drivers/crypto/hisilicon/trng/trng.c b/drivers/crypto/hisilico= n/trng/trng.c index 97e500db0a82..b2d9b5310b78 100644 --- a/drivers/crypto/hisilicon/trng/trng.c +++ b/drivers/crypto/hisilicon/trng/trng.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2019 HiSilicon Limited. */ =20 +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include =20 #define HISI_TRNG_REG 0x00F0 #define HISI_TRNG_BYTES 4 @@ -40,6 +40,7 @@ #define SEED_SHIFT_24 24 #define SEED_SHIFT_16 16 #define SEED_SHIFT_8 8 +#define SW_MAX_RANDOM_BYTES 65520 =20 struct hisi_trng_list { struct mutex lock; @@ -53,8 +54,10 @@ struct hisi_trng { struct list_head list; struct hwrng rng; u32 ver; - bool is_used; - struct mutex mutex; + u32 ctx_num; + /* The bytes of the random number generated since the last seeding. */ + u32 random_bytes; + struct mutex lock; }; =20 struct hisi_trng_ctx { @@ -63,10 +66,14 @@ struct hisi_trng_ctx { =20 static atomic_t trng_active_devs; static struct hisi_trng_list trng_devices; +static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool w= ait); =20 -static void hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) +static int hisi_trng_set_seed(struct hisi_trng *trng, const u8 *seed) { u32 val, seed_reg, i; + int ret; + + writel(0x0, trng->base + SW_DRBG_BLOCKS); =20 for (i =3D 0; i < SW_DRBG_SEED_SIZE; i +=3D SW_DRBG_SEED_SIZE / SW_DRBG_SEED_REGS_NUM) { @@ -78,6 +85,20 @@ static void hisi_trng_set_seed(struct hisi_trng *trng, c= onst u8 *seed) seed_reg =3D (i >> SW_DRBG_NUM_SHIFT) % SW_DRBG_SEED_REGS_NUM; writel(val, trng->base + SW_DRBG_SEED(seed_reg)); } + + writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), + trng->base + SW_DRBG_BLOCKS); + writel(0x1, trng->base + SW_DRBG_INIT); + ret =3D readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, + val, val & BIT(0), SLEEP_US, TIMEOUT_US); + if (ret) { + pr_err("failed to init trng(%d)\n", ret); + return -EIO; + } + + trng->random_bytes =3D 0; + + return 0; } =20 static int hisi_trng_seed(struct crypto_rng *tfm, const u8 *seed, @@ -85,8 +106,7 @@ static int hisi_trng_seed(struct crypto_rng *tfm, const = u8 *seed, { struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); struct hisi_trng *trng =3D ctx->trng; - u32 val =3D 0; - int ret =3D 0; + int ret; =20 if (slen < SW_DRBG_SEED_SIZE) { pr_err("slen(%u) is not matched with trng(%d)\n", slen, @@ -94,43 +114,45 @@ static int hisi_trng_seed(struct crypto_rng *tfm, cons= t u8 *seed, return -EINVAL; } =20 - writel(0x0, trng->base + SW_DRBG_BLOCKS); - hisi_trng_set_seed(trng, seed); + mutex_lock(&trng->lock); + ret =3D hisi_trng_set_seed(trng, seed); + mutex_unlock(&trng->lock); =20 - writel(SW_DRBG_BLOCKS_NUM | (0x1 << SW_DRBG_ENABLE_SHIFT), - trng->base + SW_DRBG_BLOCKS); - writel(0x1, trng->base + SW_DRBG_INIT); + return ret; +} =20 - ret =3D readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, - val, val & BIT(0), SLEEP_US, TIMEOUT_US); - if (ret) - pr_err("fail to init trng(%d)\n", ret); +static int hisi_trng_reseed(struct hisi_trng *trng) +{ + u8 seed[SW_DRBG_SEED_SIZE]; + int size; =20 - return ret; + if (!trng->random_bytes) + return 0; + + size =3D hisi_trng_read(&trng->rng, seed, SW_DRBG_SEED_SIZE, false); + if (size !=3D SW_DRBG_SEED_SIZE) + return -EIO; + + return hisi_trng_set_seed(trng, seed); } =20 -static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, - unsigned int slen, u8 *dstn, unsigned int dlen) +static int hisi_trng_get_bytes(struct hisi_trng *trng, u8 *dstn, unsigned = int dlen) { - struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); - struct hisi_trng *trng =3D ctx->trng; u32 data[SW_DRBG_DATA_NUM]; u32 currsize =3D 0; u32 val =3D 0; int ret; u32 i; =20 - if (dlen > SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES || dlen =3D=3D 0) { - pr_err("dlen(%d) exceeds limit(%d)!\n", dlen, - SW_DRBG_BLOCKS_NUM * SW_DRBG_BYTES); - return -EINVAL; - } + ret =3D hisi_trng_reseed(trng); + if (ret) + return ret; =20 do { ret =3D readl_relaxed_poll_timeout(trng->base + SW_DRBG_STATUS, - val, val & BIT(1), SLEEP_US, TIMEOUT_US); + val, val & BIT(1), SLEEP_US, TIMEOUT_US); if (ret) { - pr_err("fail to generate random number(%d)!\n", ret); + pr_err("failed to generate random number(%d)!\n", ret); break; } =20 @@ -145,30 +167,57 @@ static int hisi_trng_generate(struct crypto_rng *tfm,= const u8 *src, currsize =3D dlen; } =20 + trng->random_bytes +=3D SW_DRBG_BYTES; writel(0x1, trng->base + SW_DRBG_GEN); } while (currsize < dlen); =20 return ret; } =20 +static int hisi_trng_generate(struct crypto_rng *tfm, const u8 *src, + unsigned int slen, u8 *dstn, unsigned int dlen) +{ + struct hisi_trng_ctx *ctx =3D crypto_rng_ctx(tfm); + struct hisi_trng *trng =3D ctx->trng; + unsigned int currsize =3D 0; + unsigned int block_size; + int ret; + + if (!dstn || !dlen) { + pr_err("output is error, dlen %u!\n", dlen); + return -EINVAL; + } + + do { + block_size =3D min_t(unsigned int, dlen - currsize, SW_MAX_RANDOM_BYTES); + mutex_lock(&trng->lock); + ret =3D hisi_trng_get_bytes(trng, dstn + currsize, block_size); + mutex_unlock(&trng->lock); + if (ret) + return ret; + currsize +=3D block_size; + } while (currsize < dlen); + + return 0; +} + static int hisi_trng_init(struct crypto_tfm *tfm) { struct hisi_trng_ctx *ctx =3D crypto_tfm_ctx(tfm); struct hisi_trng *trng; - int ret =3D -EBUSY; + u32 ctx_num =3D ~0; =20 mutex_lock(&trng_devices.lock); list_for_each_entry(trng, &trng_devices.list, list) { - if (!trng->is_used) { - trng->is_used =3D true; + if (trng->ctx_num < ctx_num) { + ctx_num =3D trng->ctx_num; ctx->trng =3D trng; - ret =3D 0; - break; } } + ctx->trng->ctx_num++; mutex_unlock(&trng_devices.lock); =20 - return ret; + return 0; } =20 static void hisi_trng_exit(struct crypto_tfm *tfm) @@ -176,7 +225,7 @@ static void hisi_trng_exit(struct crypto_tfm *tfm) struct hisi_trng_ctx *ctx =3D crypto_tfm_ctx(tfm); =20 mutex_lock(&trng_devices.lock); - ctx->trng->is_used =3D false; + ctx->trng->ctx_num--; mutex_unlock(&trng_devices.lock); } =20 @@ -238,7 +287,7 @@ static int hisi_trng_del_from_list(struct hisi_trng *tr= ng) int ret =3D -EBUSY; =20 mutex_lock(&trng_devices.lock); - if (!trng->is_used) { + if (!trng->ctx_num) { list_del(&trng->list); ret =3D 0; } @@ -262,7 +311,9 @@ static int hisi_trng_probe(struct platform_device *pdev) if (IS_ERR(trng->base)) return PTR_ERR(trng->base); =20 - trng->is_used =3D false; + trng->ctx_num =3D 0; + trng->random_bytes =3D SW_MAX_RANDOM_BYTES; + mutex_init(&trng->lock); trng->ver =3D readl(trng->base + HISI_TRNG_VERSION); if (!trng_devices.is_init) { INIT_LIST_HEAD(&trng_devices.list); diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/his= ilicon/zip/zip_crypto.c index 6608971d10cd..d21ce4094d7d 100644 --- a/drivers/crypto/hisilicon/zip/zip_crypto.c +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c @@ -16,36 +16,14 @@ #define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0) /* hisi_zip_sqe dw9 */ #define HZIP_REQ_TYPE_M GENMASK(7, 0) -#define HZIP_ALG_TYPE_ZLIB 0x02 -#define HZIP_ALG_TYPE_GZIP 0x03 +#define HZIP_ALG_TYPE_DEFLATE 0x01 #define HZIP_BUF_TYPE_M GENMASK(11, 8) -#define HZIP_PBUFFER 0x0 #define HZIP_SGL 0x1 =20 -#define HZIP_ZLIB_HEAD_SIZE 2 -#define HZIP_GZIP_HEAD_SIZE 10 - -#define GZIP_HEAD_FHCRC_BIT BIT(1) -#define GZIP_HEAD_FEXTRA_BIT BIT(2) -#define GZIP_HEAD_FNAME_BIT BIT(3) -#define GZIP_HEAD_FCOMMENT_BIT BIT(4) - -#define GZIP_HEAD_FLG_SHIFT 3 -#define GZIP_HEAD_FEXTRA_SHIFT 10 -#define GZIP_HEAD_FEXTRA_XLEN 2UL -#define GZIP_HEAD_FHCRC_SIZE 2 - -#define HZIP_GZIP_HEAD_BUF 256 #define HZIP_ALG_PRIORITY 300 #define HZIP_SGL_SGE_NR 10 =20 -#define HZIP_ALG_ZLIB GENMASK(1, 0) -#define HZIP_ALG_GZIP GENMASK(3, 2) - -static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] =3D {0x78, 0x9c}; -static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] =3D { - 0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03 -}; +#define HZIP_ALG_DEFLATE GENMASK(5, 4) =20 enum hisi_zip_alg_type { HZIP_ALG_TYPE_COMP =3D 0, @@ -58,26 +36,17 @@ enum { HZIP_CTX_Q_NUM }; =20 +#define GET_REQ_FROM_SQE(sqe) ((u64)(sqe)->dw26 | (u64)(sqe)->dw27 << 32) #define COMP_NAME_TO_TYPE(alg_name) \ - (!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB : \ - !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0) \ - -#define TO_HEAD_SIZE(req_type) \ - (((req_type) =3D=3D HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) : \ - ((req_type) =3D=3D HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0) \ - -#define TO_HEAD(req_type) \ - (((req_type) =3D=3D HZIP_ALG_TYPE_ZLIB) ? zlib_head : \ - ((req_type) =3D=3D HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL) \ + (!strcmp((alg_name), "deflate") ? HZIP_ALG_TYPE_DEFLATE : 0) =20 struct hisi_zip_req { struct acomp_req *req; - u32 sskip; - u32 dskip; struct hisi_acc_hw_sgl *hw_src; struct hisi_acc_hw_sgl *hw_dst; dma_addr_t dma_src; dma_addr_t dma_dst; + struct hisi_zip_qp_ctx *qp_ctx; u16 req_id; }; =20 @@ -104,7 +73,6 @@ struct hisi_zip_sqe_ops { void (*fill_req_type)(struct hisi_zip_sqe *sqe, u8 req_type); void (*fill_tag)(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req); void (*fill_sqe_type)(struct hisi_zip_sqe *sqe, u8 sqe_type); - u32 (*get_tag)(struct hisi_zip_sqe *sqe); u32 (*get_status)(struct hisi_zip_sqe *sqe); u32 (*get_dstlen)(struct hisi_zip_sqe *sqe); }; @@ -138,85 +106,8 @@ static u16 sgl_sge_nr =3D HZIP_SGL_SGE_NR; module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444); MODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)"); =20 -static u32 get_extra_field_size(const u8 *start) -{ - return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN; -} - -static u32 get_name_field_size(const u8 *start) -{ - return strlen(start) + 1; -} - -static u32 get_comment_field_size(const u8 *start) -{ - return strlen(start) + 1; -} - -static u32 __get_gzip_head_size(const u8 *src) -{ - u8 head_flg =3D *(src + GZIP_HEAD_FLG_SHIFT); - u32 size =3D GZIP_HEAD_FEXTRA_SHIFT; - - if (head_flg & GZIP_HEAD_FEXTRA_BIT) - size +=3D get_extra_field_size(src + size); - if (head_flg & GZIP_HEAD_FNAME_BIT) - size +=3D get_name_field_size(src + size); - if (head_flg & GZIP_HEAD_FCOMMENT_BIT) - size +=3D get_comment_field_size(src + size); - if (head_flg & GZIP_HEAD_FHCRC_BIT) - size +=3D GZIP_HEAD_FHCRC_SIZE; - - return size; -} - -static u32 __maybe_unused get_gzip_head_size(struct scatterlist *sgl) -{ - char buf[HZIP_GZIP_HEAD_BUF]; - - sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf)); - - return __get_gzip_head_size(buf); -} - -static int add_comp_head(struct scatterlist *dst, u8 req_type) -{ - int head_size =3D TO_HEAD_SIZE(req_type); - const u8 *head =3D TO_HEAD(req_type); - int ret; - - ret =3D sg_copy_from_buffer(dst, sg_nents(dst), head, head_size); - if (unlikely(ret !=3D head_size)) { - pr_err("the head size of buffer is wrong (%d)!\n", ret); - return -ENOMEM; - } - - return head_size; -} - -static int get_comp_head_size(struct acomp_req *acomp_req, u8 req_type) -{ - if (unlikely(!acomp_req->src || !acomp_req->slen)) - return -EINVAL; - - if (unlikely(req_type =3D=3D HZIP_ALG_TYPE_GZIP && - acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT)) - return -EINVAL; - - switch (req_type) { - case HZIP_ALG_TYPE_ZLIB: - return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB); - case HZIP_ALG_TYPE_GZIP: - return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP); - default: - pr_err("request type does not support!\n"); - return -EINVAL; - } -} - -static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, - struct hisi_zip_qp_ctx *qp_ctx, - size_t head_size, bool is_comp) +static struct hisi_zip_req *hisi_zip_create_req(struct hisi_zip_qp_ctx *qp= _ctx, + struct acomp_req *req) { struct hisi_zip_req_q *req_q =3D &qp_ctx->req_q; struct hisi_zip_req *q =3D req_q->q; @@ -238,14 +129,7 @@ static struct hisi_zip_req *hisi_zip_create_req(struct= acomp_req *req, req_cache =3D q + req_id; req_cache->req_id =3D req_id; req_cache->req =3D req; - - if (is_comp) { - req_cache->sskip =3D 0; - req_cache->dskip =3D head_size; - } else { - req_cache->sskip =3D head_size; - req_cache->dskip =3D 0; - } + req_cache->qp_ctx =3D qp_ctx; =20 return req_cache; } @@ -272,10 +156,8 @@ static void hisi_zip_fill_buf_size(struct hisi_zip_sqe= *sqe, struct hisi_zip_req { struct acomp_req *a_req =3D req->req; =20 - sqe->input_data_length =3D a_req->slen - req->sskip; - sqe->dest_avail_out =3D a_req->dlen - req->dskip; - sqe->dw7 =3D FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, req->sskip); - sqe->dw8 =3D FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, req->dskip); + sqe->input_data_length =3D a_req->slen; + sqe->dest_avail_out =3D a_req->dlen; } =20 static void hisi_zip_fill_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type) @@ -296,14 +178,10 @@ static void hisi_zip_fill_req_type(struct hisi_zip_sq= e *sqe, u8 req_type) sqe->dw9 =3D val; } =20 -static void hisi_zip_fill_tag_v1(struct hisi_zip_sqe *sqe, struct hisi_zip= _req *req) -{ - sqe->dw13 =3D req->req_id; -} - -static void hisi_zip_fill_tag_v2(struct hisi_zip_sqe *sqe, struct hisi_zip= _req *req) +static void hisi_zip_fill_tag(struct hisi_zip_sqe *sqe, struct hisi_zip_re= q *req) { - sqe->dw26 =3D req->req_id; + sqe->dw26 =3D lower_32_bits((u64)req); + sqe->dw27 =3D upper_32_bits((u64)req); } =20 static void hisi_zip_fill_sqe_type(struct hisi_zip_sqe *sqe, u8 sqe_type) @@ -330,8 +208,8 @@ static void hisi_zip_fill_sqe(struct hisi_zip_ctx *ctx,= struct hisi_zip_sqe *sqe ops->fill_sqe_type(sqe, ops->sqe_type); } =20 -static int hisi_zip_do_work(struct hisi_zip_req *req, - struct hisi_zip_qp_ctx *qp_ctx) +static int hisi_zip_do_work(struct hisi_zip_qp_ctx *qp_ctx, + struct hisi_zip_req *req) { struct hisi_acc_sgl_pool *pool =3D qp_ctx->sgl_pool; struct hisi_zip_dfx *dfx =3D &qp_ctx->zip_dev->dfx; @@ -357,7 +235,7 @@ static int hisi_zip_do_work(struct hisi_zip_req *req, &req->dma_dst); if (IS_ERR(req->hw_dst)) { ret =3D PTR_ERR(req->hw_dst); - dev_err(dev, "failed to map the dst buffer to hw slg (%d)!\n", + dev_err(dev, "failed to map the dst buffer to hw sgl (%d)!\n", ret); goto err_unmap_input; } @@ -383,16 +261,6 @@ static int hisi_zip_do_work(struct hisi_zip_req *req, return ret; } =20 -static u32 hisi_zip_get_tag_v1(struct hisi_zip_sqe *sqe) -{ - return sqe->dw13; -} - -static u32 hisi_zip_get_tag_v2(struct hisi_zip_sqe *sqe) -{ - return sqe->dw26; -} - static u32 hisi_zip_get_status(struct hisi_zip_sqe *sqe) { return sqe->dw3 & HZIP_BD_STATUS_M; @@ -405,17 +273,15 @@ static u32 hisi_zip_get_dstlen(struct hisi_zip_sqe *s= qe) =20 static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) { - struct hisi_zip_qp_ctx *qp_ctx =3D qp->qp_ctx; + struct hisi_zip_sqe *sqe =3D data; + struct hisi_zip_req *req =3D (struct hisi_zip_req *)GET_REQ_FROM_SQE(sqe); + struct hisi_zip_qp_ctx *qp_ctx =3D req->qp_ctx; const struct hisi_zip_sqe_ops *ops =3D qp_ctx->ctx->ops; struct hisi_zip_dfx *dfx =3D &qp_ctx->zip_dev->dfx; - struct hisi_zip_req_q *req_q =3D &qp_ctx->req_q; struct device *dev =3D &qp->qm->pdev->dev; - struct hisi_zip_sqe *sqe =3D data; - u32 tag =3D ops->get_tag(sqe); - struct hisi_zip_req *req =3D req_q->q + tag; struct acomp_req *acomp_req =3D req->req; - u32 status, dlen, head_size; int err =3D 0; + u32 status; =20 atomic64_inc(&dfx->recv_cnt); status =3D ops->get_status(sqe); @@ -427,13 +293,10 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, voi= d *data) err =3D -EIO; } =20 - dlen =3D ops->get_dstlen(sqe); - hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src); hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst); =20 - head_size =3D (qp->alg_type =3D=3D 0) ? TO_HEAD_SIZE(qp->req_type) : 0; - acomp_req->dlen =3D dlen + head_size; + acomp_req->dlen =3D ops->get_dstlen(sqe); =20 if (acomp_req->base.complete) acomp_request_complete(acomp_req, err); @@ -447,22 +310,13 @@ static int hisi_zip_acompress(struct acomp_req *acomp= _req) struct hisi_zip_qp_ctx *qp_ctx =3D &ctx->qp_ctx[HZIP_QPC_COMP]; struct device *dev =3D &qp_ctx->qp->qm->pdev->dev; struct hisi_zip_req *req; - int head_size; int ret; =20 - /* let's output compression head now */ - head_size =3D add_comp_head(acomp_req->dst, qp_ctx->qp->req_type); - if (unlikely(head_size < 0)) { - dev_err_ratelimited(dev, "failed to add comp head (%d)!\n", - head_size); - return head_size; - } - - req =3D hisi_zip_create_req(acomp_req, qp_ctx, head_size, true); + req =3D hisi_zip_create_req(qp_ctx, acomp_req); if (IS_ERR(req)) return PTR_ERR(req); =20 - ret =3D hisi_zip_do_work(req, qp_ctx); + ret =3D hisi_zip_do_work(qp_ctx, req); if (unlikely(ret !=3D -EINPROGRESS)) { dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret); hisi_zip_remove_req(qp_ctx, req); @@ -477,20 +331,13 @@ static int hisi_zip_adecompress(struct acomp_req *aco= mp_req) struct hisi_zip_qp_ctx *qp_ctx =3D &ctx->qp_ctx[HZIP_QPC_DECOMP]; struct device *dev =3D &qp_ctx->qp->qm->pdev->dev; struct hisi_zip_req *req; - int head_size, ret; - - head_size =3D get_comp_head_size(acomp_req, qp_ctx->qp->req_type); - if (unlikely(head_size < 0)) { - dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n", - head_size); - return head_size; - } + int ret; =20 - req =3D hisi_zip_create_req(acomp_req, qp_ctx, head_size, false); + req =3D hisi_zip_create_req(qp_ctx, acomp_req); if (IS_ERR(req)) return PTR_ERR(req); =20 - ret =3D hisi_zip_do_work(req, qp_ctx); + ret =3D hisi_zip_do_work(qp_ctx, req); if (unlikely(ret !=3D -EINPROGRESS)) { dev_info_ratelimited(dev, "failed to do decompress (%d)!\n", ret); @@ -527,28 +374,14 @@ static void hisi_zip_release_qp(struct hisi_zip_qp_ct= x *qp_ctx) hisi_qm_free_qps(&qp_ctx->qp, 1); } =20 -static const struct hisi_zip_sqe_ops hisi_zip_ops_v1 =3D { - .sqe_type =3D 0, - .fill_addr =3D hisi_zip_fill_addr, - .fill_buf_size =3D hisi_zip_fill_buf_size, - .fill_buf_type =3D hisi_zip_fill_buf_type, - .fill_req_type =3D hisi_zip_fill_req_type, - .fill_tag =3D hisi_zip_fill_tag_v1, - .fill_sqe_type =3D hisi_zip_fill_sqe_type, - .get_tag =3D hisi_zip_get_tag_v1, - .get_status =3D hisi_zip_get_status, - .get_dstlen =3D hisi_zip_get_dstlen, -}; - -static const struct hisi_zip_sqe_ops hisi_zip_ops_v2 =3D { +static const struct hisi_zip_sqe_ops hisi_zip_ops =3D { .sqe_type =3D 0x3, .fill_addr =3D hisi_zip_fill_addr, .fill_buf_size =3D hisi_zip_fill_buf_size, .fill_buf_type =3D hisi_zip_fill_buf_type, .fill_req_type =3D hisi_zip_fill_req_type, - .fill_tag =3D hisi_zip_fill_tag_v2, + .fill_tag =3D hisi_zip_fill_tag, .fill_sqe_type =3D hisi_zip_fill_sqe_type, - .get_tag =3D hisi_zip_get_tag_v2, .get_status =3D hisi_zip_get_status, .get_dstlen =3D hisi_zip_get_dstlen, }; @@ -584,10 +417,7 @@ static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi= _zip_ctx, u8 req_type, int qp_ctx->zip_dev =3D hisi_zip; } =20 - if (hisi_zip->qm.ver < QM_HW_V3) - hisi_zip_ctx->ops =3D &hisi_zip_ops_v1; - else - hisi_zip_ctx->ops =3D &hisi_zip_ops_v2; + hisi_zip_ctx->ops =3D &hisi_zip_ops; =20 return 0; } @@ -739,101 +569,53 @@ static void hisi_zip_acomp_exit(struct crypto_acomp = *tfm) { struct hisi_zip_ctx *ctx =3D crypto_tfm_ctx(&tfm->base); =20 - hisi_zip_set_acomp_cb(ctx, NULL); hisi_zip_release_sgl_pool(ctx); hisi_zip_release_req_q(ctx); hisi_zip_ctx_exit(ctx); } =20 -static struct acomp_alg hisi_zip_acomp_zlib =3D { +static struct acomp_alg hisi_zip_acomp_deflate =3D { .init =3D hisi_zip_acomp_init, .exit =3D hisi_zip_acomp_exit, .compress =3D hisi_zip_acompress, .decompress =3D hisi_zip_adecompress, .base =3D { - .cra_name =3D "zlib-deflate", - .cra_driver_name =3D "hisi-zlib-acomp", + .cra_name =3D "deflate", + .cra_driver_name =3D "hisi-deflate-acomp", .cra_module =3D THIS_MODULE, - .cra_priority =3D HZIP_ALG_PRIORITY, + .cra_priority =3D HZIP_ALG_PRIORITY, .cra_ctxsize =3D sizeof(struct hisi_zip_ctx), } }; =20 -static int hisi_zip_register_zlib(struct hisi_qm *qm) +static int hisi_zip_register_deflate(struct hisi_qm *qm) { int ret; =20 - if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB)) + if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE)) return 0; =20 - ret =3D crypto_register_acomp(&hisi_zip_acomp_zlib); + ret =3D crypto_register_acomp(&hisi_zip_acomp_deflate); if (ret) - dev_err(&qm->pdev->dev, "failed to register to zlib (%d)!\n", ret); + dev_err(&qm->pdev->dev, "failed to register to deflate (%d)!\n", ret); =20 return ret; } =20 -static void hisi_zip_unregister_zlib(struct hisi_qm *qm) +static void hisi_zip_unregister_deflate(struct hisi_qm *qm) { - if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB)) + if (!hisi_zip_alg_support(qm, HZIP_ALG_DEFLATE)) return; =20 - crypto_unregister_acomp(&hisi_zip_acomp_zlib); -} - -static struct acomp_alg hisi_zip_acomp_gzip =3D { - .init =3D hisi_zip_acomp_init, - .exit =3D hisi_zip_acomp_exit, - .compress =3D hisi_zip_acompress, - .decompress =3D hisi_zip_adecompress, - .base =3D { - .cra_name =3D "gzip", - .cra_driver_name =3D "hisi-gzip-acomp", - .cra_module =3D THIS_MODULE, - .cra_priority =3D HZIP_ALG_PRIORITY, - .cra_ctxsize =3D sizeof(struct hisi_zip_ctx), - } -}; - -static int hisi_zip_register_gzip(struct hisi_qm *qm) -{ - int ret; - - if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP)) - return 0; - - ret =3D crypto_register_acomp(&hisi_zip_acomp_gzip); - if (ret) - dev_err(&qm->pdev->dev, "failed to register to gzip (%d)!\n", ret); - - return ret; -} - -static void hisi_zip_unregister_gzip(struct hisi_qm *qm) -{ - if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP)) - return; - - crypto_unregister_acomp(&hisi_zip_acomp_gzip); + crypto_unregister_acomp(&hisi_zip_acomp_deflate); } =20 int hisi_zip_register_to_crypto(struct hisi_qm *qm) { - int ret =3D 0; - - ret =3D hisi_zip_register_zlib(qm); - if (ret) - return ret; - - ret =3D hisi_zip_register_gzip(qm); - if (ret) - hisi_zip_unregister_zlib(qm); - - return ret; + return hisi_zip_register_deflate(qm); } =20 void hisi_zip_unregister_from_crypto(struct hisi_qm *qm) { - hisi_zip_unregister_zlib(qm); - hisi_zip_unregister_gzip(qm); + hisi_zip_unregister_deflate(qm); } diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisil= icon/zip/zip_main.c index b70aa6032874..91212d9584bf 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -238,8 +238,8 @@ static struct hisi_qm_cap_info zip_basic_cap_info[] =3D= { {ZIP_CLUSTER_DECOMP_NUM_CAP, 0x313C, 0, GENMASK(7, 0), 0x6, 0x6, 0x3}, {ZIP_DECOMP_ENABLE_BITMAP, 0x3140, 16, GENMASK(15, 0), 0xFC, 0xFC, 0x1C}, {ZIP_COMP_ENABLE_BITMAP, 0x3140, 0, GENMASK(15, 0), 0x3, 0x3, 0x3}, - {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0xF, 0xF, 0xF}, - {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0xFF}, + {ZIP_DRV_ALG_BITMAP, 0x3144, 0, GENMASK(31, 0), 0x0, 0x0, 0x30}, + {ZIP_DEV_ALG_BITMAP, 0x3148, 0, GENMASK(31, 0), 0xF, 0xF, 0x3F}, {ZIP_CORE1_ALG_BITMAP, 0x314C, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5}, {ZIP_CORE2_ALG_BITMAP, 0x3150, 0, GENMASK(31, 0), 0x5, 0x5, 0xD5}, {ZIP_CORE3_ALG_BITMAP, 0x3154, 0, GENMASK(31, 0), 0xA, 0xA, 0x2A}, diff --git a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c b/driv= ers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c index 388e58bcbcaf..4a1ea3e72032 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c +++ b/drivers/crypto/intel/qat/qat_common/adf_pfvf_pf_proto.c @@ -148,6 +148,16 @@ static struct pfvf_message handle_blkmsg_req(struct ad= f_accel_vf_info *vf_info, blk_byte =3D FIELD_GET(ADF_VF2PF_SMALL_BLOCK_BYTE_MASK, req.data); byte_max =3D ADF_VF2PF_SMALL_BLOCK_BYTE_MAX; break; + default: + dev_err(&GET_DEV(vf_info->accel_dev), + "Invalid BlockMsg type 0x%.4x received from VF%u\n", + req.type, vf_info->vf_nr); + resp.type =3D ADF_PF2VF_MSGTYPE_BLKMSG_RESP; + resp.data =3D FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_TYPE_MASK, + ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR) | + FIELD_PREP(ADF_PF2VF_BLKMSG_RESP_DATA_MASK, + ADF_PF2VF_UNSPECIFIED_ERROR); + return resp; } =20 /* Is this a request for CRC or data? */ diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c b/drivers/cry= pto/marvell/octeontx/otx_cptvf_main.c index 88a41d1ca5f6..6c0bfb3ea1c9 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_main.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_main.c @@ -168,7 +168,8 @@ static void free_command_queues(struct otx_cptvf *cptvf, chunk =3D list_first_entry(&cqinfo->queue[i].chead, struct otx_cpt_cmd_chunk, nextchunk); =20 - dma_free_coherent(&pdev->dev, chunk->size, + dma_free_coherent(&pdev->dev, + chunk->size + OTX_CPT_NEXT_CHUNK_PTR_SIZE, chunk->head, chunk->dma_addr); chunk->head =3D NULL; diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index 36b20b844b10..f9738c863df0 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -710,14 +710,13 @@ static int cxl_decoder_commit(struct cxl_decoder *cxl= d) writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); up_read(&cxl_dpa_rwsem); =20 - port->commit_end++; rc =3D cxld_await_commit(hdm, cxld->id); if (rc) { dev_dbg(&port->dev, "%s: error %d committing decoder\n", dev_name(&cxld->dev), rc); - cxld->reset(cxld); return rc; } + port->commit_end++; cxld->flags |=3D CXL_DECODER_F_ENABLE; =20 return 0; diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 4f426be28688..93e00130400d 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -225,6 +225,7 @@ static void axi_dmac_start_transfer(struct axi_dmac_cha= n *chan) return; list_move_tail(&vdesc->node, &chan->active_descs); desc =3D to_axi_dmac_desc(vdesc); + chan->next_desc =3D desc; } sg =3D &desc->sg[desc->num_submitted]; =20 @@ -242,8 +243,6 @@ static void axi_dmac_start_transfer(struct axi_dmac_cha= n *chan) else chan->next_desc =3D NULL; flags |=3D AXI_DMAC_FLAG_LAST; - } else { - chan->next_desc =3D desc; } =20 sg->id =3D axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_ID); diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c index eccbcf67951f..34b194759d21 100644 --- a/drivers/dma/fsl-edma-main.c +++ b/drivers/dma/fsl-edma-main.c @@ -669,7 +669,7 @@ static int fsl_edma_probe(struct platform_device *pdev) return 0; } =20 -static int fsl_edma_remove(struct platform_device *pdev) +static void fsl_edma_remove(struct platform_device *pdev) { struct device_node *np =3D pdev->dev.of_node; struct fsl_edma_engine *fsl_edma =3D platform_get_drvdata(pdev); @@ -678,9 +678,6 @@ static int fsl_edma_remove(struct platform_device *pdev) of_dma_controller_free(np); dma_async_device_unregister(&fsl_edma->dma_dev); fsl_edma_cleanup_vchan(&fsl_edma->dma_dev); - fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs); - - return 0; } =20 static int fsl_edma_suspend_late(struct device *dev) @@ -749,7 +746,7 @@ static struct platform_driver fsl_edma_driver =3D { .pm =3D &fsl_edma_pm_ops, }, .probe =3D fsl_edma_probe, - .remove =3D fsl_edma_remove, + .remove_new =3D fsl_edma_remove, }; =20 static int __init fsl_edma_init(void) diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/m= tk-uart-apdma.c index 06d12ac39144..aa42a09fde1a 100644 --- a/drivers/dma/mediatek/mtk-uart-apdma.c +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -41,7 +41,7 @@ #define VFF_STOP_CLR_B 0 #define VFF_EN_CLR_B 0 #define VFF_INT_EN_CLR_B 0 -#define VFF_4G_SUPPORT_CLR_B 0 +#define VFF_ADDR2_CLR_B 0 =20 /* * interrupt trigger level for tx @@ -72,7 +72,7 @@ /* TX: the buffer size SW can write. RX: the buffer size HW can write. */ #define VFF_LEFT_SIZE 0x40 #define VFF_DEBUG_STATUS 0x50 -#define VFF_4G_SUPPORT 0x54 +#define VFF_ADDR2 0x54 =20 struct mtk_uart_apdmadev { struct dma_device ddev; @@ -149,7 +149,7 @@ static void mtk_uart_apdma_start_tx(struct mtk_chan *c) mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); =20 if (mtkd->support_33bits) - mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); + mtk_uart_apdma_write(c, VFF_ADDR2, upper_32_bits(d->addr)); } =20 mtk_uart_apdma_write(c, VFF_EN, VFF_EN_B); @@ -192,7 +192,7 @@ static void mtk_uart_apdma_start_rx(struct mtk_chan *c) mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B); =20 if (mtkd->support_33bits) - mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); + mtk_uart_apdma_write(c, VFF_ADDR2, upper_32_bits(d->addr)); } =20 mtk_uart_apdma_write(c, VFF_INT_EN, VFF_RX_INT_EN_B); @@ -298,7 +298,7 @@ static int mtk_uart_apdma_alloc_chan_resources(struct d= ma_chan *chan) } =20 if (mtkd->support_33bits) - mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); + mtk_uart_apdma_write(c, VFF_ADDR2, VFF_ADDR2_CLR_B); =20 err_pm: pm_runtime_put_noidle(mtkd->ddev.dev); diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index f414efdbd809..87956563cb1d 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -732,7 +732,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan= *chan, struct stm32_mdma_chan_config *chan_config =3D &chan->chan_config; struct scatterlist *sg; dma_addr_t src_addr, dst_addr; - u32 m2m_hw_period, ccr, ctcr, ctbr; + u32 m2m_hw_period =3D 0, ccr =3D 0, ctcr, ctbr; int i, ret =3D 0; =20 if (chan_config->m2m_hw) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 2469efddf540..6a384bd46952 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -582,6 +582,22 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *= dev_id) return ret; } =20 +static u32 find_burst_size(const u32 burst_lengths, u32 maxburst) +{ + if (!maxburst) + return 1; + + if (BIT(maxburst) & burst_lengths) + return maxburst; + + /* Hardware only does power-of-two bursts. */ + for (u32 burst =3D rounddown_pow_of_two(maxburst); burst > 0; burst /=3D = 2) + if (BIT(burst) & burst_lengths) + return burst; + + return 1; +} + static int set_config(struct sun6i_dma_dev *sdev, struct dma_slave_config *sconfig, enum dma_transfer_direction direction, @@ -615,15 +631,13 @@ static int set_config(struct sun6i_dma_dev *sdev, return -EINVAL; if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths)) return -EINVAL; - if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths)) - return -EINVAL; - if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths)) - return -EINVAL; =20 src_width =3D convert_buswidth(src_addr_width); dst_width =3D convert_buswidth(dst_addr_width); - dst_burst =3D convert_burst(dst_maxburst); - src_burst =3D convert_burst(src_maxburst); + src_burst =3D find_burst_size(sdev->cfg->src_burst_lengths, src_maxburst); + dst_burst =3D find_burst_size(sdev->cfg->dst_burst_lengths, dst_maxburst); + dst_burst =3D convert_burst(dst_burst); + src_burst =3D convert_burst(src_burst); =20 *p_cfg =3D DMA_CHAN_CFG_SRC_WIDTH(src_width) | DMA_CHAN_CFG_DST_WIDTH(dst_width); diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 4f8f87207b67..dc1915ffc3cb 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -1573,8 +1573,7 @@ static int altr_portb_setup(struct altr_edac_device_d= ev *device) goto err_release_group_1; } rc =3D devm_request_irq(&altdev->ddev, altdev->sb_irq, - prv->ecc_irq_handler, - IRQF_ONESHOT | IRQF_TRIGGER_HIGH, + prv->ecc_irq_handler, IRQF_TRIGGER_HIGH, ecc_name, altdev); if (rc) { edac_printk(KERN_ERR, EDAC_DEVICE, "PortB SBERR IRQ error\n"); @@ -1597,8 +1596,7 @@ static int altr_portb_setup(struct altr_edac_device_d= ev *device) goto err_release_group_1; } rc =3D devm_request_irq(&altdev->ddev, altdev->db_irq, - prv->ecc_irq_handler, - IRQF_ONESHOT | IRQF_TRIGGER_HIGH, + prv->ecc_irq_handler, IRQF_TRIGGER_HIGH, ecc_name, altdev); if (rc) { edac_printk(KERN_ERR, EDAC_DEVICE, "PortB DBERR IRQ error\n"); @@ -1981,8 +1979,7 @@ static int altr_edac_a10_device_add(struct altr_arria= 10_edac *edac, goto err_release_group1; } rc =3D devm_request_irq(edac->dev, altdev->sb_irq, prv->ecc_irq_handler, - IRQF_ONESHOT | IRQF_TRIGGER_HIGH, - ecc_name, altdev); + IRQF_TRIGGER_HIGH, ecc_name, altdev); if (rc) { edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n"); goto err_release_group1; @@ -2004,7 +2001,7 @@ static int altr_edac_a10_device_add(struct altr_arria= 10_edac *edac, goto err_release_group1; } rc =3D devm_request_irq(edac->dev, altdev->db_irq, prv->ecc_irq_handler, - IRQF_ONESHOT | IRQF_TRIGGER_HIGH, + IRQF_TRIGGER_HIGH, ecc_name, altdev); if (rc) { edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n"); diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 4b5a71f8739d..8c6a291e01f6 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1111,6 +1111,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) =20 n =3D snprintf(p, space, " "); p +=3D n; + space -=3D n; for (branch =3D 0; branch < MAX_BRANCHES; branch++) { n =3D snprintf(p, space, " branch %d | ", branch); p +=3D n; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 49b4499269fb..68afb3bb8e29 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1025,13 +1025,13 @@ static void calculate_dimm_size(struct i5400_pvt *p= vt) space -=3D n; } =20 - space -=3D n; edac_dbg(2, "%s\n", mem_buffer); p =3D mem_buffer; space =3D PAGE_SIZE; =20 n =3D snprintf(p, space, " "); p +=3D n; + space -=3D n; for (branch =3D 0; branch < MAX_BRANCHES; branch++) { n =3D snprintf(p, space, " branch %d | ", branch); p +=3D n; diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-ar= m.c index 52d18490b59e..70e1735dfcdd 100644 --- a/drivers/firmware/efi/cper-arm.c +++ b/drivers/firmware/efi/cper-arm.c @@ -226,7 +226,8 @@ static void cper_print_arm_err_info(const char *pfx, u3= 2 type, } =20 void cper_print_proc_arm(const char *pfx, - const struct cper_sec_proc_arm *proc) + const struct cper_sec_proc_arm *proc, + u32 length) { int i, len, max_ctx_type; struct cper_arm_err_info *err_info; @@ -238,9 +239,12 @@ void cper_print_proc_arm(const char *pfx, =20 len =3D proc->section_length - (sizeof(*proc) + proc->err_info_num * (sizeof(*err_info))); - if (len < 0) { - printk("%ssection length: %d\n", pfx, proc->section_length); - printk("%ssection length is too small\n", pfx); + + if (len < 0 || proc->section_length > length) { + printk("%ssection length: %d, CPER size: %d\n", + pfx, proc->section_length, length); + printk("%ssection length is too %s\n", pfx, + (len < 0) ? "small" : "big"); printk("%sfirmware-generated error record is incorrect\n", pfx); printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num); return; diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 74ffaf44d74c..9d0f0bf3067c 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -555,6 +555,11 @@ static void cper_print_fw_err(const char *pfx, } else { offset =3D sizeof(*fw_err); } + if (offset > length) { + printk("%s""error section length is too small: offset=3D%d, length=3D%d\= n", + pfx, offset, length); + return; + } =20 buf +=3D offset; length -=3D offset; @@ -635,7 +640,8 @@ cper_estatus_print_section(const char *pfx, struct acpi= _hest_generic_data *gdata =20 printk("%ssection_type: ARM processor error\n", newpfx); if (gdata->error_data_length >=3D sizeof(*arm_err)) - cper_print_proc_arm(newpfx, arm_err); + cper_print_proc_arm(newpfx, arm_err, + gdata->error_data_length); else goto err_section_too_small; #endif diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 1ab161e00c86..ef55e3851b36 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -648,13 +648,13 @@ static __init int match_config_table(const efi_guid_t= *guid, =20 static __init void reserve_unaccepted(struct efi_unaccepted_memory *unacce= pted) { - phys_addr_t start, size; + phys_addr_t start, end; =20 start =3D PAGE_ALIGN_DOWN(efi.unaccepted); - size =3D PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size); + end =3D PAGE_ALIGN(efi.unaccepted + sizeof(*unaccepted) + unaccepted->siz= e); =20 - memblock_add(start, size); - memblock_reserve(start, size); + memblock_add(start, end - start); + memblock_reserve(start, end - start); } =20 int __init efi_config_parse_tables(const efi_config_table_t *config_tables, diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c index dd7a783d53b5..f1ced28793d2 100644 --- a/drivers/fpga/dfl.c +++ b/drivers/fpga/dfl.c @@ -2029,7 +2029,7 @@ static void __exit dfl_fpga_exit(void) bus_unregister(&dfl_bus_type); } =20 -module_init(dfl_fpga_init); +subsys_initcall(dfl_fpga_init); module_exit(dfl_fpga_exit); =20 MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support"); diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index a6affd83f275..ed6eae985117 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -83,7 +83,7 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct= device_node *np) * done with the bridges. * * Return: 0 for success (even if there are no bridges specified) - * or -EBUSY if any of the bridges are in use. + * or an error code if any of the bridges are not available. */ static int of_fpga_region_get_bridges(struct fpga_region *region) { @@ -130,10 +130,10 @@ static int of_fpga_region_get_bridges(struct fpga_reg= ion *region) ®ion->bridge_list); of_node_put(br); =20 - /* If any of the bridges are in use, give up */ - if (ret =3D=3D -EBUSY) { + /* If any of the bridges are not available, give up */ + if (ret) { fpga_bridges_put(®ion->bridge_list); - return -EBUSY; + return ret; } } =20 diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sg= pio.c index 72755fee6478..e69a6ce7be3f 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -534,7 +534,7 @@ static const struct of_device_id aspeed_sgpio_of_table[= ] =3D { =20 MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); =20 -static int __init aspeed_sgpio_probe(struct platform_device *pdev) +static int aspeed_sgpio_probe(struct platform_device *pdev) { u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask; const struct aspeed_sgpio_pdata *pdata; @@ -629,11 +629,12 @@ static int __init aspeed_sgpio_probe(struct platform_= device *pdev) } =20 static struct platform_driver aspeed_sgpio_driver =3D { + .probe =3D aspeed_sgpio_probe, .driver =3D { .name =3D KBUILD_MODNAME, .of_match_table =3D aspeed_sgpio_of_table, }, }; =20 -module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); +module_platform_driver(aspeed_sgpio_driver); MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd= /amdgpu/amdgpu_acpi.c index 8b2f2b921d9d..7730e5644493 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1128,8 +1128,10 @@ static int amdgpu_acpi_enumerate_xcc(void) if (!dev_info) ret =3D amdgpu_acpi_dev_init(&dev_info, xcc_info, bdf); =20 - if (ret =3D=3D -ENOMEM) + if (ret =3D=3D -ENOMEM) { + kfree(xcc_info); return ret; + } =20 if (!dev_info) { kfree(xcc_info); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/dr= m/amd/amdgpu/amdgpu_discovery.c index 2e492f779b54..5c4aa5ff873b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2491,6 +2491,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_devi= ce *adev) case IP_VERSION(6, 0, 0): case IP_VERSION(6, 0, 1): case IP_VERSION(6, 1, 0): + case IP_VERSION(6, 1, 1): adev->hdp.funcs =3D &hdp_v6_0_funcs; break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_job.c index e9adfc88a54a..8175d831abd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -65,7 +65,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct= drm_sched_job *s_job) DRM_ERROR("Process information: process %s pid %d thread %s pid %d\n", ti.process_name, ti.tgid, ti.task_name, ti.pid); =20 - dma_fence_set_error(&s_job->s_fence->finished, -ETIME); + if (dma_fence_get_status(&s_job->s_fence->finished) =3D=3D 0) + dma_fence_set_error(&s_job->s_fence->finished, -ETIME); =20 if (amdgpu_device_should_recover_gpu(ring->adev)) { struct amdgpu_reset_context reset_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_psp.c index 08886e0ee642..2ef87646e6bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -656,7 +656,7 @@ psp_cmd_submit_buf(struct psp_context *psp, ras_intr =3D amdgpu_ras_intr_triggered(); if (ras_intr) break; - usleep_range(10, 100); + usleep_range(60, 100); amdgpu_device_invalidate_hdp(psp->adev, NULL); } =20 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_ras.c index 7cba98f8bbdc..4214bbd7a1a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2673,7 +2673,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev) * to handle fatal error */ r =3D amdgpu_nbio_ras_sw_init(adev); if (r) - return r; + goto release_con; =20 if (adev->nbio.ras && adev->nbio.ras->init_ras_controller_interrupt) { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/am= dgpu/vcn_v2_0.c index 18794394c5a0..2505951ad06a 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -1862,7 +1862,8 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device = *adev) struct mmsch_v2_0_cmd_end end =3D { {0} }; struct mmsch_v2_0_init_header *header; uint32_t *init_table =3D adev->virt.mm_table.cpu_addr; - uint8_t i =3D 0; + + /* This path only programs VCN instance 0. */ =20 header =3D (struct mmsch_v2_0_init_header *)init_table; direct_wt.cmd_header.command_type =3D MMSCH_COMMAND__DIRECT_REG_WRITE; @@ -1881,93 +1882,93 @@ static int vcn_v2_0_start_sriov(struct amdgpu_devic= e *adev) size =3D AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4); =20 MMSCH_V2_0_INSERT_DIRECT_RD_MOD_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_STATUS), + SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), 0xFFFFFFFF, 0x00000004); =20 /* mc resume*/ if (adev->firmware.load_type =3D=3D AMDGPU_FW_LOAD_PSP) { MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi); offset =3D 0; } else { MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), lower_32_bits(adev->vcn.inst->gpu_addr)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), upper_32_bits(adev->vcn.inst->gpu_addr)); offset =3D size; } =20 MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET0), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0), 0); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE0), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE0), size); =20 MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), lower_32_bits(adev->vcn.inst->gpu_addr + offset)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), upper_32_bits(adev->vcn.inst->gpu_addr + offset)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET1), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1), 0); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE1), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE); =20 MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), lower_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), upper_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_OFFSET2), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2), 0); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_VCPU_CACHE_SIZE2), + SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE); =20 for (r =3D 0; r < adev->vcn.num_enc_rings; ++r) { ring =3D &adev->vcn.inst->ring_enc[r]; ring->wptr =3D 0; MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_RB_BASE_LO), + SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO), lower_32_bits(ring->gpu_addr)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_RB_BASE_HI), + SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI), upper_32_bits(ring->gpu_addr)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_RB_SIZE), + SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE), ring->ring_size / 4); } =20 ring =3D &adev->vcn.inst->ring_dec; ring->wptr =3D 0; MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW), lower_32_bits(ring->gpu_addr)); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, + SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH), upper_32_bits(ring->gpu_addr)); /* force RBC into idle state */ @@ -1978,7 +1979,7 @@ static int vcn_v2_0_start_sriov(struct amdgpu_device = *adev) tmp =3D REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1); tmp =3D REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1); MMSCH_V2_0_INSERT_DIRECT_WT( - SOC15_REG_OFFSET(UVD, i, mmUVD_RBC_RB_CNTL), tmp); + SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), tmp); =20 /* add end packet */ tmp =3D sizeof(struct mmsch_v2_0_cmd_end); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/a= mdkfd/kfd_debug.c index 9c32c64c407f..267650dcced9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c @@ -381,47 +381,45 @@ static int kfd_dbg_get_dev_watch_id(struct kfd_proces= s_device *pdd, int *watch_i =20 *watch_id =3D KFD_DEBUGGER_INVALID_WATCH_POINT_ID; =20 - spin_lock(&pdd->dev->kfd->watch_points_lock); + spin_lock(&pdd->dev->watch_points_lock); =20 for (i =3D 0; i < MAX_WATCH_ADDRESSES; i++) { /* device watchpoint in use so skip */ - if ((pdd->dev->kfd->alloc_watch_ids >> i) & 0x1) + if ((pdd->dev->alloc_watch_ids >> i) & 0x1) continue; =20 pdd->alloc_watch_ids |=3D 0x1 << i; - pdd->dev->kfd->alloc_watch_ids |=3D 0x1 << i; + pdd->dev->alloc_watch_ids |=3D 0x1 << i; *watch_id =3D i; - spin_unlock(&pdd->dev->kfd->watch_points_lock); + spin_unlock(&pdd->dev->watch_points_lock); return 0; } =20 - spin_unlock(&pdd->dev->kfd->watch_points_lock); + spin_unlock(&pdd->dev->watch_points_lock); =20 return -ENOMEM; } =20 -static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, int= watch_id) +static void kfd_dbg_clear_dev_watch_id(struct kfd_process_device *pdd, u32= watch_id) { - spin_lock(&pdd->dev->kfd->watch_points_lock); + spin_lock(&pdd->dev->watch_points_lock); =20 /* process owns device watch point so safe to clear */ - if ((pdd->alloc_watch_ids >> watch_id) & 0x1) { - pdd->alloc_watch_ids &=3D ~(0x1 << watch_id); - pdd->dev->kfd->alloc_watch_ids &=3D ~(0x1 << watch_id); + if (pdd->alloc_watch_ids & BIT(watch_id)) { + pdd->alloc_watch_ids &=3D ~BIT(watch_id); + pdd->dev->alloc_watch_ids &=3D ~BIT(watch_id); } =20 - spin_unlock(&pdd->dev->kfd->watch_points_lock); + spin_unlock(&pdd->dev->watch_points_lock); } =20 -static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, int = watch_id) +static bool kfd_dbg_owns_dev_watch_id(struct kfd_process_device *pdd, u32 = watch_id) { bool owns_watch_id =3D false; =20 - spin_lock(&pdd->dev->kfd->watch_points_lock); - owns_watch_id =3D watch_id < MAX_WATCH_ADDRESSES && - ((pdd->alloc_watch_ids >> watch_id) & 0x1); - - spin_unlock(&pdd->dev->kfd->watch_points_lock); + spin_lock(&pdd->dev->watch_points_lock); + owns_watch_id =3D pdd->alloc_watch_ids & BIT(watch_id); + spin_unlock(&pdd->dev->watch_points_lock); =20 return owns_watch_id; } @@ -431,6 +429,9 @@ int kfd_dbg_trap_clear_dev_address_watch(struct kfd_pro= cess_device *pdd, { int r; =20 + if (watch_id >=3D MAX_WATCH_ADDRESSES) + return -EINVAL; + if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id)) return -EINVAL; =20 @@ -468,6 +469,9 @@ int kfd_dbg_trap_set_dev_address_watch(struct kfd_proce= ss_device *pdd, if (r) return r; =20 + if (*watch_id >=3D MAX_WATCH_ADDRESSES) + return -EINVAL; + if (!pdd->dev->kfd->shared_resources.enable_mes) { r =3D debug_lock_and_unmap(pdd->dev->dqm); if (r) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/= amdkfd/kfd_device.c index 6af65db4de94..af50aa9638ca 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -815,13 +815,14 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, dev_err(kfd_device, "Error initializing KFD node\n"); goto node_init_error; } + + spin_lock_init(&node->watch_points_lock); + kfd->nodes[i] =3D node; } =20 svm_range_set_max_pages(kfd->adev); =20 - spin_lock_init(&kfd->watch_points_lock); - kfd->init_complete =3D true; dev_info(kfd_device, "added device %x:%x\n", kfd->adev->pdev->vendor, kfd->adev->pdev->device); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/= amdkfd/kfd_events.c index 2b07c0000df6..c98a08c269ae 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -330,6 +330,12 @@ static int kfd_event_page_set(struct kfd_process *p, v= oid *kernel_address, if (p->signal_page) return -EBUSY; =20 + if (size < KFD_SIGNAL_EVENT_LIMIT * 8) { + pr_err("Event page size %llu is too small, need at least %lu bytes\n", + size, (unsigned long)(KFD_SIGNAL_EVENT_LIMIT * 8)); + return -EINVAL; + } + page =3D kzalloc(sizeof(*page), GFP_KERNEL); if (!page) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd= /amdkfd/kfd_migrate.c index f99e3b812ee4..59575e2424d0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -62,7 +62,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t n= pages, *gart_addr =3D adev->gmc.gart_start; =20 num_dw =3D ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); - num_bytes =3D npages * 8; + num_bytes =3D npages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; =20 r =3D amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr, AMDGPU_FENCE_OWNER_UNDEFINED, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/am= dkfd/kfd_priv.h index b475c2ab9768..0b69ff5375c5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -316,6 +316,10 @@ struct kfd_node { struct kfd_local_mem_info local_mem_info; =20 struct kfd_dev *kfd; + + /* Track per device allocated watch points */ + uint32_t alloc_watch_ids; + spinlock_t watch_points_lock; }; =20 struct kfd_dev { @@ -368,10 +372,6 @@ struct kfd_dev { struct kfd_node *nodes[MAX_KFD_NODES]; unsigned int num_nodes; =20 - /* Track per device allocated watch points */ - uint32_t alloc_watch_ids; - spinlock_t watch_points_lock; - /* Kernel doorbells for KFD device */ struct amdgpu_bo *doorbells; =20 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gp= u/drm/amd/display/amdgpu_dm/amdgpu_dm.c index faef07fdfd30..26047109726e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8934,7 +8934,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_a= tomic_state *state) */ dummy_updates =3D kzalloc(sizeof(struct dc_surface_update) * MAX_SURFACE= S, GFP_ATOMIC); for (j =3D 0; j < status->plane_count; j++) - dummy_updates[j].surface =3D status->plane_states[0]; + dummy_updates[j].surface =3D status->plane_states[j]; =20 =20 mutex_lock(&dm->dc_lock); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/driv= ers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index d1329f20b7bd..746df72405eb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -970,10 +970,15 @@ static void get_min_max_dc_plane_scaling(struct drm_d= evice *dev, *min_downscale =3D plane_cap->max_downscale_factor.nv12; break; =20 + /* All 64 bpp formats have the same fp16 scaling limits */ case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_ARGB16161616F: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_XRGB16161616: + case DRM_FORMAT_ARGB16161616: + case DRM_FORMAT_XBGR16161616: + case DRM_FORMAT_ABGR16161616: *max_upscale =3D plane_cap->max_upscale_factor.fp16; *min_downscale =3D plane_cap->max_downscale_factor.fp16; break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu= /drm/amd/display/dc/dcn32/dcn32_mpc.c index 1d052f08aff5..f20f0b2be4c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -716,8 +716,7 @@ bool mpc32_program_shaper( return false; } =20 - if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) - mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true); + mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true); =20 current_mode =3D mpc32_get_shaper_current(mpc, mpcc_id); =20 diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/a= md/pm/legacy-dpm/si_dpm.c index caf590caaf2c..e75900404693 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -3449,6 +3449,11 @@ static void si_apply_state_adjust_rules(struct amdgp= u_device *adev, max_sclk =3D 60000; max_mclk =3D 80000; } + if ((adev->pdev->device =3D=3D 0x666f) && + (adev->pdev->revision =3D=3D 0x00)) { + max_sclk =3D 80000; + max_mclk =3D 95000; + } } else if (adev->asic_type =3D=3D CHIP_OLAND) { if ((adev->pdev->revision =3D=3D 0xC7) || (adev->pdev->revision =3D=3D 0x80) || diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/= drm/atmel-hlcdc/atmel_hlcdc_plane.c index daa508504f47..b35d367b8614 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -78,8 +78,6 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_pla= ne_state *s) return container_of(s, struct atmel_hlcdc_plane_state, base); } =20 -#define SUBPIXEL_MASK 0xffff - static uint32_t rgb_formats[] =3D { DRM_FORMAT_C8, DRM_FORMAT_XRGB4444, @@ -619,24 +617,15 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_= plane *p, if (ret || !s->visible) return ret; =20 - hstate->src_x =3D s->src.x1; - hstate->src_y =3D s->src.y1; - hstate->src_w =3D drm_rect_width(&s->src); - hstate->src_h =3D drm_rect_height(&s->src); + hstate->src_x =3D s->src.x1 >> 16; + hstate->src_y =3D s->src.y1 >> 16; + hstate->src_w =3D drm_rect_width(&s->src) >> 16; + hstate->src_h =3D drm_rect_height(&s->src) >> 16; hstate->crtc_x =3D s->dst.x1; hstate->crtc_y =3D s->dst.y1; hstate->crtc_w =3D drm_rect_width(&s->dst); hstate->crtc_h =3D drm_rect_height(&s->dst); =20 - if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) & - SUBPIXEL_MASK) - return -EINVAL; - - hstate->src_x >>=3D 16; - hstate->src_y >>=3D 16; - hstate->src_w >>=3D 16; - hstate->src_h >>=3D 16; - hstate->nplanes =3D fb->format->num_planes; if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES) return -EINVAL; @@ -915,8 +904,7 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_pla= ne *p) return NULL; } =20 - if (copy->base.fb) - drm_framebuffer_get(copy->base.fb); + __drm_atomic_helper_plane_duplicate_state(p, ©->base); =20 return ©->base; } @@ -934,8 +922,7 @@ static void atmel_hlcdc_plane_atomic_destroy_state(stru= ct drm_plane *p, state->dscrs[i]->self); } =20 - if (s->fb) - drm_framebuffer_put(s->fb); + __drm_atomic_helper_plane_destroy_state(s); =20 kfree(state); } diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/dr= m/display/drm_dp_mst_topology.c index 21ff7ef7ce92..d4a5489d010c 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4527,7 +4527,8 @@ int drm_dp_atomic_release_time_slots(struct drm_atomi= c_state *state, if (!payload->delete) { payload->pbn =3D 0; payload->delete =3D true; - topology_state->payload_mask &=3D ~BIT(payload->vcpi - 1); + if (payload->vcpi > 0) + topology_state->payload_mask &=3D ~BIT(payload->vcpi - 1); } =20 return 0; diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index dfec479830e4..b4ee7d4110f8 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -561,7 +561,7 @@ drm_property_create_blob(struct drm_device *dev, size_t= length, if (!length || length > INT_MAX - sizeof(struct drm_property_blob)) return ERR_PTR(-EINVAL); =20 - blob =3D kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); + blob =3D kvzalloc(sizeof(struct drm_property_blob) + length, GFP_KERNEL_A= CCOUNT); if (!blob) return ERR_PTR(-ENOMEM); =20 diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i9= 15/display/intel_acpi.c index 9df78e7caa2b..231b341d968a 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -93,6 +93,7 @@ static void intel_dsm_platform_mux_info(acpi_handle dhand= le) =20 if (!pkg->package.count) { DRM_DEBUG_DRIVER("no connection in _DSM\n"); + ACPI_FREE(pkg); return; } =20 diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/in= tel_wakeref.c index 718f2f1b6174..a2bffa4a4dd1 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -76,7 +76,7 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, u= nsigned long flags) /* Assume we are not in process context and so cannot sleep. */ if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) { mod_delayed_work(wf->i915->unordered_wq, &wf->work, - FIELD_GET(INTEL_WAKEREF_PUT_DELAY, flags)); + FIELD_GET(INTEL_WAKEREF_PUT_DELAY_MASK, flags)); return; } =20 diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/in= tel_wakeref.h index ec881b097368..9923628d706c 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -119,17 +119,16 @@ intel_wakeref_get_if_active(struct intel_wakeref *wf) return atomic_inc_not_zero(&wf->count); } =20 -enum { - INTEL_WAKEREF_PUT_ASYNC_BIT =3D 0, - __INTEL_WAKEREF_PUT_LAST_BIT__ -}; - static inline void intel_wakeref_might_get(struct intel_wakeref *wf) { might_lock(&wf->mutex); } =20 +/* flags for __intel_wakeref_put() and __intel_wakeref_put_last */ +#define INTEL_WAKEREF_PUT_ASYNC BIT(0) +#define INTEL_WAKEREF_PUT_DELAY_MASK GENMASK(BITS_PER_LONG - 1, 1) + /** * __intel_wakeref_put: Release the wakeref * @wf: the wakeref @@ -145,9 +144,6 @@ intel_wakeref_might_get(struct intel_wakeref *wf) */ static inline void __intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) -#define INTEL_WAKEREF_PUT_ASYNC BIT(INTEL_WAKEREF_PUT_ASYNC_BIT) -#define INTEL_WAKEREF_PUT_DELAY \ - GENMASK(BITS_PER_LONG - 1, __INTEL_WAKEREF_PUT_LAST_BIT__) { INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <=3D 0); if (unlikely(!atomic_add_unless(&wf->count, -1, 1))) @@ -172,7 +168,7 @@ intel_wakeref_put_delay(struct intel_wakeref *wf, unsig= ned long delay) { __intel_wakeref_put(wf, INTEL_WAKEREF_PUT_ASYNC | - FIELD_PREP(INTEL_WAKEREF_PUT_DELAY, delay)); + FIELD_PREP(INTEL_WAKEREF_PUT_DELAY_MASK, delay)); } =20 static inline void diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/ad= reno/a2xx_gpu.c index 535c89ce5d62..0410a1657b15 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -77,7 +77,10 @@ static bool a2xx_me_init(struct msm_gpu *gpu) =20 /* Vertex and Pixel Shader Start Addresses in instructions * (3 DWORDS per instruction) */ - OUT_RING(ring, 0x80000180); + if (adreno_is_a225(adreno_gpu)) + OUT_RING(ring, 0x80000300); + else + OUT_RING(ring, 0x80000180); /* Maximum Contexts */ OUT_RING(ring, 0x00000001); /* Write Confirm Interval and The CP will wait the diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drive= rs/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h index 9195cb996f44..cbaca4bf2864 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h @@ -14,6 +14,7 @@ static const struct dpu_caps sc7280_dpu_caps =3D { .has_dim_layer =3D true, .has_idle_pc =3D true, .max_linewidth =3D 2400, + .has_3d_merge =3D true, .pixel_ram_size =3D DEFAULT_PIXEL_RAM_SIZE, }; =20 @@ -145,7 +146,7 @@ static const struct dpu_pingpong_cfg sc7280_pp[] =3D { .base =3D 0x6b000, .len =3D 0, .features =3D BIT(DPU_PINGPONG_DITHER), .sblk =3D &sc7280_pp_sblk, - .merge_3d =3D 0, + .merge_3d =3D MERGE_3D_1, .intr_done =3D DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), .intr_rdptr =3D -1, }, { @@ -153,12 +154,19 @@ static const struct dpu_pingpong_cfg sc7280_pp[] =3D { .base =3D 0x6c000, .len =3D 0, .features =3D BIT(DPU_PINGPONG_DITHER), .sblk =3D &sc7280_pp_sblk, - .merge_3d =3D 0, + .merge_3d =3D MERGE_3D_1, .intr_done =3D DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), .intr_rdptr =3D -1, }, }; =20 +static const struct dpu_merge_3d_cfg sc7280_merge_3d[] =3D { + { + .name =3D "merge_3d_1", .id =3D MERGE_3D_1, + .base =3D 0x4f000, .len =3D 0x8, + }, +}; + /* NOTE: sc7280 only has one DSC hard slice encoder */ static const struct dpu_dsc_cfg sc7280_dsc[] =3D { { @@ -265,6 +273,8 @@ const struct dpu_mdss_cfg dpu_sc7280_cfg =3D { .mixer =3D sc7280_lm, .pingpong_count =3D ARRAY_SIZE(sc7280_pp), .pingpong =3D sc7280_pp, + .merge_3d_count =3D ARRAY_SIZE(sc7280_merge_3d), + .merge_3d =3D sc7280_merge_3d, .dsc_count =3D ARRAY_SIZE(sc7280_dsc), .dsc =3D sc7280_dsc, .wb_count =3D ARRAY_SIZE(sc7280_wb), diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers= /gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c index 83a804ebf8d7..fd2400c4665d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c @@ -675,10 +675,11 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done( if (!dpu_encoder_phys_cmd_is_master(phys_enc)) return 0; =20 - if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) - return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); + if (phys_enc->irq[INTR_IDX_CTL_START] && + !phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) + return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); =20 - return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); + return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); } =20 static void dpu_encoder_phys_cmd_handle_post_kickoff( diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dp= m.c index fbf968e3f6d7..c688b4d91481 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2969,6 +2969,11 @@ static void si_apply_state_adjust_rules(struct radeo= n_device *rdev, max_sclk =3D 60000; max_mclk =3D 80000; } + if ((rdev->pdev->device =3D=3D 0x666f) && + (rdev->pdev->revision =3D=3D 0x00)) { + max_sclk =3D 80000; + max_mclk =3D 95000; + } } else if (rdev->family =3D=3D CHIP_OLAND) { if ((rdev->pdev->revision =3D=3D 0xC7) || (rdev->pdev->revision =3D=3D 0x80) || diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 0e8ea9901188..691a8c8848e4 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -242,6 +242,8 @@ static int v3d_platform_drm_probe(struct platform_devic= e *pdev) if (ret) goto clk_disable; =20 + dma_set_max_seg_size(&pdev->dev, UINT_MAX); + v3d->va_width =3D 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH); =20 ident1 =3D V3D_READ(V3D_HUB_IDENT1); diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index ffbeb39341e1..851ddbc25bed 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -328,6 +328,7 @@ config HID_ELECOM - EX-G Trackballs (M-XT3DRBK, M-XT3URBK) - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK) - HUGE Trackballs (M-HT1DRBK, M-HT1URBK) + - HUGE Plus Trackball (M-HT1MRBK) =20 config HID_ELO tristate "ELO USB 4000/4500 touchscreen" diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 2b8021628d3c..9dd5c698fefe 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -340,6 +340,7 @@ static const struct apple_key_translation swapped_fn_le= ftctrl_keys[] =3D { }; =20 static const struct apple_non_apple_keyboard non_apple_keyboards[] =3D { + { "SONiX KN85 Keyboard" }, { "SONiX USB DEVICE" }, { "SONiX AK870 PRO" }, { "Keychron" }, diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index f76fec79e890..9aeb2d2b43a4 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -5,6 +5,7 @@ * - EX-G Trackballs (M-XT3DRBK, M-XT3URBK, M-XT4DRBK) * - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK) * - HUGE Trackballs (M-HT1DRBK, M-HT1URBK) + * - HUGE Plus Trackball (M-HT1MRBK) * * Copyright (c) 2010 Richard Nauber * Copyright (c) 2016 Yuxuan Shui @@ -111,12 +112,25 @@ static __u8 *elecom_report_fixup(struct hid_device *h= dev, __u8 *rdesc, */ mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16, 8); break; + case USB_DEVICE_ID_ELECOM_M_HT1MRBK: + case USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB: + case USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC: + /* + * Report descriptor format: + * 24: button bit count + * 28: padding bit count + * 22: button report size + * 16: button usage maximum + */ + mouse_button_fixup(hdev, rdesc, *rsize, 24, 28, 22, 16, 8); + break; } return rdesc; } =20 static const struct hid_device_id elecom_devices[] =3D { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) = }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MR= BK_01AC) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) = }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_00F= B) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018= F) }, @@ -127,6 +141,8 @@ static const struct hid_device_id elecom_devices[] =3D { { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010= D) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011= C) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01A= B) }, { } }; MODULE_DEVICE_TABLE(hid, elecom_devices); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 931746cf3630..a1910e12f7e0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -427,6 +427,7 @@ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 +#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000 0xc000 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002 0xc002 =20 #define USB_VENDOR_ID_EDIFIER 0x2d99 @@ -452,6 +453,9 @@ #define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D 0x010d #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C 0x011c +#define USB_DEVICE_ID_ELECOM_M_HT1MRBK 0x01aa +#define USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AB 0x01ab +#define USB_DEVICE_ID_ELECOM_M_HT1MRBK_01AC 0x01ac =20 #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hi= dpp.c index 5a2fe703cf57..339a227c457e 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4339,7 +4339,7 @@ static int hidpp_get_report_length(struct hid_device = *hdev, int id) =20 re =3D &(hdev->report_enum[HID_OUTPUT_REPORT]); report =3D re->report_id_hash[id]; - if (!report) + if (!report || !report->maxfield) return 0; =20 return report->field[0]->report_count + 1; diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 4fe1e0bc2449..99d0dbf62af3 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -712,6 +712,11 @@ static int magicmouse_input_configured(struct hid_devi= ce *hdev, struct magicmouse_sc *msc =3D hid_get_drvdata(hdev); int ret; =20 + if (!msc->input) { + hid_err(hdev, "magicmouse setup input failed (no input)"); + return -EINVAL; + } + ret =3D magicmouse_setup_input(msc->input, hdev); if (ret) { hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 6d9a85c5fc40..b6c2cb7153fd 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -2020,6 +2020,9 @@ static const struct hid_device_id mt_devices[] =3D { { .driver_data =3D MT_CLS_EGALAX_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, + { .driver_data =3D MT_CLS_EGALAX_SERIAL, + MT_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000) }, { .driver_data =3D MT_CLS_EGALAX, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) }, diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 93fb07ec3180..d1a1ddd933ab 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c @@ -194,9 +194,14 @@ static int pl_probe(struct hid_device *hdev, const str= uct hid_device_id *id) goto err; } =20 - plff_init(hdev); + ret =3D plff_init(hdev); + if (ret) + goto stop; =20 return 0; + +stop: + hid_hw_stop(hdev); err: return ret; } diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 32f65c45fdc8..199f76988bae 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -732,7 +732,9 @@ static struct input_dev *ps_gamepad_create(struct hid_d= evice *hdev, #if IS_ENABLED(CONFIG_PLAYSTATION_FF) if (play_effect) { input_set_capability(gamepad, EV_FF, FF_RUMBLE); - input_ff_create_memless(gamepad, NULL, play_effect); + ret =3D input_ff_create_memless(gamepad, NULL, play_effect); + if (ret) + return ERR_PTR(ret); } #endif =20 diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index e4e9471d0f1e..f20d29566b4d 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -388,6 +388,10 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm= , u8 *data) bit_mask =3D (bit_mask << 8) | data[2]; bit_mask =3D (bit_mask << 8) | data[3]; =20 + /* robustness in case input_mapping hook does not get called */ + if (!pm->input_ep82) + return 0; + /* break keys */ for (bit_index =3D 0; bit_index < 24; bit_index++) { if (!((0x01 << bit_index) & bit_mask)) { diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 1f531626192c..7a3e0675d9ba 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -415,6 +415,7 @@ static const struct hid_device_id hid_have_special_driv= er[] =3D { #if IS_ENABLED(CONFIG_HID_ELECOM) { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) = }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20= DLBK) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MR= BK_01AC) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_00F= B) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018= F) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) }, @@ -424,6 +425,8 @@ static const struct hid_device_id hid_have_special_driv= er[] =3D { { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010= D) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011= C) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1MRBK_01A= B) }, #endif #if IS_ENABLED(CONFIG_HID_ELO) { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 27207ec6f7fe..5e3c8be255e8 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -51,6 +51,7 @@ #define SIO_F81866_ID 0x1010 /* Chipset ID */ #define SIO_F71858AD_ID 0x0903 /* Chipset ID */ #define SIO_F81966_ID 0x1502 /* Chipset ID */ +#define SIO_F81968_ID 0x1806 /* Chipset ID */ =20 #define REGION_LENGTH 8 #define ADDR_REG_OFFSET 5 @@ -2571,6 +2572,7 @@ static int __init f71882fg_find(int sioaddr, struct f= 71882fg_sio_data *sio_data) break; case SIO_F81866_ID: case SIO_F81966_ID: + case SIO_F81968_ID: sio_data->type =3D f81866a; break; default: @@ -2600,9 +2602,9 @@ static int __init f71882fg_find(int sioaddr, struct f= 71882fg_sio_data *sio_data) address &=3D ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ =20 err =3D address; - pr_info("Found %s chip at %#x, revision %d\n", + pr_info("Found %s chip at %#x, revision %d, devid: %04x\n", f71882fg_names[sio_data->type], (unsigned int)address, - (int)superio_inb(sioaddr, SIO_REG_DEVREV)); + (int)superio_inb(sioaddr, SIO_REG_DEVREV), devid); exit: superio_exit(sioaddr); return err; diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index 40fff7e95ea1..db066b368918 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -282,9 +282,6 @@ static ssize_t ibmpex_high_low_store(struct device *dev, { struct ibmpex_bmc_data *data =3D dev_get_drvdata(dev); =20 - if (!data) - return -ENODEV; - ibmpex_reset_high_low_data(data); =20 return count; @@ -517,9 +514,6 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *d= ata) { int i, j; =20 - hwmon_device_unregister(data->hwmon_dev); - dev_set_drvdata(data->bmc_device, NULL); - device_remove_file(data->bmc_device, &sensor_dev_attr_reset_high_low.dev_attr); device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); @@ -533,7 +527,8 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *d= ata) } =20 list_del(&data->list); - + dev_set_drvdata(data->bmc_device, NULL); + hwmon_device_unregister(data->hwmon_dev); ipmi_destroy_user(data->user); kfree(data->sensors); kfree(data); diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platf= orm.c index 7e0ac3fcbc05..b09fd5791db8 100644 --- a/drivers/hwmon/nct6775-platform.c +++ b/drivers/hwmon/nct6775-platform.c @@ -1356,6 +1356,7 @@ static const char * const asus_msi_boards[] =3D { "Pro WS W680-ACE IPMI", "Pro WS W790-ACE", "Pro WS W790E-SAGE SE", + "Pro WS WRX90E-SAGE SE", "ProArt B650-CREATOR", "ProArt B660-CREATOR D4", "ProArt B760-CREATOR D4", diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/h= wtracing/coresight/coresight-etm3x-core.c index 116a91d90ac2..4cef1023f029 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -814,16 +814,16 @@ static int __init etm_hp_setup(void) { int ret; =20 - ret =3D cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_START= ING, - "arm/coresight:starting", - etm_starting_cpu, etm_dying_cpu); + ret =3D cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING, + "arm/coresight:starting", + etm_starting_cpu, etm_dying_cpu); =20 if (ret) return ret; =20 - ret =3D cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, - "arm/coresight:online", - etm_online_cpu, NULL); + ret =3D cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight:online", + etm_online_cpu, NULL); =20 /* HP dyn state ID returned in ret on success */ if (ret > 0) { diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 060f70e4d52d..f74ef65d257d 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -586,7 +586,8 @@ static int i3c_set_hotjoin(struct i3c_master_controller= *master, bool enable) else ret =3D master->ops->disable_hotjoin(master); =20 - master->hotjoin =3D enable; + if (!ret) + master->hotjoin =3D enable; =20 i3c_bus_normaluse_unlock(&master->bus); =20 @@ -2769,7 +2770,6 @@ int i3c_master_register(struct i3c_master_controller = *master, INIT_LIST_HEAD(&master->boardinfo.i3c); =20 device_initialize(&master->dev); - dev_set_name(&master->dev, "i3c-%d", i3cbus->id); =20 master->dev.dma_mask =3D parent->dma_mask; master->dev.coherent_dma_mask =3D parent->coherent_dma_mask; @@ -2779,6 +2779,8 @@ int i3c_master_register(struct i3c_master_controller = *master, if (ret) goto err_put_dev; =20 + dev_set_name(&master->dev, "i3c-%d", i3cbus->id); + ret =3D of_populate_i3c_bus(master); if (ret) goto err_put_dev; diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c= -master.c index 030127525672..cee2805fccd0 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -1483,6 +1483,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, spin_lock_init(&master->xferqueue.lock); INIT_LIST_HEAD(&master->xferqueue.list); =20 + spin_lock_init(&master->devs_lock); + writel(INTR_ALL, master->regs + INTR_STATUS); irq =3D platform_get_irq(pdev, 0); ret =3D devm_request_irq(&pdev->dev, irq, diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i= 3c-master.c index 3222b8f56a92..94792f3559a0 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -418,8 +418,8 @@ static void svc_i3c_master_ibi_work(struct work_struct = *work) { struct svc_i3c_master *master =3D container_of(work, struct svc_i3c_maste= r, ibi_work); struct svc_i3c_i2c_dev_data *data; + struct i3c_dev_desc *dev =3D NULL; unsigned int ibitype, ibiaddr; - struct i3c_dev_desc *dev; u32 status, val; int ret; =20 @@ -503,7 +503,7 @@ static void svc_i3c_master_ibi_work(struct work_struct = *work) * for the slave to interrupt again. */ if (svc_i3c_master_error(master)) { - if (master->ibi.tbq_slot) { + if (master->ibi.tbq_slot && dev) { data =3D i3c_dev_get_master_data(dev); i3c_generic_ibi_recycle_slot(data->ibi_pool, master->ibi.tbq_slot); diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 13439f52d26d..0eabcd695797 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -996,8 +996,9 @@ static int bma180_probe(struct i2c_client *client) } =20 ret =3D devm_request_irq(dev, client->irq, - iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, - "bma180_event", data->trig); + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING | IRQF_NO_THREAD, + "bma180_event", data->trig); if (ret) { dev_err(dev, "unable to request IRQ\n"); goto err_trigger_free; diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 87c54e41f6cc..2b87f7f5508b 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1496,7 +1496,11 @@ static int sca3000_probe(struct spi_device *spi) if (ret) goto error_free_irq; =20 - return iio_device_register(indio_dev); + ret =3D iio_device_register(indio_dev); + if (ret) + goto error_free_irq; + + return 0; =20 error_free_irq: if (spi->irq) diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c index 3079a0872947..d1d010c1dbf6 100644 --- a/drivers/iio/adc/ad7766.c +++ b/drivers/iio/adc/ad7766.c @@ -261,7 +261,7 @@ static int ad7766_probe(struct spi_device *spi) * don't enable the interrupt to avoid extra load on the system */ ret =3D devm_request_irq(&spi->dev, spi->irq, ad7766_irq, - IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, + IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN | IRQF_NO_THREAD, dev_name(&spi->dev), ad7766->trig); if (ret < 0) diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_b= uffer.c index 4cfa0d439560..d1c125a77308 100644 --- a/drivers/iio/gyro/itg3200_buffer.c +++ b/drivers/iio/gyro/itg3200_buffer.c @@ -118,11 +118,9 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) if (!st->trig) return -ENOMEM; =20 - ret =3D request_irq(st->i2c->irq, - &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "itg3200_data_rdy", - st->trig); + ret =3D request_irq(st->i2c->irq, &iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING | IRQF_NO_THREAD, + "itg3200_data_rdy", st->trig); if (ret) goto error_free_trig; =20 diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_cor= e.c index 53fb92f0ac7e..1127dd9f0df2 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -93,6 +93,8 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: reg =3D (u8)chan->address; ret =3D itg3200_read_reg_s16(indio_dev, reg, val); + if (ret) + return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val =3D 0; diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-cor= e.c index a791ba3a693a..de126561f197 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -1172,10 +1172,8 @@ int mpu3050_common_probe(struct device *dev, mpu3050->regs[1].supply =3D mpu3050_reg_vlogic; ret =3D devm_regulator_bulk_get(dev, ARRAY_SIZE(mpu3050->regs), mpu3050->regs); - if (ret) { - dev_err(dev, "Cannot get regulators\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Cannot get regulators\n"); =20 ret =3D mpu3050_power_up(mpu3050); if (ret) diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 77666b780a5c..9655214a3827 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1251,7 +1251,7 @@ static int si1145_probe_trigger(struct iio_dev *indio= _dev) =20 ret =3D devm_request_irq(&client->dev, client->irq, iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_FALLING | IRQF_NO_THREAD, "si1145_irq", trig); if (ret < 0) { diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/a= k8975.c index 3a98d6bae1b2..c1894a26ffd6 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -542,7 +542,7 @@ static int ak8975_setup_irq(struct ak8975_data *data) irq =3D gpiod_to_irq(data->eoc_gpiod); =20 rc =3D devm_request_irq(&client->dev, irq, ak8975_irq_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_RISING, dev_name(&client->dev), data); if (rc < 0) { dev_err(&client->dev, "irq %d request failed: %d\n", irq, rc); diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprl= s0025pa.c index 829c472812e4..566c21bf3ea0 100644 --- a/drivers/iio/pressure/mprls0025pa.c +++ b/drivers/iio/pressure/mprls0025pa.c @@ -132,8 +132,8 @@ static const struct iio_chan_spec mpr_channels[] =3D { BIT(IIO_CHAN_INFO_OFFSET), .scan_index =3D 0, .scan_type =3D { - .sign =3D 's', - .realbits =3D 32, + .sign =3D 'u', + .realbits =3D 24, .storagebits =3D 32, .endianness =3D IIO_CPU, }, diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cach= e.c index 77c0b8925991..cda4fb81174f 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -927,6 +927,13 @@ static int gid_table_setup_one(struct ib_device *ib_de= v) if (err) return err; =20 + /* + * Mark the device as ready for GID cache updates. This allows netdev + * event handlers to update the GID cache even before the device is + * fully registered. + */ + ib_device_enable_gid_updates(ib_dev); + rdma_roce_rescan_device(ib_dev); =20 return err; @@ -1566,7 +1573,8 @@ static void ib_cache_event_task(struct work_struct *_= work) * the cache. */ ret =3D ib_cache_update(work->event.device, work->event.element.port_num, - work->event.event =3D=3D IB_EVENT_GID_CHANGE, + work->event.event =3D=3D IB_EVENT_GID_CHANGE || + work->event.event =3D=3D IB_EVENT_CLIENT_REREGISTER, work->event.event =3D=3D IB_EVENT_PKEY_CHANGE, work->enforce_security); =20 @@ -1667,6 +1675,12 @@ void ib_cache_release_one(struct ib_device *device) =20 void ib_cache_cleanup_one(struct ib_device *device) { + /* + * Clear the GID updates mark first to prevent event handlers from + * accessing the device while it's being torn down. + */ + ib_device_disable_gid_updates(device); + /* The cleanup function waits for all in-progress workqueue * elements and cleans up the GID cache. This function should be * called after the device was removed from the devices list and diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/= core_priv.h index f66f48d860ec..149dacf5b64d 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -100,6 +100,9 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter, roce_netdev_callback cb, void *cookie); =20 +void ib_device_enable_gid_updates(struct ib_device *device); +void ib_device_disable_gid_updates(struct ib_device *device); + typedef int (*nldev_callback)(struct ib_device *device, struct sk_buff *skb, struct netlink_callback *cb, diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/dev= ice.c index d5931bb1de41..1a241864b7b5 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -93,6 +93,7 @@ static struct workqueue_struct *ib_unreg_wq; static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC); static DECLARE_RWSEM(devices_rwsem); #define DEVICE_REGISTERED XA_MARK_1 +#define DEVICE_GID_UPDATES XA_MARK_2 =20 static u32 highest_client_id; #define CLIENT_REGISTERED XA_MARK_1 @@ -2344,11 +2345,42 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter fi= lter, unsigned long index; =20 down_read(&devices_rwsem); - xa_for_each_marked (&devices, index, dev, DEVICE_REGISTERED) + xa_for_each_marked(&devices, index, dev, DEVICE_GID_UPDATES) ib_enum_roce_netdev(dev, filter, filter_cookie, cb, cookie); up_read(&devices_rwsem); } =20 +/** + * ib_device_enable_gid_updates - Mark device as ready for GID cache updat= es + * @device: Device to mark + * + * Called after GID table is allocated and initialized. After this mark is= set, + * netdevice event handlers can update the device's GID cache. This allows + * events that arrive during device registration to be processed, avoiding + * stale GID entries when netdev properties change during the device + * registration process. + */ +void ib_device_enable_gid_updates(struct ib_device *device) +{ + down_write(&devices_rwsem); + xa_set_mark(&devices, device->index, DEVICE_GID_UPDATES); + up_write(&devices_rwsem); +} + +/** + * ib_device_disable_gid_updates - Clear the GID updates mark + * @device: Device to unmark + * + * Called before GID table cleanup to prevent event handlers from accessing + * the device while it's being torn down. + */ +void ib_device_disable_gid_updates(struct ib_device *device) +{ + down_write(&devices_rwsem); + xa_clear_mark(&devices, device->index, DEVICE_GID_UPDATES); + up_write(&devices_rwsem); +} + /* * ib_enum_all_devs - enumerate all ib_devices * @cb: Callback to call for each found ib_device diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c index 8367974b7998..2522ff1cc462 100644 --- a/drivers/infiniband/core/rw.c +++ b/drivers/infiniband/core/rw.c @@ -651,34 +651,57 @@ unsigned int rdma_rw_mr_factor(struct ib_device *devi= ce, u32 port_num, } EXPORT_SYMBOL(rdma_rw_mr_factor); =20 +/** + * rdma_rw_max_send_wr - compute max Send WRs needed for RDMA R/W contexts + * @dev: RDMA device + * @port_num: port number + * @max_rdma_ctxs: number of rdma_rw_ctx structures + * @create_flags: QP create flags (pass IB_QP_CREATE_INTEGRITY_EN if + * data integrity will be enabled on the QP) + * + * Returns the total number of Send Queue entries needed for + * @max_rdma_ctxs. The result accounts for memory registration and + * invalidation work requests when the device requires them. + * + * ULPs use this to size Send Queues and Send CQs before creating a + * Queue Pair. + */ +unsigned int rdma_rw_max_send_wr(struct ib_device *dev, u32 port_num, + unsigned int max_rdma_ctxs, u32 create_flags) +{ + unsigned int factor =3D 1; + unsigned int result; + + if (create_flags & IB_QP_CREATE_INTEGRITY_EN || + rdma_rw_can_use_mr(dev, port_num)) + factor +=3D 2; /* reg + inv */ + + if (check_mul_overflow(factor, max_rdma_ctxs, &result)) + return UINT_MAX; + return result; +} +EXPORT_SYMBOL(rdma_rw_max_send_wr); + void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr) { - u32 factor; + unsigned int factor =3D 1; =20 WARN_ON_ONCE(attr->port_num =3D=3D 0); =20 /* - * Each context needs at least one RDMA READ or WRITE WR. - * - * For some hardware we might need more, eventually we should ask the - * HCA driver for a multiplier here. - */ - factor =3D 1; - - /* - * If the devices needs MRs to perform RDMA READ or WRITE operations, - * we'll need two additional MRs for the registrations and the - * invalidation. + * If the device uses MRs to perform RDMA READ or WRITE operations, + * or if data integrity is enabled, account for registration and + * invalidation work requests. */ if (attr->create_flags & IB_QP_CREATE_INTEGRITY_EN || rdma_rw_can_use_mr(dev, attr->port_num)) - factor +=3D 2; /* inv + reg */ + factor +=3D 2; /* reg + inv */ =20 attr->cap.max_send_wr +=3D factor * attr->cap.max_rdma_ctxs; =20 /* - * But maybe we were just too high in the sky and the device doesn't - * even support all we need, and we'll have to live with what we get.. + * The device might not support all we need, and we'll have to + * live with what we get. */ attr->cap.max_send_wr =3D min_t(u32, attr->cap.max_send_wr, dev->attrs.max_qp_wr); diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/cor= e/umem_dmabuf.c index 39357dc2d229..66f576019747 100644 --- a/drivers/infiniband/core/umem_dmabuf.c +++ b/drivers/infiniband/core/umem_dmabuf.c @@ -205,13 +205,11 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(stru= ct ib_device *device, =20 err =3D ib_umem_dmabuf_map_pages(umem_dmabuf); if (err) - goto err_unpin; + goto err_release; dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); =20 return umem_dmabuf; =20 -err_unpin: - dma_buf_unpin(umem_dmabuf->attach); err_release: dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); ib_umem_release(&umem_dmabuf->umem); diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/u= ser_mad.c index 2ed749f50a29..285f251fc014 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -514,7 +514,8 @@ static ssize_t ib_umad_write(struct file *filp, const c= har __user *buf, struct rdma_ah_attr ah_attr; struct ib_ah *ah; __be64 *tid; - int ret, data_len, hdr_len, copy_offset, rmpp_active; + int ret, hdr_len, copy_offset, rmpp_active; + size_t data_len; u8 base_version; =20 if (count < hdr_size(file) + IB_MGMT_RMPP_HDR) @@ -588,7 +589,10 @@ static ssize_t ib_umad_write(struct file *filp, const = char __user *buf, } =20 base_version =3D ((struct ib_mad_hdr *)&packet->mad.data)->base_version; - data_len =3D count - hdr_size(file) - hdr_len; + if (check_sub_overflow(count, hdr_size(file) + hdr_len, &data_len)) { + ret =3D -EINVAL; + goto err_ah; + } packet->msg =3D ib_create_send_mad(agent, be32_to_cpu(packet->mad.hdr.qpn), packet->mad.hdr.pkey_index, rmpp_active, diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core= /uverbs_cmd.c index 33e2fe0facd5..2e4265ba35b7 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -2030,7 +2030,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bu= ndle *attrs) if (ret) return ret; =20 - user_wr =3D kmalloc(cmd.wqe_size, GFP_KERNEL); + if (cmd.wqe_size < sizeof(struct ib_uverbs_send_wr)) + return -EINVAL; + + user_wr =3D kmalloc(cmd.wqe_size, GFP_KERNEL | __GFP_NOWARN); if (!user_wr) return -ENOMEM; =20 @@ -2220,7 +2223,7 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *ite= r, u32 wr_count, if (ret) return ERR_PTR(ret); =20 - user_wr =3D kmalloc(wqe_size, GFP_KERNEL); + user_wr =3D kmalloc(wqe_size, GFP_KERNEL | __GFP_NOWARN); if (!user_wr) return ERR_PTR(-ENOMEM); =20 diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/= efa/efa_verbs.c index 2a5b93ef4b33..121384fee669 100644 --- a/drivers/infiniband/hw/efa/efa_verbs.c +++ b/drivers/infiniband/hw/efa/efa_verbs.c @@ -1567,7 +1567,7 @@ static struct efa_mr *efa_alloc_mr(struct ib_pd *ibpd= , int access_flags, struct efa_mr *mr; =20 if (udata && udata->inlen && - !ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) { + !ib_is_udata_cleared(udata, 0, udata->inlen)) { ibdev_dbg(&dev->ibdev, "Incompatible ABI params, udata not cleared\n"); return ERR_PTR(-EINVAL); diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniban= d/hw/hns/hns_roce_hw_v2.c index f1d4494c7d00..b50529a65274 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -3588,6 +3588,23 @@ static void hns_roce_v2_write_cqc(struct hns_roce_de= v *hr_dev, HNS_ROCE_V2_CQ_DEFAULT_INTERVAL); } =20 +static bool left_sw_wc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr= _cq) +{ + struct hns_roce_qp *hr_qp; + + list_for_each_entry(hr_qp, &hr_cq->sq_list, sq_node) { + if (hr_qp->sq.head !=3D hr_qp->sq.tail) + return true; + } + + list_for_each_entry(hr_qp, &hr_cq->rq_list, rq_node) { + if (hr_qp->rq.head !=3D hr_qp->rq.tail) + return true; + } + + return false; +} + static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) { @@ -3596,6 +3613,12 @@ static int hns_roce_v2_req_notify_cq(struct ib_cq *i= bcq, struct hns_roce_v2_db cq_db =3D {}; u32 notify_flag; =20 + if (hr_dev->state >=3D HNS_ROCE_DEVICE_STATE_RST_DOWN) { + if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && + left_sw_wc(hr_dev, hr_cq)) + return 1; + return 0; + } /* * flags =3D 0, then notify_flag : next * flags =3D 1, then notify flag : solocited @@ -6604,7 +6627,8 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_= dev *hr_dev) =20 INIT_WORK(&hr_dev->ecc_work, fmea_ram_ecc_work); =20 - hr_dev->irq_workq =3D alloc_ordered_workqueue("hns_roce_irq_workq", 0); + hr_dev->irq_workq =3D alloc_ordered_workqueue("hns_roce_irq_workq", + WQ_MEM_RECLAIM); if (!hr_dev->irq_workq) { dev_err(dev, "failed to create irq workqueue.\n"); ret =3D -ENOMEM; diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/r= xe/rxe_comp.c index c997b7cbf2a9..81b645c727a1 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -119,12 +119,15 @@ void retransmit_timer(struct timer_list *t) =20 rxe_dbg_qp(qp, "retransmit timer fired\n"); =20 + if (!rxe_get(qp)) + return; spin_lock_irqsave(&qp->state_lock, flags); if (qp->valid) { qp->comp.timeout =3D 1; rxe_sched_task(&qp->comp.task); } spin_unlock_irqrestore(&qp->state_lock, flags); + rxe_put(qp); } =20 void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb) diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rx= e/rxe_req.c index 7ff152ffe15b..4d550ac0dac5 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -103,6 +103,8 @@ void rnr_nak_timer(struct timer_list *t) =20 rxe_dbg_qp(qp, "nak timer fired\n"); =20 + if (!rxe_get(qp)) + return; spin_lock_irqsave(&qp->state_lock, flags); if (qp->valid) { /* request a send queue retry */ @@ -111,6 +113,7 @@ void rnr_nak_timer(struct timer_list *t) rxe_sched_task(&qp->req.task); } spin_unlock_irqrestore(&qp->state_lock, flags); + rxe_put(qp); } =20 static void req_check_sq_drain_done(struct rxe_qp *qp) diff --git a/drivers/infiniband/sw/rxe/rxe_srq.c b/drivers/infiniband/sw/rx= e/rxe_srq.c index 2a234f26ac10..c9a7cd38953d 100644 --- a/drivers/infiniband/sw/rxe/rxe_srq.c +++ b/drivers/infiniband/sw/rxe/rxe_srq.c @@ -77,9 +77,6 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq= *srq, goto err_free; } =20 - srq->rq.queue =3D q; - init->attr.max_wr =3D srq->rq.max_wr; - if (uresp) { if (copy_to_user(&uresp->srq_num, &srq->srq_num, sizeof(uresp->srq_num))) { @@ -88,6 +85,9 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq= *srq, } } =20 + srq->rq.queue =3D q; + init->attr.max_wr =3D srq->rq.max_wr; + return 0; =20 err_free: diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/= siw/siw_qp_rx.c index 58bbf738e4e5..e2ad2425d57d 100644 --- a/drivers/infiniband/sw/siw/siw_qp_rx.c +++ b/drivers/infiniband/sw/siw/siw_qp_rx.c @@ -1456,7 +1456,8 @@ int siw_tcp_rx_data(read_descriptor_t *rd_desc, struc= t sk_buff *skb, } if (unlikely(rv !=3D 0 && rv !=3D -EAGAIN)) { if ((srx->state > SIW_GET_HDR || - qp->rx_fpdu->more_ddp_segs) && run_completion) + (qp->rx_fpdu && qp->rx_fpdu->more_ddp_segs)) && + run_completion) siw_rdmap_complete(qp, rv); =20 siw_dbg_qp(qp, "rx error %d, rx state %d\n", rv, diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ul= p/rtrs/rtrs-clt.c index eaf911e2ffa9..1af2ee8c8ed5 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -1922,7 +1922,7 @@ static int rtrs_rdma_conn_rejected(struct rtrs_clt_co= n *con, struct rtrs_path *s =3D con->c.path; const struct rtrs_msg_conn_rsp *msg; const char *rej_msg; - int status, errno; + int status, errno =3D -ECONNRESET; u8 data_len; =20 status =3D ev->status; @@ -1944,7 +1944,7 @@ static int rtrs_rdma_conn_rejected(struct rtrs_clt_co= n *con, status, rej_msg); } =20 - return -ECONNRESET; + return errno; } =20 void rtrs_clt_close_conns(struct rtrs_clt_path *clt_path, bool wait) diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ul= p/rtrs/rtrs-srv.c index 5dbf315630c1..2c3c8b32190f 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -205,7 +205,6 @@ static int rdma_write_sg(struct rtrs_srv_op *id) size_t sg_cnt; int err, offset; bool need_inval; - u32 rkey =3D 0; struct ib_reg_wr rwr; struct ib_sge *plist; struct ib_sge list; @@ -237,11 +236,6 @@ static int rdma_write_sg(struct rtrs_srv_op *id) wr->wr.num_sge =3D 1; wr->remote_addr =3D le64_to_cpu(id->rd_msg->desc[0].addr); wr->rkey =3D le32_to_cpu(id->rd_msg->desc[0].key); - if (rkey =3D=3D 0) - rkey =3D wr->rkey; - else - /* Only one key is actually used */ - WARN_ON_ONCE(rkey !=3D wr->rkey); =20 wr->wr.opcode =3D IB_WR_RDMA_WRITE; wr->wr.wr_cqe =3D &io_comp_cqe; @@ -274,7 +268,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) inv_wr.opcode =3D IB_WR_SEND_WITH_INV; inv_wr.wr_cqe =3D &io_comp_cqe; inv_wr.send_flags =3D 0; - inv_wr.ex.invalidate_rkey =3D rkey; + inv_wr.ex.invalidate_rkey =3D wr->rkey; } =20 imm_wr.wr.next =3D NULL; @@ -598,7 +592,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path) srv_path->mrs_num++) { struct rtrs_srv_mr *srv_mr =3D &srv_path->mrs[srv_path->mrs_num]; struct scatterlist *s; - int nr, nr_sgt, chunks; + int nr, nr_sgt, chunks, ind; =20 sgt =3D &srv_mr->sgt; chunks =3D chunks_per_mr * srv_path->mrs_num; @@ -628,7 +622,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path) } nr =3D ib_map_mr_sg(mr, sgt->sgl, nr_sgt, NULL, max_chunk_size); - if (nr !=3D nr_sgt) { + if (nr < nr_sgt) { err =3D nr < 0 ? nr : -EINVAL; goto dereg_mr; } @@ -644,9 +638,24 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_pat= h) goto dereg_mr; } } - /* Eventually dma addr for each chunk can be cached */ - for_each_sg(sgt->sgl, s, nr_sgt, i) - srv_path->dma_addr[chunks + i] =3D sg_dma_address(s); + + /* + * Cache DMA addresses by traversing sg entries. If + * regions were merged, an inner loop is required to + * populate the DMA address array by traversing larger + * regions. + */ + ind =3D chunks; + for_each_sg(sgt->sgl, s, nr_sgt, i) { + unsigned int dma_len =3D sg_dma_len(s); + u64 dma_addr =3D sg_dma_address(s); + u64 dma_addr_end =3D dma_addr + dma_len; + + do { + srv_path->dma_addr[ind++] =3D dma_addr; + dma_addr +=3D max_chunk_size; + } while (dma_addr < dma_addr_end); + } =20 ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); srv_mr->mr =3D mr; diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 23cfb98fe90a..d119a104a343 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -941,7 +941,12 @@ static int wait_on_sem(struct amd_iommu *iommu, u64 da= ta) { int i =3D 0; =20 - while (*iommu->cmd_sem !=3D data && i < LOOP_TIMEOUT) { + /* + * cmd_sem holds a monotonically non-decreasing completion sequence + * number. + */ + while ((__s64)(READ_ONCE(*iommu->cmd_sem) - data) < 0 && + i < LOOP_TIMEOUT) { udelay(1); i +=3D 1; } @@ -1210,14 +1215,13 @@ static int iommu_completion_wait(struct amd_iommu *= iommu) raw_spin_lock_irqsave(&iommu->lock, flags); =20 ret =3D __iommu_queue_command_sync(iommu, &cmd, false); + raw_spin_unlock_irqrestore(&iommu->lock, flags); + if (ret) - goto out_unlock; + return ret; =20 ret =3D wait_on_sem(iommu, data); =20 -out_unlock: - raw_spin_unlock_irqrestore(&iommu->lock, flags); - return ret; } =20 @@ -2879,13 +2883,18 @@ static void iommu_flush_irt_and_complete(struct amd= _iommu *iommu, u16 devid) raw_spin_lock_irqsave(&iommu->lock, flags); ret =3D __iommu_queue_command_sync(iommu, &cmd, true); if (ret) - goto out; + goto out_err; ret =3D __iommu_queue_command_sync(iommu, &cmd2, false); if (ret) - goto out; + goto out_err; + raw_spin_unlock_irqrestore(&iommu->lock, flags); + wait_on_sem(iommu, data); -out: + return; + +out_err: raw_spin_unlock_irqrestore(&iommu->lock, flags); + return; } =20 static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid, diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/ar= m/arm-smmu-v3/arm-smmu-v3.c index f2260f45728e..bb7365b43219 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -443,20 +443,26 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_de= vice *smmu) */ static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq) { - int val; - /* - * We can try to avoid the cmpxchg() loop by simply incrementing the - * lock counter. When held in exclusive state, the lock counter is set - * to INT_MIN so these increments won't hurt as the value will remain - * negative. + * When held in exclusive state, the lock counter is set to INT_MIN + * so these increments won't hurt as the value will remain negative. + * The increment will also signal the exclusive locker that there are + * shared waiters. */ if (atomic_fetch_inc_relaxed(&cmdq->lock) >=3D 0) return; =20 - do { - val =3D atomic_cond_read_relaxed(&cmdq->lock, VAL >=3D 0); - } while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) !=3D val); + /* + * Someone else is holding the lock in exclusive state, so wait + * for them to finish. Since we already incremented the lock counter, + * no exclusive lock can be acquired until we finish. We don't need + * the return value since we only care that the exclusive lock is + * released (i.e. the lock counter is non-negative). + * Once the exclusive locker releases the lock, the sign bit will + * be cleared and our increment will make the lock counter positive, + * allowing us to proceed. + */ + atomic_cond_read_relaxed(&cmdq->lock, VAL > 0); } =20 static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq) @@ -483,9 +489,14 @@ static bool arm_smmu_cmdq_shared_tryunlock(struct arm_= smmu_cmdq *cmdq) __ret; \ }) =20 +/* + * Only clear the sign bit when releasing the exclusive lock this will + * allow any shared_lock() waiters to proceed without the possibility + * of entering the exclusive lock in a tight loop. + */ #define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags) \ ({ \ - atomic_set_release(&cmdq->lock, 0); \ + atomic_fetch_andnot_release(INT_MIN, &cmdq->lock); \ local_irq_restore(flags); \ }) =20 diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index 8faa93cffac4..99589ac3b96b 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -207,6 +207,9 @@ static struct pasid_entry *intel_pasid_get_entry(struct= device *dev, u32 pasid) if (!entries) return NULL; =20 + if (!ecap_coherent(info->iommu->ecap)) + clflush_cache_range(entries, VTD_PAGE_SIZE); + /* * The pasid directory table entry won't be freed after * allocation. No worry about the race with free and @@ -218,10 +221,8 @@ static struct pasid_entry *intel_pasid_get_entry(struc= t device *dev, u32 pasid) free_pgtable_page(entries); goto retry; } - if (!ecap_coherent(info->iommu->ecap)) { - clflush_cache_range(entries, VTD_PAGE_SIZE); + if (!ecap_coherent(info->iommu->ecap)) clflush_cache_range(&dir[dir_index].val, sizeof(*dir)); - } } =20 return &entries[index]; @@ -428,7 +429,7 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iomm= u, if (!info || !info->ats_enabled) return; =20 - if (pci_dev_is_disconnected(to_pci_dev(dev))) + if (!pci_device_is_present(to_pci_dev(dev))) return; =20 sid =3D info->bus << 8 | info->devfn; diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-= lpg.c index a41c2b13766d..9843fe2e5f9e 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -221,7 +221,7 @@ static int lpg_lut_store(struct lpg *lpg, struct led_pa= ttern *pattern, { unsigned int idx; u16 val; - int i; + int i, ret; =20 idx =3D bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size, 0, len, 0); @@ -231,8 +231,10 @@ static int lpg_lut_store(struct lpg *lpg, struct led_p= attern *pattern, for (i =3D 0; i < len; i++) { val =3D pattern[i].brightness; =20 - regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i), - &val, sizeof(val)); + ret =3D regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i), + &val, sizeof(val)); + if (ret) + return ret; } =20 bitmap_set(lpg->lut_bitmap, idx, len); diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-fle= xrm-mailbox.c index a2b8839d4e7c..a1e02efe93ad 100644 --- a/drivers/mailbox/bcm-flexrm-mailbox.c +++ b/drivers/mailbox/bcm-flexrm-mailbox.c @@ -1173,14 +1173,6 @@ static int flexrm_debugfs_stats_show(struct seq_file= *file, void *offset) =20 /* =3D=3D=3D=3D=3D=3D FlexRM interrupt handler =3D=3D=3D=3D=3D */ =20 -static irqreturn_t flexrm_irq_event(int irq, void *dev_id) -{ - /* We only have MSI for completions so just wakeup IRQ thread */ - /* Ring related errors will be informed via completion descriptors */ - - return IRQ_WAKE_THREAD; -} - static irqreturn_t flexrm_irq_thread(int irq, void *dev_id) { flexrm_process_completions(dev_id); @@ -1271,10 +1263,8 @@ static int flexrm_startup(struct mbox_chan *chan) ret =3D -ENODEV; goto fail_free_cmpl_memory; } - ret =3D request_threaded_irq(ring->irq, - flexrm_irq_event, - flexrm_irq_thread, - 0, dev_name(ring->mbox->dev), ring); + ret =3D request_threaded_irq(ring->irq, NULL, flexrm_irq_thread, + IRQF_ONESHOT, dev_name(ring->mbox->dev), ring); if (ret) { dev_err(ring->mbox->dev, "failed to request ring%d IRQ\n", ring->num); diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c index 3ef4dd8adf5d..5eef59f00abd 100644 --- a/drivers/mailbox/imx-mailbox.c +++ b/drivers/mailbox/imx-mailbox.c @@ -113,6 +113,7 @@ struct imx_mu_dcfg { u32 xRR; /* Receive Register0 */ u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */ u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */ + bool skip_suspend_flag; }; =20 #define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 = - (x)))) @@ -906,6 +907,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp =3D { .xRR =3D 0x40, .xSR =3D {0x60, 0x60, 0x60, 0x60}, .xCR =3D {0x64, 0x64, 0x64, 0x64, 0x64}, + .skip_suspend_flag =3D true, }; =20 static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp =3D { @@ -986,7 +988,8 @@ static int __maybe_unused imx_mu_suspend_noirq(struct d= evice *dev) priv->xcr[i] =3D imx_mu_read(priv, priv->dcfg->xCR[i]); } =20 - priv->suspend =3D true; + if (!priv->dcfg->skip_suspend_flag) + priv->suspend =3D true; =20 return 0; } @@ -1009,7 +1012,8 @@ static int __maybe_unused imx_mu_resume_noirq(struct = device *dev) imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]); } =20 - priv->suspend =3D false; + if (!priv->dcfg->skip_suspend_flag) + priv->suspend =3D false; =20 return 0; } diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 2b7d0bc92072..1d4191cb9138 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -481,7 +481,7 @@ static int pcc_startup(struct mbox_chan *chan) =20 if (pchan->plat_irq > 0) { irqflags =3D pcc_chan_plat_irq_can_be_shared(pchan) ? - IRQF_SHARED | IRQF_ONESHOT : 0; + IRQF_SHARED : 0; rc =3D devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, irqflags, MBOX_IRQ_NAME, chan); if (unlikely(rc)) { diff --git a/drivers/mailbox/sprd-mailbox.c b/drivers/mailbox/sprd-mailbox.c index 9ae57de77d4d..109ff60c4ac7 100644 --- a/drivers/mailbox/sprd-mailbox.c +++ b/drivers/mailbox/sprd-mailbox.c @@ -167,6 +167,11 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *= data) return IRQ_NONE; } =20 + /* Clear FIFO delivery and overflow status first */ + writel(fifo_sts & + (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK), + priv->inbox_base + SPRD_MBOX_FIFO_RST); + while (send_sts) { id =3D __ffs(send_sts); send_sts &=3D (send_sts - 1); @@ -182,11 +187,6 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *= data) mbox_chan_txdone(chan, 0); } =20 - /* Clear FIFO delivery and overflow status */ - writel(fifo_sts & - (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK), - priv->inbox_base + SPRD_MBOX_FIFO_RST); - /* Clear irq status */ writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS); =20 @@ -244,21 +244,19 @@ static int sprd_mbox_startup(struct mbox_chan *chan) /* Select outbox FIFO mode and reset the outbox FIFO status */ writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST); =20 - /* Enable inbox FIFO overflow and delivery interrupt */ - val =3D readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK); - val &=3D ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ); + /* Enable inbox FIFO delivery interrupt */ + val =3D SPRD_INBOX_FIFO_IRQ_MASK; + val &=3D ~SPRD_INBOX_FIFO_DELIVER_IRQ; writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK); =20 /* Enable outbox FIFO not empty interrupt */ - val =3D readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK); + val =3D SPRD_OUTBOX_FIFO_IRQ_MASK; val &=3D ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK); =20 /* Enable supplementary outbox as the fundamental one */ if (priv->supp_base) { writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST); - val =3D readl(priv->supp_base + SPRD_MBOX_IRQ_MSK); - val &=3D ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK); } } diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-stor= e.c index c3799757bf4a..88f119a0a2ae 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -116,7 +116,7 @@ int dm_exception_store_type_register(struct dm_exceptio= n_store_type *type) if (!__find_exception_store_type(type->name)) list_add(&type->list, &_exception_store_types); else - r =3D -EEXIST; + r =3D -EBUSY; spin_unlock(&_lock); =20 return r; diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 6442d41622ef..be1bf3865415 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -2313,7 +2313,7 @@ static void dm_integrity_map_continue(struct dm_integ= rity_io *dio, bool from_map =20 new_pos =3D find_journal_node(ic, dio->range.logical_sector, &next_secto= r); if (unlikely(new_pos !=3D NOT_FOUND) || - unlikely(next_sector < dio->range.logical_sector - dio->range.n_sect= ors)) { + unlikely(next_sector < dio->range.logical_sector + dio->range.n_sect= ors)) { remove_range_unlocked(ic, &dio->range); spin_unlock_irq(&ic->endio_wait.lock); queue_work(ic->commit_wq, &ic->commit_work); @@ -3258,14 +3258,27 @@ static void dm_integrity_resume(struct dm_target *t= i) struct dm_integrity_c *ic =3D ti->private; __u64 old_provided_data_sectors =3D le64_to_cpu(ic->sb->provided_data_sec= tors); int r; + __le32 flags; =20 DEBUG_print("resume\n"); =20 ic->wrote_to_journal =3D false; =20 + flags =3D ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING); + r =3D sync_rw_sb(ic, REQ_OP_READ); + if (r) + dm_integrity_io_error(ic, "reading superblock", r); + if ((ic->sb->flags & flags) !=3D flags) { + ic->sb->flags |=3D flags; + r =3D sync_rw_sb(ic, REQ_OP_WRITE | REQ_FUA); + if (unlikely(r)) + dm_integrity_io_error(ic, "writing superblock", r); + } + if (ic->provided_data_sectors !=3D old_provided_data_sectors) { if (ic->provided_data_sectors > old_provided_data_sectors && ic->mode =3D=3D 'B' && + ic->sb->flags & cpu_to_le32(SB_FLAG_DIRTY_BITMAP) && ic->sb->log2_blocks_per_bitmap_bit =3D=3D ic->log2_blocks_per_bitmap= _bit) { rw_journal_sectors(ic, REQ_OP_READ, 0, ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL); diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index f7f9c2100937..e215478bcee0 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -121,7 +121,7 @@ int dm_dirty_log_type_register(struct dm_dirty_log_type= *type) if (!__find_dirty_log_type(type->name)) list_add(&type->list, &_log_types); else - r =3D -EEXIST; + r =3D -EBUSY; spin_unlock(&_lock); =20 return r; diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index bea3cda9938e..9a03658aec20 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -220,6 +220,7 @@ static struct multipath *alloc_multipath(struct dm_targ= et *ti) mutex_init(&m->work_mutex); =20 m->queue_mode =3D DM_TYPE_NONE; + m->pg_init_delay_msecs =3D DM_PG_INIT_DELAY_DEFAULT; =20 m->ti =3D ti; ti->private =3D m; @@ -252,7 +253,6 @@ static int alloc_multipath_stage2(struct dm_target *ti,= struct multipath *m) set_bit(MPATHF_QUEUE_IO, &m->flags); atomic_set(&m->pg_init_in_progress, 0); atomic_set(&m->pg_init_count, 0); - m->pg_init_delay_msecs =3D DM_PG_INIT_DELAY_DEFAULT; init_waitqueue_head(&m->pg_init_wait); =20 return 0; diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c index 3e4cb81ce512..78f98545ca72 100644 --- a/drivers/md/dm-path-selector.c +++ b/drivers/md/dm-path-selector.c @@ -107,7 +107,7 @@ int dm_register_path_selector(struct path_selector_type= *pst) =20 if (__find_path_selector_type(pst->name)) { kfree(psi); - r =3D -EEXIST; + r =3D -EBUSY; } else list_add(&psi->list, &_path_selectors); =20 diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 499f8cc8a39f..29d6ee68d4df 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -109,14 +109,21 @@ static void end_clone_bio(struct bio *clone) */ tio->completed +=3D nr_bytes; =20 + if (!is_last) + return; + /* + * At this moment we know this is the last bio of the cloned request, + * and all cloned bios have been released, so reset the clone request's + * bio pointer to avoid double free. + */ + tio->clone->bio =3D NULL; + exit: /* * Update the original request. * Do not use blk_mq_end_request() here, because it may complete * the original request before the clone, and break the ordering. */ - if (is_last) - exit: - blk_update_request(tio->orig, BLK_STS_OK, tio->completed); + blk_update_request(tio->orig, BLK_STS_OK, tio->completed); } =20 static struct dm_rq_target_io *tio_from_request(struct request *rq) @@ -278,8 +285,7 @@ static void dm_complete_request(struct request *rq, blk= _status_t error) struct dm_rq_target_io *tio =3D tio_from_request(rq); =20 tio->error =3D error; - if (likely(!blk_should_fake_timeout(rq->q))) - blk_mq_complete_request(rq); + blk_mq_complete_request(rq); } =20 /* diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 27e2992ff249..4d1f04b40653 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c @@ -88,7 +88,7 @@ int dm_register_target(struct target_type *tt) if (__find_target_type(tt->name)) { DMERR("%s: '%s' target already registered", __func__, tt->name); - rv =3D -EEXIST; + rv =3D -EBUSY; } else { list_add(&tt->list, &_targets); } diff --git a/drivers/md/dm-unstripe.c b/drivers/md/dm-unstripe.c index e8a9432057dc..17be48359564 100644 --- a/drivers/md/dm-unstripe.c +++ b/drivers/md/dm-unstripe.c @@ -117,7 +117,7 @@ static void unstripe_dtr(struct dm_target *ti) static sector_t map_to_core(struct dm_target *ti, struct bio *bio) { struct unstripe_c *uc =3D ti->private; - sector_t sector =3D bio->bi_iter.bi_sector; + sector_t sector =3D dm_target_offset(ti, bio->bi_iter.bi_sector); sector_t tmp_sector =3D sector; =20 /* Shift us up to the right "row" on the stripe */ diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 4474352ad3d1..9275053b387b 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -566,9 +566,9 @@ void verity_fec_dtr(struct dm_verity *v) mempool_exit(&f->output_pool); kmem_cache_destroy(f->cache); =20 - if (f->data_bufio) + if (!IS_ERR_OR_NULL(f->data_bufio)) dm_bufio_client_destroy(f->data_bufio); - if (f->bufio) + if (!IS_ERR_OR_NULL(f->bufio)) dm_bufio_client_destroy(f->bufio); =20 if (f->dev) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f0c4c3553c01..1d03536fded0 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1363,6 +1363,8 @@ void dm_submit_bio_remap(struct bio *clone, struct bi= o *tgt_clone) if (!tgt_clone) tgt_clone =3D clone; =20 + bio_clone_blkg_association(tgt_clone, io->orig_bio); + /* * Account io->origin_bio to DM dev on behalf of target * that took ownership of IO with DM_MAPIO_SUBMITTED. diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 1f1991634d0a..ace28eb81111 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -2224,6 +2224,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t = blocks, memcpy(page_address(store.sb_page), page_address(bitmap->storage.sb_page), sizeof(bitmap_super_t)); + mutex_lock(&bitmap->mddev->bitmap_info.mutex); spin_lock_irq(&bitmap->counts.lock); md_bitmap_file_unmap(&bitmap->storage); bitmap->storage =3D store; @@ -2331,7 +2332,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t = blocks, set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); } spin_unlock_irq(&bitmap->counts.lock); - + mutex_unlock(&bitmap->mddev->bitmap_info.mutex); if (!init) { md_bitmap_unplug(bitmap); bitmap->mddev->pers->quiesce(bitmap->mddev, 0); diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 6a89f6b5d64f..54f90afbafe9 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -532,8 +532,13 @@ static void process_metadata_update(struct mddev *mdde= v, struct cluster_msg *msg =20 dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR); =20 - /* daemaon thread must exist */ thread =3D rcu_dereference_protected(mddev->thread, true); + if (!thread) { + pr_warn("md-cluster: Received metadata update but MD thread is not ready= \n"); + dlm_unlock_sync(cinfo->no_new_dev_lockres); + return; + } + wait_event(thread->wqueue, (got_lock =3D mddev_trylock(mddev)) || test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state)); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a75d090a7fa1..8546ef98bfa7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3533,7 +3533,6 @@ static sector_t raid10_sync_request(struct mddev *mdd= ev, sector_t sector_nr, !test_bit(In_sync, &rdev->flags)) continue; /* This is where we read from */ - any_working =3D 1; sector =3D r10_bio->devs[j].addr; =20 if (is_badblock(rdev, sector, max_sync, @@ -3548,6 +3547,7 @@ static sector_t raid10_sync_request(struct mddev *mdd= ev, sector_t sector_nr, continue; } } + any_working =3D 1; bio =3D r10_bio->devs[0].bio; bio->bi_next =3D biolist; biolist =3D bio; diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxde= v.c index 9ce5f010de3f..804fb339f735 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -396,11 +396,11 @@ static int dvb_dmxdev_section_callback(const u8 *buff= er1, size_t buffer1_len, if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) { ret =3D dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, buffer1, buffer1_len, - buffer_flags); + buffer_flags, true); if (ret =3D=3D buffer1_len) ret =3D dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx, buffer2, buffer2_len, - buffer_flags); + buffer_flags, true); } else { ret =3D dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); @@ -451,10 +451,10 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, = size_t buffer1_len, =20 if (dvb_vb2_is_streaming(ctx)) { ret =3D dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len, - buffer_flags); + buffer_flags, false); if (ret =3D=3D buffer1_len) ret =3D dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len, - buffer_flags); + buffer_flags, false); } else { if (buffer->error) { spin_unlock(&dmxdevfilter->dev->lock); diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_= vb2.c index 909df82fed33..8950e608a87a 100644 --- a/drivers/media/dvb-core/dvb_vb2.c +++ b/drivers/media/dvb-core/dvb_vb2.c @@ -252,7 +252,8 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx) =20 int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, const unsigned char *src, int len, - enum dmx_buffer_flags *buffer_flags) + enum dmx_buffer_flags *buffer_flags, + bool flush) { unsigned long flags =3D 0; void *vbuf =3D NULL; @@ -309,7 +310,7 @@ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, } } =20 - if (ctx->nonblocking && ctx->buf) { + if (flush && ctx->buf) { vb2_set_plane_payload(&ctx->buf->vb, 0, ll); vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); list_del(&ctx->buf->list); diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index ecb0e7b1f2a5..4778ae653ca9 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -471,6 +471,13 @@ static int adv7180_g_frame_interval(struct v4l2_subdev= *sd, fi->interval.denominator =3D 25; } =20 + /* + * If the de-interlacer is active, the chip produces full video frames + * at the field rate. + */ + if (state->field =3D=3D V4L2_FIELD_NONE) + fi->interval.denominator *=3D 2; + return 0; } =20 diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-c= ore.c index 4d31b2bb8f09..ae8309bd5e4d 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -2386,7 +2386,7 @@ static void ccs_set_compose_scaler(struct v4l2_subdev= *subdev, * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.height; max_m =3D crops[CCS_PAD_SINK]->width * CCS_LIM(sensor, SCALER_N_MIN) - / CCS_LIM(sensor, MIN_X_OUTPUT_SIZE); + / (CCS_LIM(sensor, MIN_X_OUTPUT_SIZE) ?: 1); =20 a =3D clamp(a, CCS_LIM(sensor, SCALER_M_MIN), CCS_LIM(sensor, SCALER_M_MAX)); @@ -3530,7 +3530,21 @@ static int ccs_probe(struct i2c_client *client) sensor->scale_m =3D CCS_LIM(sensor, SCALER_N_MIN); =20 /* prepare PLL configuration input values */ - sensor->pll.bus_type =3D CCS_PLL_BUS_TYPE_CSI2_DPHY; + switch (sensor->hwcfg.csi_signalling_mode) { + case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY: + sensor->pll.bus_type =3D CCS_PLL_BUS_TYPE_CSI2_CPHY; + break; + case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY: + case SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK: + case SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE: + sensor->pll.bus_type =3D CCS_PLL_BUS_TYPE_CSI2_DPHY; + break; + default: + dev_err(&client->dev, "unsupported signalling mode %u\n", + sensor->hwcfg.csi_signalling_mode); + rval =3D -EINVAL; + goto out_cleanup; + } sensor->pll.csi2.lanes =3D sensor->hwcfg.lanes; if (CCS_LIM(sensor, CLOCK_CALCULATION) & CCS_CLOCK_CALCULATION_LANE_SPEED) { diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c index 9afe9bf50334..a0e8b1ed0fc9 100644 --- a/drivers/media/i2c/ov01a10.c +++ b/drivers/media/i2c/ov01a10.c @@ -17,7 +17,7 @@ #include =20 #define OV01A10_LINK_FREQ_400MHZ 400000000ULL -#define OV01A10_SCLK 40000000LL +#define OV01A10_SCLK 80000000LL #define OV01A10_DATA_LANES 1 =20 #define OV01A10_REG_CHIP_ID 0x300a @@ -49,7 +49,7 @@ /* analog gain controls */ #define OV01A10_REG_ANALOG_GAIN 0x3508 #define OV01A10_ANAL_GAIN_MIN 0x100 -#define OV01A10_ANAL_GAIN_MAX 0xffff +#define OV01A10_ANAL_GAIN_MAX 0x3fff #define OV01A10_ANAL_GAIN_STEP 1 =20 /* digital gain controls */ @@ -58,7 +58,7 @@ #define OV01A10_REG_DIGITAL_GAIN_GR 0x3513 #define OV01A10_REG_DIGITAL_GAIN_R 0x3516 #define OV01A10_DGTL_GAIN_MIN 0 -#define OV01A10_DGTL_GAIN_MAX 0x3ffff +#define OV01A10_DGTL_GAIN_MAX 0x3fff #define OV01A10_DGTL_GAIN_STEP 1 #define OV01A10_DGTL_GAIN_DEFAULT 1024 =20 @@ -76,6 +76,15 @@ #define OV01A10_REG_X_WIN 0x3811 #define OV01A10_REG_Y_WIN 0x3813 =20 +/* + * The native ov01a10 bayer-pattern is GBRG, but there was a driver bug en= abling + * hflip/mirroring by default resulting in BGGR. Because of this bug Intel= 's + * proprietary IPU6 userspace stack expects BGGR. So we report BGGR to not= break + * userspace and fix things up by shifting the crop window-x coordinate by= 1 + * when hflip is *disabled*. + */ +#define OV01A10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 + struct ov01a10_reg { u16 address; u8 val; @@ -186,14 +195,14 @@ static const struct ov01a10_reg sensor_1280x800_setti= ng[] =3D { {0x380e, 0x03}, {0x380f, 0x80}, {0x3810, 0x00}, - {0x3811, 0x08}, + {0x3811, 0x09}, {0x3812, 0x00}, {0x3813, 0x08}, {0x3814, 0x01}, {0x3815, 0x01}, {0x3816, 0x01}, {0x3817, 0x01}, - {0x3820, 0xa0}, + {0x3820, 0xa8}, {0x3822, 0x13}, {0x3832, 0x28}, {0x3833, 0x10}, @@ -241,9 +250,8 @@ static const struct ov01a10_reg sensor_1280x800_setting= [] =3D { static const char * const ov01a10_test_pattern_menu[] =3D { "Disabled", "Color Bar", - "Top-Bottom Darker Color Bar", - "Right-Left Darker Color Bar", - "Color Bar type 4", + "Left-Right Darker Color Bar", + "Bottom-Top Darker Color Bar", }; =20 static const s64 link_freq_menu_items[] =3D { @@ -401,10 +409,8 @@ static int ov01a10_update_digital_gain(struct ov01a10 = *ov01a10, u32 d_gain) =20 static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern) { - if (!pattern) - return 0; - - pattern =3D (pattern - 1) | OV01A10_TEST_PATTERN_ENABLE; + if (pattern) + pattern |=3D OV01A10_TEST_PATTERN_ENABLE; =20 return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern); } @@ -415,7 +421,7 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u= 32 hflip) int ret; u32 val, offset; =20 - offset =3D hflip ? 0x9 : 0x8; + offset =3D hflip ? 0x8 : 0x9; ret =3D ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset); if (ret) return ret; @@ -424,8 +430,8 @@ static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u= 32 hflip) if (ret) return ret; =20 - val =3D hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) : - val & ~OV01A10_HFLIP_MASK; + val =3D hflip ? val & ~OV01A10_HFLIP_MASK : + val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1); =20 return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); } @@ -614,7 +620,7 @@ static void ov01a10_update_pad_format(const struct ov01= a10_mode *mode, { fmt->width =3D mode->width; fmt->height =3D mode->height; - fmt->code =3D MEDIA_BUS_FMT_SBGGR10_1X10; + fmt->code =3D OV01A10_MEDIA_BUS_FMT; fmt->field =3D V4L2_FIELD_NONE; fmt->colorspace =3D V4L2_COLORSPACE_RAW; } @@ -800,7 +806,7 @@ static int ov01a10_enum_mbus_code(struct v4l2_subdev *s= d, if (code->index > 0) return -EINVAL; =20 - code->code =3D MEDIA_BUS_FMT_SBGGR10_1X10; + code->code =3D OV01A10_MEDIA_BUS_FMT; =20 return 0; } @@ -810,7 +816,7 @@ static int ov01a10_enum_frame_size(struct v4l2_subdev *= sd, struct v4l2_subdev_frame_size_enum *fse) { if (fse->index >=3D ARRAY_SIZE(supported_modes) || - fse->code !=3D MEDIA_BUS_FMT_SBGGR10_1X10) + fse->code !=3D OV01A10_MEDIA_BUS_FMT) return -EINVAL; =20 fse->min_width =3D supported_modes[fse->index].width; @@ -903,6 +909,7 @@ static void ov01a10_remove(struct i2c_client *client) struct v4l2_subdev *sd =3D i2c_get_clientdata(client); =20 v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); =20 @@ -973,6 +980,7 @@ static int ov01a10_probe(struct i2c_client *client) err_pm_disable: pm_runtime_disable(dev); pm_runtime_set_suspended(&client->dev); + v4l2_subdev_cleanup(&ov01a10->sd); =20 err_media_entity_cleanup: media_entity_cleanup(&ov01a10->sd.entity); diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 8de398423b7c..b8033fb7aa30 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -69,11 +69,11 @@ #define OV5647_NATIVE_HEIGHT 1956U =20 #define OV5647_PIXEL_ARRAY_LEFT 16U -#define OV5647_PIXEL_ARRAY_TOP 16U +#define OV5647_PIXEL_ARRAY_TOP 6U #define OV5647_PIXEL_ARRAY_WIDTH 2592U #define OV5647_PIXEL_ARRAY_HEIGHT 1944U =20 -#define OV5647_VBLANK_MIN 4 +#define OV5647_VBLANK_MIN 24 #define OV5647_VTS_MAX 32767 =20 #define OV5647_EXPOSURE_MIN 4 @@ -509,7 +509,7 @@ static const struct ov5647_mode ov5647_modes[] =3D { { .format =3D { .code =3D MEDIA_BUS_FMT_SBGGR10_1X10, - .colorspace =3D V4L2_COLORSPACE_SRGB, + .colorspace =3D V4L2_COLORSPACE_RAW, .field =3D V4L2_FIELD_NONE, .width =3D 2592, .height =3D 1944 @@ -530,7 +530,7 @@ static const struct ov5647_mode ov5647_modes[] =3D { { .format =3D { .code =3D MEDIA_BUS_FMT_SBGGR10_1X10, - .colorspace =3D V4L2_COLORSPACE_SRGB, + .colorspace =3D V4L2_COLORSPACE_RAW, .field =3D V4L2_FIELD_NONE, .width =3D 1920, .height =3D 1080 @@ -551,7 +551,7 @@ static const struct ov5647_mode ov5647_modes[] =3D { { .format =3D { .code =3D MEDIA_BUS_FMT_SBGGR10_1X10, - .colorspace =3D V4L2_COLORSPACE_SRGB, + .colorspace =3D V4L2_COLORSPACE_RAW, .field =3D V4L2_FIELD_NONE, .width =3D 1296, .height =3D 972 @@ -572,7 +572,7 @@ static const struct ov5647_mode ov5647_modes[] =3D { { .format =3D { .code =3D MEDIA_BUS_FMT_SBGGR10_1X10, - .colorspace =3D V4L2_COLORSPACE_SRGB, + .colorspace =3D V4L2_COLORSPACE_RAW, .field =3D V4L2_FIELD_NONE, .width =3D 640, .height =3D 480 @@ -583,7 +583,7 @@ static const struct ov5647_mode ov5647_modes[] =3D { .width =3D 2560, .height =3D 1920, }, - .pixel_rate =3D 55000000, + .pixel_rate =3D 58333000, .hts =3D 1852, .vts =3D 0x1f8, .reg_list =3D ov5647_640x480_10bpp, @@ -1297,6 +1297,8 @@ static int ov5647_init_controls(struct ov5647 *sensor) =20 v4l2_ctrl_handler_init(&sensor->ctrls, 9); =20 + sensor->ctrls.lock =3D &sensor->lock; + v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 0); =20 @@ -1430,15 +1432,15 @@ static int ov5647_probe(struct i2c_client *client) =20 sensor->mode =3D OV5647_DEFAULT_MODE; =20 - ret =3D ov5647_init_controls(sensor); - if (ret) - goto mutex_destroy; - sd =3D &sensor->sd; v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops); sd->internal_ops =3D &ov5647_subdev_internal_ops; sd->flags |=3D V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; =20 + ret =3D ov5647_init_controls(sensor); + if (ret) + goto mutex_destroy; + sensor->pad.flags =3D MEDIA_PAD_FL_SOURCE; sd->entity.function =3D MEDIA_ENT_F_CAM_SENSOR; ret =3D media_entity_pads_init(&sd->entity, 1, &sensor->pad); diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c index 996be3960af3..d17f3b9270ef 100644 --- a/drivers/media/i2c/tw9903.c +++ b/drivers/media/i2c/tw9903.c @@ -228,6 +228,7 @@ static int tw9903_probe(struct i2c_client *client) =20 if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9903\n"); + v4l2_ctrl_handler_free(hdl); return -EINVAL; } =20 diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c index 25c625f6d6e4..13cd1b25ef60 100644 --- a/drivers/media/i2c/tw9906.c +++ b/drivers/media/i2c/tw9906.c @@ -196,6 +196,7 @@ static int tw9906_probe(struct i2c_client *client) =20 if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9906\n"); + v4l2_ctrl_handler_free(hdl); return -EINVAL; } =20 diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/c= x23885/cx23885-alsa.c index 25dc8d4dc5b7..717fc6c9ef21 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -392,8 +392,10 @@ static int snd_cx23885_hw_params(struct snd_pcm_substr= eam *substream, =20 ret =3D cx23885_risc_databuffer(chip->pci, &buf->risc, buf->sglist, chip->period_size, chip->num_periods, 1); - if (ret < 0) + if (ret < 0) { + cx23885_alsa_dma_unmap(chip); goto error; + } =20 /* Loop back to start of program */ buf->risc.jmp[0] =3D cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/c= x25821/cx25821-alsa.c index a42f0c03a7ca..f463365163b7 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -535,6 +535,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substre= am *substream, chip->period_size, chip->num_periods, 1); if (ret < 0) { pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); + cx25821_alsa_dma_unmap(chip); goto error; } =20 diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/c= x25821/cx25821-core.c index 6627fa9166d3..a7336be44474 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -908,6 +908,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) =20 if (!dev->lmmio) { CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.= h\n"); + release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); cx25821_iounmap(dev); return -ENOMEM; } diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx= 88-alsa.c index 29fb1311e443..4e574d8390b4 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -483,8 +483,10 @@ static int snd_cx88_hw_params(struct snd_pcm_substream= *substream, =20 ret =3D cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, chip->period_size, chip->num_periods, 1); - if (ret < 0) + if (ret < 0) { + cx88_alsa_dma_unmap(chip); goto error; + } =20 /* Loop back to start of program */ buf->risc.jmp[0] =3D cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); diff --git a/drivers/media/pci/solo6x10/solo6x10-tw28.c b/drivers/media/pci= /solo6x10/solo6x10-tw28.c index 1b7c22a9bc94..8f53946c6792 100644 --- a/drivers/media/pci/solo6x10/solo6x10-tw28.c +++ b/drivers/media/pci/solo6x10/solo6x10-tw28.c @@ -166,7 +166,7 @@ static const u8 tbl_tw2865_pal_template[] =3D { 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, }; =20 -#define is_tw286x(__solo, __id) (!(__solo->tw2815 & (1 << __id))) +#define is_tw286x(__solo, __id) (!((__solo)->tw2815 & (1U << (__id)))) =20 static u8 tw_readbyte(struct solo_dev *solo_dev, int chip_id, u8 tw6x_off, u8 tw_off) @@ -686,6 +686,9 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ct= rl, u8 ch, chip_num =3D ch / 4; ch %=3D 4; =20 + if (chip_num >=3D TW_NUM_CHIP) + return -EINVAL; + if (val > 255 || val < 0) return -ERANGE; =20 @@ -758,6 +761,9 @@ int tw28_get_ctrl_val(struct solo_dev *solo_dev, u32 ct= rl, u8 ch, chip_num =3D ch / 4; ch %=3D 4; =20 + if (chip_num >=3D TW_NUM_CHIP) + return -EINVAL; + switch (ctrl) { case V4L2_CID_SHARPNESS: /* Only 286x has sharpness */ diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform= /amphion/vdec.c index 4f438eaa7d38..d7e477f0eb43 100644 --- a/drivers/media/platform/amphion/vdec.c +++ b/drivers/media/platform/amphion/vdec.c @@ -630,6 +630,7 @@ static int vdec_decoder_cmd(struct file *file, void *fh= , struct v4l2_decoder_cmd switch (cmd->cmd) { case V4L2_DEC_CMD_START: vdec_cmd_start(inst); + vb2_clear_last_buffer_dequeued(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx)); break; case V4L2_DEC_CMD_STOP: vdec_cmd_stop(inst); diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c b/drivers/m= edia/platform/mediatek/mdp/mtk_mdp_core.c index 917cdf38f230..98540015b1cc 100644 --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c @@ -194,11 +194,17 @@ static int mtk_mdp_probe(struct platform_device *pdev) } =20 mdp->vpu_dev =3D vpu_get_plat_device(pdev); + if (!mdp->vpu_dev) { + dev_err(&pdev->dev, "Failed to get vpu device\n"); + ret =3D -ENODEV; + goto err_vpu_get_dev; + } + ret =3D vpu_wdt_reg_handler(mdp->vpu_dev, mtk_mdp_reset_handler, mdp, VPU_RST_MDP); if (ret) { dev_err(&pdev->dev, "Failed to register reset handler\n"); - goto err_m2m_register; + goto err_reg_handler; } =20 platform_set_drvdata(pdev, mdp); @@ -206,7 +212,7 @@ static int mtk_mdp_probe(struct platform_device *pdev) ret =3D vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { dev_err(&pdev->dev, "Failed to set vb2 dma mag seg size\n"); - goto err_m2m_register; + goto err_reg_handler; } =20 pm_runtime_enable(dev); @@ -214,6 +220,12 @@ static int mtk_mdp_probe(struct platform_device *pdev) =20 return 0; =20 +err_reg_handler: + platform_device_put(mdp->vpu_dev); + +err_vpu_get_dev: + mtk_mdp_unregister_m2m_device(mdp); + err_m2m_register: v4l2_device_unregister(&mdp->v4l2_dev); =20 @@ -242,6 +254,7 @@ static void mtk_mdp_remove(struct platform_device *pdev) =20 pm_runtime_disable(&pdev->dev); vb2_dma_contig_clear_max_seg_size(&pdev->dev); + platform_device_put(mdp->vpu_dev); mtk_mdp_unregister_m2m_device(mdp); v4l2_device_unregister(&mdp->v4l2_dev); =20 diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_= stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec= _stateless.c index e29c9c58f3da..fb629a7cd812 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_statele= ss.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_statele= ss.c @@ -475,6 +475,12 @@ static int mtk_vdec_s_ctrl(struct v4l2_ctrl *ctrl) mtk_v4l2_vdec_err(ctx, "VP9: bit_depth:%d", frame->bit_depth); return -EINVAL; } + + if (!(frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || + !(frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)) { + mtk_v4l2_vdec_err(ctx, "VP9: only 420 subsampling is supported"); + return -EINVAL; + } break; case V4L2_CID_STATELESS_AV1_SEQUENCE: seq =3D (struct v4l2_ctrl_av1_sequence *)hdr_ctrl->p_new.p; diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.= c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c index eb381fa6e7d1..ca9d859376d3 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc.c @@ -865,7 +865,7 @@ static void vb2ops_venc_buf_queue(struct vb2_buffer *vb) static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int c= ount) { struct mtk_vcodec_enc_ctx *ctx =3D vb2_get_drv_priv(q); - struct venc_enc_param param; + struct venc_enc_param param =3D { }; int ret; int i; =20 @@ -1021,7 +1021,7 @@ static int mtk_venc_encode_header(void *priv) int ret; struct vb2_v4l2_buffer *src_buf, *dst_buf; struct mtk_vcodec_mem bs_buf; - struct venc_done_result enc_result; + struct venc_done_result enc_result =3D { }; =20 dst_buf =3D v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (!dst_buf) { @@ -1142,7 +1142,7 @@ static void mtk_venc_worker(struct work_struct *work) struct vb2_v4l2_buffer *src_buf, *dst_buf; struct venc_frm_buf frm_buf; struct mtk_vcodec_mem bs_buf; - struct venc_done_result enc_result; + struct venc_done_result enc_result =3D { }; int ret, i; =20 /* check dst_buf, dst_buf may be removed in device_run diff --git a/drivers/media/platform/qcom/camss/camss-vfe-480.c b/drivers/me= dia/platform/qcom/camss/camss-vfe-480.c index 8ddb8016434a..98d7398db956 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-480.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-480.c @@ -223,11 +223,13 @@ static irqreturn_t vfe_isr(int irq, void *dev) writel_relaxed(status, vfe->base + VFE_BUS_IRQ_CLEAR(0)); writel_relaxed(1, vfe->base + VFE_BUS_IRQ_CLEAR_GLOBAL); =20 - /* Loop through all WMs IRQs */ - for (i =3D 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) { + for (i =3D 0; i < MAX_VFE_OUTPUT_LINES; i++) { if (status & BUS_IRQ_MASK_0_RDI_RUP(vfe, i)) vfe_isr_reg_update(vfe, i); + } =20 + /* Loop through all WMs IRQs */ + for (i =3D 0; i < MSM_VFE_IMAGE_MASTERS_NUM; i++) { if (status & BUS_IRQ_MASK_0_COMP_DONE(vfe, RDI_COMP_GROUP(i))) vfe_isr_wm_done(vfe, i); } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platf= orm/qcom/venus/vdec.c index 8be056210f1d..f15c3b322fe4 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -568,7 +568,13 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v= 4l2_decoder_cmd *cmd) =20 fdata.buffer_type =3D HFI_BUFFER_INPUT; fdata.flags |=3D HFI_BUFFERFLAG_EOS; - if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) + + /* Send NULL EOS addr for only IRIS2 (SM8250),for firmware <=3D 1.0.87. + * SC7280 also reports "1.0." parsed as 1.0.0; restricting to IRIS2 + * avoids misapplying this quirk and breaking VP9 decode on SC7280. + */ + + if (IS_IRIS2(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) fdata.device_addr =3D 0; else fdata.device_addr =3D 0xdeadb000; @@ -1433,10 +1439,10 @@ static void vdec_buf_done(struct venus_inst *inst, = unsigned int buf_type, inst->drain_active =3D false; inst->codec_state =3D VENUS_DEC_STATE_STOPPED; } + } else { + if (!bytesused) + state =3D VB2_BUF_STATE_ERROR; } - - if (!bytesused) - state =3D VB2_BUF_STATE_ERROR; } else { vbuf->sequence =3D inst->sequence_out++; } diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drive= rs/media/platform/rockchip/rkisp1/rkisp1-params.c index 3482f7d707b7..09c20fb2d92e 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c @@ -385,12 +385,6 @@ static void rkisp1_flt_config(struct rkisp1_params *pa= rams, rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_LUM_WEIGHT, arg->lum_weight); =20 - rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE, - (arg->mode ? RKISP1_CIF_ISP_FLT_MODE_DNR : 0) | - RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | - RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | - RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1)); - /* avoid to override the old enable value */ filt_mode =3D rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE); filt_mode &=3D RKISP1_CIF_ISP_FLT_ENA; diff --git a/drivers/media/platform/ti/omap3isp/isppreview.c b/drivers/medi= a/platform/ti/omap3isp/isppreview.c index 53aedec7990d..32e4348e6837 100644 --- a/drivers/media/platform/ti/omap3isp/isppreview.c +++ b/drivers/media/platform/ti/omap3isp/isppreview.c @@ -1744,22 +1744,17 @@ static void preview_try_format(struct isp_prev_devi= ce *prev, =20 switch (pad) { case PREV_PAD_SINK: - /* When reading data from the CCDC, the input size has already - * been mangled by the CCDC output pad so it can be accepted - * as-is. - * - * When reading data from memory, clamp the requested width and - * height. The TRM doesn't specify a minimum input height, make + /* + * Clamp the requested width and height. + * The TRM doesn't specify a minimum input height, make * sure we got enough lines to enable the noise filter and color * filter array interpolation. */ - if (prev->input =3D=3D PREVIEW_INPUT_MEMORY) { - fmt->width =3D clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH, - preview_max_out_width(prev)); - fmt->height =3D clamp_t(u32, fmt->height, - PREV_MIN_IN_HEIGHT, - PREV_MAX_IN_HEIGHT); - } + fmt->width =3D clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH, + preview_max_out_width(prev)); + fmt->height =3D clamp_t(u32, fmt->height, + PREV_MIN_IN_HEIGHT, + PREV_MAX_IN_HEIGHT); =20 fmt->colorspace =3D V4L2_COLORSPACE_SRGB; =20 diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/= platform/ti/omap3isp/ispvideo.c index daca689dc082..b9e0b6215fa0 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.c +++ b/drivers/media/platform/ti/omap3isp/ispvideo.c @@ -148,12 +148,12 @@ static unsigned int isp_video_mbus_to_pix(const struc= t isp_video *video, pix->width =3D mbus->width; pix->height =3D mbus->height; =20 - for (i =3D 0; i < ARRAY_SIZE(formats); ++i) { + for (i =3D 0; i < ARRAY_SIZE(formats) - 1; ++i) { if (formats[i].code =3D=3D mbus->code) break; } =20 - if (WARN_ON(i =3D=3D ARRAY_SIZE(formats))) + if (WARN_ON(i =3D=3D ARRAY_SIZE(formats) - 1)) return 0; =20 min_bpl =3D pix->width * formats[i].bpp; @@ -191,7 +191,7 @@ static void isp_video_pix_to_mbus(const struct v4l2_pix= _format *pix, /* Skip the last format in the loop so that it will be selected if no * match is found. */ - for (i =3D 0; i < ARRAY_SIZE(formats) - 1; ++i) { + for (i =3D 0; i < ARRAY_SIZE(formats) - 2; ++i) { if (formats[i].pixelformat =3D=3D pix->pixelformat) break; } @@ -1288,6 +1288,7 @@ static const struct v4l2_ioctl_ops isp_video_ioctl_op= s =3D { static int isp_video_open(struct file *file) { struct isp_video *video =3D video_drvdata(file); + struct v4l2_mbus_framefmt fmt; struct isp_video_fh *handle; struct vb2_queue *queue; int ret =3D 0; @@ -1329,6 +1330,13 @@ static int isp_video_open(struct file *file) =20 memset(&handle->format, 0, sizeof(handle->format)); handle->format.type =3D video->type; + handle->format.fmt.pix.width =3D 720; + handle->format.fmt.pix.height =3D 480; + handle->format.fmt.pix.pixelformat =3D V4L2_PIX_FMT_UYVY; + handle->format.fmt.pix.field =3D V4L2_FIELD_NONE; + handle->format.fmt.pix.colorspace =3D V4L2_COLORSPACE_SRGB; + isp_video_pix_to_mbus(&handle->format.fmt.pix, &fmt); + isp_video_mbus_to_pix(video, &fmt, &handle->format.fmt.pix); handle->timeperframe.denominator =3D 1; =20 handle->video =3D video; diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.= c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c index ff78b3172829..03b9b78d95e8 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c @@ -72,6 +72,14 @@ : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ }) =20 +enum rockchip_av1_tx_mode { + ROCKCHIP_AV1_TX_MODE_ONLY_4X4 =3D 0, + ROCKCHIP_AV1_TX_MODE_8X8 =3D 1, + ROCKCHIP_AV1_TX_MODE_16x16 =3D 2, + ROCKCHIP_AV1_TX_MODE_32x32 =3D 3, + ROCKCHIP_AV1_TX_MODE_SELECT =3D 4, +}; + struct rockchip_av1_film_grain { u8 scaling_lut_y[256]; u8 scaling_lut_cb[256]; @@ -372,12 +380,12 @@ int rockchip_vpu981_av1_dec_init(struct hantro_ctx *c= tx) return -ENOMEM; av1_dec->global_model.size =3D GLOBAL_MODEL_SIZE; =20 - av1_dec->tile_info.cpu =3D dma_alloc_coherent(vpu->dev, AV1_MAX_TILES, + av1_dec->tile_info.cpu =3D dma_alloc_coherent(vpu->dev, AV1_TILE_INFO_SIZ= E, &av1_dec->tile_info.dma, GFP_KERNEL); if (!av1_dec->tile_info.cpu) return -ENOMEM; - av1_dec->tile_info.size =3D AV1_MAX_TILES; + av1_dec->tile_info.size =3D AV1_TILE_INFO_SIZE; =20 av1_dec->film_grain.cpu =3D dma_alloc_coherent(vpu->dev, ALIGN(sizeof(struct rockchip_av1_film_grain), 2048), @@ -1397,8 +1405,16 @@ static void rockchip_vpu981_av1_dec_set_cdef(struct = hantro_ctx *ctx) u16 luma_sec_strength =3D 0; u32 chroma_pri_strength =3D 0; u16 chroma_sec_strength =3D 0; + bool enable_cdef; int i; =20 + enable_cdef =3D !(cdef->bits =3D=3D 0 && + cdef->damping_minus_3 =3D=3D 0 && + cdef->y_pri_strength[0] =3D=3D 0 && + cdef->y_sec_strength[0] =3D=3D 0 && + cdef->uv_pri_strength[0] =3D=3D 0 && + cdef->uv_sec_strength[0] =3D=3D 0); + hantro_reg_write(vpu, &av1_enable_cdef, enable_cdef); hantro_reg_write(vpu, &av1_cdef_bits, cdef->bits); hantro_reg_write(vpu, &av1_cdef_damping, cdef->damping_minus_3); =20 @@ -1928,11 +1944,26 @@ static void rockchip_vpu981_av1_dec_set_reference_f= rames(struct hantro_ctx *ctx) rockchip_vpu981_av1_dec_set_other_frames(ctx); } =20 +static int rockchip_vpu981_av1_get_hardware_tx_mode(enum v4l2_av1_tx_mode = tx_mode) +{ + switch (tx_mode) { + case V4L2_AV1_TX_MODE_ONLY_4X4: + return ROCKCHIP_AV1_TX_MODE_ONLY_4X4; + case V4L2_AV1_TX_MODE_LARGEST: + return ROCKCHIP_AV1_TX_MODE_32x32; + case V4L2_AV1_TX_MODE_SELECT: + return ROCKCHIP_AV1_TX_MODE_SELECT; + } + + return ROCKCHIP_AV1_TX_MODE_32x32; +} + static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) { struct hantro_dev *vpu =3D ctx->dev; struct hantro_av1_dec_hw_ctx *av1_dec =3D &ctx->av1_dec; struct hantro_av1_dec_ctrls *ctrls =3D &av1_dec->ctrls; + int tx_mode; =20 hantro_reg_write(vpu, &av1_skip_mode, !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT)); @@ -1954,8 +1985,6 @@ static void rockchip_vpu981_av1_dec_set_parameters(st= ruct hantro_ctx *ctx) !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SHOW_FRAME)); hantro_reg_write(vpu, &av1_switchable_motion_mode, !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE= )); - hantro_reg_write(vpu, &av1_enable_cdef, - !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF)); hantro_reg_write(vpu, &av1_allow_masked_compound, !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND)); @@ -1990,7 +2019,7 @@ static void rockchip_vpu981_av1_dec_set_parameters(st= ruct hantro_ctx *ctx) !!(ctrls->frame->quantization.flags & V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT)); =20 - hantro_reg_write(vpu, &av1_idr_pic_e, !ctrls->frame->frame_type); + hantro_reg_write(vpu, &av1_idr_pic_e, IS_INTRA(ctrls->frame->frame_type)); hantro_reg_write(vpu, &av1_quant_base_qindex, ctrls->frame->quantization.= base_q_idx); hantro_reg_write(vpu, &av1_bit_depth_y_minus8, ctx->bit_depth - 8); hantro_reg_write(vpu, &av1_bit_depth_c_minus8, ctx->bit_depth - 8); @@ -2000,7 +2029,9 @@ static void rockchip_vpu981_av1_dec_set_parameters(st= ruct hantro_ctx *ctx) !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV)); hantro_reg_write(vpu, &av1_comp_pred_mode, (ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT) ? 2 : 0); - hantro_reg_write(vpu, &av1_transform_mode, (ctrls->frame->tx_mode =3D=3D = 1) ? 3 : 4); + + tx_mode =3D rockchip_vpu981_av1_get_hardware_tx_mode(ctrls->frame->tx_mod= e); + hantro_reg_write(vpu, &av1_transform_mode, tx_mode); hantro_reg_write(vpu, &av1_max_cb_size, (ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK) ? 7 : 6); diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-= keene.c index a35648316aa8..05d3c4b56721 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -338,7 +338,6 @@ static int usb_keene_probe(struct usb_interface *intf, if (hdl->error) { retval =3D hdl->error; =20 - v4l2_ctrl_handler_free(hdl); goto err_v4l2; } retval =3D v4l2_device_register(&intf->dev, &radio->v4l2_dev); @@ -384,6 +383,7 @@ static int usb_keene_probe(struct usb_interface *intf, err_vdev: v4l2_device_unregister(&radio->v4l2_dev); err_v4l2: + v4l2_ctrl_handler_free(&radio->hdl); kfree(radio->buffer); kfree(radio); err: diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pv= rusb2/pvrusb2-hdw.c index 2de104736f87..943d56b10251 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -3709,6 +3709,11 @@ status); "Failed to submit read-control URB status=3D%d", status); hdw->ctl_read_pend_flag =3D 0; + if (hdw->ctl_write_pend_flag) { + usb_unlink_urb(hdw->ctl_write_urb); + while (hdw->ctl_write_pend_flag) + wait_for_completion(&hdw->ctl_done); + } goto done; } } diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_= video.c index a9f880eb518a..ea7d91b19079 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1819,7 +1819,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming= *stream, npackets =3D UVC_MAX_PACKETS; =20 /* Retry allocations until one succeed. */ - for (; npackets > 1; npackets /=3D 2) { + for (; npackets > 0; npackets /=3D 2) { stream->urb_size =3D psize * npackets; =20 for (i =3D 0; i < UVC_URBS; ++i) { @@ -1844,6 +1844,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming= *stream, uvc_dbg(stream->dev, VIDEO, "Failed to allocate URB buffers (%u bytes per packet)\n", psize); + stream->urb_size =3D 0; return 0; } =20 diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core= /v4l2-async.c index ac4d987bba25..cf2923dea84b 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -339,7 +339,6 @@ static int v4l2_async_match_notify(struct v4l2_async_no= tifier *notifier, struct v4l2_subdev *sd, struct v4l2_async_connection *asc) { - struct v4l2_async_notifier *subdev_notifier; bool registered =3D false; int ret; =20 @@ -385,6 +384,25 @@ static int v4l2_async_match_notify(struct v4l2_async_n= otifier *notifier, dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n", dev_name(sd->dev), ret); =20 + return 0; + +err_call_unbind: + v4l2_async_nf_call_unbind(notifier, sd, asc); + list_del(&asc->asc_subdev_entry); + +err_unregister_subdev: + if (registered) + v4l2_device_unregister_subdev(sd); + + return ret; +} + +static int +v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd) +{ + struct v4l2_async_notifier *subdev_notifier; + /* * See if the sub-device has a notifier. If not, return here. */ @@ -400,16 +418,6 @@ static int v4l2_async_match_notify(struct v4l2_async_n= otifier *notifier, subdev_notifier->parent =3D notifier; =20 return v4l2_async_nf_try_all_subdevs(subdev_notifier); - -err_call_unbind: - v4l2_async_nf_call_unbind(notifier, sd, asc); - list_del(&asc->asc_subdev_entry); - -err_unregister_subdev: - if (registered) - v4l2_device_unregister_subdev(sd); - - return ret; } =20 /* Test all async sub-devices in a notifier for a match. */ @@ -441,6 +449,10 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifi= er *notifier) if (ret < 0) return ret; =20 + ret =3D v4l2_async_nf_try_subdev_notifier(notifier, sd); + if (ret < 0) + return ret; + /* * v4l2_async_match_notify() may lead to registering a * new notifier and thus changing the async subdevs @@ -823,7 +835,11 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) ret =3D v4l2_async_match_notify(notifier, v4l2_dev, sd, asc); if (ret) - goto err_unbind; + goto err_unlock; + + ret =3D v4l2_async_nf_try_subdev_notifier(notifier, sd); + if (ret) + goto err_unbind_one; =20 ret =3D v4l2_async_nf_try_complete(notifier); if (ret) @@ -847,9 +863,10 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) if (subdev_notifier) v4l2_async_nf_unbind_all_subdevs(subdev_notifier); =20 - if (asc) - v4l2_async_unbind_subdev_one(notifier, asc); +err_unbind_one: + v4l2_async_unbind_subdev_one(notifier, asc); =20 +err_unlock: mutex_unlock(&list_lock); =20 return ret; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 68d71b4b55bd..cfb22fb7b238 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -335,6 +335,17 @@ config MFD_CS47L92 help Support for Cirrus Logic CS42L92, CS47L92 and CS47L93 Smart Codecs =20 +config MFD_TN48M_CPLD + tristate "Delta Networks TN48M switch CPLD driver" + depends on I2C + depends on ARCH_MVEBU || COMPILE_TEST + select MFD_SIMPLE_MFD_I2C + help + Select this option to enable support for Delta Networks TN48M switch + CPLD. It consists of reset and GPIO drivers. CPLD provides GPIOS-s + for the SFP slots as well as power supply related information. + SFP support depends on the GPIO driver being selected. + config PMIC_DA903X bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" depends on I2C=3Dy @@ -1137,6 +1148,19 @@ config MFD_QCOM_RPM Say M here if you want to include support for the Qualcomm RPM as a module. This will build a module called "qcom_rpm". =20 +config MFD_SPACEMIT_P1 + tristate "SpacemiT P1 PMIC" + depends on ARCH_SPACEMIT || COMPILE_TEST + depends on I2C + select I2C_K1 + select MFD_SIMPLE_MFD_I2C + help + This option supports the I2C-based SpacemiT P1 PMIC, which + contains regulators, a power switch, GPIOs, an RTC, and more. + This option is selected when any of the supported sub-devices + is configured. The basic functionality is implemented by the + simple MFD I2C driver. + config MFD_SPMI_PMIC tristate "Qualcomm SPMI PMICs" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 19a0adf8ce3d..35f516d934c8 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1100,7 +1100,7 @@ int arizona_dev_init(struct arizona *arizona) } else if (val & 0x01) { ret =3D wm5102_clear_write_sequencer(arizona); if (ret) - return ret; + goto err_reset; } break; default: diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index 80fc5c0cac2f..be5f2b34e18a 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -37,7 +37,7 @@ static int da9052_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, da9052); =20 config =3D da9052_regmap_config; - config.write_flag_mask =3D 1; + config.read_flag_mask =3D 1; config.reg_bits =3D 7; config.pad_bits =3D 1; config.val_bits =3D 8; diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 2b85509a90fc..2b323d1430f5 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -22,6 +22,7 @@ #include =20 static LIST_HEAD(mfd_of_node_list); +static DEFINE_MUTEX(mfd_of_node_mutex); =20 struct mfd_of_node_entry { struct list_head list; @@ -105,9 +106,11 @@ static int mfd_match_of_node_to_dev(struct platform_de= vice *pdev, u64 of_node_addr; =20 /* Skip if OF node has previously been allocated to a device */ - list_for_each_entry(of_entry, &mfd_of_node_list, list) - if (of_entry->np =3D=3D np) - return -EAGAIN; + scoped_guard(mutex, &mfd_of_node_mutex) { + list_for_each_entry(of_entry, &mfd_of_node_list, list) + if (of_entry->np =3D=3D np) + return -EAGAIN; + } =20 if (!cell->use_of_reg) /* No of_reg defined - allocate first free compatible match */ @@ -129,7 +132,8 @@ static int mfd_match_of_node_to_dev(struct platform_dev= ice *pdev, =20 of_entry->dev =3D &pdev->dev; of_entry->np =3D np; - list_add_tail(&of_entry->list, &mfd_of_node_list); + scoped_guard(mutex, &mfd_of_node_mutex) + list_add_tail(&of_entry->list, &mfd_of_node_list); =20 pdev->dev.of_node =3D np; pdev->dev.fwnode =3D &np->fwnode; @@ -286,11 +290,13 @@ static int mfd_add_device(struct device *parent, int = id, if (cell->swnode) device_remove_software_node(&pdev->dev); fail_of_entry: - list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) - if (of_entry->dev =3D=3D &pdev->dev) { - list_del(&of_entry->list); - kfree(of_entry); - } + scoped_guard(mutex, &mfd_of_node_mutex) { + list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) + if (of_entry->dev =3D=3D &pdev->dev) { + list_del(&of_entry->list); + kfree(of_entry); + } + } fail_alias: regulator_bulk_unregister_supply_alias(&pdev->dev, cell->parent_supplies, @@ -360,11 +366,13 @@ static int mfd_remove_devices_fn(struct device *dev, = void *data) if (cell->swnode) device_remove_software_node(&pdev->dev); =20 - list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) - if (of_entry->dev =3D=3D &pdev->dev) { - list_del(&of_entry->list); - kfree(of_entry); - } + scoped_guard(mutex, &mfd_of_node_mutex) { + list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) + if (of_entry->dev =3D=3D &pdev->dev) { + list_del(&of_entry->list); + kfree(of_entry); + } + } =20 regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies); diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c index 6eda79533208..908eae338fee 100644 --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c @@ -83,11 +83,42 @@ static const struct simple_mfd_data maxim_max5970 =3D { .mfd_cell_size =3D ARRAY_SIZE(max5970_cells), }; =20 +static const struct mfd_cell max77705_sensor_cells[] =3D { + { .name =3D "max77705-battery" }, + { .name =3D "max77705-hwmon", }, +}; + +static const struct simple_mfd_data maxim_mon_max77705 =3D { + .mfd_cell =3D max77705_sensor_cells, + .mfd_cell_size =3D ARRAY_SIZE(max77705_sensor_cells), +}; + +static const struct regmap_config spacemit_p1_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, +}; + +static const struct mfd_cell spacemit_p1_cells[] =3D { + { .name =3D "spacemit-p1-regulator", }, + { .name =3D "spacemit-p1-rtc", }, +}; + +static const struct simple_mfd_data spacemit_p1 =3D { + .regmap_config =3D &spacemit_p1_regmap_config, + .mfd_cell =3D spacemit_p1_cells, + .mfd_cell_size =3D ARRAY_SIZE(spacemit_p1_cells), +}; + static const struct of_device_id simple_mfd_i2c_of_match[] =3D { + { .compatible =3D "delta,tn48m-cpld" }, + { .compatible =3D "fsl,ls1028aqds-fpga" }, + { .compatible =3D "fsl,lx2160aqds-fpga" }, { .compatible =3D "kontron,sl28cpld" }, - { .compatible =3D "silergy,sy7636a", .data =3D &silergy_sy7636a}, { .compatible =3D "maxim,max5970", .data =3D &maxim_max5970}, { .compatible =3D "maxim,max5978", .data =3D &maxim_max5970}, + { .compatible =3D "maxim,max77705-battery", .data =3D &maxim_mon_max77705= }, + { .compatible =3D "silergy,sy7636a", .data =3D &silergy_sy7636a}, + { .compatible =3D "spacemit,p1", .data =3D &spacemit_p1, }, {} }; MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); diff --git a/drivers/misc/bcm-vk/bcm_vk_msg.c b/drivers/misc/bcm-vk/bcm_vk_= msg.c index e17d81231ea6..54e25e9bc51b 100644 --- a/drivers/misc/bcm-vk/bcm_vk_msg.c +++ b/drivers/misc/bcm-vk/bcm_vk_msg.c @@ -1010,6 +1010,9 @@ ssize_t bcm_vk_read(struct file *p_file, struct device *dev =3D &vk->pdev->dev; struct bcm_vk_msg_chan *chan =3D &vk->to_h_msg_chan; struct bcm_vk_wkent *entry =3D NULL, *iter; + struct vk_msg_blk tmp_msg; + u32 tmp_usr_msg_id; + u32 tmp_blks; u32 q_num; u32 rsp_length; =20 @@ -1034,6 +1037,9 @@ ssize_t bcm_vk_read(struct file *p_file, entry =3D iter; } else { /* buffer not big enough */ + tmp_msg =3D iter->to_h_msg[0]; + tmp_usr_msg_id =3D iter->usr_msg_id; + tmp_blks =3D iter->to_h_blks; rc =3D -EMSGSIZE; } goto read_loop_exit; @@ -1052,14 +1058,12 @@ ssize_t bcm_vk_read(struct file *p_file, =20 bcm_vk_free_wkent(dev, entry); } else if (rc =3D=3D -EMSGSIZE) { - struct vk_msg_blk tmp_msg =3D entry->to_h_msg[0]; - /* * in this case, return just the first block, so * that app knows what size it is looking for. */ - set_msg_id(&tmp_msg, entry->usr_msg_id); - tmp_msg.size =3D entry->to_h_blks - 1; + set_msg_id(&tmp_msg, tmp_usr_msg_id); + tmp_msg.size =3D tmp_blks - 1; if (copy_to_user(buf, &tmp_msg, VK_MSGQ_BLK_SIZE) !=3D 0) { dev_err(dev, "Error return 1st block in -EMSGSIZE\n"); rc =3D -EFAULT; diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eepr= om_93xx46.c index b630625b3024..b510d0b5ddfa 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -23,6 +23,7 @@ #define OP_START 0x4 #define OP_WRITE (OP_START | 0x1) #define OP_READ (OP_START | 0x2) +/* The following addresses are offset for the 1K EEPROM variant in 16-bit = mode */ #define ADDR_EWDS 0x00 #define ADDR_ERAL 0x20 #define ADDR_EWEN 0x30 @@ -173,10 +174,7 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *= edev, int is_on) bits =3D edev->addrlen + 3; =20 cmd_addr =3D OP_START << edev->addrlen; - if (edev->pdata->flags & EE_ADDR8) - cmd_addr |=3D (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; - else - cmd_addr |=3D (is_on ? ADDR_EWEN : ADDR_EWDS); + cmd_addr |=3D (is_on ? ADDR_EWEN : ADDR_EWDS) << (edev->addrlen - 6); =20 if (has_quirk_instruction_length(edev)) { cmd_addr <<=3D 2; @@ -320,10 +318,7 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev= *edev) bits =3D edev->addrlen + 3; =20 cmd_addr =3D OP_START << edev->addrlen; - if (edev->pdata->flags & EE_ADDR8) - cmd_addr |=3D ADDR_ERAL << 1; - else - cmd_addr |=3D ADDR_ERAL; + cmd_addr |=3D ADDR_ERAL << (edev->addrlen - 6); =20 if (has_quirk_instruction_length(edev)) { cmd_addr <<=3D 2; diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/n= and/raw/cadence-nand-controller.c index 202b4fc064fa..0831feb58e13 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -1018,7 +1018,7 @@ static int cadence_nand_cdma_send(struct cdns_nand_ct= rl *cdns_ctrl, } =20 /* Send SDMA command and wait for finish. */ -static u32 +static int cadence_nand_cdma_send_and_wait(struct cdns_nand_ctrl *cdns_ctrl, u8 thread) { diff --git a/drivers/mtd/nand/raw/pl35x-nand-controller.c b/drivers/mtd/nan= d/raw/pl35x-nand-controller.c index c506e92a3e45..eaaaf3319bf8 100644 --- a/drivers/mtd/nand/raw/pl35x-nand-controller.c +++ b/drivers/mtd/nand/raw/pl35x-nand-controller.c @@ -976,6 +976,7 @@ static int pl35x_nand_attach_chip(struct nand_chip *chi= p) fallthrough; case NAND_ECC_ENGINE_TYPE_NONE: case NAND_ECC_ENGINE_TYPE_SOFT: + chip->ecc.write_page_raw =3D nand_monolithic_write_page_raw; break; case NAND_ECC_ENGINE_TYPE_ON_HOST: ret =3D pl35x_nand_init_hw_ecc_controller(nfc, chip); diff --git a/drivers/mtd/parsers/ofpart_core.c b/drivers/mtd/parsers/ofpart= _core.c index e7b8e9d0a910..3cf75b56d5a2 100644 --- a/drivers/mtd/parsers/ofpart_core.c +++ b/drivers/mtd/parsers/ofpart_core.c @@ -77,6 +77,7 @@ static int parse_fixed_partitions(struct mtd_info *master, of_id =3D of_match_node(parse_ofpart_match_table, ofpart_node); if (dedicated && !of_id) { /* The 'partitions' subnode might be used by another parser */ + of_node_put(ofpart_node); return 0; } =20 @@ -91,12 +92,18 @@ static int parse_fixed_partitions(struct mtd_info *mast= er, nr_parts++; } =20 - if (nr_parts =3D=3D 0) + if (nr_parts =3D=3D 0) { + if (dedicated) + of_node_put(ofpart_node); return 0; + } =20 parts =3D kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); - if (!parts) + if (!parts) { + if (dedicated) + of_node_put(ofpart_node); return -ENOMEM; + } =20 i =3D 0; for_each_child_of_node(ofpart_node, pp) { @@ -175,6 +182,9 @@ static int parse_fixed_partitions(struct mtd_info *mast= er, if (quirks && quirks->post_parse) quirks->post_parse(master, parts, nr_parts); =20 + if (dedicated) + of_node_put(ofpart_node); + *pparts =3D parts; return nr_parts; =20 @@ -183,6 +193,8 @@ static int parse_fixed_partitions(struct mtd_info *mast= er, master->name, pp, mtd_node); ret =3D -EINVAL; ofpart_none: + if (dedicated) + of_node_put(ofpart_node); of_node_put(pp); kfree(parts); return ret; diff --git a/drivers/mtd/parsers/tplink_safeloader.c b/drivers/mtd/parsers/= tplink_safeloader.c index 1c689dafca2a..3580c79e3277 100644 --- a/drivers/mtd/parsers/tplink_safeloader.c +++ b/drivers/mtd/parsers/tplink_safeloader.c @@ -116,6 +116,7 @@ static int mtd_parser_tplink_safeloader_parse(struct mt= d_info *mtd, return idx; =20 err_free: + kfree(buf); for (idx -=3D 1; idx >=3D 0; idx--) kfree(parts[idx].name); err_free_parts: diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_mai= n.c index 4373e300879d..836d7fcac71a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -727,26 +727,29 @@ static int bond_update_speed_duplex(struct slave *sla= ve) struct ethtool_link_ksettings ecmd; int res; =20 - slave->speed =3D SPEED_UNKNOWN; - slave->duplex =3D DUPLEX_UNKNOWN; - res =3D __ethtool_get_link_ksettings(slave_dev, &ecmd); if (res < 0) - return 1; + goto speed_duplex_unknown; if (ecmd.base.speed =3D=3D 0 || ecmd.base.speed =3D=3D ((__u32)-1)) - return 1; + goto speed_duplex_unknown; switch (ecmd.base.duplex) { case DUPLEX_FULL: case DUPLEX_HALF: break; default: - return 1; + goto speed_duplex_unknown; } =20 slave->speed =3D ecmd.base.speed; slave->duplex =3D ecmd.base.duplex; =20 return 0; + +speed_duplex_unknown: + slave->speed =3D SPEED_UNKNOWN; + slave->duplex =3D DUPLEX_UNKNOWN; + + return 1; } =20 const char *bond_slave_link_status(s8 link) @@ -4398,9 +4401,13 @@ static int bond_close(struct net_device *bond_dev) =20 bond_work_cancel_all(bond); bond->send_peer_notif =3D 0; + WRITE_ONCE(bond->recv_probe, NULL); + + /* Wait for any in-flight RX handlers */ + synchronize_net(); + if (bond_is_lb(bond)) bond_alb_deinitialize(bond); - bond->recv_probe =3D NULL; =20 if (bond_uses_primary(bond)) { rcu_read_lock(); diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index ed3a589def6b..699ed0ff461e 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -298,6 +298,7 @@ static void ser_release(struct work_struct *work) { struct list_head list; struct ser_device *ser, *tmp; + struct tty_struct *tty; =20 spin_lock(&ser_lock); list_replace_init(&ser_release_list, &list); @@ -306,9 +307,11 @@ static void ser_release(struct work_struct *work) if (!list_empty(&list)) { rtnl_lock(); list_for_each_entry_safe(ser, tmp, &list, node) { + tty =3D ser->tty; dev_close(ser->dev); unregister_netdevice(ser->dev); debugfs_deinit(ser); + tty_kref_put(tty); } rtnl_unlock(); } @@ -369,8 +372,6 @@ static void ldisc_close(struct tty_struct *tty) { struct ser_device *ser =3D tty->disc_data; =20 - tty_kref_put(ser->tty); - spin_lock(&ser_lock); list_move(&ser->node, &ser_release_list); spin_unlock(&ser_lock); diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/etherne= t/cadence/macb_main.c index 5cbda8ccdbf0..e1df1546a2d6 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -756,14 +756,12 @@ static void macb_mac_link_up(struct phylink_config *c= onfig, if (rx_pause) ctrl |=3D MACB_BIT(PAE); =20 - /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down - * cleared the pipeline and control registers. - */ - macb_init_buffers(bp); - - for (q =3D 0, queue =3D bp->queues; q < bp->num_queues; ++q, ++queue) + for (q =3D 0, queue =3D bp->queues; q < bp->num_queues; ++q, ++queue) { + queue->tx_head =3D 0; + queue->tx_tail =3D 0; queue_writel(queue, IER, bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); + } } =20 macb_or_gem_writel(bp, NCFGR, ctrl); @@ -2953,6 +2951,7 @@ static int macb_open(struct net_device *dev) } =20 bp->macbgem_ops.mog_init_rings(bp); + macb_init_buffers(bp); =20 for (q =3D 0, queue =3D bp->queues; q < bp->num_queues; ++q, ++queue) { napi_enable(&queue->napi_rx); diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c index c2c5c589a5e3..6233602d7c5a 100644 --- a/drivers/net/ethernet/ec_bhf.c +++ b/drivers/net/ethernet/ec_bhf.c @@ -424,7 +424,7 @@ static int ec_bhf_open(struct net_device *net_dev) =20 error_rx_free: dma_free_coherent(dev, priv->rx_buf.alloc_len, priv->rx_buf.alloc, - priv->rx_buf.alloc_len); + priv->rx_buf.alloc_phys); out: return err; } diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/= net/ethernet/freescale/dpaa2/dpaa2-switch.c index 37e3224262ed..2631732ab216 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -2998,6 +2998,13 @@ static int dpaa2_switch_init(struct fsl_mc_device *s= w_dev) goto err_close; } =20 + if (ethsw->sw_attr.num_ifs >=3D DPSW_MAX_IF) { + dev_err(dev, "DPSW num_ifs %u exceeds max %u\n", + ethsw->sw_attr.num_ifs, DPSW_MAX_IF); + err =3D -EINVAL; + goto err_close; + } + err =3D dpsw_get_api_version(ethsw->mc_io, 0, ðsw->major, ðsw->minor); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/= ethernet/hisilicon/hns3/hns3_enet.c index 34627de2e311..107e692e8c87 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1048,13 +1048,13 @@ static void hns3_init_tx_spare_buffer(struct hns3_e= net_ring *ring) int order; =20 if (!alloc_size) - return; + goto not_init; =20 order =3D get_order(alloc_size); if (order > MAX_ORDER) { if (net_ratelimit()) dev_warn(ring_to_dev(ring), "failed to allocate tx spare buffer, exceed= to max order\n"); - return; + goto not_init; } =20 tx_spare =3D devm_kzalloc(ring_to_dev(ring), sizeof(*tx_spare), @@ -1092,6 +1092,13 @@ static void hns3_init_tx_spare_buffer(struct hns3_en= et_ring *ring) devm_kfree(ring_to_dev(ring), tx_spare); devm_kzalloc_error: ring->tqp->handle->kinfo.tx_spare_buf_size =3D 0; +not_init: + /* When driver init or reset_init, the ring->tx_spare is always NULL; + * but when called from hns3_set_ringparam, it's usually not NULL, and + * will be restored if hns3_init_all_ring() failed. So it's safe to set + * ring->tx_spare to NULL here. + */ + ring->tx_spare =3D NULL; } =20 /* Use hns3_tx_spare_space() to make sure there is enough buffer diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drive= rs/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 659d6351f26c..f404a4c10e8f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -727,8 +727,8 @@ struct hclge_fd_tcam_config_3_cmd { =20 #define HCLGE_FD_AD_DROP_B 0 #define HCLGE_FD_AD_DIRECT_QID_B 1 -#define HCLGE_FD_AD_QID_S 2 -#define HCLGE_FD_AD_QID_M GENMASK(11, 2) +#define HCLGE_FD_AD_QID_L_S 2 +#define HCLGE_FD_AD_QID_L_M GENMASK(11, 2) #define HCLGE_FD_AD_USE_COUNTER_B 12 #define HCLGE_FD_AD_COUNTER_NUM_S 13 #define HCLGE_FD_AD_COUNTER_NUM_M GENMASK(19, 13) @@ -741,6 +741,7 @@ struct hclge_fd_tcam_config_3_cmd { #define HCLGE_FD_AD_TC_OVRD_B 16 #define HCLGE_FD_AD_TC_SIZE_S 17 #define HCLGE_FD_AD_TC_SIZE_M GENMASK(20, 17) +#define HCLGE_FD_AD_QID_H_B 21 =20 struct hclge_fd_ad_config_cmd { u8 stage; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/driv= ers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 72a5df4e3a32..04c58928585c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5606,11 +5606,13 @@ static int hclge_fd_ad_config(struct hclge_dev *hde= v, u8 stage, int loc, hnae3_set_field(ad_data, HCLGE_FD_AD_TC_SIZE_M, HCLGE_FD_AD_TC_SIZE_S, (u32)action->tc_size); } + hnae3_set_bit(ad_data, HCLGE_FD_AD_QID_H_B, + action->queue_id >=3D HCLGE_TQP_MAX_SIZE_DEV_V2 ? 1 : 0); ad_data <<=3D 32; hnae3_set_bit(ad_data, HCLGE_FD_AD_DROP_B, action->drop_packet); hnae3_set_bit(ad_data, HCLGE_FD_AD_DIRECT_QID_B, action->forward_to_direct_queue); - hnae3_set_field(ad_data, HCLGE_FD_AD_QID_M, HCLGE_FD_AD_QID_S, + hnae3_set_field(ad_data, HCLGE_FD_AD_QID_L_M, HCLGE_FD_AD_QID_L_S, action->queue_id); hnae3_set_bit(ad_data, HCLGE_FD_AD_USE_COUNTER_B, action->use_counter); hnae3_set_field(ad_data, HCLGE_FD_AD_COUNTER_NUM_M, diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethe= rnet/intel/i40e/i40e_main.c index 8a0eb51fe974..1f233fac9d4e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -74,7 +74,13 @@ static const struct pci_device_id i40e_pci_tbl[] =3D { {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0}, - {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0}, + /* + * This ID conflicts with ipw2200, but the devices can be differentiated + * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200 + * devices use PCI_CLASS_NETWORK_OTHER. + */ + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_B), + PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, diff --git a/drivers/net/ethernet/marvell/octeon_ep/Makefile b/drivers/net/= ethernet/marvell/octeon_ep/Makefile index 2026c8118158..02a4a21bc298 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/Makefile +++ b/drivers/net/ethernet/marvell/octeon_ep/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_OCTEON_EP) +=3D octeon_ep.o =20 octeon_ep-y :=3D octep_main.o octep_cn9k_pf.o octep_tx.o octep_rx.o \ - octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o + octep_ethtool.o octep_ctrl_mbox.o octep_ctrl_net.o \ + octep_cnxk_pf.o diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c b/drive= rs/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c index 90c3a419932d..0ed07aad066f 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c @@ -16,9 +16,6 @@ #define CTRL_MBOX_MAX_PF 128 #define CTRL_MBOX_SZ ((size_t)(0x400000 / CTRL_MBOX_MAX_PF)) =20 -#define FW_HB_INTERVAL_IN_SECS 1 -#define FW_HB_MISS_COUNT 10 - /* Names of Hardware non-queue generic interrupts */ static char *cn93_non_ioq_msix_names[] =3D { "epf_ire_rint", @@ -250,12 +247,11 @@ static void octep_init_config_cn93_pf(struct octep_de= vice *oct) link =3D PCI_DEVFN(PCI_SLOT(oct->pdev->devfn), link); } conf->ctrl_mbox_cfg.barmem_addr =3D (void __iomem *)oct->mmio[2].hw_addr + - (0x400000ull * 7) + + CN93_PEM_BAR4_INDEX_OFFSET + (link * CTRL_MBOX_SZ); =20 - conf->hb_interval =3D FW_HB_INTERVAL_IN_SECS; - conf->max_hb_miss_cnt =3D FW_HB_MISS_COUNT; - + conf->fw_info.hb_interval =3D OCTEP_DEFAULT_FW_HB_INTERVAL; + conf->fw_info.hb_miss_count =3D OCTEP_DEFAULT_FW_HB_MISS_COUNT; } =20 /* Setup registers for a hardware Tx Queue */ @@ -306,7 +302,7 @@ static void octep_setup_iq_regs_cn93_pf(struct octep_de= vice *oct, int iq_no) } =20 /* Setup registers for a hardware Rx Queue */ -static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_n= o) +static int octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no) { u64 reg_val; u64 oq_ctl =3D 0ULL; @@ -354,6 +350,7 @@ static void octep_setup_oq_regs_cn93_pf(struct octep_de= vice *oct, int oq_no) reg_val =3D ((u64)time_threshold << 32) | CFG_GET_OQ_INTR_PKT(oct->conf); octep_write_csr64(oct, CN93_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + return 0; } =20 /* Setup registers for a PF mailbox */ @@ -373,34 +370,40 @@ static void octep_setup_mbox_regs_cn93_pf(struct octe= p_device *oct, int q_no) mbox->mbox_read_reg =3D oct->mmio[0].hw_addr + CN93_SDP_R_MBOX_VF_PF_DATA= (q_no); } =20 -/* Process non-ioq interrupts required to keep pf interface running. - * OEI_RINT is needed for control mailbox - */ -static bool octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct) -{ - bool handled =3D false; - u64 reg0; - - /* Check for OEI INTR */ - reg0 =3D octep_read_csr64(oct, CN93_SDP_EPF_OEI_RINT); - if (reg0) { - dev_info(&oct->pdev->dev, - "Received OEI_RINT intr: 0x%llx\n", - reg0); - octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT, reg0); - if (reg0 & CN93_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) +/* Poll OEI events like heartbeat */ +static void octep_poll_oei_cn93_pf(struct octep_device *oct) +{ + u64 reg; + + reg =3D octep_read_csr64(oct, CN93_SDP_EPF_OEI_RINT); + if (reg) { + octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT, reg); + if (reg & CN93_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) queue_work(octep_wq, &oct->ctrl_mbox_task); - else if (reg0 & CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) + else if (reg & CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) atomic_set(&oct->hb_miss_cnt, 0); - - handled =3D true; } +} + +/* OEI interrupt handler */ +static irqreturn_t octep_oei_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; =20 - return handled; + octep_poll_oei_cn93_pf(oct); + return IRQ_HANDLED; } =20 -/* Interrupts handler for all non-queue generic interrupts. */ -static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(void *dev) +/* Process non-ioq interrupts required to keep pf interface running. + * OEI_RINT is needed for control mailbox + */ +static void octep_poll_non_ioq_interrupts_cn93_pf(struct octep_device *oct) +{ + octep_poll_oei_cn93_pf(oct); +} + +/* Interrupt handler for input ring error interrupts. */ +static irqreturn_t octep_ire_intr_handler_cn93_pf(void *dev) { struct octep_device *oct =3D (struct octep_device *)dev; struct pci_dev *pdev =3D oct->pdev; @@ -425,8 +428,17 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(= void *dev) reg_val); } } - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for output ring error interrupts. */ +static irqreturn_t octep_ore_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + int i =3D 0; =20 /* Check for ORERR INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_ORERR_RINT); @@ -444,9 +456,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(= void *dev) reg_val); } } - - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for vf input ring error interrupts. */ +static irqreturn_t octep_vfire_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; =20 /* Check for VFIRE INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_VFIRE_RINT(0)); @@ -454,8 +473,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(= void *dev) dev_info(&pdev->dev, "Received VFIRE_RINT intr: 0x%llx\n", reg_val); octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT(0), reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for vf output ring error interrupts. */ +static irqreturn_t octep_vfore_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; =20 /* Check for VFORE INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_VFORE_RINT(0)); @@ -463,19 +490,30 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf= (void *dev) dev_info(&pdev->dev, "Received VFORE_RINT intr: 0x%llx\n", reg_val); octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT(0), reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} =20 - /* Check for MBOX INTR and OEI INTR */ - if (octep_poll_non_ioq_interrupts_cn93_pf(oct)) - goto irq_handled; +/* Interrupt handler for dpi dma related interrupts. */ +static irqreturn_t octep_dma_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + u64 reg_val =3D 0; =20 /* Check for DMA INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_DMA_RINT); if (reg_val) { octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT, reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for dpi dma transaction error interrupts for VFs */ +static irqreturn_t octep_dma_vf_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; =20 /* Check for DMA VF INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT(0)); @@ -483,8 +521,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(= void *dev) dev_info(&pdev->dev, "Received DMA_VF_RINT intr: 0x%llx\n", reg_val); octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT(0), reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for pp transaction error interrupts for VFs */ +static irqreturn_t octep_pp_vf_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; =20 /* Check for PPVF INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_PP_VF_RINT(0)); @@ -492,8 +538,16 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf(= void *dev) dev_info(&pdev->dev, "Received PP_VF_RINT intr: 0x%llx\n", reg_val); octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT(0), reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupt handler for mac related interrupts. */ +static irqreturn_t octep_misc_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; =20 /* Check for MISC INTR */ reg_val =3D octep_read_csr64(oct, CN93_SDP_EPF_MISC_RINT); @@ -501,11 +555,17 @@ static irqreturn_t octep_non_ioq_intr_handler_cn93_pf= (void *dev) dev_info(&pdev->dev, "Received MISC_RINT intr: 0x%llx\n", reg_val); octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT, reg_val); - goto irq_handled; } + return IRQ_HANDLED; +} + +/* Interrupts handler for all reserved interrupts. */ +static irqreturn_t octep_rsvd_intr_handler_cn93_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; =20 dev_info(&pdev->dev, "Reserved interrupts raised; Ignore\n"); -irq_handled: return IRQ_HANDLED; } =20 @@ -569,27 +629,53 @@ static void octep_enable_interrupts_cn93_pf(struct oc= tep_device *oct) octep_write_csr64(oct, CN93_SDP_EPF_IRERR_RINT_ENA_W1S, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_ORERR_RINT_ENA_W1S, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT_ENA_W1S, -1ULL); + + octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT_ENA_W1S(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT_ENA_W1S(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask); + + octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); } =20 /* Disable all interrupts */ static void octep_disable_interrupts_cn93_pf(struct octep_device *oct) { - u64 intr_mask =3D 0ULL; + u64 reg_val, intr_mask =3D 0ULL; int srn, num_rings, i; =20 srn =3D CFG_GET_PORTS_PF_SRN(oct->conf); num_rings =3D CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); =20 - for (i =3D 0; i < num_rings; i++) - intr_mask |=3D (0x1ULL << (srn + i)); + for (i =3D 0; i < num_rings; i++) { + intr_mask |=3D BIT_ULL(srn + i); + reg_val =3D octep_read_csr64(oct, + CN93_SDP_R_IN_INT_LEVELS(srn + i)); + reg_val &=3D ~CN93_INT_ENA_BIT; + octep_write_csr64(oct, + CN93_SDP_R_IN_INT_LEVELS(srn + i), reg_val); + + reg_val =3D octep_read_csr64(oct, + CN93_SDP_R_OUT_INT_LEVELS(srn + i)); + reg_val &=3D ~CN93_INT_ENA_BIT; + octep_write_csr64(oct, + CN93_SDP_R_OUT_INT_LEVELS(srn + i), reg_val); + } =20 octep_write_csr64(oct, CN93_SDP_EPF_IRERR_RINT_ENA_W1C, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_ORERR_RINT_ENA_W1C, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_OEI_RINT_ENA_W1C, -1ULL); + + octep_write_csr64(oct, CN93_SDP_EPF_VFIRE_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_VFORE_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); octep_write_csr64(oct, CN93_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); + + octep_write_csr64(oct, CN93_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CN93_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); } =20 /* Get new Octeon Read Index: index of descriptor that Octeon reads next. = */ @@ -722,7 +808,16 @@ void octep_device_setup_cn93_pf(struct octep_device *o= ct) oct->hw_ops.setup_oq_regs =3D octep_setup_oq_regs_cn93_pf; oct->hw_ops.setup_mbox_regs =3D octep_setup_mbox_regs_cn93_pf; =20 - oct->hw_ops.non_ioq_intr_handler =3D octep_non_ioq_intr_handler_cn93_pf; + oct->hw_ops.oei_intr_handler =3D octep_oei_intr_handler_cn93_pf; + oct->hw_ops.ire_intr_handler =3D octep_ire_intr_handler_cn93_pf; + oct->hw_ops.ore_intr_handler =3D octep_ore_intr_handler_cn93_pf; + oct->hw_ops.vfire_intr_handler =3D octep_vfire_intr_handler_cn93_pf; + oct->hw_ops.vfore_intr_handler =3D octep_vfore_intr_handler_cn93_pf; + oct->hw_ops.dma_intr_handler =3D octep_dma_intr_handler_cn93_pf; + oct->hw_ops.dma_vf_intr_handler =3D octep_dma_vf_intr_handler_cn93_pf; + oct->hw_ops.pp_vf_intr_handler =3D octep_pp_vf_intr_handler_cn93_pf; + oct->hw_ops.misc_intr_handler =3D octep_misc_intr_handler_cn93_pf; + oct->hw_ops.rsvd_intr_handler =3D octep_rsvd_intr_handler_cn93_pf; oct->hw_ops.ioq_intr_handler =3D octep_ioq_intr_handler_cn93_pf; oct->hw_ops.soft_reset =3D octep_soft_reset_cn93_pf; oct->hw_ops.reinit_regs =3D octep_reinit_regs_cn93_pf; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c b/drive= rs/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c new file mode 100644 index 000000000000..b1f7bf6e0f5d --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c @@ -0,0 +1,935 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell Octeon EP (EndPoint) Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#include +#include +#include +#include + +#include "octep_config.h" +#include "octep_main.h" +#include "octep_regs_cnxk_pf.h" + +/* We will support 128 pf's in control mbox */ +#define CTRL_MBOX_MAX_PF 128 +#define CTRL_MBOX_SZ ((size_t)(0x400000 / CTRL_MBOX_MAX_PF)) + +/* Names of Hardware non-queue generic interrupts */ +static char *cnxk_non_ioq_msix_names[] =3D { + "epf_ire_rint", + "epf_ore_rint", + "epf_vfire_rint", + "epf_rsvd0", + "epf_vfore_rint", + "epf_rsvd1", + "epf_mbox_rint", + "epf_rsvd2_0", + "epf_rsvd2_1", + "epf_dma_rint", + "epf_dma_vf_rint", + "epf_rsvd3", + "epf_pp_vf_rint", + "epf_rsvd3", + "epf_misc_rint", + "epf_rsvd5", + /* Next 16 are for OEI_RINT */ + "epf_oei_rint0", + "epf_oei_rint1", + "epf_oei_rint2", + "epf_oei_rint3", + "epf_oei_rint4", + "epf_oei_rint5", + "epf_oei_rint6", + "epf_oei_rint7", + "epf_oei_rint8", + "epf_oei_rint9", + "epf_oei_rint10", + "epf_oei_rint11", + "epf_oei_rint12", + "epf_oei_rint13", + "epf_oei_rint14", + "epf_oei_rint15", + /* IOQ interrupt */ + "octeon_ep" +}; + +/* Dump useful hardware CSRs for debug purpose */ +static void cnxk_dump_regs(struct octep_device *oct, int qno) +{ + struct device *dev =3D &oct->pdev->dev; + + dev_info(dev, "IQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_IN_INSTR_DBELL[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_INSTR_DBELL(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(qno))); + dev_info(dev, "R[%d]_IN_CONTROL[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_CONTROL(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(qno))); + dev_info(dev, "R[%d]_IN_ENABLE[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_ENABLE(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(qno))); + dev_info(dev, "R[%d]_IN_INSTR_BADDR[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_INSTR_BADDR(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(qno))); + dev_info(dev, "R[%d]_IN_INSTR_RSIZE[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_INSTR_RSIZE(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(qno))); + dev_info(dev, "R[%d]_IN_CNTS[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_CNTS(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_CNTS(qno))); + dev_info(dev, "R[%d]_IN_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_INT_LEVELS(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_IN_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_PKT_CNT(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_PKT_CNT(qno))); + dev_info(dev, "R[%d]_IN_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_IN_BYTE_CNT(qno), + octep_read_csr64(oct, CNXK_SDP_R_IN_BYTE_CNT(qno))); + + dev_info(dev, "OQ-%d register dump\n", qno); + dev_info(dev, "R[%d]_OUT_SLIST_DBELL[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_SLIST_DBELL(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(qno))); + dev_info(dev, "R[%d]_OUT_CONTROL[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_CONTROL(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(qno))); + dev_info(dev, "R[%d]_OUT_ENABLE[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_ENABLE(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_BADDR[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_SLIST_BADDR(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(qno))); + dev_info(dev, "R[%d]_OUT_SLIST_RSIZE[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_SLIST_RSIZE(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(qno))); + dev_info(dev, "R[%d]_OUT_CNTS[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_CNTS(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_CNTS(qno))); + dev_info(dev, "R[%d]_OUT_INT_LEVELS[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_INT_LEVELS(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(qno))); + dev_info(dev, "R[%d]_OUT_PKT_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_PKT_CNT(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_PKT_CNT(qno))); + dev_info(dev, "R[%d]_OUT_BYTE_CNT[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_OUT_BYTE_CNT(qno), + octep_read_csr64(oct, CNXK_SDP_R_OUT_BYTE_CNT(qno))); + dev_info(dev, "R[%d]_ERR_TYPE[0x%llx]: 0x%016llx\n", + qno, CNXK_SDP_R_ERR_TYPE(qno), + octep_read_csr64(oct, CNXK_SDP_R_ERR_TYPE(qno))); +} + +/* Reset Hardware Tx queue */ +static int cnxk_reset_iq(struct octep_device *oct, int q_no) +{ + struct octep_config *conf =3D oct->conf; + u64 val =3D 0ULL; + + dev_dbg(&oct->pdev->dev, "Reset PF IQ-%d\n", q_no); + + /* Get absolute queue number */ + q_no +=3D conf->pf_ring_cfg.srn; + + /* Disable the Tx/Instruction Ring */ + octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(q_no), val); + + /* clear the Instruction Ring packet/byte counts and doorbell CSRs */ + octep_write_csr64(oct, CNXK_SDP_R_IN_CNTS(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_IN_PKT_CNT(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_IN_BYTE_CNT(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(q_no), val); + + val =3D 0xFFFFFFFF; + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(q_no), val); + + return 0; +} + +/* Reset Hardware Rx queue */ +static void cnxk_reset_oq(struct octep_device *oct, int q_no) +{ + u64 val =3D 0ULL; + + q_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + + /* Disable Output (Rx) Ring */ + octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(q_no), val); + octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(q_no), val); + + /* Clear count CSRs */ + val =3D octep_read_csr(oct, CNXK_SDP_R_OUT_CNTS(q_no)); + octep_write_csr(oct, CNXK_SDP_R_OUT_CNTS(q_no), val); + + octep_write_csr64(oct, CNXK_SDP_R_OUT_PKT_CNT(q_no), 0xFFFFFFFFFULL); + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(q_no), 0xFFFFFFFF); +} + +/* Reset all hardware Tx/Rx queues */ +static void octep_reset_io_queues_cnxk_pf(struct octep_device *oct) +{ + struct pci_dev *pdev =3D oct->pdev; + int q; + + dev_dbg(&pdev->dev, "Reset OCTEP_CNXK PF IO Queues\n"); + + for (q =3D 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + cnxk_reset_iq(oct, q); + cnxk_reset_oq(oct, q); + } +} + +/* Initialize windowed addresses to access some hardware registers */ +static void octep_setup_pci_window_regs_cnxk_pf(struct octep_device *oct) +{ + u8 __iomem *bar0_pciaddr =3D oct->mmio[0].hw_addr; + + oct->pci_win_regs.pci_win_wr_addr =3D (u8 __iomem *)(bar0_pciaddr + CNXK_= SDP_WIN_WR_ADDR64); + oct->pci_win_regs.pci_win_rd_addr =3D (u8 __iomem *)(bar0_pciaddr + CNXK_= SDP_WIN_RD_ADDR64); + oct->pci_win_regs.pci_win_wr_data =3D (u8 __iomem *)(bar0_pciaddr + CNXK_= SDP_WIN_WR_DATA64); + oct->pci_win_regs.pci_win_rd_data =3D (u8 __iomem *)(bar0_pciaddr + CNXK_= SDP_WIN_RD_DATA64); +} + +/* Configure Hardware mapping: inform hardware which rings belong to PF. */ +static void octep_configure_ring_mapping_cnxk_pf(struct octep_device *oct) +{ + struct octep_config *conf =3D oct->conf; + struct pci_dev *pdev =3D oct->pdev; + u64 pf_srn =3D CFG_GET_PORTS_PF_SRN(oct->conf); + int q; + + for (q =3D 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(conf); q++) { + u64 regval =3D 0; + + if (oct->pcie_port) + regval =3D 8 << CNXK_SDP_FUNC_SEL_EPF_BIT_POS; + + octep_write_csr64(oct, CNXK_SDP_EPVF_RING(pf_srn + q), regval); + + regval =3D octep_read_csr64(oct, CNXK_SDP_EPVF_RING(pf_srn + q)); + dev_dbg(&pdev->dev, "Write SDP_EPVF_RING[0x%llx] =3D 0x%llx\n", + CNXK_SDP_EPVF_RING(pf_srn + q), regval); + } +} + +/* Initialize configuration limits and initial active config */ +static void octep_init_config_cnxk_pf(struct octep_device *oct) +{ + struct octep_config *conf =3D oct->conf; + struct pci_dev *pdev =3D oct->pdev; + u8 link =3D 0; + u64 val; + int pos; + + /* Read ring configuration: + * PF ring count, number of VFs and rings per VF supported + */ + val =3D octep_read_csr64(oct, CNXK_SDP_EPF_RINFO); + dev_info(&pdev->dev, "SDP_EPF_RINFO[0x%x]:0x%llx\n", CNXK_SDP_EPF_RINFO, = val); + conf->sriov_cfg.max_rings_per_vf =3D CNXK_SDP_EPF_RINFO_RPVF(val); + conf->sriov_cfg.active_rings_per_vf =3D conf->sriov_cfg.max_rings_per_vf; + conf->sriov_cfg.max_vfs =3D CNXK_SDP_EPF_RINFO_NVFS(val); + conf->sriov_cfg.active_vfs =3D conf->sriov_cfg.max_vfs; + conf->sriov_cfg.vf_srn =3D CNXK_SDP_EPF_RINFO_SRN(val); + + val =3D octep_read_csr64(oct, CNXK_SDP_MAC_PF_RING_CTL(oct->pcie_port)); + dev_info(&pdev->dev, "SDP_MAC_PF_RING_CTL[%d]:0x%llx\n", oct->pcie_port, = val); + conf->pf_ring_cfg.srn =3D CNXK_SDP_MAC_PF_RING_CTL_SRN(val); + conf->pf_ring_cfg.max_io_rings =3D CNXK_SDP_MAC_PF_RING_CTL_RPPF(val); + conf->pf_ring_cfg.active_io_rings =3D conf->pf_ring_cfg.max_io_rings; + dev_info(&pdev->dev, "pf_srn=3D%u rpvf=3D%u nvfs=3D%u rppf=3D%u\n", + conf->pf_ring_cfg.srn, conf->sriov_cfg.active_rings_per_vf, + conf->sriov_cfg.active_vfs, conf->pf_ring_cfg.active_io_rings); + + conf->iq.num_descs =3D OCTEP_IQ_MAX_DESCRIPTORS; + conf->iq.instr_type =3D OCTEP_64BYTE_INSTR; + conf->iq.db_min =3D OCTEP_DB_MIN; + conf->iq.intr_threshold =3D OCTEP_IQ_INTR_THRESHOLD; + + conf->oq.num_descs =3D OCTEP_OQ_MAX_DESCRIPTORS; + conf->oq.buf_size =3D OCTEP_OQ_BUF_SIZE; + conf->oq.refill_threshold =3D OCTEP_OQ_REFILL_THRESHOLD; + conf->oq.oq_intr_pkt =3D OCTEP_OQ_INTR_PKT_THRESHOLD; + conf->oq.oq_intr_time =3D OCTEP_OQ_INTR_TIME_THRESHOLD; + conf->oq.wmark =3D OCTEP_OQ_WMARK_MIN; + + conf->msix_cfg.non_ioq_msix =3D CNXK_NUM_NON_IOQ_INTR; + conf->msix_cfg.ioq_msix =3D conf->pf_ring_cfg.active_io_rings; + conf->msix_cfg.non_ioq_msix_names =3D cnxk_non_ioq_msix_names; + + pos =3D pci_find_ext_capability(oct->pdev, PCI_EXT_CAP_ID_SRIOV); + if (pos) { + pci_read_config_byte(oct->pdev, + pos + PCI_SRIOV_FUNC_LINK, + &link); + link =3D PCI_DEVFN(PCI_SLOT(oct->pdev->devfn), link); + } + conf->ctrl_mbox_cfg.barmem_addr =3D (void __iomem *)oct->mmio[2].hw_addr + + CNXK_PEM_BAR4_INDEX_OFFSET + + (link * CTRL_MBOX_SZ); + + conf->fw_info.hb_interval =3D OCTEP_DEFAULT_FW_HB_INTERVAL; + conf->fw_info.hb_miss_count =3D OCTEP_DEFAULT_FW_HB_MISS_COUNT; +} + +/* Setup registers for a hardware Tx Queue */ +static void octep_setup_iq_regs_cnxk_pf(struct octep_device *oct, int iq_n= o) +{ + struct octep_iq *iq =3D oct->iq[iq_no]; + u32 reset_instr_cnt; + u64 reg_val; + + iq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CNXK_R_IN_CTL_IDLE)) { + do { + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no)); + } while (!(reg_val & CNXK_R_IN_CTL_IDLE)); + } + + reg_val |=3D CNXK_R_IN_CTL_RDSIZE; + reg_val |=3D CNXK_R_IN_CTL_IS_64B; + reg_val |=3D CNXK_R_IN_CTL_ESR; + octep_write_csr64(oct, CNXK_SDP_R_IN_CONTROL(iq_no), reg_val); + + /* Write the start of the input queue's ring and its size */ + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_BADDR(iq_no), + iq->desc_ring_dma); + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_RSIZE(iq_no), + iq->max_count); + + /* Remember the doorbell & instruction count register addr + * for this queue + */ + iq->doorbell_reg =3D oct->mmio[0].hw_addr + + CNXK_SDP_R_IN_INSTR_DBELL(iq_no); + iq->inst_cnt_reg =3D oct->mmio[0].hw_addr + + CNXK_SDP_R_IN_CNTS(iq_no); + iq->intr_lvl_reg =3D oct->mmio[0].hw_addr + + CNXK_SDP_R_IN_INT_LEVELS(iq_no); + + /* Store the current instruction counter (used in flush_iq calculation) */ + reset_instr_cnt =3D readl(iq->inst_cnt_reg); + writel(reset_instr_cnt, iq->inst_cnt_reg); + + /* INTR_THRESHOLD is set to max(FFFFFFFF) to disable the INTR */ + reg_val =3D CFG_GET_IQ_INTR_THRESHOLD(oct->conf) & 0xffffffff; + octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no), reg_val); +} + +/* Setup registers for a hardware Rx Queue */ +static int octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no) +{ + struct octep_oq *oq =3D oct->oq[oq_no]; + unsigned long t_out_jiffies; + u32 time_threshold =3D 0; + u64 oq_ctl =3D 0ULL; + u64 reg_ba_val; + u64 reg_val; + + oq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); + + /* wait for IDLE to set to 1 */ + if (!(reg_val & CNXK_R_OUT_CTL_IDLE)) { + do { + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); + } while (!(reg_val & CNXK_R_OUT_CTL_IDLE)); + } + octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no), oq->max_count); + /* Wait for WMARK to get applied */ + usleep_range(10, 15); + + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no), + oq->desc_ring_dma); + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no), + oq->max_count); + reg_ba_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no)); + + if (reg_ba_val !=3D oq->desc_ring_dma) { + t_out_jiffies =3D jiffies + 10 * HZ; + do { + if (reg_ba_val =3D=3D ULLONG_MAX) + return -EFAULT; + octep_write_csr64(oct, + CNXK_SDP_R_OUT_SLIST_BADDR(oq_no), + oq->desc_ring_dma); + octep_write_csr64(oct, + CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no), + oq->max_count); + reg_ba_val =3D + octep_read_csr64(oct, + CNXK_SDP_R_OUT_SLIST_BADDR(oq_no)); + } while ((reg_ba_val !=3D oq->desc_ring_dma) && + time_before(jiffies, t_out_jiffies)); + + if (reg_ba_val !=3D oq->desc_ring_dma) + return -EAGAIN; + } + + reg_val &=3D ~(CNXK_R_OUT_CTL_IMODE); + reg_val &=3D ~(CNXK_R_OUT_CTL_ROR_P); + reg_val &=3D ~(CNXK_R_OUT_CTL_NSR_P); + reg_val &=3D ~(CNXK_R_OUT_CTL_ROR_I); + reg_val &=3D ~(CNXK_R_OUT_CTL_NSR_I); + reg_val &=3D ~(CNXK_R_OUT_CTL_ES_I); + reg_val &=3D ~(CNXK_R_OUT_CTL_ROR_D); + reg_val &=3D ~(CNXK_R_OUT_CTL_NSR_D); + reg_val &=3D ~(CNXK_R_OUT_CTL_ES_D); + reg_val |=3D (CNXK_R_OUT_CTL_ES_P); + + octep_write_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no), reg_val); + + oq_ctl =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no)); + + /* Clear the ISIZE and BSIZE (22-0) */ + oq_ctl &=3D ~0x7fffffULL; + + /* Populate the BSIZE (15-0) */ + oq_ctl |=3D (oq->buffer_size & 0xffff); + octep_write_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no), oq_ctl); + + /* Get the mapped address of the pkt_sent and pkts_credit regs */ + oq->pkts_sent_reg =3D oct->mmio[0].hw_addr + CNXK_SDP_R_OUT_CNTS(oq_no); + oq->pkts_credit_reg =3D oct->mmio[0].hw_addr + + CNXK_SDP_R_OUT_SLIST_DBELL(oq_no); + + time_threshold =3D CFG_GET_OQ_INTR_TIME(oct->conf); + reg_val =3D ((u64)time_threshold << 32) | + CFG_GET_OQ_INTR_PKT(oct->conf); + octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + + /* set watermark for backpressure */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no)); + reg_val &=3D ~0xFFFFFFFFULL; + reg_val |=3D CFG_GET_OQ_WMARK(oct->conf); + octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no), reg_val); + return 0; +} + +/* Setup registers for a PF mailbox */ +static void octep_setup_mbox_regs_cnxk_pf(struct octep_device *oct, int q_= no) +{ + struct octep_mbox *mbox =3D oct->mbox[q_no]; + + mbox->q_no =3D q_no; + + /* PF mbox interrupt reg */ + mbox->mbox_int_reg =3D oct->mmio[0].hw_addr + CNXK_SDP_EPF_MBOX_RINT(0); + + /* PF to VF DATA reg. PF writes into this reg */ + mbox->mbox_write_reg =3D oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_PF_VF_DAT= A(q_no); + + /* VF to PF DATA reg. PF reads from this reg */ + mbox->mbox_read_reg =3D oct->mmio[0].hw_addr + CNXK_SDP_R_MBOX_VF_PF_DATA= (q_no); +} + +/* Poll OEI events like heartbeat */ +static void octep_poll_oei_cnxk_pf(struct octep_device *oct) +{ + u64 reg0; + + /* Check for OEI INTR */ + reg0 =3D octep_read_csr64(oct, CNXK_SDP_EPF_OEI_RINT); + if (reg0) { + octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT, reg0); + if (reg0 & CNXK_SDP_EPF_OEI_RINT_DATA_BIT_MBOX) + queue_work(octep_wq, &oct->ctrl_mbox_task); + if (reg0 & CNXK_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT) + atomic_set(&oct->hb_miss_cnt, 0); + } +} + +/* OEI interrupt handler */ +static irqreturn_t octep_oei_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + + octep_poll_oei_cnxk_pf(oct); + return IRQ_HANDLED; +} + +/* Process non-ioq interrupts required to keep pf interface running. + * OEI_RINT is needed for control mailbox + * MBOX_RINT is needed for pfvf mailbox + */ +static void octep_poll_non_ioq_interrupts_cnxk_pf(struct octep_device *oct) +{ + octep_poll_oei_cnxk_pf(oct); +} + +/* Interrupt handler for input ring error interrupts. */ +static irqreturn_t octep_ire_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + int i =3D 0; + + /* Check for IRERR INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_IRERR_RINT); + if (reg_val) { + dev_info(&pdev->dev, + "received IRERR_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT, reg_val); + + for (i =3D 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + reg_val =3D octep_read_csr64(oct, + CNXK_SDP_R_ERR_TYPE(i)); + if (reg_val) { + dev_info(&pdev->dev, + "Received err type on IQ-%d: 0x%llx\n", + i, reg_val); + octep_write_csr64(oct, CNXK_SDP_R_ERR_TYPE(i), + reg_val); + } + } + } + return IRQ_HANDLED; +} + +/* Interrupt handler for output ring error interrupts. */ +static irqreturn_t octep_ore_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + int i =3D 0; + + /* Check for ORERR INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_ORERR_RINT); + if (reg_val) { + dev_info(&pdev->dev, + "Received ORERR_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT, reg_val); + for (i =3D 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) { + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_ERR_TYPE(i)); + if (reg_val) { + dev_info(&pdev->dev, + "Received err type on OQ-%d: 0x%llx\n", + i, reg_val); + octep_write_csr64(oct, CNXK_SDP_R_ERR_TYPE(i), + reg_val); + } + } + } + return IRQ_HANDLED; +} + +/* Interrupt handler for vf input ring error interrupts. */ +static irqreturn_t octep_vfire_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + + /* Check for VFIRE INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT(0)); + if (reg_val) { + dev_info(&pdev->dev, + "Received VFIRE_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT(0), reg_val); + } + return IRQ_HANDLED; +} + +/* Interrupt handler for vf output ring error interrupts. */ +static irqreturn_t octep_vfore_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + + /* Check for VFORE INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_VFORE_RINT(0)); + if (reg_val) { + dev_info(&pdev->dev, + "Received VFORE_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT(0), reg_val); + } + return IRQ_HANDLED; +} + +/* Interrupt handler for dpi dma related interrupts. */ +static irqreturn_t octep_dma_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + u64 reg_val =3D 0; + + /* Check for DMA INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_DMA_RINT); + if (reg_val) + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT, reg_val); + + return IRQ_HANDLED; +} + +/* Interrupt handler for dpi dma transaction error interrupts for VFs */ +static irqreturn_t octep_dma_vf_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + + /* Check for DMA VF INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT(0)); + if (reg_val) { + dev_info(&pdev->dev, + "Received DMA_VF_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT(0), reg_val); + } + return IRQ_HANDLED; +} + +/* Interrupt handler for pp transaction error interrupts for VFs */ +static irqreturn_t octep_pp_vf_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + + /* Check for PPVF INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT(0)); + if (reg_val) { + dev_info(&pdev->dev, + "Received PP_VF_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT(0), reg_val); + } + return IRQ_HANDLED; +} + +/* Interrupt handler for mac related interrupts. */ +static irqreturn_t octep_misc_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + u64 reg_val =3D 0; + + /* Check for MISC INTR */ + reg_val =3D octep_read_csr64(oct, CNXK_SDP_EPF_MISC_RINT); + if (reg_val) { + dev_info(&pdev->dev, + "Received MISC_RINT intr: 0x%llx\n", reg_val); + octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT, reg_val); + } + return IRQ_HANDLED; +} + +/* Interrupts handler for all reserved interrupts. */ +static irqreturn_t octep_rsvd_intr_handler_cnxk_pf(void *dev) +{ + struct octep_device *oct =3D (struct octep_device *)dev; + struct pci_dev *pdev =3D oct->pdev; + + dev_info(&pdev->dev, "Reserved interrupts raised; Ignore\n"); + return IRQ_HANDLED; +} + +/* Tx/Rx queue interrupt handler */ +static irqreturn_t octep_ioq_intr_handler_cnxk_pf(void *data) +{ + struct octep_ioq_vector *vector =3D (struct octep_ioq_vector *)data; + struct octep_oq *oq =3D vector->oq; + + napi_schedule_irqoff(oq->napi); + return IRQ_HANDLED; +} + +/* soft reset */ +static int octep_soft_reset_cnxk_pf(struct octep_device *oct) +{ + dev_info(&oct->pdev->dev, "CNXKXX: Doing soft reset\n"); + + octep_write_csr64(oct, CNXK_SDP_WIN_WR_MASK_REG, 0xFF); + + /* Firmware status CSR is supposed to be cleared by + * core domain reset, but due to a hw bug, it is not. + * Set it to RUNNING right before reset so that it is not + * left in READY (1) state after a reset. This is required + * in addition to the early setting to handle the case where + * the OcteonTX is unexpectedly reset, reboots, and then + * the module is removed. + */ + OCTEP_PCI_WIN_WRITE(oct, CNXK_PEMX_PFX_CSX_PFCFGX(0, 0, CNXK_PCIEEP_VSECS= T_CTL), + FW_STATUS_RUNNING); + + /* Set chip domain reset bit */ + OCTEP_PCI_WIN_WRITE(oct, CNXK_RST_CHIP_DOMAIN_W1S, 1); + /* Wait till Octeon resets. */ + mdelay(10); + /* restore the reset value */ + octep_write_csr64(oct, CNXK_SDP_WIN_WR_MASK_REG, 0xFF); + + return 0; +} + +/* Re-initialize Octeon hardware registers */ +static void octep_reinit_regs_cnxk_pf(struct octep_device *oct) +{ + u32 i; + + for (i =3D 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_iq_regs(oct, i); + + for (i =3D 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + oct->hw_ops.setup_oq_regs(oct, i); + + oct->hw_ops.enable_interrupts(oct); + oct->hw_ops.enable_io_queues(oct); + + for (i =3D 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++) + writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg); +} + +/* Enable all interrupts */ +static void octep_enable_interrupts_cnxk_pf(struct octep_device *oct) +{ + u64 intr_mask =3D 0ULL; + int srn, num_rings, i; + + srn =3D CFG_GET_PORTS_PF_SRN(oct->conf); + num_rings =3D CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + + for (i =3D 0; i < num_rings; i++) + intr_mask |=3D (0x1ULL << (srn + i)); + + octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT_ENA_W1S, -1ULL); + + octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S(0), -1ULL); + octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT_ENA_W1S(0), -1ULL); + + octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1S, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1S, intr_mask); + + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(0), -1ULL); + octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(0), -1ULL); +} + +/* Disable all interrupts */ +static void octep_disable_interrupts_cnxk_pf(struct octep_device *oct) +{ + u64 reg_val, intr_mask =3D 0ULL; + int srn, num_rings, i; + + srn =3D CFG_GET_PORTS_PF_SRN(oct->conf); + num_rings =3D CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + + for (i =3D 0; i < num_rings; i++) { + intr_mask |=3D BIT_ULL(srn + i); + reg_val =3D octep_read_csr64(oct, + CNXK_SDP_R_IN_INT_LEVELS(srn + i)); + reg_val &=3D ~CNXK_INT_ENA_BIT; + octep_write_csr64(oct, + CNXK_SDP_R_IN_INT_LEVELS(srn + i), reg_val); + + reg_val =3D octep_read_csr64(oct, + CNXK_SDP_R_OUT_INT_LEVELS(srn + i)); + reg_val &=3D ~CNXK_INT_ENA_BIT; + octep_write_csr64(oct, + CNXK_SDP_R_OUT_INT_LEVELS(srn + i), reg_val); + } + + octep_write_csr64(oct, CNXK_SDP_EPF_IRERR_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_ORERR_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_OEI_RINT_ENA_W1C, -1ULL); + + octep_write_csr64(oct, CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CNXK_SDP_EPF_VFORE_RINT_ENA_W1C(0), -1ULL); + + octep_write_csr64(oct, CNXK_SDP_EPF_MISC_RINT_ENA_W1C, intr_mask); + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_RINT_ENA_W1C, intr_mask); + + octep_write_csr64(oct, CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(0), -1ULL); + octep_write_csr64(oct, CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(0), -1ULL); +} + +/* Get new Octeon Read Index: index of descriptor that Octeon reads next. = */ +static u32 octep_update_iq_read_index_cnxk_pf(struct octep_iq *iq) +{ + u32 pkt_in_done =3D readl(iq->inst_cnt_reg); + u32 last_done, new_idx; + + last_done =3D pkt_in_done - iq->pkt_in_done; + iq->pkt_in_done =3D pkt_in_done; + + new_idx =3D (iq->octep_read_index + last_done) % iq->max_count; + + return new_idx; +} + +/* Enable a hardware Tx Queue */ +static void octep_enable_iq_cnxk_pf(struct octep_device *oct, int iq_no) +{ + u64 loop =3D HZ; + u64 reg_val; + + iq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + + octep_write_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(iq_no), 0xFFFFFFFF); + + while (octep_read_csr64(oct, CNXK_SDP_R_IN_INSTR_DBELL(iq_no)) && + loop--) { + schedule_timeout_interruptible(1); + } + + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no)); + reg_val |=3D (0x1ULL << 62); + octep_write_csr64(oct, CNXK_SDP_R_IN_INT_LEVELS(iq_no), reg_val); + + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no)); + reg_val |=3D 0x1ULL; + octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no), reg_val); +} + +/* Enable a hardware Rx Queue */ +static void octep_enable_oq_cnxk_pf(struct octep_device *oct, int oq_no) +{ + u64 reg_val =3D 0ULL; + + oq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no)); + reg_val |=3D (0x1ULL << 62); + octep_write_csr64(oct, CNXK_SDP_R_OUT_INT_LEVELS(oq_no), reg_val); + + octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_DBELL(oq_no), 0xFFFFFFFF); + + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no)); + reg_val |=3D 0x1ULL; + octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no), reg_val); +} + +/* Enable all hardware Tx/Rx Queues assined to PF */ +static void octep_enable_io_queues_cnxk_pf(struct octep_device *oct) +{ + u8 q; + + for (q =3D 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_enable_iq_cnxk_pf(oct, q); + octep_enable_oq_cnxk_pf(oct, q); + } +} + +/* Disable a hardware Tx Queue assined to PF */ +static void octep_disable_iq_cnxk_pf(struct octep_device *oct, int iq_no) +{ + u64 reg_val =3D 0ULL; + + iq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no)); + reg_val &=3D ~0x1ULL; + octep_write_csr64(oct, CNXK_SDP_R_IN_ENABLE(iq_no), reg_val); +} + +/* Disable a hardware Rx Queue assined to PF */ +static void octep_disable_oq_cnxk_pf(struct octep_device *oct, int oq_no) +{ + u64 reg_val =3D 0ULL; + + oq_no +=3D CFG_GET_PORTS_PF_SRN(oct->conf); + reg_val =3D octep_read_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no)); + reg_val &=3D ~0x1ULL; + octep_write_csr64(oct, CNXK_SDP_R_OUT_ENABLE(oq_no), reg_val); +} + +/* Disable all hardware Tx/Rx Queues assined to PF */ +static void octep_disable_io_queues_cnxk_pf(struct octep_device *oct) +{ + int q =3D 0; + + for (q =3D 0; q < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); q++) { + octep_disable_iq_cnxk_pf(oct, q); + octep_disable_oq_cnxk_pf(oct, q); + } +} + +/* Dump hardware registers (including Tx/Rx queues) for debugging. */ +static void octep_dump_registers_cnxk_pf(struct octep_device *oct) +{ + u8 srn, num_rings, q; + + srn =3D CFG_GET_PORTS_PF_SRN(oct->conf); + num_rings =3D CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); + + for (q =3D srn; q < srn + num_rings; q++) + cnxk_dump_regs(oct, q); +} + +/** + * octep_device_setup_cnxk_pf() - Setup Octeon device. + * + * @oct: Octeon device private data structure. + * + * - initialize hardware operations. + * - get target side pcie port number for the device. + * - setup window access to hardware registers. + * - set initial configuration and max limits. + * - setup hardware mapping of rings to the PF device. + */ +void octep_device_setup_cnxk_pf(struct octep_device *oct) +{ + oct->hw_ops.setup_iq_regs =3D octep_setup_iq_regs_cnxk_pf; + oct->hw_ops.setup_oq_regs =3D octep_setup_oq_regs_cnxk_pf; + oct->hw_ops.setup_mbox_regs =3D octep_setup_mbox_regs_cnxk_pf; + + oct->hw_ops.oei_intr_handler =3D octep_oei_intr_handler_cnxk_pf; + oct->hw_ops.ire_intr_handler =3D octep_ire_intr_handler_cnxk_pf; + oct->hw_ops.ore_intr_handler =3D octep_ore_intr_handler_cnxk_pf; + oct->hw_ops.vfire_intr_handler =3D octep_vfire_intr_handler_cnxk_pf; + oct->hw_ops.vfore_intr_handler =3D octep_vfore_intr_handler_cnxk_pf; + oct->hw_ops.dma_intr_handler =3D octep_dma_intr_handler_cnxk_pf; + oct->hw_ops.dma_vf_intr_handler =3D octep_dma_vf_intr_handler_cnxk_pf; + oct->hw_ops.pp_vf_intr_handler =3D octep_pp_vf_intr_handler_cnxk_pf; + oct->hw_ops.misc_intr_handler =3D octep_misc_intr_handler_cnxk_pf; + oct->hw_ops.rsvd_intr_handler =3D octep_rsvd_intr_handler_cnxk_pf; + oct->hw_ops.ioq_intr_handler =3D octep_ioq_intr_handler_cnxk_pf; + oct->hw_ops.soft_reset =3D octep_soft_reset_cnxk_pf; + oct->hw_ops.reinit_regs =3D octep_reinit_regs_cnxk_pf; + + oct->hw_ops.enable_interrupts =3D octep_enable_interrupts_cnxk_pf; + oct->hw_ops.disable_interrupts =3D octep_disable_interrupts_cnxk_pf; + oct->hw_ops.poll_non_ioq_interrupts =3D octep_poll_non_ioq_interrupts_cnx= k_pf; + + oct->hw_ops.update_iq_read_idx =3D octep_update_iq_read_index_cnxk_pf; + + oct->hw_ops.enable_iq =3D octep_enable_iq_cnxk_pf; + oct->hw_ops.enable_oq =3D octep_enable_oq_cnxk_pf; + oct->hw_ops.enable_io_queues =3D octep_enable_io_queues_cnxk_pf; + + oct->hw_ops.disable_iq =3D octep_disable_iq_cnxk_pf; + oct->hw_ops.disable_oq =3D octep_disable_oq_cnxk_pf; + oct->hw_ops.disable_io_queues =3D octep_disable_io_queues_cnxk_pf; + oct->hw_ops.reset_io_queues =3D octep_reset_io_queues_cnxk_pf; + + oct->hw_ops.dump_registers =3D octep_dump_registers_cnxk_pf; + + octep_setup_pci_window_regs_cnxk_pf(oct); + + oct->pcie_port =3D octep_read_csr64(oct, CNXK_SDP_MAC_NUMBER) & 0xff; + dev_info(&oct->pdev->dev, + "Octeon device using PCIE Port %d\n", oct->pcie_port); + + octep_init_config_cnxk_pf(oct); + octep_configure_ring_mapping_cnxk_pf(oct); + + /* Firmware status CSR is supposed to be cleared by + * core domain reset, but due to IPBUPEM-38842, it is not. + * Set it to RUNNING early in boot, so that unexpected resets + * leave it in a state that is not READY (1). + */ + OCTEP_PCI_WIN_WRITE(oct, CNXK_PEMX_PFX_CSX_PFCFGX(0, 0, CNXK_PCIEEP_VSECS= T_CTL), + FW_STATUS_RUNNING); +} diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h b/driver= s/net/ethernet/marvell/octeon_ep/octep_config.h index df7cd39d9fce..ecc294793141 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_config.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_config.h @@ -19,6 +19,9 @@ /* Packet threshold for Tx queue interrupt */ #define OCTEP_IQ_INTR_THRESHOLD 0x0 =20 +/* Minimum watermark for backpressure */ +#define OCTEP_OQ_WMARK_MIN 256 + /* Rx Queue: maximum descriptors per ring */ #define OCTEP_OQ_MAX_DESCRIPTORS 1024 =20 @@ -49,6 +52,11 @@ /* Default MTU */ #define OCTEP_DEFAULT_MTU 1500 =20 +/* pf heartbeat interval in milliseconds */ +#define OCTEP_DEFAULT_FW_HB_INTERVAL 1000 +/* pf heartbeat miss count */ +#define OCTEP_DEFAULT_FW_HB_MISS_COUNT 20 + /* Macros to get octeon config params */ #define CFG_GET_IQ_CFG(cfg) ((cfg)->iq) #define CFG_GET_IQ_NUM_DESC(cfg) ((cfg)->iq.num_descs) @@ -63,6 +71,7 @@ #define CFG_GET_OQ_REFILL_THRESHOLD(cfg) ((cfg)->oq.refill_threshold) #define CFG_GET_OQ_INTR_PKT(cfg) ((cfg)->oq.oq_intr_pkt) #define CFG_GET_OQ_INTR_TIME(cfg) ((cfg)->oq.oq_intr_time) +#define CFG_GET_OQ_WMARK(cfg) ((cfg)->oq.wmark) =20 #define CFG_GET_PORTS_MAX_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.max_io_ring= s) #define CFG_GET_PORTS_ACTIVE_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.active_io_r= ings) @@ -132,6 +141,12 @@ struct octep_oq_config { * default. The time is specified in microseconds. */ u32 oq_intr_time; + + /* Water mark for backpressure. + * Output queue sends backpressure signal to source when + * free buffer count falls below wmark. + */ + u32 wmark; }; =20 /* Tx/Rx configuration */ @@ -181,6 +196,16 @@ struct octep_ctrl_mbox_config { void __iomem *barmem_addr; }; =20 +/* Info from firmware */ +struct octep_fw_info { + /* interface pkind */ + u16 pkind; + /* heartbeat interval in milliseconds */ + u16 hb_interval; + /* heartbeat miss count */ + u16 hb_miss_count; +}; + /* Data Structure to hold configuration limits and active config */ struct octep_config { /* Input Queue attributes. */ @@ -201,10 +226,7 @@ struct octep_config { /* ctrl mbox config */ struct octep_ctrl_mbox_config ctrl_mbox_cfg; =20 - /* Configured maximum heartbeat miss count */ - u32 max_hb_miss_cnt; - - /* Configured firmware heartbeat interval in secs */ - u32 hb_interval; + /* fw info */ + struct octep_fw_info fw_info; }; #endif /* _OCTEP_CONFIG_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/driv= ers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c index 17bfd5cdf462..0594607a2585 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c @@ -26,7 +26,7 @@ static atomic_t ctrl_net_msg_id; =20 /* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */ static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MA= X] =3D { - [OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_LINK_INFO] =3D + [OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_GET_INFO] =3D OCTEP_CP_VERSION(1, 0, 0) }; =20 @@ -353,6 +353,28 @@ void octep_ctrl_net_recv_fw_messages(struct octep_devi= ce *oct) } } =20 +int octep_ctrl_net_get_info(struct octep_device *oct, int vfid, + struct octep_fw_info *info) +{ + struct octep_ctrl_net_wait_data d =3D {0}; + struct octep_ctrl_net_h2f_resp *resp; + struct octep_ctrl_net_h2f_req *req; + int err; + + req =3D &d.data.req; + init_send_req(&d.msg, req, 0, vfid); + req->hdr.s.cmd =3D OCTEP_CTRL_NET_H2F_CMD_GET_INFO; + req->link_info.cmd =3D OCTEP_CTRL_NET_CMD_GET; + err =3D octep_send_mbox_req(oct, &d, true); + if (err < 0) + return err; + + resp =3D &d.data.resp; + memcpy(info, &resp->info.fw_info, sizeof(struct octep_fw_info)); + + return 0; +} + int octep_ctrl_net_uninit(struct octep_device *oct) { struct octep_ctrl_net_wait_data *pos, *n; diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h b/driv= ers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h index 1c2ef4ee31d9..b330f370131b 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h @@ -41,6 +41,7 @@ enum octep_ctrl_net_h2f_cmd { OCTEP_CTRL_NET_H2F_CMD_LINK_STATUS, OCTEP_CTRL_NET_H2F_CMD_RX_STATE, OCTEP_CTRL_NET_H2F_CMD_LINK_INFO, + OCTEP_CTRL_NET_H2F_CMD_GET_INFO, OCTEP_CTRL_NET_H2F_CMD_MAX }; =20 @@ -161,6 +162,11 @@ struct octep_ctrl_net_h2f_resp_cmd_state { u16 state; }; =20 +/* get info request */ +struct octep_ctrl_net_h2f_resp_cmd_get_info { + struct octep_fw_info fw_info; +}; + /* Host to fw response data */ struct octep_ctrl_net_h2f_resp { union octep_ctrl_net_resp_hdr hdr; @@ -171,6 +177,7 @@ struct octep_ctrl_net_h2f_resp { struct octep_ctrl_net_h2f_resp_cmd_state link; struct octep_ctrl_net_h2f_resp_cmd_state rx; struct octep_ctrl_net_link_info link_info; + struct octep_ctrl_net_h2f_resp_cmd_get_info info; }; } __packed; =20 @@ -330,6 +337,17 @@ int octep_ctrl_net_set_link_info(struct octep_device *= oct, */ void octep_ctrl_net_recv_fw_messages(struct octep_device *oct); =20 +/** Get info from firmware. + * + * @param oct: non-null pointer to struct octep_device. + * @param vfid: Index of virtual function. + * @param info: non-null pointer to struct octep_fw_info. + * + * return value: 0 on success, -errno on failure. + */ +int octep_ctrl_net_get_info(struct octep_device *oct, int vfid, + struct octep_fw_info *info); + /** Uninitialize data for ctrl net. * * @param oct: non-null pointer to struct octep_device. diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/= net/ethernet/marvell/octeon_ep/octep_main.c index c38508454663..db24c290a907 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c @@ -24,6 +24,10 @@ struct workqueue_struct *octep_wq; static const struct pci_device_id octep_pci_id_tbl[] =3D { {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN93_PF)}, {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF95N_PF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KA_PF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KA_PF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CNF10KB_PF)}, + {PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OCTEP_PCI_DEVICE_ID_CN10KB_PF)}, {0, }, }; MODULE_DEVICE_TABLE(pci, octep_pci_id_tbl); @@ -155,18 +159,153 @@ static void octep_disable_msix(struct octep_device *= oct) } =20 /** - * octep_non_ioq_intr_handler() - common handler for all generic interrupt= s. + * octep_oei_intr_handler() - common handler for output endpoint interrupt= s. * * @irq: Interrupt number. * @data: interrupt data. * - * this is common handler for all non-queue (generic) interrupts. + * this is common handler for all output endpoint interrupts. + */ +static irqreturn_t octep_oei_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.oei_intr_handler(oct); +} + +/** + * octep_ire_intr_handler() - common handler for input ring error interrup= ts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for input ring error interrupts. + */ +static irqreturn_t octep_ire_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.ire_intr_handler(oct); +} + +/** + * octep_ore_intr_handler() - common handler for output ring error interru= pts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for output ring error interrupts. + */ +static irqreturn_t octep_ore_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.ore_intr_handler(oct); +} + +/** + * octep_vfire_intr_handler() - common handler for vf input ring error int= errupts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for vf input ring error interrupts. + */ +static irqreturn_t octep_vfire_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.vfire_intr_handler(oct); +} + +/** + * octep_vfore_intr_handler() - common handler for vf output ring error in= terrupts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for vf output ring error interrupts. + */ +static irqreturn_t octep_vfore_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.vfore_intr_handler(oct); +} + +/** + * octep_dma_intr_handler() - common handler for dpi dma related interrupt= s. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for dpi dma related interrupts. + */ +static irqreturn_t octep_dma_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.dma_intr_handler(oct); +} + +/** + * octep_dma_vf_intr_handler() - common handler for dpi dma transaction er= ror interrupts for VFs. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for dpi dma transaction error interrupts for VFs. + */ +static irqreturn_t octep_dma_vf_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.dma_vf_intr_handler(oct); +} + +/** + * octep_pp_vf_intr_handler() - common handler for pp transaction error in= terrupts for VFs. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for pp transaction error interrupts for VFs. + */ +static irqreturn_t octep_pp_vf_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.pp_vf_intr_handler(oct); +} + +/** + * octep_misc_intr_handler() - common handler for mac related interrupts. + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for mac related interrupts. */ -static irqreturn_t octep_non_ioq_intr_handler(int irq, void *data) +static irqreturn_t octep_misc_intr_handler(int irq, void *data) { struct octep_device *oct =3D data; =20 - return oct->hw_ops.non_ioq_intr_handler(oct); + return oct->hw_ops.misc_intr_handler(oct); +} + +/** + * octep_rsvd_intr_handler() - common handler for reserved interrupts (fut= ure use). + * + * @irq: Interrupt number. + * @data: interrupt data. + * + * this is common handler for all reserved interrupts. + */ +static irqreturn_t octep_rsvd_intr_handler(int irq, void *data) +{ + struct octep_device *oct =3D data; + + return oct->hw_ops.rsvd_intr_handler(oct); } =20 /** @@ -222,9 +361,57 @@ static int octep_request_irqs(struct octep_device *oct) =20 snprintf(irq_name, OCTEP_MSIX_NAME_SIZE, "%s-%s", netdev->name, non_ioq_msix_names[i]); - ret =3D request_irq(msix_entry->vector, - octep_non_ioq_intr_handler, 0, - irq_name, oct); + if (!strncmp(non_ioq_msix_names[i], "epf_oei_rint", + strlen("epf_oei_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_oei_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_ire_rint", + strlen("epf_ire_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_ire_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_ore_rint", + strlen("epf_ore_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_ore_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_vfire_rint", + strlen("epf_vfire_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_vfire_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_vfore_rint", + strlen("epf_vfore_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_vfore_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_dma_rint", + strlen("epf_dma_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_dma_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_dma_vf_rint", + strlen("epf_dma_vf_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_dma_vf_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_pp_vf_rint", + strlen("epf_pp_vf_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_pp_vf_intr_handler, 0, + irq_name, oct); + } else if (!strncmp(non_ioq_msix_names[i], "epf_misc_rint", + strlen("epf_misc_rint"))) { + ret =3D request_irq(msix_entry->vector, + octep_misc_intr_handler, 0, + irq_name, oct); + } else { + ret =3D request_irq(msix_entry->vector, + octep_rsvd_intr_handler, 0, + irq_name, oct); + } + if (ret) { netdev_err(netdev, "request_irq failed for %s; err=3D%d", @@ -907,9 +1094,9 @@ static void octep_hb_timeout_task(struct work_struct *= work) int miss_cnt; =20 miss_cnt =3D atomic_inc_return(&oct->hb_miss_cnt); - if (miss_cnt < oct->conf->max_hb_miss_cnt) { + if (miss_cnt < oct->conf->fw_info.hb_miss_count) { queue_delayed_work(octep_wq, &oct->hb_task, - msecs_to_jiffies(oct->conf->hb_interval * 1000)); + msecs_to_jiffies(oct->conf->fw_info.hb_interval)); return; } =20 @@ -943,6 +1130,14 @@ static const char *octep_devid_to_str(struct octep_de= vice *oct) return "CN93XX"; case OCTEP_PCI_DEVICE_ID_CNF95N_PF: return "CNF95N"; + case OCTEP_PCI_DEVICE_ID_CN10KA_PF: + return "CN10KA"; + case OCTEP_PCI_DEVICE_ID_CNF10KA_PF: + return "CNF10KA"; + case OCTEP_PCI_DEVICE_ID_CNF10KB_PF: + return "CNF10KB"; + case OCTEP_PCI_DEVICE_ID_CN10KB_PF: + return "CN10KB"; default: return "Unsupported"; } @@ -988,6 +1183,14 @@ int octep_device_setup(struct octep_device *oct) OCTEP_MINOR_REV(oct)); octep_device_setup_cn93_pf(oct); break; + case OCTEP_PCI_DEVICE_ID_CNF10KA_PF: + case OCTEP_PCI_DEVICE_ID_CN10KA_PF: + case OCTEP_PCI_DEVICE_ID_CNF10KB_PF: + case OCTEP_PCI_DEVICE_ID_CN10KB_PF: + dev_info(&pdev->dev, "Setting up OCTEON %s PF PASS%d.%d\n", + octep_devid_to_str(oct), OCTEP_MAJOR_REV(oct), OCTEP_MINOR_REV(oct)); + octep_device_setup_cnxk_pf(oct); + break; default: dev_err(&pdev->dev, "%s: unsupported device\n", __func__); @@ -1002,8 +1205,7 @@ int octep_device_setup(struct octep_device *oct) =20 atomic_set(&oct->hb_miss_cnt, 0); INIT_DELAYED_WORK(&oct->hb_task, octep_hb_timeout_task); - queue_delayed_work(octep_wq, &oct->hb_task, - msecs_to_jiffies(oct->conf->hb_interval * 1000)); + return 0; =20 unsupported_dev: @@ -1133,6 +1335,15 @@ static int octep_probe(struct pci_dev *pdev, const s= truct pci_device_id *ent) dev_err(&pdev->dev, "Device setup failed\n"); goto err_octep_config; } + + octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID, + &octep_dev->conf->fw_info); + dev_info(&octep_dev->pdev->dev, "Heartbeat interval %u msecs Heartbeat mi= ss count %u\n", + octep_dev->conf->fw_info.hb_interval, + octep_dev->conf->fw_info.hb_miss_count); + queue_delayed_work(octep_wq, &octep_dev->hb_task, + msecs_to_jiffies(octep_dev->conf->fw_info.hb_interval)); + INIT_WORK(&octep_dev->tx_timeout_task, octep_tx_timeout_task); INIT_WORK(&octep_dev->ctrl_mbox_task, octep_ctrl_mbox_task); INIT_DELAYED_WORK(&octep_dev->intr_poll_task, octep_intr_poll_task); diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/= net/ethernet/marvell/octeon_ep/octep_main.h index e0907a719133..ce92a2012789 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h @@ -23,6 +23,11 @@ =20 #define OCTEP_PCI_DEVICE_ID_CNF95N_PF 0xB400 //95N PF =20 +#define OCTEP_PCI_DEVICE_ID_CN10KA_PF 0xB900 //CN10KA PF +#define OCTEP_PCI_DEVICE_ID_CNF10KA_PF 0xBA00 //CNF10KA PF +#define OCTEP_PCI_DEVICE_ID_CNF10KB_PF 0xBC00 //CNF10KB PF +#define OCTEP_PCI_DEVICE_ID_CN10KB_PF 0xBD00 //CN10KB PF + #define OCTEP_MAX_QUEUES 63 #define OCTEP_MAX_IQ OCTEP_MAX_QUEUES #define OCTEP_MAX_OQ OCTEP_MAX_QUEUES @@ -62,10 +67,19 @@ struct octep_pci_win_regs { =20 struct octep_hw_ops { void (*setup_iq_regs)(struct octep_device *oct, int q); - void (*setup_oq_regs)(struct octep_device *oct, int q); + int (*setup_oq_regs)(struct octep_device *oct, int q); void (*setup_mbox_regs)(struct octep_device *oct, int mbox); =20 - irqreturn_t (*non_ioq_intr_handler)(void *ioq_vector); + irqreturn_t (*oei_intr_handler)(void *ioq_vector); + irqreturn_t (*ire_intr_handler)(void *ioq_vector); + irqreturn_t (*ore_intr_handler)(void *ioq_vector); + irqreturn_t (*vfire_intr_handler)(void *ioq_vector); + irqreturn_t (*vfore_intr_handler)(void *ioq_vector); + irqreturn_t (*dma_intr_handler)(void *ioq_vector); + irqreturn_t (*dma_vf_intr_handler)(void *ioq_vector); + irqreturn_t (*pp_vf_intr_handler)(void *ioq_vector); + irqreturn_t (*misc_intr_handler)(void *ioq_vector); + irqreturn_t (*rsvd_intr_handler)(void *ioq_vector); irqreturn_t (*ioq_intr_handler)(void *ioq_vector); int (*soft_reset)(struct octep_device *oct); void (*reinit_regs)(struct octep_device *oct); @@ -73,7 +87,7 @@ struct octep_hw_ops { =20 void (*enable_interrupts)(struct octep_device *oct); void (*disable_interrupts)(struct octep_device *oct); - bool (*poll_non_ioq_interrupts)(struct octep_device *oct); + void (*poll_non_ioq_interrupts)(struct octep_device *oct); =20 void (*enable_io_queues)(struct octep_device *oct); void (*disable_io_queues)(struct octep_device *oct); @@ -368,6 +382,7 @@ int octep_setup_oqs(struct octep_device *oct); void octep_free_oqs(struct octep_device *oct); void octep_oq_dbell_init(struct octep_device *oct); void octep_device_setup_cn93_pf(struct octep_device *oct); +void octep_device_setup_cnxk_pf(struct octep_device *oct); int octep_iq_process_completions(struct octep_iq *iq, u16 budget); int octep_oq_process_rx(struct octep_oq *oq, int budget); void octep_set_ethtool_ops(struct net_device *netdev); diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h b/= drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h index b25c3093dc7b..9ecfbabe3b9c 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h @@ -370,4 +370,9 @@ /* bit 1 for firmware heartbeat interrupt */ #define CN93_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT BIT_ULL(1) =20 +#define CN93_PEM_BAR4_INDEX 7 +#define CN93_PEM_BAR4_INDEX_SIZE 0x400000ULL +#define CN93_PEM_BAR4_INDEX_OFFSET (CN93_PEM_BAR4_INDEX * CN93_PEM_BAR= 4_INDEX_SIZE) +#define CN93_INT_ENA_BIT BIT_ULL(62) + #endif /* _OCTEP_REGS_CN9K_PF_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h b/= drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h new file mode 100644 index 000000000000..f0b3937002b6 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_regs_cnxk_pf.h @@ -0,0 +1,404 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell Octeon EP (EndPoint) Ethernet Driver + * + * Copyright (C) 2020 Marvell. + * + */ + +#ifndef _OCTEP_REGS_CNXK_PF_H_ +#define _OCTEP_REGS_CNXK_PF_H_ + +/* ############################ RST ######################### */ +#define CNXK_RST_BOOT 0x000087E006001600ULL +#define CNXK_RST_CHIP_DOMAIN_W1S 0x000087E006001810ULL +#define CNXK_RST_CORE_DOMAIN_W1S 0x000087E006001820ULL +#define CNXK_RST_CORE_DOMAIN_W1C 0x000087E006001828ULL + +#define CNXK_CONFIG_XPANSION_BAR 0x38 +#define CNXK_CONFIG_PCIE_CAP 0x70 +#define CNXK_CONFIG_PCIE_DEVCAP 0x74 +#define CNXK_CONFIG_PCIE_DEVCTL 0x78 +#define CNXK_CONFIG_PCIE_LINKCAP 0x7C +#define CNXK_CONFIG_PCIE_LINKCTL 0x80 +#define CNXK_CONFIG_PCIE_SLOTCAP 0x84 +#define CNXK_CONFIG_PCIE_SLOTCTL 0x88 + +#define CNXK_PCIE_SRIOV_FDL 0x188 /* 0x98 */ +#define CNXK_PCIE_SRIOV_FDL_BIT_POS 0x10 +#define CNXK_PCIE_SRIOV_FDL_MASK 0xFF + +#define CNXK_CONFIG_PCIE_FLTMSK 0x720 + +/* ################# Offsets of RING, EPF, MAC ######################### */ +#define CNXK_RING_OFFSET (0x1ULL << 17) +#define CNXK_EPF_OFFSET (0x1ULL << 25) +#define CNXK_MAC_OFFSET (0x1ULL << 4) +#define CNXK_BIT_ARRAY_OFFSET (0x1ULL << 4) +#define CNXK_EPVF_RING_OFFSET (0x1ULL << 4) + +/* ################# Scratch Registers ######################### */ +#define CNXK_SDP_EPF_SCRATCH 0x209E0 + +/* ################# Window Registers ######################### */ +#define CNXK_SDP_WIN_WR_ADDR64 0x20000 +#define CNXK_SDP_WIN_RD_ADDR64 0x20010 +#define CNXK_SDP_WIN_WR_DATA64 0x20020 +#define CNXK_SDP_WIN_WR_MASK_REG 0x20030 +#define CNXK_SDP_WIN_RD_DATA64 0x20040 + +#define CNXK_SDP_MAC_NUMBER 0x2C100 + +/* ################# Global Previliged registers #########################= */ +#define CNXK_SDP_EPF_RINFO 0x209F0 + +#define CNXK_SDP_EPF_RINFO_SRN(val) ((val) & 0x7F) +#define CNXK_SDP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF) +#define CNXK_SDP_EPF_RINFO_NVFS(val) (((val) >> 48) & 0x7F) + +/* SDP Function select */ +#define CNXK_SDP_FUNC_SEL_EPF_BIT_POS 7 +#define CNXK_SDP_FUNC_SEL_FUNC_BIT_POS 0 + +/* ##### RING IN (Into device from PCI: Tx Ring) REGISTERS #### */ +#define CNXK_SDP_R_IN_CONTROL_START 0x10000 +#define CNXK_SDP_R_IN_ENABLE_START 0x10010 +#define CNXK_SDP_R_IN_INSTR_BADDR_START 0x10020 +#define CNXK_SDP_R_IN_INSTR_RSIZE_START 0x10030 +#define CNXK_SDP_R_IN_INSTR_DBELL_START 0x10040 +#define CNXK_SDP_R_IN_CNTS_START 0x10050 +#define CNXK_SDP_R_IN_INT_LEVELS_START 0x10060 +#define CNXK_SDP_R_IN_PKT_CNT_START 0x10080 +#define CNXK_SDP_R_IN_BYTE_CNT_START 0x10090 + +#define CNXK_SDP_R_IN_CONTROL(ring) \ + (CNXK_SDP_R_IN_CONTROL_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_ENABLE(ring) \ + (CNXK_SDP_R_IN_ENABLE_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INSTR_BADDR(ring) \ + (CNXK_SDP_R_IN_INSTR_BADDR_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INSTR_RSIZE(ring) \ + (CNXK_SDP_R_IN_INSTR_RSIZE_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INSTR_DBELL(ring) \ + (CNXK_SDP_R_IN_INSTR_DBELL_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_CNTS(ring) \ + (CNXK_SDP_R_IN_CNTS_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INT_LEVELS(ring) \ + (CNXK_SDP_R_IN_INT_LEVELS_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_PKT_CNT(ring) \ + (CNXK_SDP_R_IN_PKT_CNT_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_BYTE_CNT(ring) \ + (CNXK_SDP_R_IN_BYTE_CNT_START + ((ring) * CNXK_RING_OFFSET)) + +/* Rings per Virtual Function */ +#define CNXK_R_IN_CTL_RPVF_MASK (0xF) +#define CNXK_R_IN_CTL_RPVF_POS (48) + +/* Number of instructions to be read in one MAC read request. + * setting to Max value(4) + */ +#define CNXK_R_IN_CTL_IDLE (0x1ULL << 28) +#define CNXK_R_IN_CTL_RDSIZE (0x3ULL << 25) +#define CNXK_R_IN_CTL_IS_64B (0x1ULL << 24) +#define CNXK_R_IN_CTL_D_NSR (0x1ULL << 8) +#define CNXK_R_IN_CTL_D_ESR (0x1ULL << 6) +#define CNXK_R_IN_CTL_D_ROR (0x1ULL << 5) +#define CNXK_R_IN_CTL_NSR (0x1ULL << 3) +#define CNXK_R_IN_CTL_ESR (0x1ULL << 1) +#define CNXK_R_IN_CTL_ROR (0x1ULL << 0) + +#define CNXK_R_IN_CTL_MASK (CNXK_R_IN_CTL_RDSIZE | CNXK_R_IN_CTL_IS_64= B) + +/* ##### RING OUT (out from device to PCI host: Rx Ring) REGISTERS #### */ +#define CNXK_SDP_R_OUT_CNTS_START 0x10100 +#define CNXK_SDP_R_OUT_INT_LEVELS_START 0x10110 +#define CNXK_SDP_R_OUT_SLIST_BADDR_START 0x10120 +#define CNXK_SDP_R_OUT_SLIST_RSIZE_START 0x10130 +#define CNXK_SDP_R_OUT_SLIST_DBELL_START 0x10140 +#define CNXK_SDP_R_OUT_CONTROL_START 0x10150 +#define CNXK_SDP_R_OUT_WMARK_START 0x10160 +#define CNXK_SDP_R_OUT_ENABLE_START 0x10170 +#define CNXK_SDP_R_OUT_PKT_CNT_START 0x10180 +#define CNXK_SDP_R_OUT_BYTE_CNT_START 0x10190 + +#define CNXK_SDP_R_OUT_CONTROL(ring) \ + (CNXK_SDP_R_OUT_CONTROL_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_ENABLE(ring) \ + (CNXK_SDP_R_OUT_ENABLE_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_SLIST_BADDR(ring) \ + (CNXK_SDP_R_OUT_SLIST_BADDR_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_SLIST_RSIZE(ring) \ + (CNXK_SDP_R_OUT_SLIST_RSIZE_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_SLIST_DBELL(ring) \ + (CNXK_SDP_R_OUT_SLIST_DBELL_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_WMARK(ring) \ + (CNXK_SDP_R_OUT_WMARK_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_CNTS(ring) \ + (CNXK_SDP_R_OUT_CNTS_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_INT_LEVELS(ring) \ + (CNXK_SDP_R_OUT_INT_LEVELS_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_PKT_CNT(ring) \ + (CNXK_SDP_R_OUT_PKT_CNT_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_BYTE_CNT(ring) \ + (CNXK_SDP_R_OUT_BYTE_CNT_START + ((ring) * CNXK_RING_OFFSET)) + +/*------------------ R_OUT Masks ----------------*/ +#define CNXK_R_OUT_INT_LEVELS_BMODE BIT_ULL(63) +#define CNXK_R_OUT_INT_LEVELS_TIMET (32) + +#define CNXK_R_OUT_CTL_IDLE BIT_ULL(40) +#define CNXK_R_OUT_CTL_ES_I BIT_ULL(34) +#define CNXK_R_OUT_CTL_NSR_I BIT_ULL(33) +#define CNXK_R_OUT_CTL_ROR_I BIT_ULL(32) +#define CNXK_R_OUT_CTL_ES_D BIT_ULL(30) +#define CNXK_R_OUT_CTL_NSR_D BIT_ULL(29) +#define CNXK_R_OUT_CTL_ROR_D BIT_ULL(28) +#define CNXK_R_OUT_CTL_ES_P BIT_ULL(26) +#define CNXK_R_OUT_CTL_NSR_P BIT_ULL(25) +#define CNXK_R_OUT_CTL_ROR_P BIT_ULL(24) +#define CNXK_R_OUT_CTL_IMODE BIT_ULL(23) + +/* ############### Interrupt Moderation Registers ############### */ +#define CNXK_SDP_R_IN_INT_MDRT_CTL0_START 0x10280 +#define CNXK_SDP_R_IN_INT_MDRT_CTL1_START 0x102A0 +#define CNXK_SDP_R_IN_INT_MDRT_DBG_START 0x102C0 + +#define CNXK_SDP_R_OUT_INT_MDRT_CTL0_START 0x10380 +#define CNXK_SDP_R_OUT_INT_MDRT_CTL1_START 0x103A0 +#define CNXK_SDP_R_OUT_INT_MDRT_DBG_START 0x103C0 + +#define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510 +#define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520 + +#define CNXK_SDP_R_IN_INT_MDRT_CTL0(ring) \ + (CNXK_SDP_R_IN_INT_MDRT_CTL0_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INT_MDRT_CTL1(ring) \ + (CNXK_SDP_R_IN_INT_MDRT_CTL1_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_INT_MDRT_DBG(ring) \ + (CNXK_SDP_R_IN_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_INT_MDRT_CTL0(ring) \ + (CNXK_SDP_R_OUT_INT_MDRT_CTL0_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_INT_MDRT_CTL1(ring) \ + (CNXK_SDP_R_OUT_INT_MDRT_CTL1_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_INT_MDRT_DBG(ring) \ + (CNXK_SDP_R_OUT_INT_MDRT_DBG_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_CNTS_ISM(ring) \ + (CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_CNTS_ISM(ring) \ + (CNXK_SDP_R_IN_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) + +/* ##################### Mail Box Registers ########################## */ +/* INT register for VF. when a MBOX write from PF happed to a VF, + * corresponding bit will be set in this register as well as in + * PF_VF_INT register. + * + * This is a RO register, the int can be cleared by writing 1 to PF_VF_INT + */ +/* Basically first 3 are from PF to VF. The last one is data from VF to PF= */ +#define CNXK_SDP_R_MBOX_PF_VF_DATA_START 0x10210 +#define CNXK_SDP_R_MBOX_PF_VF_INT_START 0x10220 +#define CNXK_SDP_R_MBOX_VF_PF_DATA_START 0x10230 + +#define CNXK_SDP_R_MBOX_PF_VF_DATA(ring) \ + (CNXK_SDP_R_MBOX_PF_VF_DATA_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_MBOX_PF_VF_INT(ring) \ + (CNXK_SDP_R_MBOX_PF_VF_INT_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_MBOX_VF_PF_DATA(ring) \ + (CNXK_SDP_R_MBOX_VF_PF_DATA_START + ((ring) * CNXK_RING_OFFSET)) + +/* ##################### Interrupt Registers ########################## */ +#define CNXK_SDP_R_ERR_TYPE_START 0x10400 + +#define CNXK_SDP_R_ERR_TYPE(ring) \ + (CNXK_SDP_R_ERR_TYPE_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_MBOX_ISM_START 0x10500 +#define CNXK_SDP_R_OUT_CNTS_ISM_START 0x10510 +#define CNXK_SDP_R_IN_CNTS_ISM_START 0x10520 + +#define CNXK_SDP_R_MBOX_ISM(ring) \ + (CNXK_SDP_R_MBOX_ISM_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_OUT_CNTS_ISM(ring) \ + (CNXK_SDP_R_OUT_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_R_IN_CNTS_ISM(ring) \ + (CNXK_SDP_R_IN_CNTS_ISM_START + ((ring) * CNXK_RING_OFFSET)) + +#define CNXK_SDP_EPF_MBOX_RINT_START 0x20100 +#define CNXK_SDP_EPF_MBOX_RINT_W1S_START 0x20120 +#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1C_START 0x20140 +#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1S_START 0x20160 + +#define CNXK_SDP_EPF_VFIRE_RINT_START 0x20180 +#define CNXK_SDP_EPF_VFIRE_RINT_W1S_START 0x201A0 +#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C_START 0x201C0 +#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S_START 0x201E0 + +#define CNXK_SDP_EPF_IRERR_RINT 0x20200 +#define CNXK_SDP_EPF_IRERR_RINT_W1S 0x20210 +#define CNXK_SDP_EPF_IRERR_RINT_ENA_W1C 0x20220 +#define CNXK_SDP_EPF_IRERR_RINT_ENA_W1S 0x20230 + +#define CNXK_SDP_EPF_VFORE_RINT_START 0x20240 +#define CNXK_SDP_EPF_VFORE_RINT_W1S_START 0x20260 +#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1C_START 0x20280 +#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1S_START 0x202A0 + +#define CNXK_SDP_EPF_ORERR_RINT 0x20320 +#define CNXK_SDP_EPF_ORERR_RINT_W1S 0x20330 +#define CNXK_SDP_EPF_ORERR_RINT_ENA_W1C 0x20340 +#define CNXK_SDP_EPF_ORERR_RINT_ENA_W1S 0x20350 + +#define CNXK_SDP_EPF_OEI_RINT 0x20400 +#define CNXK_SDP_EPF_OEI_RINT_W1S 0x20500 +#define CNXK_SDP_EPF_OEI_RINT_ENA_W1C 0x20600 +#define CNXK_SDP_EPF_OEI_RINT_ENA_W1S 0x20700 + +#define CNXK_SDP_EPF_DMA_RINT 0x20800 +#define CNXK_SDP_EPF_DMA_RINT_W1S 0x20810 +#define CNXK_SDP_EPF_DMA_RINT_ENA_W1C 0x20820 +#define CNXK_SDP_EPF_DMA_RINT_ENA_W1S 0x20830 + +#define CNXK_SDP_EPF_DMA_INT_LEVEL_START 0x20840 +#define CNXK_SDP_EPF_DMA_CNT_START 0x20860 +#define CNXK_SDP_EPF_DMA_TIM_START 0x20880 + +#define CNXK_SDP_EPF_MISC_RINT 0x208A0 +#define CNXK_SDP_EPF_MISC_RINT_W1S 0x208B0 +#define CNXK_SDP_EPF_MISC_RINT_ENA_W1C 0x208C0 +#define CNXK_SDP_EPF_MISC_RINT_ENA_W1S 0x208D0 + +#define CNXK_SDP_EPF_DMA_VF_RINT_START 0x208E0 +#define CNXK_SDP_EPF_DMA_VF_RINT_W1S_START 0x20900 +#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C_START 0x20920 +#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S_START 0x20940 + +#define CNXK_SDP_EPF_PP_VF_RINT_START 0x20960 +#define CNXK_SDP_EPF_PP_VF_RINT_W1S_START 0x20980 +#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C_START 0x209A0 +#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S_START 0x209C0 + +#define CNXK_SDP_EPF_MBOX_RINT(index) \ + (CNXK_SDP_EPF_MBOX_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_MBOX_RINT_W1S(index) \ + (CNXK_SDP_EPF_MBOX_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1C(index) \ + (CNXK_SDP_EPF_MBOX_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSET= )) +#define CNXK_SDP_EPF_MBOX_RINT_ENA_W1S(index) \ + (CNXK_SDP_EPF_MBOX_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET= )) + +#define CNXK_SDP_EPF_VFIRE_RINT(index) \ + (CNXK_SDP_EPF_VFIRE_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_VFIRE_RINT_W1S(index) \ + (CNXK_SDP_EPF_VFIRE_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C(index) \ + (CNXK_SDP_EPF_VFIRE_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSE= T)) +#define CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S(index) \ + (CNXK_SDP_EPF_VFIRE_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSE= T)) + +#define CNXK_SDP_EPF_VFORE_RINT(index) \ + (CNXK_SDP_EPF_VFORE_RINT_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_VFORE_RINT_W1S(index) \ + (CNXK_SDP_EPF_VFORE_RINT_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1C(index) \ + (CNXK_SDP_EPF_VFORE_RINT_ENA_W1C_START + ((index) * CNXK_BIT_ARRAY_OFFSE= T)) +#define CNXK_SDP_EPF_VFORE_RINT_ENA_W1S(index) \ + (CNXK_SDP_EPF_VFORE_RINT_ENA_W1S_START + ((index) * CNXK_BIT_ARRAY_OFFSE= T)) + +#define CNXK_SDP_EPF_DMA_VF_RINT(index) \ + (CNXK_SDP_EPF_DMA_VF_RINT_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_DMA_VF_RINT_W1S(index) \ + (CNXK_SDP_EPF_DMA_VF_RINT_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C(index) \ + (CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1C_START + ((index) + CNXK_BIT_ARRAY_OFFS= ET)) +#define CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S(index) \ + (CNXK_SDP_EPF_DMA_VF_RINT_ENA_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFS= ET)) + +#define CNXK_SDP_EPF_PP_VF_RINT(index) \ + (CNXK_SDP_EPF_PP_VF_RINT_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_PP_VF_RINT_W1S(index) \ + (CNXK_SDP_EPF_PP_VF_RINT_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSET)) +#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C(index) \ + (CNXK_SDP_EPF_PP_VF_RINT_ENA_W1C_START + ((index) + CNXK_BIT_ARRAY_OFFSE= T)) +#define CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S(index) \ + (CNXK_SDP_EPF_PP_VF_RINT_ENA_W1S_START + ((index) + CNXK_BIT_ARRAY_OFFSE= T)) + +/*------------------ Interrupt Masks ----------------*/ +#define CNXK_INTR_R_SEND_ISM BIT_ULL(63) +#define CNXK_INTR_R_OUT_INT BIT_ULL(62) +#define CNXK_INTR_R_IN_INT BIT_ULL(61) +#define CNXK_INTR_R_MBOX_INT BIT_ULL(60) +#define CNXK_INTR_R_RESEND BIT_ULL(59) +#define CNXK_INTR_R_CLR_TIM BIT_ULL(58) + +/* ####################### Ring Mapping Registers ########################= ########## */ +#define CNXK_SDP_EPVF_RING_START 0x26000 +#define CNXK_SDP_IN_RING_TB_MAP_START 0x28000 +#define CNXK_SDP_IN_RATE_LIMIT_START 0x2A000 +#define CNXK_SDP_MAC_PF_RING_CTL_START 0x2C000 + +#define CNXK_SDP_EPVF_RING(ring) \ + (CNXK_SDP_EPVF_RING_START + ((ring) * CNXK_EPVF_RING_OFFSET)) +#define CNXK_SDP_IN_RING_TB_MAP(ring) \ + (CNXK_SDP_N_RING_TB_MAP_START + ((ring) * CNXK_EPVF_RING_OFFSET)) +#define CNXK_SDP_IN_RATE_LIMIT(ring) \ + (CNXK_SDP_IN_RATE_LIMIT_START + ((ring) * CNXK_EPVF_RING_OFFSET)) +#define CNXK_SDP_MAC_PF_RING_CTL(mac) \ + (CNXK_SDP_MAC_PF_RING_CTL_START + ((mac) * CNXK_MAC_OFFSET)) + +#define CNXK_SDP_MAC_PF_RING_CTL_NPFS(val) ((val) & 0x3) +#define CNXK_SDP_MAC_PF_RING_CTL_SRN(val) (((val) >> 8) & 0x7F) +#define CNXK_SDP_MAC_PF_RING_CTL_RPPF(val) (((val) >> 16) & 0x3F) + +/* Number of non-queue interrupts in CNXKxx */ +#define CNXK_NUM_NON_IOQ_INTR 32 + +/* bit 0 for control mbox interrupt */ +#define CNXK_SDP_EPF_OEI_RINT_DATA_BIT_MBOX BIT_ULL(0) +/* bit 1 for firmware heartbeat interrupt */ +#define CNXK_SDP_EPF_OEI_RINT_DATA_BIT_HBEAT BIT_ULL(1) +#define FW_STATUS_RUNNING 2ULL +#define CNXK_PEMX_PFX_CSX_PFCFGX(pem, pf, offset) ({ typeof(offset) _= off =3D (offset); \ + ((0x8e0000008000 | \ + (uint64_t)(pem) << 36 \ + | (pf) << 18 \ + | ((_off >> 16) & 1) << 16 \ + | (_off >> 3) << 3) \ + + (((_off >> 2) & 1) << 2)); \ + }) + +/* Register defines for use with CNXK_PEMX_PFX_CSX_PFCFGX */ +#define CNXK_PCIEEP_VSECST_CTL 0x418 + +#define CNXK_PEM_BAR4_INDEX 7 +#define CNXK_PEM_BAR4_INDEX_SIZE 0x400000ULL +#define CNXK_PEM_BAR4_INDEX_OFFSET (CNXK_PEM_BAR4_INDEX * CNXK_PEM_BAR4_IN= DEX_SIZE) +#define CNXK_INT_ENA_BIT BIT_ULL(62) + +#endif /* _OCTEP_REGS_CNXK_PF_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/ne= t/ethernet/marvell/octeon_ep/octep_rx.c index c7f4e3c058b7..60afb6bf2f67 100644 --- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c +++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c @@ -12,6 +12,8 @@ #include "octep_config.h" #include "octep_main.h" =20 +static void octep_oq_free_ring_buffers(struct octep_oq *oq); + static void octep_oq_reset_indices(struct octep_oq *oq) { oq->host_read_idx =3D 0; @@ -169,11 +171,15 @@ static int octep_setup_oq(struct octep_device *oct, i= nt q_no) goto oq_fill_buff_err; =20 octep_oq_reset_indices(oq); - oct->hw_ops.setup_oq_regs(oct, q_no); + if (oct->hw_ops.setup_oq_regs(oct, q_no)) + goto oq_setup_err; + oct->num_oqs++; =20 return 0; =20 +oq_setup_err: + octep_oq_free_ring_buffers(oq); oq_fill_buff_err: vfree(oq->buff_info); oq->buff_info =3D NULL; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/= ethernet/marvell/octeontx2/af/cgx.c index 729d1833a829..278dc1aabd4b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -1793,6 +1793,8 @@ static int cgx_lmac_exit(struct cgx *cgx) cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, false); cgx_configure_interrupt(cgx, lmac, lmac->lmac_id, true); kfree(lmac->mac_to_index_bmap.bmap); + rvu_free_bitmap(&lmac->rx_fc_pfvf_bmap); + rvu_free_bitmap(&lmac->tx_fc_pfvf_bmap); kfree(lmac->name); kfree(lmac); } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.c index 846049b6c4d6..a7fcea9b1ee7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -3444,11 +3444,22 @@ static void rvu_remove(struct pci_dev *pdev) devm_kfree(&pdev->dev, rvu); } =20 +static void rvu_shutdown(struct pci_dev *pdev) +{ + struct rvu *rvu =3D pci_get_drvdata(pdev); + + if (!rvu) + return; + + rvu_clear_rvum_blk_revid(rvu); +} + static struct pci_driver rvu_driver =3D { .name =3D DRV_NAME, .id_table =3D rvu_id_table, .probe =3D rvu_probe, .remove =3D rvu_remove, + .shutdown =3D rvu_shutdown, }; =20 static int __init rvu_init_module(void) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_nix.c index 29487518ca67..0703b0d8df78 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -4509,12 +4509,18 @@ static int rvu_nix_block_init(struct rvu *rvu, stru= ct nix_hw *nix_hw) /* Set chan/link to backpressure TL3 instead of TL2 */ rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01); =20 - /* Disable SQ manager's sticky mode operation (set TM6 =3D 0) + /* Disable SQ manager's sticky mode operation (set TM6 =3D 0, TM11 =3D 0) * This sticky mode is known to cause SQ stalls when multiple - * SQs are mapped to same SMQ and transmitting pkts at a time. + * SQs are mapped to same SMQ and transmitting pkts simultaneously. + * NIX PSE may deadlock when there are any sticky to non-sticky + * transmission. Hence disable it (TM5 =3D 0). */ cfg =3D rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS); - cfg &=3D ~BIT_ULL(15); + cfg &=3D ~(BIT_ULL(15) | BIT_ULL(14) | BIT_ULL(23)); + /* NIX may drop credits when condition clocks are turned off. + * Hence enable control flow clk (set TM9 =3D 1). + */ + cfg |=3D BIT_ULL(21); rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg); =20 ltdefs =3D rvu->kpu.lt_def; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index 00ef6d201b97..9b8a6046e6df 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -1070,32 +1070,35 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu= , u16 pcifunc, int nixlf, rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action); =20 - /* update the VF flow rule action with the VF default entry action */ - if (mcam_index < 0) - npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, - *(u64 *)&action); - /* update the action change in default rule */ pfvf =3D rvu_get_pfvf(rvu, pcifunc); if (pfvf->def_ucast_rule) pfvf->def_ucast_rule->rx_action =3D action; =20 - index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, - nixlf, NIXLF_PROMISC_ENTRY); + if (mcam_index < 0) { + /* update the VF flow rule action with the VF default + * entry action + */ + npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, + *(u64 *)&action); =20 - /* If PF's promiscuous entry is enabled, - * Set RSS action for that entry as well - */ - npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr, - alg_idx); + index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, + nixlf, NIXLF_PROMISC_ENTRY); =20 - index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, - nixlf, NIXLF_ALLMULTI_ENTRY); - /* If PF's allmulti entry is enabled, - * Set RSS action for that entry as well - */ - npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr, - alg_idx); + /* If PF's promiscuous entry is enabled, + * Set RSS action for that entry as well + */ + npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, + blkaddr, alg_idx); + + index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, + nixlf, NIXLF_ALLMULTI_ENTRY); + /* If PF's allmulti entry is enabled, + * Set RSS action for that entry as well + */ + npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, + blkaddr, alg_idx); + } } =20 void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc, diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers= /net/ethernet/marvell/octeontx2/nic/otx2_pf.c index b4194ec2a1f2..784130b4b086 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -3097,6 +3097,7 @@ static int otx2_probe(struct pci_dev *pdev, const str= uct pci_device_id *id) return 0; =20 err_pf_sriov_init: + otx2_unregister_dl(pf); otx2_shutdown_tc(pf); err_mcam_flow_del: otx2_mcam_flow_del(pf); diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/mar= vell/skge.c index 1b43704baceb..2bb77e238970 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -78,7 +78,6 @@ static const struct pci_device_id skge_id_table[] =3D { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B)= */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 = */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001= /8003/8010 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/= ethernet/mellanox/mlx5/core/sriov.c index a2fc937d5461..172862a70c70 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -193,7 +193,9 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int = num_vfs) err =3D pci_enable_sriov(pdev, num_vfs); if (err) { mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err); + devl_lock(devlink); mlx5_device_disable_sriov(dev, num_vfs, true, true); + devl_unlock(devlink); } return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c b/dr= ivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c index 7e36e1062139..ebe81c5aa611 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c @@ -664,8 +664,8 @@ static int dr_dump_domain_all(struct seq_file *file, st= ruct mlx5dr_domain *dmn) struct mlx5dr_table *tbl; int ret; =20 - mutex_lock(&dmn->dump_info.dbg_mutex); mlx5dr_domain_lock(dmn); + mutex_lock(&dmn->dump_info.dbg_mutex); =20 ret =3D dr_dump_domain(file, dmn); if (ret < 0) @@ -678,8 +678,8 @@ static int dr_dump_domain_all(struct seq_file *file, st= ruct mlx5dr_domain *dmn) } =20 unlock_mutex: - mlx5dr_domain_unlock(dmn); mutex_unlock(&dmn->dump_info.dbg_mutex); + mlx5dr_domain_unlock(dmn); return ret; } =20 diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/n= et/ethernet/microchip/sparx5/sparx5_ptp.c index 5a932460db58..6b2dbfbeef37 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c @@ -562,7 +562,7 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *pt= p, s64 delta) static struct ptp_clock_info sparx5_ptp_clock_info =3D { .owner =3D THIS_MODULE, .name =3D "sparx5 ptp", - .max_adj =3D 200000, + .max_adj =3D 10000000, .gettime64 =3D sparx5_ptp_gettime64, .settime64 =3D sparx5_ptp_settime64, .adjtime =3D sparx5_ptp_adjtime, diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h b/drivers/n= et/ethernet/microchip/sparx5/sparx5_qos.h index ced35033a6c5..b1c6c5c6f16c 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_qos.h @@ -35,7 +35,7 @@ #define SPX5_SE_BURST_UNIT 4096 =20 /* Dwrr */ -#define SPX5_DWRR_COST_MAX 63 +#define SPX5_DWRR_COST_MAX 31 =20 struct sparx5_shaper { u32 mode; diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/= mscc/ocelot_net.c index 21a87a3fc556..b516b4e1ed97 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -551,44 +551,81 @@ static int ocelot_port_stop(struct net_device *dev) return 0; } =20 -static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device= *dev) +static bool ocelot_xmit_timestamp(struct ocelot *ocelot, int port, + struct sk_buff *skb, u32 *rew_op) { - struct ocelot_port_private *priv =3D netdev_priv(dev); - struct ocelot_port *ocelot_port =3D &priv->port; - struct ocelot *ocelot =3D ocelot_port->ocelot; - int port =3D priv->port.index; - u32 rew_op =3D 0; - - if (!static_branch_unlikely(&ocelot_fdma_enabled) && - !ocelot_can_inject(ocelot, 0)) - return NETDEV_TX_BUSY; - - /* Check if timestamping is needed */ if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { struct sk_buff *clone =3D NULL; =20 if (ocelot_port_txtstamp_request(ocelot, port, skb, &clone)) { kfree_skb(skb); - return NETDEV_TX_OK; + return false; } =20 if (clone) OCELOT_SKB_CB(skb)->clone =3D clone; =20 - rew_op =3D ocelot_ptp_rew_op(skb); + *rew_op =3D ocelot_ptp_rew_op(skb); } =20 - if (static_branch_unlikely(&ocelot_fdma_enabled)) { - ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev); - } else { - ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); + return true; +} + +static netdev_tx_t ocelot_port_xmit_fdma(struct sk_buff *skb, + struct net_device *dev) +{ + struct ocelot_port_private *priv =3D netdev_priv(dev); + struct ocelot_port *ocelot_port =3D &priv->port; + struct ocelot *ocelot =3D ocelot_port->ocelot; + int port =3D priv->port.index; + u32 rew_op =3D 0; + + if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op)) + return NETDEV_TX_OK; + + ocelot_fdma_inject_frame(ocelot, port, rew_op, skb, dev); + + return NETDEV_TX_OK; +} =20 - consume_skb(skb); +static netdev_tx_t ocelot_port_xmit_inj(struct sk_buff *skb, + struct net_device *dev) +{ + struct ocelot_port_private *priv =3D netdev_priv(dev); + struct ocelot_port *ocelot_port =3D &priv->port; + struct ocelot *ocelot =3D ocelot_port->ocelot; + int port =3D priv->port.index; + u32 rew_op =3D 0; + + ocelot_lock_inj_grp(ocelot, 0); + + if (!ocelot_can_inject(ocelot, 0)) { + ocelot_unlock_inj_grp(ocelot, 0); + return NETDEV_TX_BUSY; } =20 + if (!ocelot_xmit_timestamp(ocelot, port, skb, &rew_op)) { + ocelot_unlock_inj_grp(ocelot, 0); + return NETDEV_TX_OK; + } + + ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); + + ocelot_unlock_inj_grp(ocelot, 0); + + consume_skb(skb); + return NETDEV_TX_OK; } =20 +static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device= *dev) +{ + if (static_branch_unlikely(&ocelot_fdma_enabled)) + return ocelot_port_xmit_fdma(skb, dev); + + return ocelot_port_xmit_inj(skb, dev); +} + enum ocelot_action_type { OCELOT_MACT_LEARN, OCELOT_MACT_FORGET, diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net= /ethernet/myricom/myri10ge/myri10ge.c index 7b7e1c5b00f4..f3b1605f6adc 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -688,6 +688,9 @@ static int myri10ge_get_firmware_capabilities(struct my= ri10ge_priv *mgp) =20 /* probe for IPv6 TSO support */ mgp->features =3D NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; + cmd.data0 =3D 0, + cmd.data1 =3D 0, + cmd.data2 =3D 0, status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, &cmd, 0); if (status =3D=3D 0) { @@ -806,6 +809,7 @@ static int myri10ge_update_mac_address(struct myri10ge_= priv *mgp, | (addr[2] << 8) | addr[3]); =20 cmd.data1 =3D ((addr[4] << 8) | (addr[5])); + cmd.data2 =3D 0; =20 status =3D myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0); return status; @@ -817,6 +821,9 @@ static int myri10ge_change_pause(struct myri10ge_priv *= mgp, int pause) int status, ctl; =20 ctl =3D pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL; + cmd.data0 =3D 0, + cmd.data1 =3D 0, + cmd.data2 =3D 0, status =3D myri10ge_send_cmd(mgp, ctl, &cmd, 0); =20 if (status) { @@ -834,6 +841,9 @@ myri10ge_change_promisc(struct myri10ge_priv *mgp, int = promisc, int atomic) int status, ctl; =20 ctl =3D promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC; + cmd.data0 =3D 0; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status =3D myri10ge_send_cmd(mgp, ctl, &cmd, atomic); if (status) netdev_err(mgp->dev, "Failed to set promisc mode\n"); @@ -1946,6 +1956,8 @@ static int myri10ge_allocate_rings(struct myri10ge_sl= ice_state *ss) /* get ring sizes */ slice =3D ss - mgp->ss; cmd.data0 =3D slice; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); tx_ring_size =3D cmd.data0; cmd.data0 =3D slice; @@ -2238,12 +2250,16 @@ static int myri10ge_get_txrx(struct myri10ge_priv *= mgp, int slice) status =3D 0; if (slice =3D=3D 0 || (mgp->dev->real_num_tx_queues > 1)) { cmd.data0 =3D slice; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); ss->tx.lanai =3D (struct mcp_kreq_ether_send __iomem *) (mgp->sram + cmd.data0); } cmd.data0 =3D slice; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status |=3D myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0); ss->rx_small.lanai =3D (struct mcp_kreq_ether_recv __iomem *) @@ -2312,6 +2328,7 @@ static int myri10ge_open(struct net_device *dev) if (mgp->num_slices > 1) { cmd.data0 =3D mgp->num_slices; cmd.data1 =3D MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE; + cmd.data2 =3D 0; if (mgp->dev->real_num_tx_queues > 1) cmd.data1 |=3D MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES; status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, @@ -2414,6 +2431,8 @@ static int myri10ge_open(struct net_device *dev) =20 /* now give firmware buffers sizes, and MTU */ cmd.data0 =3D dev->mtu + ETH_HLEN + VLAN_HLEN; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0); cmd.data0 =3D mgp->small_bytes; status |=3D @@ -2472,7 +2491,6 @@ static int myri10ge_open(struct net_device *dev) static int myri10ge_close(struct net_device *dev) { struct myri10ge_priv *mgp =3D netdev_priv(dev); - struct myri10ge_cmd cmd; int status, old_down_cnt; int i; =20 @@ -2491,8 +2509,13 @@ static int myri10ge_close(struct net_device *dev) =20 netif_tx_stop_all_queues(dev); if (mgp->rebooted =3D=3D 0) { + struct myri10ge_cmd cmd; + old_down_cnt =3D mgp->down_cnt; mb(); + cmd.data0 =3D 0; + cmd.data1 =3D 0; + cmd.data2 =3D 0; status =3D myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0); if (status) @@ -2956,6 +2979,9 @@ static void myri10ge_set_multicast_list(struct net_de= vice *dev) =20 /* Disable multicast filtering */ =20 + cmd.data0 =3D 0; + cmd.data1 =3D 0; + cmd.data2 =3D 0; err =3D myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1); if (err !=3D 0) { netdev_err(dev, "Failed MXGEFW_ENABLE_ALLMULTI, error status: %d\n", diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/= net/ethernet/pensando/ionic/ionic_ethtool.c index d76e63f57ff1..b07dd56b0c76 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -222,9 +222,10 @@ static int ionic_get_link_ksettings(struct net_device = *netdev, /* This means there's no module plugged in */ break; default: - dev_info(lif->ionic->dev, "unknown xcvr type pid=3D%d / 0x%x\n", - idev->port_info->status.xcvr.pid, - idev->port_info->status.xcvr.pid); + dev_dbg_ratelimited(lif->ionic->dev, + "unknown xcvr type pid=3D%d / 0x%x\n", + idev->port_info->status.xcvr.pid, + idev->port_info->status.xcvr.pid); break; } =20 diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/s= unhme.c index b983b9c23be6..61ca7377b612 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2551,6 +2551,9 @@ static int happy_meal_sbus_probe_one(struct platform_= device *op, int is_qfe) goto err_out_clear_quattro; } =20 + /* BIGMAC may have bogus sizes */ + if ((op->resource[3].end - op->resource[3].start) >=3D BMAC_REG_SIZE) + op->resource[3].end =3D op->resource[3].start + BMAC_REG_SIZE - 1; hp->bigmacregs =3D devm_platform_ioremap_resource(op, 3); if (IS_ERR(hp->bigmacregs)) { dev_err(&op->dev, "Cannot map BIGMAC registers.\n"); diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/c= psw_new.c index 1c1d4806c119..1f98044b3666 100644 --- a/drivers/net/ethernet/ti/cpsw_new.c +++ b/drivers/net/ethernet/ti/cpsw_new.c @@ -1967,7 +1967,7 @@ static int cpsw_probe(struct platform_device *pdev) /* setup netdevs */ ret =3D cpsw_create_ports(cpsw); if (ret) - goto clean_unregister_netdev; + goto clean_cpts; =20 /* Grab RX and TX IRQs. Note that we also have RX_THRESHOLD and * MISC IRQs which are always kept disabled with this driver so @@ -1981,14 +1981,14 @@ static int cpsw_probe(struct platform_device *pdev) 0, dev_name(dev), cpsw); if (ret < 0) { dev_err(dev, "error attaching irq (%d)\n", ret); - goto clean_unregister_netdev; + goto clean_cpts; } =20 ret =3D devm_request_irq(dev, cpsw->irqs_table[1], cpsw_tx_interrupt, 0, dev_name(dev), cpsw); if (ret < 0) { dev_err(dev, "error attaching irq (%d)\n", ret); - goto clean_unregister_netdev; + goto clean_cpts; } =20 if (!cpsw->cpts) @@ -1998,7 +1998,7 @@ static int cpsw_probe(struct platform_device *pdev) 0, dev_name(&pdev->dev), cpsw); if (ret < 0) { dev_err(dev, "error attaching misc irq (%d)\n", ret); - goto clean_unregister_netdev; + goto clean_cpts; } =20 /* Enable misc CPTS evnt_pend IRQ */ @@ -2007,7 +2007,7 @@ static int cpsw_probe(struct platform_device *pdev) skip_cpts: ret =3D cpsw_register_notifiers(cpsw); if (ret) - goto clean_unregister_netdev; + goto clean_cpts; =20 ret =3D cpsw_register_devlink(cpsw); if (ret) @@ -2029,8 +2029,6 @@ static int cpsw_probe(struct platform_device *pdev) =20 clean_unregister_notifiers: cpsw_unregister_notifiers(cpsw); -clean_unregister_netdev: - cpsw_unregister_ports(cpsw); clean_cpts: cpts_release(cpsw->cpts); cpdma_ctlr_destroy(cpsw->dma); diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/etherne= t/xscale/ixp4xx_eth.c index 3b0c5f177447..aa6d30dd35c3 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -386,28 +386,29 @@ static void ixp_tx_timestamp(struct port *port, struc= t sk_buff *skb) __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); } =20 -static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) +static int ixp4xx_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) { - struct hwtstamp_config cfg; struct ixp46x_ts_regs *regs; struct port *port =3D netdev_priv(netdev); int ret; int ch; =20 - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; + if (!netif_running(netdev)) + return -EINVAL; =20 ret =3D ixp46x_ptp_find(&port->timesync_regs, &port->phc_index); if (ret) - return ret; + return -EOPNOTSUPP; =20 ch =3D PORT2CHANNEL(port); regs =3D port->timesync_regs; =20 - if (cfg.tx_type !=3D HWTSTAMP_TX_OFF && cfg.tx_type !=3D HWTSTAMP_TX_ON) + if (cfg->tx_type !=3D HWTSTAMP_TX_OFF && cfg->tx_type !=3D HWTSTAMP_TX_ON) return -ERANGE; =20 - switch (cfg.rx_filter) { + switch (cfg->rx_filter) { case HWTSTAMP_FILTER_NONE: port->hwts_rx_en =3D 0; break; @@ -423,39 +424,45 @@ static int hwtstamp_set(struct net_device *netdev, st= ruct ifreq *ifr) return -ERANGE; } =20 - port->hwts_tx_en =3D cfg.tx_type =3D=3D HWTSTAMP_TX_ON; + port->hwts_tx_en =3D cfg->tx_type =3D=3D HWTSTAMP_TX_ON; =20 /* Clear out any old time stamps. */ __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); =20 - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + return 0; } =20 -static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) +static int ixp4xx_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *cfg) { - struct hwtstamp_config cfg; struct port *port =3D netdev_priv(netdev); =20 - cfg.flags =3D 0; - cfg.tx_type =3D port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + if (!cpu_is_ixp46x()) + return -EOPNOTSUPP; + + if (!netif_running(netdev)) + return -EINVAL; + + cfg->flags =3D 0; + cfg->tx_type =3D port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; =20 switch (port->hwts_rx_en) { case 0: - cfg.rx_filter =3D HWTSTAMP_FILTER_NONE; + cfg->rx_filter =3D HWTSTAMP_FILTER_NONE; break; case PTP_SLAVE_MODE: - cfg.rx_filter =3D HWTSTAMP_FILTER_PTP_V1_L4_SYNC; + cfg->rx_filter =3D HWTSTAMP_FILTER_PTP_V1_L4_SYNC; break; case PTP_MASTER_MODE: - cfg.rx_filter =3D HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; + cfg->rx_filter =3D HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; break; default: WARN_ON_ONCE(1); return -ERANGE; } =20 - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + return 0; } =20 static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, @@ -977,21 +984,6 @@ static void eth_set_mcast_list(struct net_device *dev) } =20 =20 -static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) -{ - if (!netif_running(dev)) - return -EINVAL; - - if (cpu_is_ixp46x()) { - if (cmd =3D=3D SIOCSHWTSTAMP) - return hwtstamp_set(dev, req); - if (cmd =3D=3D SIOCGHWTSTAMP) - return hwtstamp_get(dev, req); - } - - return phy_mii_ioctl(dev->phydev, req, cmd); -} - /* ethtool support */ =20 static void ixp4xx_get_drvinfo(struct net_device *dev, @@ -1376,9 +1368,11 @@ static const struct net_device_ops ixp4xx_netdev_ops= =3D { .ndo_stop =3D eth_close, .ndo_start_xmit =3D eth_xmit, .ndo_set_rx_mode =3D eth_set_mcast_list, - .ndo_eth_ioctl =3D eth_ioctl, + .ndo_eth_ioctl =3D phy_do_ioctl_running, .ndo_set_mac_address =3D eth_mac_addr, .ndo_validate_addr =3D eth_validate_addr, + .ndo_hwtstamp_get =3D ixp4xx_hwtstamp_get, + .ndo_hwtstamp_set =3D ixp4xx_hwtstamp_set, }; =20 static struct eth_plat_info *ixp4xx_of_get_platdata(struct device *dev) diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/etherne= t/xscale/ptp_ixp46x.c index 94203eb46e6b..93c64db22a69 100644 --- a/drivers/net/ethernet/xscale/ptp_ixp46x.c +++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c @@ -232,6 +232,9 @@ static struct ixp_clock ixp_clock; =20 int ixp46x_ptp_find(struct ixp46x_ts_regs *__iomem *regs, int *phc_index) { + if (!cpu_is_ixp46x()) + return -ENODEV; + *regs =3D ixp_clock.regs; *phc_index =3D ptp_clock_index(ixp_clock.ptp_clock); =20 diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fea7352e2a47..4e28fcbf13c7 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1577,6 +1577,11 @@ int macvlan_common_newlink(struct net *src_net, stru= ct net_device *dev, if (create) macvlan_port_destroy(port->dev); } + /* @dev might have been made visible before an error was detected. + * Make sure to observe an RCU grace period before our caller + * (rtnl_newlink()) frees it. + */ + synchronize_net(); return err; } EXPORT_SYMBOL_GPL(macvlan_common_newlink); diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c index fbe8483a07b5..c8c2c5dc46eb 100644 --- a/drivers/net/mctp/mctp-i2c.c +++ b/drivers/net/mctp/mctp-i2c.c @@ -243,6 +243,12 @@ static int mctp_i2c_slave_cb(struct i2c_client *client, return 0; =20 switch (event) { + case I2C_SLAVE_READ_REQUESTED: + case I2C_SLAVE_READ_PROCESSED: + /* MCTP I2C transport only uses writes */ + midev->rx_pos =3D 0; + *val =3D 0xff; + break; case I2C_SLAVE_WRITE_RECEIVED: if (midev->rx_pos < MCTP_I2C_BUFSZ) { midev->rx_buffer[midev->rx_pos] =3D *val; @@ -280,6 +286,9 @@ static int mctp_i2c_recv(struct mctp_i2c_dev *midev) size_t recvlen; int status; =20 + if (midev->rx_pos =3D=3D 0) + return 0; + /* + 1 for the PEC */ if (midev->rx_pos < MCTP_I2C_MINLEN + 1) { ndev->stats.rx_length_errors++; diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3fd7dccf0f9c..fe9e8483e8c5 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -320,7 +320,6 @@ config USB_NET_DM9601 config USB_NET_SR9700 tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices" depends on USB_USBNET - select CRC32 help This option adds support for CoreChip-sz SR9700 based USB 1.1 10/100 Ethernet adapters. diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index ff439ef535ac..98346cb4ece0 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -64,6 +64,16 @@ static const char driver_name[] =3D "catc"; #define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */ #define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */ =20 +/* + * USB endpoints. + */ + +enum catc_usb_ep { + CATC_USB_EP_CONTROL =3D 0, + CATC_USB_EP_BULK =3D 1, + CATC_USB_EP_INT_IN =3D 2, +}; + /* * Control requests. */ @@ -772,6 +782,13 @@ static int catc_probe(struct usb_interface *intf, cons= t struct usb_device_id *id u8 broadcast[ETH_ALEN]; u8 *macbuf; int pktsz, ret =3D -ENOMEM; + static const u8 bulk_ep_addr[] =3D { + CATC_USB_EP_BULK | USB_DIR_OUT, + CATC_USB_EP_BULK | USB_DIR_IN, + 0}; + static const u8 int_ep_addr[] =3D { + CATC_USB_EP_INT_IN | USB_DIR_IN, + 0}; =20 macbuf =3D kmalloc(ETH_ALEN, GFP_KERNEL); if (!macbuf) @@ -784,6 +801,14 @@ static int catc_probe(struct usb_interface *intf, cons= t struct usb_device_id *id goto fail_mem; } =20 + /* Verify that all required endpoints are present */ + if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || + !usb_check_int_endpoints(intf, int_ep_addr)) { + dev_err(dev, "Missing or invalid endpoints\n"); + ret =3D -ENODEV; + goto fail_mem; + } + netdev =3D alloc_etherdev(sizeof(struct catc)); if (!netdev) goto fail_mem; @@ -828,14 +853,14 @@ static int catc_probe(struct usb_interface *intf, con= st struct usb_device_id *id usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), NULL, NULL, 0, catc_ctrl_done, catc); =20 - usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1), - NULL, 0, catc_tx_done, catc); + usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, CATC_USB_= EP_BULK), + NULL, 0, catc_tx_done, catc); =20 - usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), - catc->rx_buf, pktsz, catc_rx_done, catc); + usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, CATC_USB_= EP_BULK), + catc->rx_buf, pktsz, catc_rx_done, catc); =20 - usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), - catc->irq_buf, 2, catc_irq_done, catc, 1); + usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, CATC_USB_E= P_INT_IN), + catc->irq_buf, 2, catc_irq_done, catc, 1); =20 if (!catc->is_f5u011) { u32 *buf; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index c9efb7df892e..e01d14f6c366 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -765,7 +765,6 @@ static void kaweth_set_rx_mode(struct net_device *net) =20 netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap); =20 - netif_stop_queue(net); =20 if (net->flags & IFF_PROMISC) { packet_filter_bitmap |=3D KAWETH_PACKET_FILTER_PROMISCUOUS; @@ -775,7 +774,6 @@ static void kaweth_set_rx_mode(struct net_device *net) } =20 kaweth->packet_filter_bitmap =3D packet_filter_bitmap; - netif_wake_queue(net); } =20 /**************************************************************** diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 121f1c15c679..4a6377ac3160 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2106,8 +2106,6 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) dev->mdiobus->phy_mask =3D ~(1 << 1); break; case ID_REV_CHIP_ID_7801_: - /* scan thru PHYAD[2..0] */ - dev->mdiobus->phy_mask =3D ~(0xFF); break; } =20 diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index c514483134f0..0f16a133c75d 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -31,6 +31,17 @@ static const char driver_name[] =3D "pegasus"; BMSR_100FULL | BMSR_ANEGCAPABLE) #define CARRIER_CHECK_DELAY (2 * HZ) =20 +/* + * USB endpoints. + */ + +enum pegasus_usb_ep { + PEGASUS_USB_EP_CONTROL =3D 0, + PEGASUS_USB_EP_BULK_IN =3D 1, + PEGASUS_USB_EP_BULK_OUT =3D 2, + PEGASUS_USB_EP_INT_IN =3D 3, +}; + static bool loopback; static bool mii_mode; static char *devid; @@ -545,7 +556,7 @@ static void read_bulk_callback(struct urb *urb) goto tl_sched; goon: usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), pegasus->rx_skb->data, PEGASUS_MTU, read_bulk_callback, pegasus); rx_status =3D usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); @@ -585,7 +596,7 @@ static void rx_fixup(struct tasklet_struct *t) return; } usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), pegasus->rx_skb->data, PEGASUS_MTU, read_bulk_callback, pegasus); try_again: @@ -713,7 +724,7 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *s= kb, ((__le16 *) pegasus->tx_buff)[0] =3D cpu_to_le16(l16); skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len); usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, - usb_sndbulkpipe(pegasus->usb, 2), + usb_sndbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_OUT), pegasus->tx_buff, count, write_bulk_callback, pegasus); if ((res =3D usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { @@ -840,7 +851,7 @@ static int pegasus_open(struct net_device *net) set_registers(pegasus, EthID, 6, net->dev_addr); =20 usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), + usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN), pegasus->rx_skb->data, PEGASUS_MTU, read_bulk_callback, pegasus); if ((res =3D usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { @@ -851,7 +862,7 @@ static int pegasus_open(struct net_device *net) } =20 usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, - usb_rcvintpipe(pegasus->usb, 3), + usb_rcvintpipe(pegasus->usb, PEGASUS_USB_EP_INT_IN), pegasus->intr_buff, sizeof(pegasus->intr_buff), intr_callback, pegasus, pegasus->intr_interval); if ((res =3D usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { @@ -1136,10 +1147,24 @@ static int pegasus_probe(struct usb_interface *intf, pegasus_t *pegasus; int dev_index =3D id - pegasus_ids; int res =3D -ENOMEM; + static const u8 bulk_ep_addr[] =3D { + PEGASUS_USB_EP_BULK_IN | USB_DIR_IN, + PEGASUS_USB_EP_BULK_OUT | USB_DIR_OUT, + 0}; + static const u8 int_ep_addr[] =3D { + PEGASUS_USB_EP_INT_IN | USB_DIR_IN, + 0}; =20 if (pegasus_blacklisted(dev)) return -ENODEV; =20 + /* Verify that all required endpoints are present */ + if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || + !usb_check_int_endpoints(intf, int_ep_addr)) { + dev_err(&intf->dev, "Missing or invalid endpoints\n"); + return -ENODEV; + } + net =3D alloc_etherdev(sizeof(struct pegasus)); if (!net) goto out; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 386376ceeda2..a2e3f9583def 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -2445,6 +2445,8 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct= tx_agg *agg) ret =3D usb_submit_urb(agg->urb, GFP_ATOMIC); if (ret < 0) usb_autopm_put_interface_async(tp->intf); + else + netif_trans_update(tp->netdev); =20 out_tx_fill: return ret; diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index 213b4817cfdf..e4d7bcd0d99c 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -18,7 +18,6 @@ #include #include #include -#include #include =20 #include "sr9700.h" @@ -265,31 +264,15 @@ static const struct ethtool_ops sr9700_ethtool_ops = =3D { static void sr9700_set_multicast(struct net_device *netdev) { struct usbnet *dev =3D netdev_priv(netdev); - /* We use the 20 byte dev->data for our 8 byte filter buffer - * to avoid allocating memory that is tricky to free later - */ - u8 *hashes =3D (u8 *)&dev->data; /* rx_ctl setting : enable, disable_long, disable_crc */ u8 rx_ctl =3D RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG; =20 - memset(hashes, 0x00, SR_MCAST_SIZE); - /* broadcast address */ - hashes[SR_MCAST_SIZE - 1] |=3D SR_MCAST_ADDR_FLAG; - if (netdev->flags & IFF_PROMISC) { + if (netdev->flags & IFF_PROMISC) rx_ctl |=3D RCR_PRMSC; - } else if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > SR_MCAST_MAX) { - rx_ctl |=3D RCR_RUNT; - } else if (!netdev_mc_empty(netdev)) { - struct netdev_hw_addr *ha; - - netdev_for_each_mc_addr(ha, netdev) { - u32 crc =3D ether_crc(ETH_ALEN, ha->addr) >> 26; - hashes[crc >> 3] |=3D 1 << (crc & 0x7); - } - } + else if (netdev->flags & IFF_ALLMULTI || !netdev_mc_empty(netdev)) + /* The chip has no multicast filter */ + rx_ctl |=3D RCR_ALL; =20 - sr_write_async(dev, SR_MAR, SR_MCAST_SIZE, hashes); sr_write_reg_async(dev, SR_RCR, rx_ctl); } =20 diff --git a/drivers/net/usb/sr9700.h b/drivers/net/usb/sr9700.h index ea2b4de621c8..c479908f7d82 100644 --- a/drivers/net/usb/sr9700.h +++ b/drivers/net/usb/sr9700.h @@ -104,9 +104,7 @@ #define WCR_LINKEN (1 << 5) /* Physical Address Reg */ #define SR_PAR 0x10 /* 0x10 ~ 0x15 6 bytes for PAR */ -/* Multicast Address Reg */ -#define SR_MAR 0x16 /* 0x16 ~ 0x1D 8 bytes for MAR */ -/* 0x1e unused */ +/* 0x16 --> 0x1E unused */ /* Phy Reset Reg */ #define SR_PRR 0x1F #define PRR_PHY_RST (1 << 0) @@ -161,9 +159,6 @@ /* parameters */ #define SR_SHARE_TIMEOUT 1000 #define SR_EEPROM_LEN 256 -#define SR_MCAST_SIZE 8 -#define SR_MCAST_ADDR_FLAG 0x80 -#define SR_MCAST_MAX 64 #define SR_TX_OVERHEAD 2 /* 2bytes header */ #define SR_RX_OVERHEAD 7 /* 3bytes header + 4crc tail */ =20 diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 5b01642ca44e..6b2d1e63855e 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2550,6 +2550,8 @@ fst_remove_one(struct pci_dev *pdev) =20 fst_disable_intr(card); free_irq(card->irq, card); + tasklet_kill(&fst_tx_task); + tasklet_kill(&fst_int_task); =20 iounmap(card->ctlmem); iounmap(card->mem); diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index fd50bb313b92..7176055cb38a 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -790,18 +790,14 @@ static void uhdlc_memclean(struct ucc_hdlc_private *p= riv) =20 if (priv->rx_buffer) { dma_free_coherent(priv->dev, - RX_BD_RING_LEN * MAX_RX_BUF_LENGTH, + (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH, priv->rx_buffer, priv->dma_rx_addr); priv->rx_buffer =3D NULL; priv->dma_rx_addr =3D 0; - } =20 - if (priv->tx_buffer) { - dma_free_coherent(priv->dev, - TX_BD_RING_LEN * MAX_RX_BUF_LENGTH, - priv->tx_buffer, priv->dma_tx_addr); priv->tx_buffer =3D NULL; priv->dma_tx_addr =3D 0; + } } =20 diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/= ath/ath10k/sdio.c index 850d999615a2..7d0a522e5402 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -2486,7 +2486,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) if (fast_dump) ath10k_bmi_start(ar); =20 + mutex_lock(&ar->dump_mutex); + + spin_lock_bh(&ar->data_lock); ar->stats.fw_crash_counter++; + spin_unlock_bh(&ar->data_lock); =20 ath10k_sdio_disable_intrs(ar); =20 @@ -2504,6 +2508,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) =20 ath10k_sdio_enable_intrs(ar); =20 + mutex_unlock(&ar->dump_mutex); + ath10k_core_start_recovery(ar); } =20 diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/a= th/ath10k/wmi.c index c7c96d210061..ee41f45b3426 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5283,8 +5283,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k = *ar, struct sk_buff *skb) struct ath10k_sta *arsta; u8 peer_addr[ETH_ALEN]; =20 - lockdep_assert_held(&ar->data_lock); - ev =3D (struct wmi_peer_sta_ps_state_chg_event *)skb->data; ether_addr_copy(peer_addr, ev->peer_macaddr.addr); =20 @@ -5299,7 +5297,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k = *ar, struct sk_buff *skb) } =20 arsta =3D (struct ath10k_sta *)sta->drv_priv; + spin_lock_bh(&ar->data_lock); arsta->peer_ps_state =3D __le32_to_cpu(ev->peer_ps_state); + spin_unlock_bh(&ar->data_lock); =20 exit: rcu_read_unlock(); diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/= ath/ath11k/core.c index 355424baeedd..9eb8887f84e7 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -789,6 +789,34 @@ static const struct dmi_system_id ath11k_pm_quirk_tabl= e[] =3D { DMI_MATCH(DMI_PRODUCT_NAME, "21F9"), }, }, + { + .driver_data =3D (void *)ATH11K_PM_WOW, + .matches =3D { /* Z13 G1 */ + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D2"), + }, + }, + { + .driver_data =3D (void *)ATH11K_PM_WOW, + .matches =3D { /* Z13 G1 */ + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D3"), + }, + }, + { + .driver_data =3D (void *)ATH11K_PM_WOW, + .matches =3D { /* Z16 G1 */ + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D4"), + }, + }, + { + .driver_data =3D (void *)ATH11K_PM_WOW, + .matches =3D { /* Z16 G1 */ + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21D5"), + }, + }, {} }; =20 diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/a= th/ath12k/wmi.c index 7e400a0e0eb1..fe920ecd25ba 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -3804,7 +3804,7 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base= *soc, =20 pref =3D soc->wmi_ab.preferred_hw_mode; =20 - if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) { + if (ath12k_hw_mode_pri_map[mode] <=3D ath12k_hw_mode_pri_map[pref]) { svc_rdy_ext->pref_hw_mode_caps =3D *hw_mode_caps; soc->wmi_ab.preferred_hw_mode =3D mode; } diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wir= eless/intel/ipw2x00/ipw2200.c index 820100cac491..76e67870f385 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -11384,7 +11384,13 @@ static const struct pci_device_id card_ids[] =3D { {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0}, - {PCI_VDEVICE(INTEL, 0x104f), 0}, + /* + * This ID conflicts with i40e, but the devices can be differentiated + * because i40e devices use PCI_CLASS_NETWORK_ETHERNET and ipw2200 + * devices use PCI_CLASS_NETWORK_OTHER. + */ + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x104f), + PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0}, {PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */ {PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */ {PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */ diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/w= ireless/intel/iwlegacy/3945-mac.c index 9eaf5ec133f9..5d61cebbdc40 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c @@ -3262,7 +3262,9 @@ il3945_store_measurement(struct device *d, struct dev= ice_attribute *attr, =20 D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n", type, params.channel, buf); + mutex_lock(&il->mutex); il3945_get_measurement(il, ¶ms, type); + mutex_unlock(&il->mutex); =20 return count; } diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/w= ireless/intel/iwlegacy/4965-mac.c index 75118e240619..b345fa225634 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -4612,7 +4612,9 @@ il4965_store_tx_power(struct device *d, struct device= _attribute *attr, if (ret) IL_INFO("%s is not in decimal form.\n", buf); else { + mutex_lock(&il->mutex); ret =3D il_set_tx_power(il, val, false); + mutex_unlock(&il->mutex); if (ret) IL_ERR("failed setting tx power (0x%08x).\n", ret); else diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/ne= t/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 9c97691e6038..60472c89fca3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1722,6 +1722,20 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *m= vm, =20 mvmvif =3D iwl_mvm_vif_from_mac80211(vif); =20 + /* + * len_low should be 2 + n*13 (where n is the number of descriptors. + * 13 is the size of a NoA descriptor). We can have either one or two + * descriptors. + */ + if (IWL_FW_CHECK(mvm, notif->noa_active && + notif->noa_attr.len_low !=3D 2 + + sizeof(struct ieee80211_p2p_noa_desc) && + notif->noa_attr.len_low !=3D 2 + + sizeof(struct ieee80211_p2p_noa_desc) * 2, + "Invalid noa_attr.len_low (%d)\n", + notif->noa_attr.len_low)) + return; + new_data =3D kzalloc(sizeof(*new_data), GFP_KERNEL); if (!new_data) return; diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/w= ireless/marvell/libertas/if_usb.c index 2240b4db8c03..d98c81539ba5 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -426,6 +426,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint= 8_t *payload, uint16_t nb goto tx_ret; } =20 + usb_kill_urb(cardp->tx_urb); + usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, usb_sndbulkpipe(cardp->udev, cardp->ep_out), diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wirele= ss/realtek/rtw88/main.c index c7396ae9256b..9a4c23163fba 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -710,10 +710,10 @@ void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt= _stat, u8 channel) } EXPORT_SYMBOL(rtw_set_rx_freq_band); =20 -void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period) +void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period) { rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE); - rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1); + rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period ? dtim_period - 1 := 0); } =20 void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel, diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wirele= ss/realtek/rtw88/main.h index c42ef8294d59..6e0e1c9c28f7 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -2154,7 +2154,7 @@ enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_sup= ported_band hw_band) } =20 void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel); -void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period); +void rtw_set_dtim_period(struct rtw_dev *rtwdev, u8 dtim_period); void rtw_get_channel_params(struct cfg80211_chan_def *chandef, struct rtw_channel_params *ch_param); bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target= ); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/w= ireless/realtek/rtw88/rtw8821cu.c index a019f4085e73..1f5af09aed99 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c @@ -37,6 +37,8 @@ static const struct usb_device_id rtw_8821cu_id_table[] = =3D { .driver_info =3D (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff), .driver_info =3D (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0105, 0xff, 0xff, 0xff), + .driver_info =3D (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Mercusys */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wi= reless/realtek/rtw88/rtw8822b.c index 99318a82b43f..e792d7c86699 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -1044,7 +1044,8 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwde= v, hal->antenna_tx =3D antenna_tx; hal->antenna_rx =3D antenna_rx; =20 - rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false); + if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) + rtw8822b_config_trx_mode(rtwdev, antenna_tx, antenna_rx, false); =20 return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireles= s/realtek/rtw89/pci.c index 33b2543ee4d2..1ac5d021893d 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -3856,6 +3856,7 @@ static int __maybe_unused rtw89_pci_resume(struct dev= ice *dev) rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1, B_AX_SEL_REQ_ENTR_L1); } + rtw89_pci_hci_ldo(rtwdev); rtw89_pci_l2_hci_ldo(rtwdev); rtw89_pci_filter_out(rtwdev); rtw89_pci_link_cfg(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireles= s/realtek/rtw89/wow.c index aa9efca04025..f558df21a2fd 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -100,6 +100,10 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_= dev *rtwdev) reason =3D rtw89_read8(rtwdev, wow_reason_reg); =20 switch (reason) { + case RTW89_WOW_RSN_RX_DISASSOC: + wakeup.disconnect =3D true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx disassoc\n"); + break; case RTW89_WOW_RSN_RX_DEAUTH: wakeup.disconnect =3D true; rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n"); diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireles= s/realtek/rtw89/wow.h index a2f7b2e3cdb4..fd85772ccb04 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.h +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -8,6 +8,7 @@ enum rtw89_wake_reason { RTW89_WOW_RSN_RX_PTK_REKEY =3D 0x1, RTW89_WOW_RSN_RX_GTK_REKEY =3D 0x2, + RTW89_WOW_RSN_RX_DISASSOC =3D 0x4, RTW89_WOW_RSN_RX_DEAUTH =3D 0x8, RTW89_WOW_RSN_DISCONNECT =3D 0x10, RTW89_WOW_RSN_RX_MAGIC_PKT =3D 0x21, diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xen= bus.c index a78a25b87240..61b547aab286 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -735,10 +735,11 @@ static void connect(struct backend_info *be) */ requested_num_queues =3D xenbus_read_unsigned(dev->otherend, "multi-queue-num-queues", 1); - if (requested_num_queues > xenvif_max_queues) { + if (requested_num_queues > xenvif_max_queues || + requested_num_queues =3D=3D 0) { /* buggy or malicious guest */ xenbus_dev_fatal(dev, -EINVAL, - "guest requested %u queues, exceeding the maximum of %u.", + "guest requested %u queues, but valid range is 1 - %u.", requested_num_queues, xenvif_max_queues); return; } diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index 3ae4b41c59ac..edf5514795fd 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -305,7 +305,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client) =20 r =3D request_threaded_irq(client->irq, NULL, nxp_nci_i2c_irq_thread_fn, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_ONESHOT, NXP_NCI_I2C_DRIVER_NAME, phy); if (r < 0) nfc_err(&client->dev, "Unable to register IRQ handler\n"); diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/n= tb_hw_switchtec.c index b5f93f07e22a..7f23f10ef64e 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c @@ -1202,7 +1202,8 @@ static void switchtec_ntb_init_mw(struct switchtec_nt= b *sndev) sndev->mmio_self_ctrl); =20 sndev->nr_lut_mw =3D ioread16(&sndev->mmio_self_ctrl->lut_table_entries); - sndev->nr_lut_mw =3D rounddown_pow_of_two(sndev->nr_lut_mw); + if (sndev->nr_lut_mw) + sndev->nr_lut_mw =3D rounddown_pow_of_two(sndev->nr_lut_mw); =20 dev_dbg(&sndev->stdev->dev, "MWs: %d direct, %d lut\n", sndev->nr_direct_mw, sndev->nr_lut_mw); @@ -1212,7 +1213,8 @@ static void switchtec_ntb_init_mw(struct switchtec_nt= b *sndev) =20 sndev->peer_nr_lut_mw =3D ioread16(&sndev->mmio_peer_ctrl->lut_table_entries); - sndev->peer_nr_lut_mw =3D rounddown_pow_of_two(sndev->peer_nr_lut_mw); + if (sndev->peer_nr_lut_mw) + sndev->peer_nr_lut_mw =3D rounddown_pow_of_two(sndev->peer_nr_lut_mw); =20 dev_dbg(&sndev->stdev->dev, "Peer MWs: %d direct, %d lut\n", sndev->peer_nr_direct_mw, sndev->peer_nr_lut_mw); @@ -1314,6 +1316,12 @@ static void switchtec_ntb_init_shared(struct switcht= ec_ntb *sndev) for (i =3D 0; i < sndev->nr_lut_mw; i++) { int idx =3D sndev->nr_direct_mw + i; =20 + if (idx >=3D MAX_MWS) { + dev_err(&sndev->stdev->dev, + "Total number of MW cannot be bigger than %d", MAX_MWS); + break; + } + sndev->self_shared->mw_sizes[idx] =3D LUT_SIZE; } } diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 76cc5b49a5f1..0087c23655c7 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1227,9 +1227,9 @@ static int ntb_transport_init_queue(struct ntb_transp= ort_ctx *nt, qp->tx_max_entry =3D tx_size / qp->tx_max_frame; =20 if (nt->debugfs_node_dir) { - char debugfs_name[4]; + char debugfs_name[8]; =20 - snprintf(debugfs_name, 4, "qp%d", qp_num); + snprintf(debugfs_name, sizeof(debugfs_name), "qp%d", qp_num); qp->debugfs_dir =3D debugfs_create_dir(debugfs_name, nt->debugfs_node_dir); =20 diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c index 839f10ca56ea..e5a7b031da2d 100644 --- a/drivers/nvdimm/nd_virtio.c +++ b/drivers/nvdimm/nd_virtio.c @@ -44,6 +44,8 @@ static int virtio_pmem_flush(struct nd_region *nd_region) unsigned long flags; int err, err1; =20 + guard(mutex)(&vpmem->flush_lock); + /* * Don't bother to submit the request to the device if the device is * not activated. @@ -53,7 +55,6 @@ static int virtio_pmem_flush(struct nd_region *nd_region) return -EIO; } =20 - might_sleep(); req_data =3D kmalloc(sizeof(*req_data), GFP_KERNEL); if (!req_data) return -ENOMEM; diff --git a/drivers/nvdimm/virtio_pmem.c b/drivers/nvdimm/virtio_pmem.c index a92eb172f0e7..4eebb2ec3cf9 100644 --- a/drivers/nvdimm/virtio_pmem.c +++ b/drivers/nvdimm/virtio_pmem.c @@ -49,6 +49,7 @@ static int virtio_pmem_probe(struct virtio_device *vdev) goto out_err; } =20 + mutex_init(&vpmem->flush_lock); vpmem->vdev =3D vdev; vdev->priv =3D vpmem; err =3D init_vq(vpmem); diff --git a/drivers/nvdimm/virtio_pmem.h b/drivers/nvdimm/virtio_pmem.h index 0dddefe594c4..f72cf17f9518 100644 --- a/drivers/nvdimm/virtio_pmem.h +++ b/drivers/nvdimm/virtio_pmem.h @@ -13,6 +13,7 @@ #include #include #include +#include #include =20 struct virtio_pmem_request { @@ -35,6 +36,9 @@ struct virtio_pmem { /* Virtio pmem request queue */ struct virtqueue *req_vq; =20 + /* Serialize flush requests to the device. */ + struct mutex flush_lock; + /* nvdimm bus registers virtio pmem device */ struct nvdimm_bus *nvdimm_bus; struct nvdimm_bus_descriptor nd_desc; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index dd00cc09ae5e..5b819bbd451a 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -724,6 +724,7 @@ static int nvmem_add_cells_from_dt(struct nvmem_device = *nvmem, struct device_nod kfree(info.name); if (ret) { of_node_put(child); + of_node_put(info.np); return ret; } } diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index aae4e8ef9e36..4b7e663feee3 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -800,11 +800,13 @@ static void __init of_unittest_property_copy(void) =20 new =3D __of_prop_dup(&p1, GFP_KERNEL); unittest(new && propcmp(&p1, new), "empty property didn't copy correctly\= n"); - __of_prop_free(new); + if (new) + __of_prop_free(new); =20 new =3D __of_prop_dup(&p2, GFP_KERNEL); unittest(new && propcmp(&p2, new), "non-empty property didn't copy correc= tly\n"); - __of_prop_free(new); + if (new) + __of_prop_free(new); #endif } =20 diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/co= ntroller/dwc/pcie-dw-rockchip.c index 8af7a837a061..615bb9b42c51 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -48,6 +48,8 @@ #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) #define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0) =20 +#define PCIE_TYPE0_HDR_DBI2_OFFSET 0x100000 + struct rockchip_pcie { struct dw_pcie pci; void __iomem *apb_base; @@ -198,6 +200,8 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *p= p) if (irq < 0) return irq; =20 + pci->dbi_base2 =3D pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; + ret =3D rockchip_pcie_init_irq_domain(rockchip); if (ret < 0) dev_err(dev, "failed to init irq domain\n"); @@ -211,6 +215,10 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *= pp) rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, PCIE_CLIENT_GENERAL_CONTROL); =20 + /* Disable Root Ports BAR0 and BAR1 as they report bogus size */ + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0); + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0); + return 0; } =20 diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controlle= r/pcie-mediatek.c index 48372013f26d..82e575e4d387 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -587,8 +587,10 @@ static int mtk_pcie_init_irq_domain(struct mtk_pcie_po= rt *port, =20 if (IS_ENABLED(CONFIG_PCI_MSI)) { ret =3D mtk_pcie_allocate_msi_domains(port); - if (ret) + if (ret) { + irq_domain_remove(port->irq_domain); return ret; + } } =20 return 0; diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-e= p-cfs.c index c28c3f094496..5b64203f100f 100644 --- a/drivers/pci/endpoint/pci-ep-cfs.c +++ b/drivers/pci/endpoint/pci-ep-cfs.c @@ -65,8 +65,8 @@ static int pci_secondary_epc_epf_link(struct config_item = *epf_item, return 0; } =20 -static void pci_secondary_epc_epf_unlink(struct config_item *epc_item, - struct config_item *epf_item) +static void pci_secondary_epc_epf_unlink(struct config_item *epf_item, + struct config_item *epc_item) { struct pci_epf_group *epf_group =3D to_pci_epf_group(epf_item->ci_parent); struct pci_epc_group *epc_group =3D to_pci_epc_group(epc_item); @@ -126,8 +126,8 @@ static int pci_primary_epc_epf_link(struct config_item = *epf_item, return 0; } =20 -static void pci_primary_epc_epf_unlink(struct config_item *epc_item, - struct config_item *epf_item) +static void pci_primary_epc_epf_unlink(struct config_item *epf_item, + struct config_item *epc_item) { struct pci_epf_group *epf_group =3D to_pci_epf_group(epf_item->ci_parent); struct pci_epc_group *epc_group =3D to_pci_epc_group(epc_item); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index f97c4f0e1c7a..b8bce45a5998 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -447,7 +447,9 @@ static ssize_t sriov_numvfs_store(struct device *dev, =20 if (num_vfs =3D=3D 0) { /* disable VFs */ + pci_lock_rescan_remove(); ret =3D pdev->driver->sriov_configure(pdev, 0); + pci_unlock_rescan_remove(); goto exit; } =20 @@ -459,7 +461,9 @@ static ssize_t sriov_numvfs_store(struct device *dev, goto exit; } =20 + pci_lock_rescan_remove(); ret =3D pdev->driver->sriov_configure(pdev, num_vfs); + pci_unlock_rescan_remove(); if (ret < 0) goto exit; =20 @@ -581,18 +585,15 @@ static int sriov_add_vfs(struct pci_dev *dev, u16 num= _vfs) if (dev->no_vf_scan) return 0; =20 - pci_lock_rescan_remove(); for (i =3D 0; i < num_vfs; i++) { rc =3D pci_iov_add_virtfn(dev, i); if (rc) goto failed; } - pci_unlock_rescan_remove(); return 0; failed: while (i--) pci_iov_remove_virtfn(dev, i); - pci_unlock_rescan_remove(); =20 return rc; } @@ -712,10 +713,8 @@ static void sriov_del_vfs(struct pci_dev *dev) struct pci_sriov *iov =3D dev->sriov; int i; =20 - pci_lock_rescan_remove(); for (i =3D 0; i < iov->num_VFs; i++) pci_iov_remove_virtfn(dev, i); - pci_unlock_rescan_remove(); } =20 static void sriov_disable(struct pci_dev *dev) diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index b638731aa5ff..f6f4a778a986 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -737,7 +737,7 @@ static int msix_capability_init(struct pci_dev *dev, st= ruct msix_entry *entries, =20 ret =3D msix_setup_interrupts(dev, entries, nvec, affd); if (ret) - goto out_disable; + goto out_unmap; =20 /* Disable INTX */ pci_intx_for_msi(dev, 0); @@ -756,6 +756,8 @@ static int msix_capability_init(struct pci_dev *dev, st= ruct msix_entry *entries, pcibios_free_irq(dev); return 0; =20 +out_unmap: + iounmap(dev->msix_base); out_disable: dev->msix_enabled =3D 0; pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_= ENABLE, 0); diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 0f1e431bbfc2..f97ac18a8dc8 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct = kobject *kobj, ret =3D vm_insert_page(vma, vaddr, virt_to_page(kaddr)); if (ret) { gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len); + percpu_ref_put(ref); return ret; } percpu_ref_get(ref); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 61bded8623d2..508873c526e7 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -246,21 +246,6 @@ static acpi_status decode_type1_hpx_record(union acpi_= object *record, return AE_OK; } =20 -static bool pcie_root_rcb_set(struct pci_dev *dev) -{ - struct pci_dev *rp =3D pcie_find_root_port(dev); - u16 lnkctl; - - if (!rp) - return false; - - pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl); - if (lnkctl & PCI_EXP_LNKCTL_RCB) - return true; - - return false; -} - /* _HPX PCI Express Setting Record (Type 2) */ struct hpx_type2 { u32 revision; @@ -286,6 +271,7 @@ static void program_hpx_type2(struct pci_dev *dev, stru= ct hpx_type2 *hpx) { int pos; u32 reg32; + const struct pci_host_bridge *host; =20 if (!hpx) return; @@ -293,6 +279,15 @@ static void program_hpx_type2(struct pci_dev *dev, str= uct hpx_type2 *hpx) if (!pci_is_pcie(dev)) return; =20 + host =3D pci_find_host_bridge(dev->bus); + + /* + * Only do the _HPX Type 2 programming if OS owns PCIe native + * hotplug but not AER. + */ + if (!host->native_pcie_hotplug || host->native_aer) + return; + if (hpx->revision > 1) { pci_warn(dev, "PCIe settings rev %d not supported\n", hpx->revision); @@ -300,33 +295,27 @@ static void program_hpx_type2(struct pci_dev *dev, st= ruct hpx_type2 *hpx) } =20 /* - * Don't allow _HPX to change MPS or MRRS settings. We manage - * those to make sure they're consistent with the rest of the - * platform. + * We only allow _HPX to program DEVCTL bits related to AER, namely + * PCI_EXP_DEVCTL_CERE, PCI_EXP_DEVCTL_NFERE, PCI_EXP_DEVCTL_FERE, + * and PCI_EXP_DEVCTL_URRE. + * + * The rest of DEVCTL is managed by the OS to make sure it's + * consistent with the rest of the platform. */ - hpx->pci_exp_devctl_and |=3D PCI_EXP_DEVCTL_PAYLOAD | - PCI_EXP_DEVCTL_READRQ; - hpx->pci_exp_devctl_or &=3D ~(PCI_EXP_DEVCTL_PAYLOAD | - PCI_EXP_DEVCTL_READRQ); + hpx->pci_exp_devctl_and |=3D ~PCI_EXP_AER_FLAGS; + hpx->pci_exp_devctl_or &=3D PCI_EXP_AER_FLAGS; =20 /* Initialize Device Control Register */ pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or); =20 - /* Initialize Link Control Register */ + /* Log if _HPX attempts to modify Link Control Register */ if (pcie_cap_has_lnkctl(dev)) { - - /* - * If the Root Port supports Read Completion Boundary of - * 128, set RCB to 128. Otherwise, clear it. - */ - hpx->pci_exp_lnkctl_and |=3D PCI_EXP_LNKCTL_RCB; - hpx->pci_exp_lnkctl_or &=3D ~PCI_EXP_LNKCTL_RCB; - if (pcie_root_rcb_set(dev)) - hpx->pci_exp_lnkctl_or |=3D PCI_EXP_LNKCTL_RCB; - - pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, - ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or); + if (hpx->pci_exp_lnkctl_and !=3D 0xffff || + hpx->pci_exp_lnkctl_or !=3D 0) + pci_info(dev, "_HPX attempts Link Control setting (AND %#06x OR %#06x)\= n", + hpx->pci_exp_lnkctl_and, + hpx->pci_exp_lnkctl_or); } =20 /* Find Advanced Error Reporting Enhanced Capability */ diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 8c941d6267a5..b7a6d8a28fe9 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1668,6 +1668,14 @@ static int pci_dma_configure(struct device *dev) ret =3D acpi_dma_configure(dev, acpi_get_dma_attr(adev)); } =20 + /* + * Attempt to enable ACS regardless of capability because some Root + * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have + * the standard ACS capability but still support ACS via those + * quirks. + */ + pci_enable_acs(to_pci_dev(dev)); + pci_put_host_bridge_device(bridge); =20 if (!ret && !driver->driver_managed_dma) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9a3f6bb60eb4..d7d7913eb0ee 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -986,7 +986,7 @@ static void pci_std_enable_acs(struct pci_dev *dev) * pci_enable_acs - enable ACS if hardware support it * @dev: the PCI device */ -static void pci_enable_acs(struct pci_dev *dev) +void pci_enable_acs(struct pci_dev *dev) { if (!pci_acs_enable) goto disable_acs_redir; @@ -1427,6 +1427,9 @@ static int pci_set_low_power_state(struct pci_dev *de= v, pci_power_t state, bool || (state =3D=3D PCI_D2 && !dev->d2_support)) return -EIO; =20 + if (dev->current_state =3D=3D state) + return 0; + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); if (PCI_POSSIBLE_ERROR(pmcsr)) { pci_err(dev, "Unable to change power state from %s to %s, device inacces= sible\n", @@ -3758,14 +3761,6 @@ bool pci_acs_path_enabled(struct pci_dev *start, void pci_acs_init(struct pci_dev *dev) { dev->acs_cap =3D pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); - - /* - * Attempt to enable ACS regardless of capability because some Root - * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have - * the standard ACS capability but still support ACS via those - * quirks. - */ - pci_enable_acs(dev); } =20 /** @@ -5790,10 +5785,9 @@ static int pci_bus_trylock(struct pci_bus *bus) /* Do any devices on or below this slot prevent a bus reset? */ static bool pci_slot_resettable(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge =3D slot->bus->self; =20 - if (slot->bus->self && - (slot->bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) + if (bridge && (bridge->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) return false; =20 list_for_each_entry(dev, &slot->bus->devices, bus_list) { @@ -5810,7 +5804,10 @@ static bool pci_slot_resettable(struct pci_slot *slo= t) /* Lock devices from the top of the tree down */ static void pci_slot_lock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge =3D slot->bus->self; + + if (bridge) + pci_dev_lock(bridge); =20 list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot !=3D slot) @@ -5825,7 +5822,7 @@ static void pci_slot_lock(struct pci_slot *slot) /* Unlock devices from the bottom of the tree up */ static void pci_slot_unlock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge =3D slot->bus->self; =20 list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot !=3D slot) @@ -5835,21 +5832,25 @@ static void pci_slot_unlock(struct pci_slot *slot) else pci_dev_unlock(dev); } + + if (bridge) + pci_dev_unlock(bridge); } =20 /* Return 1 on successful lock, 0 on contention */ static int pci_slot_trylock(struct pci_slot *slot) { - struct pci_dev *dev; + struct pci_dev *dev, *bridge =3D slot->bus->self; + + if (bridge && !pci_dev_trylock(bridge)) + return 0; =20 list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot !=3D slot) continue; if (dev->subordinate) { - if (!pci_bus_trylock(dev->subordinate)) { - pci_dev_unlock(dev); + if (!pci_bus_trylock(dev->subordinate)) goto unlock; - } } else if (!pci_dev_trylock(dev)) goto unlock; } @@ -5865,6 +5866,9 @@ static int pci_slot_trylock(struct pci_slot *slot) else pci_dev_unlock(dev); } + + if (bridge) + pci_dev_unlock(bridge); return 0; } =20 diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d69a17947ffc..485f917641e1 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -22,6 +22,31 @@ */ #define PCIE_PME_TO_L2_TIMEOUT_US 10000 =20 +/* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ +#define PCIE_MSG_TYPE_R_RC 0 +#define PCIE_MSG_TYPE_R_ADDR 1 +#define PCIE_MSG_TYPE_R_ID 2 +#define PCIE_MSG_TYPE_R_BC 3 +#define PCIE_MSG_TYPE_R_LOCAL 4 +#define PCIE_MSG_TYPE_R_GATHER 5 + +/* INTx Mechanism Messages; PCIe r6.0, sec 2.2.8.1 */ +#define PCIE_MSG_CODE_ASSERT_INTA 0x20 +#define PCIE_MSG_CODE_ASSERT_INTB 0x21 +#define PCIE_MSG_CODE_ASSERT_INTC 0x22 +#define PCIE_MSG_CODE_ASSERT_INTD 0x23 +#define PCIE_MSG_CODE_DEASSERT_INTA 0x24 +#define PCIE_MSG_CODE_DEASSERT_INTB 0x25 +#define PCIE_MSG_CODE_DEASSERT_INTC 0x26 +#define PCIE_MSG_CODE_DEASSERT_INTD 0x27 + +#define PCI_BUS_BRIDGE_IO_WINDOW 0 +#define PCI_BUS_BRIDGE_MEM_WINDOW 1 +#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW 2 + +#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ + PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; =20 @@ -530,6 +555,7 @@ static inline resource_size_t pci_resource_alignment(st= ruct pci_dev *dev, } =20 void pci_acs_init(struct pci_dev *dev); +void pci_enable_acs(struct pci_dev *dev); #ifdef CONFIG_PCI_QUIRKS int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); int pci_dev_specific_enable_acs(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 8e700020ee0b..42a0f86b72fa 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c @@ -218,9 +218,6 @@ void pcie_ecrc_get_policy(char *str) } #endif /* CONFIG_PCIE_ECRC */ =20 -#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) - int pcie_aer_is_native(struct pci_dev *dev) { struct pci_host_bridge *host =3D pci_find_host_bridge(dev->bus); diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index d6e5fef54c3b..dac3ba1b2552 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -554,10 +554,10 @@ static int pcie_port_remove_service(struct device *de= v) =20 pciedev =3D to_pcie_device(dev); driver =3D to_service_driver(dev->driver); - if (driver && driver->remove) { + if (driver && driver->remove) driver->remove(pciedev); - put_device(dev); - } + + put_device(dev); return 0; } =20 diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5557290b63dc..cc56bf47c4a3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -344,64 +344,12 @@ static void pci_read_bases(struct pci_dev *dev, unsig= ned int howmany, int rom) } } =20 -static void pci_read_bridge_windows(struct pci_dev *bridge) +static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res, + bool log) { - u16 io; - u32 pmem, tmp; - - pci_read_config_word(bridge, PCI_IO_BASE, &io); - if (!io) { - pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0); - pci_read_config_word(bridge, PCI_IO_BASE, &io); - pci_write_config_word(bridge, PCI_IO_BASE, 0x0); - } - if (io) - bridge->io_window =3D 1; - - /* - * DECchip 21050 pass 2 errata: the bridge may miss an address - * disconnect boundary by one PCI data phase. Workaround: do not - * use prefetching on this device. - */ - if (bridge->vendor =3D=3D PCI_VENDOR_ID_DEC && bridge->device =3D=3D 0x00= 01) - return; - - pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); - if (!pmem) { - pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, - 0xffe0fff0); - pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); - pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); - } - if (!pmem) - return; - - bridge->pref_window =3D 1; - - if ((pmem & PCI_PREF_RANGE_TYPE_MASK) =3D=3D PCI_PREF_RANGE_TYPE_64) { - - /* - * Bridge claims to have a 64-bit prefetchable memory - * window; verify that the upper bits are actually - * writable. - */ - pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &pmem); - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, - 0xffffffff); - pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, pmem); - if (tmp) - bridge->pref_64_window =3D 1; - } -} - -static void pci_read_bridge_io(struct pci_bus *child) -{ - struct pci_dev *dev =3D child->self; u8 io_base_lo, io_limit_lo; unsigned long io_mask, io_granularity, base, limit; struct pci_bus_region region; - struct resource *res; =20 io_mask =3D PCI_IO_RANGE_MASK; io_granularity =3D 0x1000; @@ -411,7 +359,6 @@ static void pci_read_bridge_io(struct pci_bus *child) io_granularity =3D 0x400; } =20 - res =3D child->resource[0]; pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo); base =3D (io_base_lo & io_mask) << 8; @@ -431,19 +378,18 @@ static void pci_read_bridge_io(struct pci_bus *child) region.start =3D base; region.end =3D limit + io_granularity - 1; pcibios_bus_to_resource(dev->bus, res, ®ion); - pci_info(dev, " bridge window %pR\n", res); + if (log) + pci_info(dev, " bridge window %pR\n", res); } } =20 -static void pci_read_bridge_mmio(struct pci_bus *child) +static void pci_read_bridge_mmio(struct pci_dev *dev, struct resource *res, + bool log) { - struct pci_dev *dev =3D child->self; u16 mem_base_lo, mem_limit_lo; unsigned long base, limit; struct pci_bus_region region; - struct resource *res; =20 - res =3D child->resource[1]; pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo); base =3D ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16; @@ -453,20 +399,19 @@ static void pci_read_bridge_mmio(struct pci_bus *chil= d) region.start =3D base; region.end =3D limit + 0xfffff; pcibios_bus_to_resource(dev->bus, res, ®ion); - pci_info(dev, " bridge window %pR\n", res); + if (log) + pci_info(dev, " bridge window %pR\n", res); } } =20 -static void pci_read_bridge_mmio_pref(struct pci_bus *child) +static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource= *res, + bool log) { - struct pci_dev *dev =3D child->self; u16 mem_base_lo, mem_limit_lo; u64 base64, limit64; pci_bus_addr_t base, limit; struct pci_bus_region region; - struct resource *res; =20 - res =3D child->resource[2]; pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); base64 =3D (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; @@ -506,8 +451,75 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *= child) region.start =3D base; region.end =3D limit + 0xfffff; pcibios_bus_to_resource(dev->bus, res, ®ion); - pci_info(dev, " bridge window %pR\n", res); + if (log) + pci_info(dev, " bridge window %pR\n", res); + } +} + +static void pci_read_bridge_windows(struct pci_dev *bridge) +{ + u32 buses; + u16 io; + u32 pmem, tmp; + struct resource res; + + pci_read_config_dword(bridge, PCI_PRIMARY_BUS, &buses); + res.flags =3D IORESOURCE_BUS; + res.start =3D (buses >> 8) & 0xff; + res.end =3D (buses >> 16) & 0xff; + pci_info(bridge, "PCI bridge to %pR%s\n", &res, + bridge->transparent ? " (subtractive decode)" : ""); + + pci_read_config_word(bridge, PCI_IO_BASE, &io); + if (!io) { + pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0); + pci_read_config_word(bridge, PCI_IO_BASE, &io); + pci_write_config_word(bridge, PCI_IO_BASE, 0x0); + } + if (io) { + bridge->io_window =3D 1; + pci_read_bridge_io(bridge, &res, true); } + + pci_read_bridge_mmio(bridge, &res, true); + + /* + * DECchip 21050 pass 2 errata: the bridge may miss an address + * disconnect boundary by one PCI data phase. Workaround: do not + * use prefetching on this device. + */ + if (bridge->vendor =3D=3D PCI_VENDOR_ID_DEC && bridge->device =3D=3D 0x00= 01) + return; + + pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); + if (!pmem) { + pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, + 0xffe0fff0); + pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); + pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); + } + if (!pmem) + return; + + bridge->pref_window =3D 1; + + if ((pmem & PCI_PREF_RANGE_TYPE_MASK) =3D=3D PCI_PREF_RANGE_TYPE_64) { + + /* + * Bridge claims to have a 64-bit prefetchable memory + * window; verify that the upper bits are actually + * writable. + */ + pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &pmem); + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, + 0xffffffff); + pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp); + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, pmem); + if (tmp) + bridge->pref_64_window =3D 1; + } + + pci_read_bridge_mmio_pref(bridge, &res, true); } =20 void pci_read_bridge_bases(struct pci_bus *child) @@ -527,9 +539,13 @@ void pci_read_bridge_bases(struct pci_bus *child) for (i =3D 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) child->resource[i] =3D &dev->resource[PCI_BRIDGE_RESOURCES+i]; =20 - pci_read_bridge_io(child); - pci_read_bridge_mmio(child); - pci_read_bridge_mmio_pref(child); + pci_read_bridge_io(child->self, + child->resource[PCI_BUS_BRIDGE_IO_WINDOW], false); + pci_read_bridge_mmio(child->self, + child->resource[PCI_BUS_BRIDGE_MEM_WINDOW], false); + pci_read_bridge_mmio_pref(child->self, + child->resource[PCI_BUS_BRIDGE_PREF_MEM_WINDOW], + false); =20 if (dev->transparent) { pci_bus_for_each_resource(child->parent, res) { @@ -2101,7 +2117,8 @@ int pci_configure_extended_tags(struct pci_dev *dev, = void *ign) u16 ctl; int ret; =20 - if (!pci_is_pcie(dev)) + /* PCI_EXP_DEVCTL_EXT_TAG is RsvdP in VFs */ + if (!pci_is_pcie(dev) || dev->is_virtfn) return 0; =20 ret =3D pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); @@ -2287,6 +2304,37 @@ static void pci_configure_serr(struct pci_dev *dev) } } =20 +static void pci_configure_rcb(struct pci_dev *dev) +{ + struct pci_dev *rp; + u16 rp_lnkctl; + + /* + * Per PCIe r7.0, sec 7.5.3.7, RCB is only meaningful in Root Ports + * (where it is read-only), Endpoints, and Bridges. It may only be + * set for Endpoints and Bridges if it is set in the Root Port. For + * Endpoints, it is 'RsvdP' for Virtual Functions. + */ + if (!pci_is_pcie(dev) || + pci_pcie_type(dev) =3D=3D PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(dev) =3D=3D PCI_EXP_TYPE_UPSTREAM || + pci_pcie_type(dev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM || + pci_pcie_type(dev) =3D=3D PCI_EXP_TYPE_RC_EC || + dev->is_virtfn) + return; + + /* Root Port often not visible to virtualized guests */ + rp =3D pcie_find_root_port(dev); + if (!rp) + return; + + pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &rp_lnkctl); + pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_RCB, + (rp_lnkctl & PCI_EXP_LNKCTL_RCB) ? + PCI_EXP_LNKCTL_RCB : 0); +} + static void pci_configure_device(struct pci_dev *dev) { pci_configure_mps(dev); @@ -2295,6 +2343,7 @@ static void pci_configure_device(struct pci_dev *dev) pci_configure_ltr(dev); pci_configure_eetlp_prefix(dev); pci_configure_serr(dev); + pci_configure_rcb(dev); =20 pci_acpi_program_hp_params(dev); } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 30a5f809ee79..cab4cdbb3138 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3741,6 +3741,14 @@ static void quirk_no_bus_reset(struct pci_dev *dev) dev->dev_flags |=3D PCI_DEV_FLAGS_NO_BUS_RESET; } =20 +/* + * After asserting Secondary Bus Reset to downstream devices via a GB10 + * Root Port, the link may not retrain correctly. + * https://lore.kernel.org/r/20251113084441.2124737-1-Johnny-CC.Chang@medi= atek.com + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x22CE, quirk_no_bus_reset); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x22D0, quirk_no_bus_reset); + /* * Some NVIDIA GPU devices do not work with bus reset, SBR needs to be * prevented for those affected devices. @@ -3784,6 +3792,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa10= 0, quirk_no_bus_reset); */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0xb005, quirk_no_bus_reset); =20 +/* + * Reports from users making use of PCI device assignment with ASM1164 + * controllers indicate an issue with bus reset where the device fails to + * retrain. The issue appears more common in configurations with multiple + * controllers. The device does indicate PM reset support (NoSoftRst-), + * therefore this still leaves a viable reset method. + * https://forum.proxmox.com/threads/problems-with-pcie-passthrough-with-t= wo-identical-devices.149003/ + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1164, quirk_no_bus_reset= ); + static void quirk_no_pm_reset(struct pci_dev *dev) { /* @@ -5100,6 +5118,10 @@ static const struct pci_dev_acs_enabled { { PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs }, /* QCOM SA8775P root port */ { PCI_VENDOR_ID_QCOM, 0x0115, pci_quirk_qcom_rp_acs }, + /* QCOM Hamoa root port */ + { PCI_VENDOR_ID_QCOM, 0x0111, pci_quirk_qcom_rp_acs }, + /* QCOM Glymur root port */ + { PCI_VENDOR_ID_QCOM, 0x0120, pci_quirk_qcom_rp_acs }, /* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */ { PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs }, /* Intel PCH root ports */ @@ -5573,6 +5595,7 @@ static void quirk_no_ext_tags(struct pci_dev *pdev) pci_walk_bus(bridge->bus, pci_configure_extended_tags, NULL); } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1004, quirk_no_ext_tags); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1005, quirk_no_ext_tags); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0132, quirk_no_ext_ta= gs); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0140, quirk_no_ext_ta= gs); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0141, quirk_no_ext_ta= gs); @@ -6180,6 +6203,10 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0x23= 03, pci_fixup_pericom_acs_store_forward); DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0x2303, pci_fixup_pericom_acs_store_forward); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0xb404, + pci_fixup_pericom_acs_store_forward); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0xb404, + pci_fixup_pericom_acs_store_forward); =20 static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) { diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 77aa37de5988..9ca6fd740210 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -205,6 +205,7 @@ enum cmn_model { enum cmn_part { PART_CMN600 =3D 0x434, PART_CMN650 =3D 0x436, + PART_CMN600AE =3D 0x438, PART_CMN700 =3D 0x43c, PART_CI700 =3D 0x43a, }; @@ -2167,6 +2168,9 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsi= gned int rgn_offset) reg =3D readq_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_01); part =3D FIELD_GET(CMN_CFGM_PID0_PART_0, reg); part |=3D FIELD_GET(CMN_CFGM_PID1_PART_1, reg) << 8; + /* 600AE is close enough that it's not really worth more complexity */ + if (part =3D=3D PART_CMN600AE) + part =3D PART_CMN600; if (cmn->part && cmn->part !=3D part) dev_warn(cmn->dev, "Firmware binding mismatch: expected part number 0x%x, found 0x%x\n", @@ -2307,6 +2311,15 @@ static int arm_cmn_discover(struct arm_cmn *cmn, uns= igned int rgn_offset) arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn); dn->portid_bits =3D xp->portid_bits; dn->deviceid_bits =3D xp->deviceid_bits; + /* + * Logical IDs are assigned from 0 per node type, so as + * soon as we see one bigger than expected, we can assume + * there are more than we can cope with. + */ + if (dn->logid > CMN_MAX_NODES_PER_EVENT) { + dev_err(cmn->dev, "Node ID invalid for supported CMN versions: %d\n", = dn->logid); + return -ENODEV; + } =20 switch (dn->type) { case CMN_TYPE_DTC: @@ -2355,7 +2368,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsi= gned int rgn_offset) break; /* Something has gone horribly wrong */ default: - dev_err(cmn->dev, "invalid device node type: 0x%x\n", dn->type); + dev_err(cmn->dev, "Device node type invalid for supported CMN versions= : 0x%x\n", dn->type); return -ENODEV; } } @@ -2383,6 +2396,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, uns= igned int rgn_offset) cmn->mesh_x =3D cmn->num_xps; cmn->mesh_y =3D cmn->num_xps / cmn->mesh_x; =20 + if (max(cmn->mesh_x, cmn->mesh_y) > CMN_MAX_DIMENSION) { + dev_err(cmn->dev, "Mesh size invalid for supported CMN versions: %dx%d\n= ", cmn->mesh_x, cmn->mesh_y); + return -ENODEV; + } /* 1x1 config plays havoc with XP event encodings */ if (cmn->num_xps =3D=3D 1) dev_warn(cmn->dev, "1x1 config not fully supported, translate XP events = manually\n"); diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index affa78376b6a..5164078c06d2 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -102,6 +102,8 @@ struct arm_spe_pmu { /* Keep track of our dynamic hotplug state */ static enum cpuhp_state arm_spe_pmu_online; =20 +static void arm_spe_pmu_stop(struct perf_event *event, int flags); + enum arm_spe_pmu_buf_fault_action { SPE_PMU_BUF_FAULT_ACT_SPURIOUS, SPE_PMU_BUF_FAULT_ACT_FATAL, @@ -519,8 +521,8 @@ static u64 arm_spe_pmu_next_off(struct perf_output_hand= le *handle) return limit; } =20 -static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handl= e, - struct perf_event *event) +static int arm_spe_perf_aux_output_begin(struct perf_output_handle *handle, + struct perf_event *event) { u64 base, limit; struct arm_spe_pmu_buf *buf; @@ -528,7 +530,6 @@ static void arm_spe_perf_aux_output_begin(struct perf_o= utput_handle *handle, /* Start a new aux session */ buf =3D perf_aux_output_begin(handle, event); if (!buf) { - event->hw.state |=3D PERF_HES_STOPPED; /* * We still need to clear the limit pointer, since the * profiler might only be disabled by virtue of a fault. @@ -548,6 +549,7 @@ static void arm_spe_perf_aux_output_begin(struct perf_o= utput_handle *handle, =20 out_write_limit: write_sysreg_s(limit, SYS_PMBLIMITR_EL1); + return (limit & PMBLIMITR_EL1_E) ? 0 : -EIO; } =20 static void arm_spe_perf_aux_output_end(struct perf_output_handle *handle) @@ -687,7 +689,10 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, vo= id *dev) * when we get to it. */ if (!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)) { - arm_spe_perf_aux_output_begin(handle, event); + if (arm_spe_perf_aux_output_begin(handle, event)) { + arm_spe_pmu_stop(event, PERF_EF_UPDATE); + break; + } isb(); } break; @@ -782,9 +787,10 @@ static void arm_spe_pmu_start(struct perf_event *event= , int flags) struct perf_output_handle *handle =3D this_cpu_ptr(spe_pmu->handle); =20 hwc->state =3D 0; - arm_spe_perf_aux_output_begin(handle, event); - if (hwc->state) + if (arm_spe_perf_aux_output_begin(handle, event)) { + arm_spe_pmu_stop(event, 0); return; + } =20 reg =3D arm_spe_event_to_pmsfcr(event); write_sysreg_s(reg, SYS_PMSFCR_EL1); diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c index c03df0f52889..3e1a4f900611 100644 --- a/drivers/perf/cxl_pmu.c +++ b/drivers/perf/cxl_pmu.c @@ -885,7 +885,7 @@ static int cxl_pmu_probe(struct device *dev) if (!irq_name) return -ENOMEM; =20 - rc =3D devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_ONESHOT, + rc =3D devm_request_irq(dev, irq, cxl_pmu_irq, IRQF_SHARED | IRQF_NO_THRE= AD, irq_name, info); if (rc) return rc; diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/frees= cale/phy-fsl-imx8mq-usb.c index 043063699e06..41194083e358 100644 --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c @@ -411,6 +411,7 @@ static struct platform_driver imx8mq_usb_phy_driver =3D= { .driver =3D { .name =3D "imx8mq-usb-phy", .of_match_table =3D imx8mq_usb_phy_of_match, + .suppress_bind_attrs =3D true, } }; module_platform_driver(imx8mq_usb_phy_driver); diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marve= ll/phy-mvebu-cp110-utmi.c index 4922a5f3327d..30391d0d7d4b 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c @@ -326,7 +326,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_d= evice *pdev) return -ENOMEM; } =20 - port->dr_mode =3D of_usb_get_dr_mode_by_phy(child, -1); + port->dr_mode =3D of_usb_get_dr_mode_by_phy(child, 0); if ((port->dr_mode !=3D USB_DR_MODE_HOST) && (port->dr_mode !=3D USB_DR_MODE_PERIPHERAL)) { dev_err(&pdev->dev, diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctr= l-equilibrium.c index 5b5ddf7e5d0e..d7c89c310b37 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.c +++ b/drivers/pinctrl/pinctrl-equilibrium.c @@ -850,6 +850,7 @@ static int pinbank_init(struct device_node *np, =20 bank->pin_base =3D spec.args[1]; bank->nr_pins =3D spec.args[2]; + of_node_put(spec.np); =20 bank->aval_pinmap =3D readl(bank->membase + REG_AVAIL); bank->id =3D id; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-sin= gle.c index 2ee0ee3b6ed1..4aadafe2c50a 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1363,6 +1363,7 @@ static int pcs_add_gpio_func(struct device_node *node= , struct pcs_device *pcs) } range =3D devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL); if (!range) { + of_node_put(gpiospec.np); ret =3D -ENOMEM; break; } @@ -1372,6 +1373,7 @@ static int pcs_add_gpio_func(struct device_node *node= , struct pcs_device *pcs) mutex_lock(&pcs->mutex); list_add_tail(&range->node, &pcs->gpiofuncs); mutex_unlock(&pcs->mutex); + of_node_put(gpiospec.np); } return ret; } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinc= trl/qcom/pinctrl-sm8250-lpass-lpi.c index ddbc6317f2a7..422ef44b8642 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c @@ -88,7 +88,7 @@ static const char * const i2s1_ws_groups[] =3D { "gpio7" = }; static const char * const i2s1_data_groups[] =3D { "gpio8", "gpio9" }; static const char * const wsa_swr_clk_groups[] =3D { "gpio10" }; static const char * const wsa_swr_data_groups[] =3D { "gpio11" }; -static const char * const i2s2_data_groups[] =3D { "gpio12", "gpio12" }; +static const char * const i2s2_data_groups[] =3D { "gpio12", "gpio13" }; =20 static const struct lpi_pingroup sm8250_groups[] =3D { LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/= chrome/cros_ec_lightbar.c index 376425bbd8ff..0f185b4b6f65 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c @@ -118,7 +118,7 @@ static int get_lightbar_version(struct cros_ec_dev *ec, param =3D (struct ec_params_lightbar *)msg->data; param->cmd =3D LIGHTBAR_CMD_VERSION; msg->outsize =3D sizeof(param->cmd); - msg->result =3D sizeof(resp->version); + msg->insize =3D sizeof(resp->version); ret =3D cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0 && ret !=3D -EINVAL) { ret =3D 0; diff --git a/drivers/platform/chrome/cros_typec_switch.c b/drivers/platform= /chrome/cros_typec_switch.c index 0eefdcf14d63..28080f48315d 100644 --- a/drivers/platform/chrome/cros_typec_switch.c +++ b/drivers/platform/chrome/cros_typec_switch.c @@ -230,20 +230,20 @@ static int cros_typec_register_switches(struct cros_t= ypec_switch_data *sdata) =20 adev =3D to_acpi_device_node(fwnode); if (!adev) { - dev_err(fwnode->dev, "Couldn't get ACPI device handle\n"); + dev_err(dev, "Couldn't get ACPI device handle for %pfwP\n", fwnode); ret =3D -ENODEV; goto err_switch; } =20 ret =3D acpi_evaluate_integer(adev->handle, "_ADR", NULL, &index); if (ACPI_FAILURE(ret)) { - dev_err(fwnode->dev, "_ADR wasn't evaluated\n"); + dev_err(dev, "_ADR wasn't evaluated for %pfwP\n", fwnode); ret =3D -ENODATA; goto err_switch; } =20 if (index >=3D EC_USB_PD_MAX_PORTS) { - dev_err(fwnode->dev, "Invalid port index number: %llu\n", index); + dev_err(dev, "%pfwP: Invalid port index number: %llu\n", fwnode, index); ret =3D -EINVAL; goto err_switch; } diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/= nvmem-reboot-mode.c index e229308d43e2..819f11bae788 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -10,6 +10,7 @@ #include #include #include +#include =20 struct nvmem_reboot_mode { struct reboot_mode_driver reboot; @@ -19,12 +20,22 @@ struct nvmem_reboot_mode { static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, unsigned int magic) { - int ret; struct nvmem_reboot_mode *nvmem_rbm; + size_t buf_len; + void *buf; + int ret; =20 nvmem_rbm =3D container_of(reboot, struct nvmem_reboot_mode, reboot); =20 - ret =3D nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic)); + buf =3D nvmem_cell_read(nvmem_rbm->cell, &buf_len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + kfree(buf); + + if (buf_len > sizeof(magic)) + return -EINVAL; + + ret =3D nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n"); =20 diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/a= b8500_charger.c index 308e68545d44..c6d513953b04 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3456,26 +3456,6 @@ static int ab8500_charger_probe(struct platform_devi= ce *pdev) return ret; } =20 - /* Request interrupts */ - for (i =3D 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { - irq =3D platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); - if (irq < 0) - return irq; - - ret =3D devm_request_threaded_irq(dev, - irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_charger_irq[i].name, di); - - if (ret !=3D 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n" - , ab8500_charger_irq[i].name, irq, ret); - return ret; - } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_charger_irq[i].name, irq, ret); - } - /* initialize lock */ spin_lock_init(&di->usb_state.usb_lock); mutex_init(&di->usb_ipt_crnt_lock); @@ -3604,6 +3584,26 @@ static int ab8500_charger_probe(struct platform_devi= ce *pdev) return PTR_ERR(di->usb_chg.psy); } =20 + /* Request interrupts */ + for (i =3D 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) { + irq =3D platform_get_irq_byname(pdev, ab8500_charger_irq[i].name); + if (irq < 0) + return irq; + + ret =3D devm_request_threaded_irq(dev, + irq, NULL, ab8500_charger_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_charger_irq[i].name, di); + + if (ret !=3D 0) { + dev_err(dev, "failed to request %s IRQ %d: %d\n" + , ab8500_charger_irq[i].name, irq, ret); + return ret; + } + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_charger_irq[i].name, irq, ret); + } + /* * Check what battery we have, since we always have the USB * psy, use that as a handle. diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply= /act8945a_charger.c index e9b5f4283772..e9cb06daecea 100644 --- a/drivers/power/supply/act8945a_charger.c +++ b/drivers/power/supply/act8945a_charger.c @@ -597,14 +597,6 @@ static int act8945a_charger_probe(struct platform_devi= ce *pdev) return irq ?: -ENXIO; } =20 - ret =3D devm_request_irq(&pdev->dev, irq, act8945a_status_changed, - IRQF_TRIGGER_FALLING, "act8945a_interrupt", - charger); - if (ret) { - dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n"); - return ret; - } - charger->desc.name =3D "act8945a-charger"; charger->desc.get_property =3D act8945a_charger_get_property; charger->desc.properties =3D act8945a_charger_props; @@ -625,6 +617,14 @@ static int act8945a_charger_probe(struct platform_devi= ce *pdev) return PTR_ERR(charger->psy); } =20 + ret =3D devm_request_irq(&pdev->dev, irq, act8945a_status_changed, + IRQF_TRIGGER_FALLING, "act8945a_interrupt", + charger); + if (ret) { + dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n"); + return ret; + } + platform_set_drvdata(pdev, charger); =20 INIT_WORK(&charger->work, act8945a_work); diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/= bq256xx_charger.c index c8368dae69c7..2b0216d32d5f 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -1746,6 +1746,12 @@ static int bq256xx_probe(struct i2c_client *client) usb_register_notifier(bq->usb3_phy, &bq->usb_nb); } =20 + ret =3D bq256xx_power_supply_init(bq, &psy_cfg, dev); + if (ret) { + dev_err(dev, "Failed to register power supply\n"); + return ret; + } + if (client->irq) { ret =3D devm_request_threaded_irq(dev, client->irq, NULL, bq256xx_irq_handler_thread, @@ -1758,12 +1764,6 @@ static int bq256xx_probe(struct i2c_client *client) } } =20 - ret =3D bq256xx_power_supply_init(bq, &psy_cfg, dev); - if (ret) { - dev_err(dev, "Failed to register power supply\n"); - return ret; - } - ret =3D bq256xx_hw_init(bq); if (ret) { dev_err(dev, "Cannot initialize the chip.\n"); diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/= bq25980_charger.c index d8411722266f..fd00f9e53354 100644 --- a/drivers/power/supply/bq25980_charger.c +++ b/drivers/power/supply/bq25980_charger.c @@ -1241,6 +1241,12 @@ static int bq25980_probe(struct i2c_client *client) return ret; } =20 + ret =3D bq25980_power_supply_init(bq, dev); + if (ret) { + dev_err(dev, "Failed to register power supply\n"); + return ret; + } + if (client->irq) { ret =3D devm_request_threaded_irq(dev, client->irq, NULL, bq25980_irq_handler_thread, @@ -1251,12 +1257,6 @@ static int bq25980_probe(struct i2c_client *client) return ret; } =20 - ret =3D bq25980_power_supply_init(bq, dev); - if (ret) { - dev_err(dev, "Failed to register power supply\n"); - return ret; - } - ret =3D bq25980_hw_init(bq); if (ret) { dev_err(dev, "Cannot initialize the chip.\n"); diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/= bq27xxx_battery.c index 1f06dee4b8b4..ff01d5d850f9 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -1162,7 +1162,7 @@ static inline int bq27xxx_write(struct bq27xxx_device= _info *di, int reg_index, return -EINVAL; =20 if (!di->bus.write) - return -EPERM; + return -EOPNOTSUPP; =20 ret =3D di->bus.write(di, di->regs[reg_index], value, single); if (ret < 0) @@ -1181,7 +1181,7 @@ static inline int bq27xxx_read_block(struct bq27xxx_d= evice_info *di, int reg_ind return -EINVAL; =20 if (!di->bus.read_bulk) - return -EPERM; + return -EOPNOTSUPP; =20 ret =3D di->bus.read_bulk(di, di->regs[reg_index], data, len); if (ret < 0) @@ -1200,7 +1200,7 @@ static inline int bq27xxx_write_block(struct bq27xxx_= device_info *di, int reg_in return -EINVAL; =20 if (!di->bus.write_bulk) - return -EPERM; + return -EOPNOTSUPP; =20 ret =3D di->bus.write_bulk(di, di->regs[reg_index], data, len); if (ret < 0) diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cp= cap-battery.c index 5dd76c0ac98d..d84b81e77362 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -1122,10 +1122,6 @@ static int cpcap_battery_probe(struct platform_devic= e *pdev) =20 platform_set_drvdata(pdev, ddata); =20 - error =3D cpcap_battery_init_interrupts(pdev, ddata); - if (error) - return error; - error =3D cpcap_battery_init_iio(ddata); if (error) return error; @@ -1142,6 +1138,10 @@ static int cpcap_battery_probe(struct platform_devic= e *pdev) return error; } =20 + error =3D cpcap_battery_init_interrupts(pdev, ddata); + if (error) + return error; + atomic_set(&ddata->active, 1); =20 error =3D cpcap_battery_calibrate(ddata); diff --git a/drivers/power/supply/goldfish_battery.c b/drivers/power/supply= /goldfish_battery.c index a58d713d75ce..4d204f0e1853 100644 --- a/drivers/power/supply/goldfish_battery.c +++ b/drivers/power/supply/goldfish_battery.c @@ -224,12 +224,6 @@ static int goldfish_battery_probe(struct platform_devi= ce *pdev) if (data->irq < 0) return -ENODEV; =20 - ret =3D devm_request_irq(&pdev->dev, data->irq, - goldfish_battery_interrupt, - IRQF_SHARED, pdev->name, data); - if (ret) - return ret; - psy_cfg.drv_data =3D data; =20 data->ac =3D power_supply_register(&pdev->dev, &ac_desc, &psy_cfg); @@ -245,6 +239,12 @@ static int goldfish_battery_probe(struct platform_devi= ce *pdev) =20 platform_set_drvdata(pdev, data); =20 + ret =3D devm_request_irq(&pdev->dev, data->irq, + goldfish_battery_interrupt, + IRQF_SHARED, pdev->name, data); + if (ret) + return ret; + GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK); return 0; } diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qco= m_battmgr.c index 0c993780d3ef..e5eade132816 100644 --- a/drivers/power/supply/qcom_battmgr.c +++ b/drivers/power/supply/qcom_battmgr.c @@ -981,7 +981,8 @@ static unsigned int qcom_battmgr_sc8280xp_parse_technol= ogy(const char *chemistry if ((!strncmp(chemistry, "LIO", BATTMGR_CHEMISTRY_LEN)) || (!strncmp(chemistry, "OOI", BATTMGR_CHEMISTRY_LEN))) return POWER_SUPPLY_TECHNOLOGY_LION; - if (!strncmp(chemistry, "LIP", BATTMGR_CHEMISTRY_LEN)) + if (!strncmp(chemistry, "LIP", BATTMGR_CHEMISTRY_LEN) || + !strncmp(chemistry, "LiP", BATTMGR_CHEMISTRY_LEN)) return POWER_SUPPLY_TECHNOLOGY_LIPO; =20 pr_err("Unknown battery technology '%s'\n", chemistry); diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/r= t9455_charger.c index e4dbacd50a43..248dc2b5e1f7 100644 --- a/drivers/power/supply/rt9455_charger.c +++ b/drivers/power/supply/rt9455_charger.c @@ -1663,6 +1663,15 @@ static int rt9455_probe(struct i2c_client *client) rt9455_charger_config.supplied_to =3D rt9455_charger_supplied_to; rt9455_charger_config.num_supplicants =3D ARRAY_SIZE(rt9455_charger_supplied_to); + + info->charger =3D devm_power_supply_register(dev, &rt9455_charger_desc, + &rt9455_charger_config); + if (IS_ERR(info->charger)) { + dev_err(dev, "Failed to register charger\n"); + ret =3D PTR_ERR(info->charger); + goto put_usb_notifier; + } + ret =3D devm_request_threaded_irq(dev, client->irq, NULL, rt9455_irq_handler_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, @@ -1678,14 +1687,6 @@ static int rt9455_probe(struct i2c_client *client) goto put_usb_notifier; } =20 - info->charger =3D devm_power_supply_register(dev, &rt9455_charger_desc, - &rt9455_charger_config); - if (IS_ERR(info->charger)) { - dev_err(dev, "Failed to register charger\n"); - ret =3D PTR_ERR(info->charger); - goto put_usb_notifier; - } - return 0; =20 put_usb_notifier: diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-= battery.c index cdfc8466d129..f30a542d4716 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -1173,24 +1173,6 @@ static int sbs_probe(struct i2c_client *client) =20 i2c_set_clientdata(client, chip); =20 - if (!chip->gpio_detect) - goto skip_gpio; - - irq =3D gpiod_to_irq(chip->gpio_detect); - if (irq <=3D 0) { - dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); - goto skip_gpio; - } - - rc =3D devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(&client->dev), chip); - if (rc) { - dev_warn(&client->dev, "Failed to request irq: %d\n", rc); - goto skip_gpio; - } - -skip_gpio: /* * Before we register, we might need to make sure we can actually talk * to the battery. @@ -1216,6 +1198,24 @@ static int sbs_probe(struct i2c_client *client) return dev_err_probe(&client->dev, PTR_ERR(chip->power_supply), "Failed to register power supply\n"); =20 + if (!chip->gpio_detect) + goto out; + + irq =3D gpiod_to_irq(chip->gpio_detect); + if (irq <=3D 0) { + dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); + goto out; + } + + rc =3D devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(&client->dev), chip); + if (rc) { + dev_warn(&client->dev, "Failed to request irq: %d\n", rc); + goto out; + } + +out: dev_info(&client->dev, "%s: battery gas gauge device registered\n", client->name); =20 diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/w= m97xx_battery.c index f4b190adb335..d3e5c2f7762a 100644 --- a/drivers/power/supply/wm97xx_battery.c +++ b/drivers/power/supply/wm97xx_battery.c @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *de= v) "failed to get charge GPIO\n"); if (charge_gpiod) { gpiod_set_consumer_name(charge_gpiod, "BATT CHRG"); - ret =3D request_irq(gpiod_to_irq(charge_gpiod), - wm97xx_chrg_irq, 0, - "AC Detect", dev); - if (ret) - return dev_err_probe(&dev->dev, ret, - "failed to request GPIO irq\n"); props++; /* POWER_SUPPLY_PROP_STATUS */ } =20 @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *de= v) props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ =20 prop =3D kcalloc(props, sizeof(*prop), GFP_KERNEL); - if (!prop) { - ret =3D -ENOMEM; - goto err3; - } + if (!prop) + return -ENOMEM; =20 prop[i++] =3D POWER_SUPPLY_PROP_PRESENT; if (charge_gpiod) @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *d= ev) schedule_work(&bat_work); } else { ret =3D PTR_ERR(bat_psy); - goto err4; + goto free; + } + + if (charge_gpiod) { + ret =3D request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq, + 0, "AC Detect", dev); + if (ret) { + dev_err_probe(&dev->dev, ret, + "failed to request GPIO irq\n"); + goto unregister; + } } =20 return 0; -err4: + +unregister: + power_supply_unregister(bat_psy); + +free: kfree(prop); -err3: - if (charge_gpiod) - free_irq(gpiod_to_irq(charge_gpiod), dev); + return ret; } =20 diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_ra= pl_tpmi.c index 1c48dba0ba96..6958c2f0b766 100644 --- a/drivers/powercap/intel_rapl_tpmi.c +++ b/drivers/powercap/intel_rapl_tpmi.c @@ -156,7 +156,7 @@ static int parse_one_domain(struct tpmi_rapl_package *t= rp, u32 offset) tpmi_domain_flags =3D tpmi_domain_header >> 32 & 0xffff; =20 if (tpmi_domain_version =3D=3D TPMI_VERSION_INVALID) { - pr_warn(FW_BUG "Invalid version\n"); + pr_debug("Invalid version, other instances may be valid\n"); return -ENODEV; } =20 diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index c12941f71e2c..dcd6619a4b02 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -854,7 +854,8 @@ static struct rio_net *rio_scan_alloc_net(struct rio_mp= ort *mport, =20 if (idtab =3D=3D NULL) { pr_err("RIO: failed to allocate destID table\n"); - rio_free_net(net); + kfree(net); + mport->net =3D NULL; net =3D NULL; } else { net->enum_data =3D idtab; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 23cdf220ca7d..a1a26743430c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1466,6 +1466,33 @@ static int set_machine_constraints(struct regulator_= dev *rdev) int ret =3D 0; const struct regulator_ops *ops =3D rdev->desc->ops; =20 + /* + * If there is no mechanism for controlling the regulator then + * flag it as always_on so we don't end up duplicating checks + * for this so much. Note that we could control the state of + * a supply to control the output on a regulator that has no + * direct control. + */ + if (!rdev->ena_pin && !ops->enable) { + if (rdev->supply_name && !rdev->supply) + return -EPROBE_DEFER; + + if (rdev->supply) + rdev->constraints->always_on =3D + rdev->supply->rdev->constraints->always_on; + else + rdev->constraints->always_on =3D true; + } + + /* + * If we want to enable this regulator, make sure that we know the + * supplying regulator. + */ + if (rdev->constraints->always_on || rdev->constraints->boot_on) { + if (rdev->supply_name && !rdev->supply) + return -EPROBE_DEFER; + } + ret =3D machine_constraints_voltage(rdev, rdev->constraints); if (ret !=3D 0) return ret; @@ -1631,37 +1658,15 @@ static int set_machine_constraints(struct regulator= _dev *rdev) } } =20 - /* - * If there is no mechanism for controlling the regulator then - * flag it as always_on so we don't end up duplicating checks - * for this so much. Note that we could control the state of - * a supply to control the output on a regulator that has no - * direct control. - */ - if (!rdev->ena_pin && !ops->enable) { - if (rdev->supply_name && !rdev->supply) - return -EPROBE_DEFER; - - if (rdev->supply) - rdev->constraints->always_on =3D - rdev->supply->rdev->constraints->always_on; - else - rdev->constraints->always_on =3D true; - } - /* If the constraints say the regulator should be on at this point * and we have control then make sure it is enabled. */ if (rdev->constraints->always_on || rdev->constraints->boot_on) { bool supply_enabled =3D false; =20 - /* If we want to enable this regulator, make sure that we know - * the supplying regulator. - */ - if (rdev->supply_name && !rdev->supply) - return -EPROBE_DEFER; - - /* If supplying regulator has already been enabled, + /* We have ensured a potential supply has been resolved above. + * + * If supplying regulator has already been enabled, * it's not intended to have use_count increment * when rdev is only boot-on. */ diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_ds= p_rproc.c index 8fcda9b74545..960fbd4b1d9b 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1250,6 +1250,15 @@ static int imx_dsp_suspend(struct device *dev) if (rproc->state !=3D RPROC_RUNNING) goto out; =20 + /* + * No channel available for sending messages; + * indicates no mailboxes present, so trigger PM runtime suspend + */ + if (!priv->tx_ch) { + dev_dbg(dev, "No initialized mbox tx channel, suspend directly.\n"); + goto out; + } + reinit_completion(&priv->pm_comp); =20 /* Tell DSP that suspend is happening */ diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 251f9840d85b..fda0e644f310 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -674,6 +674,10 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rpro= c, const struct firmware * { struct imx_rproc *priv =3D rproc->priv; =20 + /* No resource table in the firmware */ + if (!rproc->table_ptr) + return NULL; + if (priv->rsc_table) return (struct resource_table *)priv->rsc_table; =20 diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index c4c535b01181..ecbece2b5ce7 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -225,7 +225,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) struct mtk_scp *scp =3D priv; int ret; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clocks\n"); return IRQ_NONE; @@ -233,7 +233,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) =20 scp->data->scp_irq_handler(scp); =20 - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); =20 return IRQ_HANDLED; } @@ -467,7 +467,7 @@ static int scp_load(struct rproc *rproc, const struct f= irmware *fw) struct device *dev =3D scp->dev; int ret; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; @@ -482,7 +482,7 @@ static int scp_load(struct rproc *rproc, const struct f= irmware *fw) =20 ret =3D scp_elf_load_segments(rproc, fw); leave: - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); =20 return ret; } @@ -493,14 +493,14 @@ static int scp_parse_fw(struct rproc *rproc, const st= ruct firmware *fw) struct device *dev =3D scp->dev; int ret; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; } =20 ret =3D scp_ipi_init(scp, fw); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } =20 @@ -511,7 +511,7 @@ static int scp_start(struct rproc *rproc) struct scp_run *run =3D &scp->run; int ret; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; @@ -536,14 +536,14 @@ static int scp_start(struct rproc *rproc) goto stop; } =20 - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); dev_info(dev, "SCP is ready. FW version %s\n", run->fw_ver); =20 return 0; =20 stop: scp->data->scp_reset_assert(scp); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } =20 @@ -638,7 +638,7 @@ static int scp_stop(struct rproc *rproc) struct mtk_scp *scp =3D rproc->priv; int ret; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clocks\n"); return ret; @@ -646,12 +646,29 @@ static int scp_stop(struct rproc *rproc) =20 scp->data->scp_reset_assert(scp); scp->data->scp_stop(scp); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); =20 return 0; } =20 +static int scp_prepare(struct rproc *rproc) +{ + struct mtk_scp *scp =3D rproc->priv; + + return clk_prepare(scp->clk); +} + +static int scp_unprepare(struct rproc *rproc) +{ + struct mtk_scp *scp =3D rproc->priv; + + clk_unprepare(scp->clk); + return 0; +} + static const struct rproc_ops scp_ops =3D { + .prepare =3D scp_prepare, + .unprepare =3D scp_unprepare, .start =3D scp_start, .stop =3D scp_stop, .load =3D scp_load, diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_= ipi.c index 9c7c17b9d181..0c3ed37bd082 100644 --- a/drivers/remoteproc/mtk_scp_ipi.c +++ b/drivers/remoteproc/mtk_scp_ipi.c @@ -168,7 +168,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf= , unsigned int len, WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf)) return -EINVAL; =20 - ret =3D clk_prepare_enable(scp->clk); + ret =3D clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clock\n"); return ret; @@ -208,7 +208,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf= , unsigned int len, =20 unlock_mutex: mutex_unlock(&scp->send_lock); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); =20 return ret; } diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 32b550c91d9f..662a67431404 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -413,50 +413,38 @@ field##_show(struct device *dev, \ } \ static DEVICE_ATTR_RO(field); =20 -#define rpmsg_string_attr(field, member) \ -static ssize_t \ -field##_store(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t sz) \ -{ \ - struct rpmsg_device *rpdev =3D to_rpmsg_device(dev); \ - const char *old; \ - char *new; \ - \ - new =3D kstrndup(buf, sz, GFP_KERNEL); \ - if (!new) \ - return -ENOMEM; \ - new[strcspn(new, "\n")] =3D '\0'; \ - \ - device_lock(dev); \ - old =3D rpdev->member; \ - if (strlen(new)) { \ - rpdev->member =3D new; \ - } else { \ - kfree(new); \ - rpdev->member =3D NULL; \ - } \ - device_unlock(dev); \ - \ - kfree(old); \ - \ - return sz; \ -} \ -static ssize_t \ -field##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct rpmsg_device *rpdev =3D to_rpmsg_device(dev); \ - \ - return sprintf(buf, "%s\n", rpdev->member); \ -} \ -static DEVICE_ATTR_RW(field) - /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ rpmsg_show_attr(name, id.name, "%s\n"); rpmsg_show_attr(src, src, "0x%x\n"); rpmsg_show_attr(dst, dst, "0x%x\n"); rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); -rpmsg_string_attr(driver_override, driver_override); + +static ssize_t driver_override_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rpmsg_device *rpdev =3D to_rpmsg_device(dev); + int ret; + + ret =3D driver_set_override(dev, &rpdev->driver_override, buf, count); + if (ret) + return ret; + + return count; +} + +static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rpmsg_device *rpdev =3D to_rpmsg_device(dev); + ssize_t len; + + device_lock(dev); + len =3D sysfs_emit(buf, "%s\n", rpdev->driver_override); + device_unlock(dev); + return len; +} +static DEVICE_ATTR_RW(driver_override); =20 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 93baffe110c0..13de2cb07f75 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -457,7 +457,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, stru= ct rtc_wkalrm *alarm) * are in, we can return -ETIME to signal that the timer has already * expired, which is true in both cases. */ - if ((scheduled - now) <=3D 1) { + if (!err && (scheduled - now) <=3D 1) { err =3D __rtc_read_time(rtc, &tm); if (err) return err; diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index b6f96c10196a..f49af7d963fb 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -330,7 +330,10 @@ static int xlnx_rtc_probe(struct platform_device *pdev) &xrtcdev->freq); if (ret) xrtcdev->freq =3D RTC_CALIB_DEF; + } else { + xrtcdev->freq--; } + ret =3D readl(xrtcdev->reg_base + RTC_CALIB_RD); if (!ret) writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR)); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 3ff46fc694f8..e50592c3d30c 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -247,7 +247,7 @@ struct subchannel *css_alloc_subchannel(struct subchann= el_id schid, err_lock: kfree(sch->lock); err: - kfree(sch); + put_device(&sch->dev); return ERR_PTR(ret); } =20 diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 72ceaf650b0d..dfe97e25635e 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -919,7 +919,8 @@ static int __init blogic_init_fp_probeinfo(struct blogi= c_adapter *adapter) a particular probe order. */ =20 -static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapt= er) +static noinline_for_stack void __init +blogic_init_probeinfo_list(struct blogic_adapter *adapter) { /* If a PCI BIOS is present, interrogate it for MultiMaster and @@ -1689,7 +1690,8 @@ static bool __init blogic_rdconfig(struct blogic_adap= ter *adapter) blogic_reportconfig reports the configuration of Host Adapter. */ =20 -static bool __init blogic_reportconfig(struct blogic_adapter *adapter) +static noinline_for_stack bool __init +blogic_reportconfig(struct blogic_adapter *adapter) { unsigned short alltgt_mask =3D (1 << adapter->maxdev) - 1; unsigned short sync_ok, fast_ok; diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio= _scsi.c index 05e1a63e00c3..ed40ae6b9800 100644 --- a/drivers/scsi/csiostor/csio_scsi.c +++ b/drivers/scsi/csiostor/csio_scsi.c @@ -2074,7 +2074,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) struct csio_scsi_level_data sld; =20 if (!rn) - goto fail; + goto fail_ret; =20 csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n", cmnd->device->lun, rn->flowid, rn->scsi_id); @@ -2220,6 +2220,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) csio_put_scsi_ioreq_lock(hw, scsim, ioreq); fail: CSIO_INC_STATS(rn, n_lun_rst_fail); +fail_ret: return FAILED; } =20 diff --git a/drivers/scsi/elx/efct/efct_driver.c b/drivers/scsi/elx/efct/ef= ct_driver.c index 49fd2cfed70c..37aba56e0721 100644 --- a/drivers/scsi/elx/efct/efct_driver.c +++ b/drivers/scsi/elx/efct/efct_driver.c @@ -415,12 +415,6 @@ efct_intr_thread(int irq, void *handle) return IRQ_HANDLED; } =20 -static irqreturn_t -efct_intr_msix(int irq, void *handle) -{ - return IRQ_WAKE_THREAD; -} - static int efct_setup_msix(struct efct *efct, u32 num_intrs) { @@ -450,7 +444,7 @@ efct_setup_msix(struct efct *efct, u32 num_intrs) intr_ctx->index =3D i; =20 rc =3D request_threaded_irq(pci_irq_vector(efct->pci, i), - efct_intr_msix, efct_intr_thread, 0, + NULL, efct_intr_thread, IRQF_ONESHOT, EFCT_DRIVER_NAME, intr_ctx); if (rc) { dev_err(&efct->pci->dev, diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/= smartpqi_init.c index 0cdeb7aa5502..dc194c76f38b 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -1240,7 +1240,8 @@ static inline int pqi_report_phys_luns(struct pqi_ctr= l_info *ctrl_info, void **b dev_err(&ctrl_info->pci_dev->dev, "RPL returned unsupported data format %u\n", rpl_response_format); - return -EINVAL; + rc =3D -EINVAL; + goto out_free_rpl_list; } else { dev_warn(&ctrl_info->pci_dev->dev, "RPL returned extended format 2 instead of 4\n"); @@ -1252,8 +1253,10 @@ static inline int pqi_report_phys_luns(struct pqi_ct= rl_info *ctrl_info, void **b =20 rpl_16byte_wwid_list =3D kmalloc(struct_size(rpl_16byte_wwid_list, lun_en= tries, num_physicals), GFP_KERNEL); - if (!rpl_16byte_wwid_list) - return -ENOMEM; + if (!rpl_16byte_wwid_list) { + rc =3D -ENOMEM; + goto out_free_rpl_list; + } =20 put_unaligned_be32(num_physicals * sizeof(struct report_phys_lun_16byte_w= wid), &rpl_16byte_wwid_list->header.list_length); @@ -1274,6 +1277,10 @@ static inline int pqi_report_phys_luns(struct pqi_ct= rl_info *ctrl_info, void **b *buffer =3D rpl_16byte_wwid_list; =20 return 0; + +out_free_rpl_list: + kfree(rpl_list); + return rc; } =20 static inline int pqi_report_logical_luns(struct pqi_ctrl_info *ctrl_info,= void **buffer) diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index 3a2f97cd5272..37d21e3de694 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -717,7 +718,7 @@ static ssize_t svs_enable_debug_write(struct file *filp, struct svs_bank *svsb =3D file_inode(filp)->i_private; struct svs_platform *svsp =3D dev_get_drvdata(svsb->dev); int enabled, ret; - char *buf =3D NULL; + char *buf __free(kfree) =3D NULL; =20 if (count >=3D PAGE_SIZE) return -EINVAL; @@ -735,8 +736,6 @@ static ssize_t svs_enable_debug_write(struct file *filp, svsb->mode_support =3D SVSB_MODE_ALL_DISABLE; } =20 - kfree(buf); - return count; } =20 diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index ab2418d2fe43..0c54a9525baf 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -354,15 +354,16 @@ static int cmd_db_dev_probe(struct platform_device *p= dev) return -EINVAL; } =20 - cmd_db_header =3D memremap(rmem->base, rmem->size, MEMREMAP_WC); - if (!cmd_db_header) { - ret =3D -ENOMEM; + cmd_db_header =3D devm_memremap(&pdev->dev, rmem->base, rmem->size, MEMRE= MAP_WC); + if (IS_ERR(cmd_db_header)) { + ret =3D PTR_ERR(cmd_db_header); cmd_db_header =3D NULL; return ret; } =20 if (!cmd_db_magic_matches(cmd_db_header)) { dev_err(&pdev->dev, "Invalid Command DB Magic\n"); + cmd_db_header =3D NULL; return -EINVAL; } =20 diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 5217ff0a434f..d039c660d04f 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -1189,7 +1189,9 @@ static int qcom_smem_probe(struct platform_device *pd= ev) smem->item_count =3D qcom_smem_get_item_count(smem); break; case SMEM_GLOBAL_HEAP_VERSION: - qcom_smem_map_global(smem, size); + ret =3D qcom_smem_map_global(smem, size); + if (ret < 0) + return ret; smem->item_count =3D SMEM_ITEM_COUNT; break; default: diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index 7a3bdef5a7c0..4724d4759dd0 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -87,7 +87,7 @@ static int k3_chipinfo_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); =20 - regmap =3D regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); + regmap =3D devm_regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg); if (IS_ERR(regmap)) return PTR_ERR(regmap); =20 diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index f49f8492dde5..e01aec084e39 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -366,12 +366,10 @@ static int pruss_clk_mux_setup(struct pruss *pruss, s= truct clk *clk_mux, =20 ret =3D devm_add_action_or_reset(dev, pruss_of_free_clk_provider, clk_mux_np); - if (ret) { + if (ret) dev_err(dev, "failed to add clkmux free action %d", ret); - goto put_clk_mux_np; - } =20 - return 0; + return ret; =20 put_clk_mux_np: of_node_put(clk_mux_np); diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c index 91ab97a456fa..5854218e1a27 100644 --- a/drivers/soundwire/dmi-quirks.c +++ b/drivers/soundwire/dmi-quirks.c @@ -122,6 +122,17 @@ static const struct dmi_system_id adr_remap_quirk_tabl= e[] =3D { }, .driver_data =3D (void *)intel_tgl_bios, }, + { + /* + * quirk used for Avell B.ON (OEM rebrand of NUC15 'Bishop County' + * LAPBC510 and LAPBC710) + */ + .matches =3D { + DMI_MATCH(DMI_SYS_VENDOR, "Avell High Performance"), + DMI_MATCH(DMI_PRODUCT_NAME, "B.ON"), + }, + .driver_data =3D (void *)intel_tgl_bios, + }, { /* quirk used for NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */ .matches =3D { diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 6a3b41dbfa70..37a20652fd2e 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -548,10 +548,10 @@ static u32 get_xfer_len_in_words(struct spi_transfer = *xfer, { u32 len; =20 - if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) - len =3D xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; + if (!(xfer->bits_per_word % MIN_WORD_LEN)) + len =3D xfer->len * BITS_PER_BYTE / xfer->bits_per_word; else - len =3D xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); + len =3D xfer->len / (xfer->bits_per_word / BITS_PER_BYTE + 1); len &=3D TRANS_LEN_MSK; =20 return len; @@ -571,7 +571,7 @@ static bool geni_can_dma(struct spi_controller *ctlr, return true; =20 len =3D get_xfer_len_in_words(xfer, mas); - fifo_size =3D mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_p= er_word; + fifo_size =3D mas->tx_fifo_depth * mas->fifo_width_bits / xfer->bits_per_= word; =20 if (len > fifo_size) return true; @@ -710,6 +710,12 @@ static int spi_geni_init(struct spi_geni_master *mas) case 0: mas->cur_xfer_mode =3D GENI_SE_FIFO; geni_se_select_mode(se, GENI_SE_FIFO); + /* setup_fifo_params assumes that these registers start with a zero valu= e */ + writel(0, se->base + SE_SPI_LOOPBACK); + writel(0, se->base + SE_SPI_DEMUX_SEL); + writel(0, se->base + SE_SPI_CPHA); + writel(0, se->base + SE_SPI_CPOL); + writel(0, se->base + SE_SPI_DEMUX_OUTPUT_INV); ret =3D 0; break; } diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index c581aa5fbf7c..932992b06022 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -175,8 +175,19 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16)) return false; =20 - if (op->cmd.nbytes !=3D 2) - return false; + /* Extra 8D-8D-8D limitations */ + if (op->cmd.dtr && op->cmd.buswidth =3D=3D 8) { + if (op->cmd.nbytes !=3D 2) + return false; + + if ((op->addr.nbytes % 2) || + (op->dummy.nbytes % 2) || + (op->data.nbytes % 2)) { + dev_err(&ctlr->dev, + "Even byte numbers not allowed in octal DTR operations\n"); + return false; + } + } } else { if (op->cmd.nbytes !=3D 1) return false; @@ -590,9 +601,18 @@ spi_mem_dirmap_create(struct spi_mem *mem, =20 desc->mem =3D mem; desc->info =3D *info; - if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) + if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) { + ret =3D spi_mem_access_start(mem); + if (ret) { + kfree(desc); + return ERR_PTR(ret); + } + ret =3D ctlr->mem_ops->dirmap_create(desc); =20 + spi_mem_access_end(mem); + } + if (ret) { desc->nodirmap =3D true; if (!spi_mem_supports_op(desc->mem, &desc->info.op_tmpl)) diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 211d9c76665b..96ee0e8456f4 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1507,11 +1507,12 @@ static void stm32h7_spi_data_idleness(struct stm32_= spi *spi, u32 len) cfg2_clrb |=3D STM32H7_SPI_CFG2_MIDI; if ((len > 1) && (spi->cur_midi > 0)) { u32 sck_period_ns =3D DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); - u32 midi =3D min_t(u32, - DIV_ROUND_UP(spi->cur_midi, sck_period_ns), - FIELD_GET(STM32H7_SPI_CFG2_MIDI, - STM32H7_SPI_CFG2_MIDI)); + u32 midi =3D DIV_ROUND_UP(spi->cur_midi, sck_period_ns); =20 + if ((spi->cur_bpw + midi) < 8) + midi =3D 8 - spi->cur_bpw; + + midi =3D min_t(u32, midi, FIELD_MAX(STM32H7_SPI_CFG2_MIDI)); =20 dev_dbg(spi->dev, "period=3D%dns, midi=3D%d(=3D%dns)\n", sck_period_ns, midi, midi * sck_period_ns); diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c index 852ffe013d32..c006889b37eb 100644 --- a/drivers/spi/spi-wpcm-fiu.c +++ b/drivers/spi/spi-wpcm-fiu.c @@ -448,12 +448,10 @@ static int wpcm_fiu_probe(struct platform_device *pde= v) fiu =3D spi_controller_get_devdata(ctrl); fiu->dev =3D dev; =20 - res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); - fiu->regs =3D devm_ioremap_resource(dev, res); - if (IS_ERR(fiu->regs)) { - dev_err(dev, "Failed to map registers\n"); - return PTR_ERR(fiu->regs); - } + fiu->regs =3D devm_platform_ioremap_resource_byname(pdev, "control"); + if (IS_ERR(fiu->regs)) + return dev_err_probe(dev, PTR_ERR(fiu->regs), + "Failed to map registers\n"); =20 fiu->clk =3D devm_clk_get_enabled(dev, NULL); if (IS_ERR(fiu->clk)) @@ -461,12 +459,11 @@ static int wpcm_fiu_probe(struct platform_device *pde= v) =20 res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); fiu->memory =3D devm_ioremap_resource(dev, res); - fiu->memory_size =3D min_t(size_t, resource_size(res), MAX_MEMORY_SIZE_TO= TAL); - if (IS_ERR(fiu->memory)) { - dev_err(dev, "Failed to map flash memory window\n"); - return PTR_ERR(fiu->memory); - } + if (IS_ERR(fiu->memory)) + return dev_err_probe(dev, PTR_ERR(fiu->memory), + "Failed to map flash memory window\n"); =20 + fiu->memory_size =3D min_t(size_t, resource_size(res), MAX_MEMORY_SIZE_TO= TAL); fiu->shm_regmap =3D syscon_regmap_lookup_by_phandle_optional(dev->of_node= , "nuvoton,shm"); =20 wpcm_fiu_hw_init(fiu); diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/ligh= t.c index 9999f8401699..eb69500e080e 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1029,14 +1029,18 @@ static int gb_lights_light_config(struct gb_lights = *glights, u8 id) if (!strlen(conf.name)) return -EINVAL; =20 - light->channels_count =3D conf.channel_count; light->name =3D kstrndup(conf.name, NAMES_MAX, GFP_KERNEL); if (!light->name) return -ENOMEM; - light->channels =3D kcalloc(light->channels_count, + light->channels =3D kcalloc(conf.channel_count, sizeof(struct gb_channel), GFP_KERNEL); if (!light->channels) return -ENOMEM; + /* + * Publish channels_count only after channels allocation so cleanup + * doesn't walk a NULL channels pointer on allocation failure. + */ + light->channels_count =3D conf.channel_count; =20 /* First we collect all the configurations for all channels */ for (i =3D 0; i < light->channels_count; i++) { diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rt= l8723bs/core/rtw_mlme.c index b221913733fb..19b877f50fb6 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -876,8 +876,10 @@ static void find_network(struct adapter *adapter) struct wlan_network *tgt_network =3D &pmlmepriv->cur_network; =20 pwlan =3D rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->networ= k.mac_address); - if (pwlan) - pwlan->fixed =3D false; + if (!pwlan) + return; + + pwlan->fixed =3D false; =20 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count =3D=3D 1)) diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/st= aging/rtl8723bs/os_dep/ioctl_cfg80211.c index af155fca39b8..f23aeb58d041 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -316,9 +316,10 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct ad= apter *padapter, struct wl len, notify_signal, GFP_ATOMIC); =20 if (unlikely(!bss)) - goto exit; + goto free_buf; =20 cfg80211_put_bss(wiphy, bss); +free_buf: kfree(buf); =20 exit: diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging= /rtl8723bs/os_dep/sdio_intf.c index 490431484524..335e6002df70 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -380,7 +380,8 @@ static int rtw_drv_init( if (status !=3D _SUCCESS) goto free_if1; =20 - if (sdio_alloc_irq(dvobj) !=3D _SUCCESS) + status =3D sdio_alloc_irq(dvobj); + if (status !=3D _SUCCESS) goto free_if1; =20 rtw_ndev_notifier_register(); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c= b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index 546b70434004..8bcac4adb9ec 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -348,8 +348,11 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct= proc_thermal_device *proc =20 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) { ret =3D sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group); - if (ret) + if (ret) { + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) + sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group); return ret; + } } =20 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) { diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/82= 50_dw.c index d67023fb52a3..6c34a68cea8f 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -753,11 +753,18 @@ static int dw8250_runtime_suspend(struct device *dev) =20 static int dw8250_runtime_resume(struct device *dev) { + int ret; struct dw8250_data *data =3D dev_get_drvdata(dev); =20 - clk_prepare_enable(data->pclk); + ret =3D clk_prepare_enable(data->pclk); + if (ret) + return ret; =20 - clk_prepare_enable(data->clk); + ret =3D clk_prepare_enable(data->clk); + if (ret) { + clk_disable_unprepare(data->pclk); + return ret; + } =20 return 0; } diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/= 8250_omap.c index e687cd0daa76..c863a8e38ca2 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -924,7 +924,6 @@ static void __dma_rx_do_complete(struct uart_8250_port = *p) goto out; =20 cookie =3D dma->rx_cookie; - dma->rx_running =3D 0; =20 /* Re-enable RX FIFO interrupt now that transfer is complete */ if (priv->habit & UART_HAS_RHR_IT_DIS) { @@ -958,6 +957,7 @@ static void __dma_rx_do_complete(struct uart_8250_port = *p) goto out; ret =3D tty_insert_flip_string(tty_port, dma->rx_buf, count); =20 + dma->rx_running =3D 0; p->port.icount.rx +=3D ret; p->port.icount.buf_overrun +=3D count - ret; out: diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 4f57833e3ec7..2b9b2235e29d 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -479,14 +479,14 @@ config SERIAL_IMX can enable its onboard serial port by enabling this option. =20 config SERIAL_IMX_CONSOLE - tristate "Console on IMX serial port" + bool "Console on IMX serial port" depends on SERIAL_IMX select SERIAL_CORE_CONSOLE help If you have enabled the serial port on the Freescale IMX - CPU you can make it the console by answering Y/M to this option. + CPU you can make it the console by answering Y to this option. =20 - Even if you say Y/M here, the currently visible virtual console + Even if you say Y here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as "console=3Dttymxc0". (Try "man bootparam" or see the documentation of @@ -661,7 +661,7 @@ config SERIAL_SH_SCI_EARLYCON default ARCH_RENESAS =20 config SERIAL_SH_SCI_DMA - bool "DMA support" if EXPERT + bool "Support for DMA on SuperH SCI(F)" if EXPERT depends on SERIAL_SH_SCI && DMA_ENGINE default ARCH_RENESAS =20 diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 9f53ee92486d..808b648e1f38 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -9836,6 +9836,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, e= num ufs_pm_op pm_op) =20 if (req_dev_pwr_mode =3D=3D UFS_ACTIVE_PWR_MODE && req_link_state =3D=3D UIC_LINK_ACTIVE_STATE) { + ufshcd_disable_auto_bkops(hba); + flush_work(&hba->eeh_work); goto vops_suspend; } =20 diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 580c8d0bd8bb..626bb9002f4a 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -72,6 +72,7 @@ config SCSI_UFS_QCOM config SCSI_UFS_MEDIATEK tristate "Mediatek specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK + depends on PM depends on RESET_CONTROLLER select PHY_MTK_UFS select RESET_TI_SYSCON diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediate= k.c index 8b4a3cc81253..606e90ce8ca7 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -1852,7 +1852,6 @@ static int ufs_mtk_remove(struct platform_device *pde= v) return 0; } =20 -#ifdef CONFIG_PM_SLEEP static int ufs_mtk_system_suspend(struct device *dev) { struct ufs_hba *hba =3D dev_get_drvdata(dev); @@ -1875,9 +1874,7 @@ static int ufs_mtk_system_resume(struct device *dev) =20 return ufshcd_system_resume(dev); } -#endif =20 -#ifdef CONFIG_PM static int ufs_mtk_runtime_suspend(struct device *dev) { struct ufs_hba *hba =3D dev_get_drvdata(dev); @@ -1900,13 +1897,10 @@ static int ufs_mtk_runtime_resume(struct device *de= v) =20 return ufshcd_runtime_resume(dev); } -#endif =20 static const struct dev_pm_ops ufs_mtk_pm_ops =3D { - SET_SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, - ufs_mtk_system_resume) - SET_RUNTIME_PM_OPS(ufs_mtk_runtime_suspend, - ufs_mtk_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, ufs_mtk_system_resume) + RUNTIME_PM_OPS(ufs_mtk_runtime_suspend, ufs_mtk_runtime_resume, NULL) .prepare =3D ufshcd_suspend_prepare, .complete =3D ufshcd_resume_complete, }; @@ -1916,7 +1910,7 @@ static struct platform_driver ufs_mtk_pltform =3D { .remove =3D ufs_mtk_remove, .driver =3D { .name =3D "ufshcd-mtk", - .pm =3D &ufs_mtk_pm_ops, + .pm =3D pm_ptr(&ufs_mtk_pm_ops), .of_match_table =3D ufs_mtk_of_match, }, }; diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 5635e4d7ec88..66080ab8c8e0 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -572,6 +572,7 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) { switch (hsotg->dr_mode) { case USB_DR_MODE_HOST: + dwc2_force_mode(hsotg, true); /* * NOTE: This is required for some rockchip soc based * platforms on their host-only dwc2. diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 45c9a399f8a5..11b938fd9de0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1892,6 +1892,20 @@ static int dwc3_get_clocks(struct dwc3 *dwc) return 0; } =20 +static void dwc3_vbus_draw_work(struct work_struct *work) +{ + struct dwc3 *dwc =3D container_of(work, struct dwc3, vbus_draw_work); + union power_supply_propval val =3D {0}; + int ret; + + val.intval =3D 1000 * (dwc->current_limit); + ret =3D power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_C= URRENT_LIMIT, &val); + + if (ret < 0) + dev_dbg(dwc->dev, "Error (%d) setting vbus draw (%d mA)\n", + ret, dwc->current_limit); +} + static struct power_supply *dwc3_get_usb_power_supply(struct dwc3 *dwc) { struct power_supply *usb_psy; @@ -1906,6 +1920,7 @@ static struct power_supply *dwc3_get_usb_power_supply= (struct dwc3 *dwc) if (!usb_psy) return ERR_PTR(-EPROBE_DEFER); =20 + INIT_WORK(&dwc->vbus_draw_work, dwc3_vbus_draw_work); return usb_psy; } =20 @@ -2097,8 +2112,10 @@ static void dwc3_remove(struct platform_device *pdev) =20 dwc3_free_event_buffers(dwc); =20 - if (dwc->usb_psy) + if (dwc->usb_psy) { + cancel_work_sync(&dwc->vbus_draw_work); power_supply_put(dwc->usb_psy); + } } =20 #ifdef CONFIG_PM diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9fc91f5c0bdb..45084ca66806 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1034,6 +1034,8 @@ struct dwc3_scratchpad_array { * @role_switch_default_mode: default operation mode of controller while * usb role is USB_ROLE_NONE. * @usb_psy: pointer to power supply interface. + * @vbus_draw_work: Work to set the vbus drawing limit + * @current_limit: How much current to draw from vbus, in milliAmperes. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1202,6 +1204,8 @@ struct dwc3 { enum usb_dr_mode role_switch_default_mode; =20 struct power_supply *usb_psy; + struct work_struct vbus_draw_work; + unsigned int current_limit; =20 u32 fladj; u32 ref_clk_per; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8781ebeaab90..7e6661781aff 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3139,8 +3139,6 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadge= t *g, static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) { struct dwc3 *dwc =3D gadget_to_dwc(g); - union power_supply_propval val =3D {0}; - int ret; =20 if (dwc->usb2_phy) return usb_phy_set_power(dwc->usb2_phy, mA); @@ -3148,10 +3146,10 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget = *g, unsigned int mA) if (!dwc->usb_psy) return -EOPNOTSUPP; =20 - val.intval =3D 1000 * mA; - ret =3D power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_C= URRENT_LIMIT, &val); + dwc->current_limit =3D mA; + schedule_work(&dwc->vbus_draw_work); =20 - return ret; + return 0; } =20 /** diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc= /bdc/bdc_core.c index 35a652807fca..c2e3fa997842 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -35,8 +35,8 @@ static int poll_oip(struct bdc *bdc, u32 usec) u32 status; int ret; =20 - ret =3D readl_poll_timeout(bdc->regs + BDC_BDCSC, status, - (BDC_CSTS(status) !=3D BDC_OIP), 10, usec); + ret =3D readl_poll_timeout_atomic(bdc->regs + BDC_BDCSC, status, + (BDC_CSTS(status) !=3D BDC_OIP), 10, usec); if (ret) dev_err(bdc->dev, "operation timedout BDCSC: 0x%08x\n", status); else diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/t= egra-xudc.c index 3a14b6b72d8c..114a80dd06fb 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -3388,17 +3388,18 @@ static void tegra_xudc_device_params_init(struct te= gra_xudc *xudc) { u32 val, imod; =20 + val =3D xudc_readl(xudc, BLCG); if (xudc->soc->has_ipfs) { - val =3D xudc_readl(xudc, BLCG); val |=3D BLCG_ALL; val &=3D ~(BLCG_DFPCI | BLCG_UFPCI | BLCG_FE | BLCG_COREPLL_PWRDN); val |=3D BLCG_IOPLL_0_PWRDN; val |=3D BLCG_IOPLL_1_PWRDN; val |=3D BLCG_IOPLL_2_PWRDN; - - xudc_writel(xudc, val, BLCG); + } else { + val &=3D ~BLCG_COREPLL_PWRDN; } + xudc_writel(xudc, val, BLCG); =20 if (xudc->soc->port_speed_quirk) tegra_xudc_limit_port_speed(xudc); @@ -3949,6 +3950,7 @@ static void tegra_xudc_remove(struct platform_device = *pdev) static int __maybe_unused tegra_xudc_powergate(struct tegra_xudc *xudc) { unsigned long flags; + u32 val; =20 dev_dbg(xudc->dev, "entering ELPG\n"); =20 @@ -3961,6 +3963,10 @@ static int __maybe_unused tegra_xudc_powergate(struc= t tegra_xudc *xudc) =20 spin_unlock_irqrestore(&xudc->lock, flags); =20 + val =3D xudc_readl(xudc, BLCG); + val |=3D BLCG_COREPLL_PWRDN; + xudc_writel(xudc, val, BLCG); + clk_bulk_disable_unprepare(xudc->soc->num_clks, xudc->clks); =20 regulator_bulk_disable(xudc->soc->num_supplies, xudc->supplies); diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index c80c23d3384e..3fc524190baf 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -87,15 +87,20 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connect= or *con, union power_supply_propval *val) { u32 pdo; + int max_voltage =3D 0; =20 switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: - if (con->num_pdos > 0) { - pdo =3D con->src_pdos[con->num_pdos - 1]; - val->intval =3D pdo_fixed_voltage(pdo) * 1000; - } else { - val->intval =3D 0; + for (int i =3D 0; i < con->num_pdos; i++) { + int pdo_voltage =3D 0; + + pdo =3D con->src_pdos[i]; + if (pdo_type(pdo) =3D=3D PDO_TYPE_FIXED) + pdo_voltage =3D pdo_fixed_voltage(pdo) * 1000; + max_voltage =3D (pdo_voltage > max_voltage) ? pdo_voltage + : max_voltage; } + val->intval =3D max_voltage; break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: @@ -143,6 +148,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connect= or *con, union power_supply_propval *val) { u32 pdo; + int max_current =3D 0; =20 if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) { val->intval =3D 0; @@ -151,12 +157,16 @@ static int ucsi_psy_get_current_max(struct ucsi_conne= ctor *con, =20 switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: - if (con->num_pdos > 0) { - pdo =3D con->src_pdos[con->num_pdos - 1]; - val->intval =3D pdo_max_current(pdo) * 1000; - } else { - val->intval =3D 0; + for (int i =3D 0; i < con->num_pdos; i++) { + int pdo_current =3D 0; + + pdo =3D con->src_pdos[i]; + if (pdo_type(pdo) =3D=3D PDO_TYPE_FIXED) + pdo_current =3D pdo_max_current(pdo) * 1000; + max_current =3D (pdo_current > max_current) ? pdo_current + : max_current; } + val->intval =3D max_current; break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: val->intval =3D UCSI_TYPEC_1_5_CURRENT * 1000; diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/= pci/hisilicon/hisi_acc_vfio_pci.c index 712b178c42aa..e544fd0a710c 100644 --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c @@ -1152,8 +1152,7 @@ static void hisi_acc_vf_pci_aer_reset_done(struct pci= _dev *pdev) { struct hisi_acc_vf_core_device *hisi_acc_vdev =3D hisi_acc_drvdata(pdev); =20 - if (hisi_acc_vdev->core_device.vdev.migration_flags !=3D - VFIO_MIGRATION_STOP_COPY) + if (!hisi_acc_vdev->core_device.vdev.mig_ops) return; =20 /* diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index c29a195a0175..f4da76fa235e 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -1424,6 +1424,7 @@ static int vhost_vdpa_mmap(struct file *file, struct = vm_area_struct *vma) if (vma->vm_end - vma->vm_start !=3D notify.size) return -ENOTSUPP; =20 + vma->vm_page_prot =3D pgprot_noncached(vma->vm_page_prot); vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); vma->vm_ops =3D &vhost_vdpa_vm_ops; return 0; diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/= qcom-wled.c index b19e5f73de8b..0d55818f554e 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1244,6 +1244,15 @@ static const struct wled_var_cfg wled4_ovp_cfg =3D { .size =3D ARRAY_SIZE(wled4_ovp_values), }; =20 +static const u32 pmi8994_wled_ovp_values[] =3D { + 31000, 29500, 19400, 17800, +}; + +static const struct wled_var_cfg pmi8994_wled_ovp_cfg =3D { + .values =3D pmi8994_wled_ovp_values, + .size =3D ARRAY_SIZE(pmi8994_wled_ovp_values), +}; + static inline u32 wled5_ovp_values_fn(u32 idx) { /* @@ -1357,6 +1366,29 @@ static int wled_configure(struct wled *wled) }, }; =20 + const struct wled_u32_opts pmi8994_wled_opts[] =3D { + { + .name =3D "qcom,current-boost-limit", + .val_ptr =3D &cfg->boost_i_limit, + .cfg =3D &wled4_boost_i_limit_cfg, + }, + { + .name =3D "qcom,current-limit-microamp", + .val_ptr =3D &cfg->string_i_limit, + .cfg =3D &wled4_string_i_limit_cfg, + }, + { + .name =3D "qcom,ovp-millivolt", + .val_ptr =3D &cfg->ovp, + .cfg =3D &pmi8994_wled_ovp_cfg, + }, + { + .name =3D "qcom,switching-freq", + .val_ptr =3D &cfg->switch_freq, + .cfg =3D &wled3_switch_freq_cfg, + }, + }; + const struct wled_u32_opts wled5_opts[] =3D { { .name =3D "qcom,current-boost-limit", @@ -1423,8 +1455,14 @@ static int wled_configure(struct wled *wled) break; =20 case 4: - u32_opts =3D wled4_opts; - size =3D ARRAY_SIZE(wled4_opts); + if (of_device_is_compatible(dev->of_node, "qcom,pmi8950-wled") || + of_device_is_compatible(dev->of_node, "qcom,pmi8994-wled")) { + u32_opts =3D pmi8994_wled_opts; + size =3D ARRAY_SIZE(pmi8994_wled_opts); + } else { + u32_opts =3D wled4_opts; + size =3D ARRAY_SIZE(wled4_opts); + } *cfg =3D wled4_config_defaults; wled->wled_set_brightness =3D wled4_set_brightness; wled->wled_sync_toggle =3D wled3_sync_toggle; diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index c137d6afe484..1b05dfbd5195 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1732,8 +1732,10 @@ static int au1200fb_drv_probe(struct platform_device= *dev) =20 /* Now hook interrupt too */ irq =3D platform_get_irq(dev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret =3D irq; + goto failed; + } =20 ret =3D request_irq(irq, au1200fb_handle_irq, IRQF_SHARED, "lcd", (void *)dev); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fb= con.c index 78a5b22c8d15..703c4e851612 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1023,7 +1023,8 @@ static void fbcon_init(struct vc_data *vc, bool init) return; =20 if (!info->fbcon_par) - con2fb_acquire_newinfo(vc, info, vc->vc_num); + if (con2fb_acquire_newinfo(vc, info, vc->vc_num)) + return; =20 /* If we are not the first console on this fb, copy the font from that console */ diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fb= con.h index 25691d4b027b..7945b360862c 100644 --- a/drivers/video/fbdev/core/fbcon.h +++ b/drivers/video/fbdev/core/fbcon.h @@ -30,7 +30,6 @@ struct fbcon_display { #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION u_short scrollmode; /* Scroll Method, use fb_scrollmode() = */ #endif - u_short inverse; /* !=3D 0 text black on white as defau= lt */ short yscroll; /* Hardware scrolling */ int vrows; /* number of virtual rows */ int cursor_shape; diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c index e3a9bb7e9dea..e8992bdd3c9a 100644 --- a/drivers/video/fbdev/ffb.c +++ b/drivers/video/fbdev/ffb.c @@ -336,6 +336,9 @@ struct ffb_dac { }; =20 #define FFB_DAC_UCTRL 0x1001 /* User Control */ +#define FFB_DAC_UCTRL_OVENAB 0x00000008 /* Overlay Enable */ +#define FFB_DAC_UCTRL_WMODE 0x00000030 /* Window Mode */ +#define FFB_DAC_UCTRL_WM_COMB 0x00000000 /* Window Mode =3D Combined */ #define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ #define FFB_DAC_UCTRL_MANREV_SHIFT 8 #define FFB_DAC_TGEN 0x6000 /* Timing Generator */ @@ -426,7 +429,7 @@ static void ffb_switch_from_graph(struct ffb_par *par) { struct ffb_fbc __iomem *fbc =3D par->fbc; struct ffb_dac __iomem *dac =3D par->dac; - unsigned long flags; + unsigned long flags, uctrl; =20 spin_lock_irqsave(&par->lock, flags); FFBWait(par); @@ -451,6 +454,15 @@ static void ffb_switch_from_graph(struct ffb_par *par) upa_writel((FFB_DAC_CUR_CTRL_P0 | FFB_DAC_CUR_CTRL_P1), &dac->value2); =20 + /* Disable overlay and window modes. */ + upa_writel(FFB_DAC_UCTRL, &dac->type); + uctrl =3D upa_readl(&dac->value); + uctrl &=3D ~FFB_DAC_UCTRL_WMODE; + uctrl |=3D FFB_DAC_UCTRL_WM_COMB; + uctrl &=3D ~FFB_DAC_UCTRL_OVENAB; + upa_writel(FFB_DAC_UCTRL, &dac->type); + upa_writel(uctrl, &dac->value); + spin_unlock_irqrestore(&par->lock, flags); } =20 diff --git a/drivers/video/fbdev/vt8500lcdfb.c b/drivers/video/fbdev/vt8500= lcdfb.c index 42d39a9d5130..f62fe1a9dd62 100644 --- a/drivers/video/fbdev/vt8500lcdfb.c +++ b/drivers/video/fbdev/vt8500lcdfb.c @@ -367,7 +367,7 @@ static int vt8500lcd_probe(struct platform_device *pdev) if (fbi->palette_cpu =3D=3D NULL) { dev_err(&pdev->dev, "Failed to allocate palette buffer\n"); ret =3D -ENOMEM; - goto failed_free_io; + goto failed_free_mem_virt; } =20 irq =3D platform_get_irq(pdev, 0); @@ -431,6 +431,9 @@ static int vt8500lcd_probe(struct platform_device *pdev) failed_free_palette: dma_free_coherent(&pdev->dev, fbi->palette_size, fbi->palette_cpu, fbi->palette_phys); +failed_free_mem_virt: + dma_free_coherent(&pdev->dev, fbi->fb.fix.smem_len, + fbi->fb.screen_buffer, fbi->fb.fix.smem_start); failed_free_io: iounmap(fbi->regbase); failed_free_res: diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_t= iming.c index bebd371c6b93..a6ec392253c3 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -181,7 +181,7 @@ struct display_timings *of_get_display_timings(const st= ruct device_node *np) if (disp->num_timings =3D=3D 0) { /* should never happen, as entry was already found above */ pr_err("%pOF: no timings specified\n", np); - goto entryfail; + goto timingfail; } =20 disp->timings =3D kcalloc(disp->num_timings, @@ -189,13 +189,13 @@ struct display_timings *of_get_display_timings(const = struct device_node *np) GFP_KERNEL); if (!disp->timings) { pr_err("%pOF: could not allocate timings array\n", np); - goto entryfail; + goto timingfail; } =20 disp->num_timings =3D 0; disp->native_mode =3D 0; =20 - for_each_child_of_node(timings_np, entry) { + for_each_child_of_node_scoped(timings_np, child) { struct display_timing *dt; int r; =20 @@ -206,7 +206,7 @@ struct display_timings *of_get_display_timings(const st= ruct device_node *np) goto timingfail; } =20 - r =3D of_parse_display_timing(entry, dt); + r =3D of_parse_display_timing(child, dt); if (r) { /* * to not encourage wrong devicetrees, fail in case of @@ -218,7 +218,7 @@ struct display_timings *of_get_display_timings(const st= ruct device_node *np) goto timingfail; } =20 - if (native_mode =3D=3D entry) + if (native_mode =3D=3D child) disp->native_mode =3D disp->num_timings; =20 disp->timings[disp->num_timings] =3D dt; diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c index c703586c6e5f..b6797845a48f 100644 --- a/drivers/watchdog/imx7ulp_wdt.c +++ b/drivers/watchdog/imx7ulp_wdt.c @@ -342,6 +342,7 @@ static int imx7ulp_wdt_probe(struct platform_device *pd= ev) watchdog_stop_on_reboot(wdog); watchdog_stop_on_unregister(wdog); watchdog_set_drvdata(wdog, imx7ulp_wdt); + watchdog_set_nowayout(wdog, nowayout); =20 imx7ulp_wdt->hw =3D of_device_get_match_data(dev); ret =3D imx7ulp_wdt_init(imx7ulp_wdt, wdog->timeout * imx7ulp_wdt->hw->wd= og_clock_rate); diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 239947df613d..1392e557fa37 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -183,6 +183,12 @@ static void _wdt_update_timeout(unsigned int t) superio_outb(t >> 8, WDTVALMSB); } =20 +/* Internal function, should be called after superio_select(GPIO) */ +static bool _wdt_running(void) +{ + return superio_inb(WDTVALLSB) || (max_units > 255 && superio_inb(WDTVALMS= B)); +} + static int wdt_update_timeout(unsigned int t) { int ret; @@ -365,6 +371,12 @@ static int __init it87_wdt_init(void) } } =20 + /* wdt already left running by firmware? */ + if (_wdt_running()) { + pr_info("Left running by firmware.\n"); + set_bit(WDOG_HW_RUNNING, &wdt_dev.status); + } + superio_exit(); =20 if (timeout < 1 || timeout > max_units * 60) { diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index 0606142ffc5e..3842a0b1b6cb 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -444,7 +444,7 @@ static int starfive_wdt_probe(struct platform_device *p= dev) platform_set_drvdata(pdev, wdt); pm_runtime_enable(&pdev->dev); if (pm_runtime_enabled(&pdev->dev)) { - ret =3D pm_runtime_get_sync(&pdev->dev); + ret =3D pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret; } else { diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 204ec1bcbd52..a76d5530533f 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -716,6 +716,7 @@ static int __init balloon_add_regions(void) static int __init balloon_init(void) { struct task_struct *task; + unsigned long current_pages; int rc; =20 if (!xen_domain()) @@ -723,12 +724,18 @@ static int __init balloon_init(void) =20 pr_info("Initialising balloon driver\n"); =20 - if (xen_released_pages >=3D get_num_physpages()) { - WARN(1, "Released pages underflow current target"); - return -ERANGE; + if (xen_pv_domain()) { + if (xen_released_pages >=3D xen_start_info->nr_pages) + goto underflow; + current_pages =3D min(xen_start_info->nr_pages - + xen_released_pages, max_pfn); + } else { + if (xen_unpopulated_pages >=3D get_num_physpages()) + goto underflow; + current_pages =3D get_num_physpages() - xen_unpopulated_pages; } =20 - balloon_stats.current_pages =3D get_num_physpages() - xen_released_pages; + balloon_stats.current_pages =3D current_pages; balloon_stats.target_pages =3D balloon_stats.current_pages; balloon_stats.balloon_low =3D 0; balloon_stats.balloon_high =3D 0; @@ -759,6 +766,10 @@ static int __init balloon_init(void) xen_balloon_init(); =20 return 0; + + underflow: + WARN(1, "Released pages underflow current target"); + return -ERANGE; } subsys_initcall(balloon_init); =20 diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c index 76f6f26265a3..12fbe8938259 100644 --- a/drivers/xen/grant-dma-ops.c +++ b/drivers/xen/grant-dma-ops.c @@ -362,7 +362,8 @@ static int xen_grant_init_backend_domid(struct device *= dev, if (np) { ret =3D xen_dt_grant_init_backend_domid(dev, np, backend_domid); of_node_put(np); - } else if (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT) || xen_pv_domain()) { + } else if (!xen_initial_domain() && + (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT) || xen_pv_domain())) { dev_info(dev, "Using dom0 as backend\n"); *backend_domid =3D 0; ret =3D 0; diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-allo= c.c index a39f2d36dd9c..ae46291e99a9 100644 --- a/drivers/xen/unpopulated-alloc.c +++ b/drivers/xen/unpopulated-alloc.c @@ -18,6 +18,9 @@ static unsigned int list_count; =20 static struct resource *target_resource; =20 +/* Pages to subtract from the memory count when setting balloon target. */ +unsigned long xen_unpopulated_pages __initdata; + /* * If arch is not happy with system "iomem_resource" being used for * the region allocation it can provide it's own view by creating specific diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbu= s/xenbus_probe_frontend.c index fcb335bb7b18..1fdf5be19343 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -148,11 +148,9 @@ static void xenbus_frontend_dev_shutdown(struct device= *_dev) } =20 static const struct dev_pm_ops xenbus_pm_ops =3D { - .suspend =3D xenbus_dev_suspend, - .resume =3D xenbus_frontend_dev_resume, .freeze =3D xenbus_dev_suspend, .thaw =3D xenbus_dev_cancel, - .restore =3D xenbus_dev_resume, + .restore =3D xenbus_frontend_dev_resume, }; =20 static struct xen_bus_type xenbus_frontend =3D { diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5e3d1a87b7e9..774bdafc822c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6196,6 +6196,10 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, str= uct fstrim_range *range) range->minlen); =20 trimmed +=3D group_trimmed; + if (ret =3D=3D -ERESTARTSYS || ret =3D=3D -EINTR) { + btrfs_put_block_group(cache); + break; + } if (ret) { bg_failed++; bg_ret =3D ret; @@ -6209,6 +6213,9 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, stru= ct fstrim_range *range) "failed to trim %llu block group(s), last error %d", bg_failed, bg_ret); =20 + if (ret =3D=3D -ERESTARTSYS || ret =3D=3D -EINTR) + return ret; + mutex_lock(&fs_devices->device_list_mutex); list_for_each_entry(device, &fs_devices->devices, dev_list) { if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) @@ -6217,10 +6224,12 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, st= ruct fstrim_range *range) ret =3D btrfs_trim_free_extents(device, &group_trimmed); =20 trimmed +=3D group_trimmed; + if (ret =3D=3D -ERESTARTSYS || ret =3D=3D -EINTR) + break; if (ret) { dev_failed++; dev_ret =3D ret; - break; + continue; } } mutex_unlock(&fs_devices->device_list_mutex); @@ -6230,6 +6239,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, stru= ct fstrim_range *range) "failed to trim %llu device(s), last error %d", dev_failed, dev_ret); range->len =3D trimmed; + if (ret =3D=3D -ERESTARTSYS || ret =3D=3D -EINTR) + return ret; if (bg_ret) return bg_ret; return dev_ret; diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index c46ea2ecf188..622febdb61e2 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1129,11 +1129,14 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_inf= o) } if (ret > 0) { /* - * Shouldn't happen, but in case it does we - * don't need to do the btrfs_next_item, just - * continue. + * Shouldn't happen because the key should still + * be there (return 0), but in case it does it + * means we have reached the end of the tree - + * there are no more leaves with items that have + * a key greater than or equals to @found_key, + * so just stop the search loop. */ - continue; + break; } } ret =3D btrfs_next_item(tree_root, path); @@ -1601,8 +1604,10 @@ static int __del_qgroup_relation(struct btrfs_trans_= handle *trans, u64 src, if (ret < 0 && ret !=3D -ENOENT) goto out; ret2 =3D del_qgroup_relation_item(trans, dst, src); - if (ret2 < 0 && ret2 !=3D -ENOENT) + if (ret2 < 0 && ret2 !=3D -ENOENT) { + ret =3D ret2; goto out; + } =20 /* At least one deletion succeeded, return 0 */ if (!ret || !ret2) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index ce1e5b5dae3a..6dbbb03be562 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -2457,13 +2457,6 @@ int btrfs_commit_transaction(struct btrfs_trans_hand= le *trans) list_add_tail(&fs_info->chunk_root->dirty_list, &cur_trans->switch_commits); =20 - if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { - btrfs_set_root_node(&fs_info->block_group_root->root_item, - fs_info->block_group_root->node); - list_add_tail(&fs_info->block_group_root->dirty_list, - &cur_trans->switch_commits); - } - switch_commit_roots(trans); =20 ASSERT(list_empty(&cur_trans->dirty_bgs)); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8207b0b4c43a..6ce083a6ed61 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3980,8 +3980,14 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_= info) * this shouldn't happen, it means the last relocate * failed */ - if (ret =3D=3D 0) - BUG(); /* FIXME break ? */ + if (unlikely(ret =3D=3D 0)) { + btrfs_err(fs_info, + "unexpected exact match of CHUNK_ITEM in chunk tree, offset 0x%llx", + key.offset); + mutex_unlock(&fs_info->reclaim_bgs_lock); + ret =3D -EUCLEAN; + goto error; + } =20 ret =3D btrfs_previous_item(chunk_root, path, 0, BTRFS_CHUNK_ITEM_KEY); diff --git a/fs/buffer.c b/fs/buffer.c index 32df6163ffed..c225eef13279 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2950,6 +2950,10 @@ bool try_to_free_buffers(struct folio *folio) if (folio_test_writeback(folio)) return false; =20 + /* Misconfigured folio check */ + if (WARN_ON_ONCE(!folio_buffers(folio))) + return true; + if (mapping =3D=3D NULL) { /* can this still happen? */ ret =3D drop_buffers(folio, &buffers_to_free); goto out; diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 2c92de964c5a..db4d11604e9d 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1833,6 +1833,7 @@ int ceph_uninline_data(struct file *file) struct ceph_osd_request *req =3D NULL; struct ceph_cap_flush *prealloc_cf =3D NULL; struct folio *folio =3D NULL; + struct ceph_snap_context *snapc =3D NULL; u64 inline_version =3D CEPH_INLINE_NONE; struct page *pages[1]; int err =3D 0; @@ -1860,6 +1861,24 @@ int ceph_uninline_data(struct file *file) if (inline_version =3D=3D 1) /* initial version, no data */ goto out_uninline; =20 + down_read(&fsc->mdsc->snap_rwsem); + spin_lock(&ci->i_ceph_lock); + if (__ceph_have_pending_cap_snap(ci)) { + struct ceph_cap_snap *capsnap =3D + list_last_entry(&ci->i_cap_snaps, + struct ceph_cap_snap, + ci_item); + snapc =3D ceph_get_snap_context(capsnap->context); + } else { + if (!ci->i_head_snapc) { + ci->i_head_snapc =3D ceph_get_snap_context( + ci->i_snap_realm->cached_context); + } + snapc =3D ceph_get_snap_context(ci->i_head_snapc); + } + spin_unlock(&ci->i_ceph_lock); + up_read(&fsc->mdsc->snap_rwsem); + folio =3D read_mapping_folio(inode->i_mapping, 0, file); if (IS_ERR(folio)) { err =3D PTR_ERR(folio); @@ -1875,7 +1894,7 @@ int ceph_uninline_data(struct file *file) req =3D ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, ceph_vino(inode), 0, &len, 0, 1, CEPH_OSD_OP_CREATE, CEPH_OSD_FLAG_WRITE, - NULL, 0, 0, false); + snapc, 0, 0, false); if (IS_ERR(req)) { err =3D PTR_ERR(req); goto out_unlock; @@ -1891,7 +1910,7 @@ int ceph_uninline_data(struct file *file) req =3D ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, ceph_vino(inode), 0, &len, 1, 3, CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE, - NULL, ci->i_truncate_seq, + snapc, ci->i_truncate_seq, ci->i_truncate_size, false); if (IS_ERR(req)) { err =3D PTR_ERR(req); @@ -1954,6 +1973,7 @@ int ceph_uninline_data(struct file *file) folio_put(folio); } out: + ceph_put_snap_context(snapc); ceph_free_cap_flush(prealloc_cf); dout("uninline_data %p %llx.%llx inline_version %llu =3D %d\n", inode, ceph_vinop(inode), inline_version, err); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 0ec78d87519b..0757eb7611da 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -2468,6 +2468,7 @@ static int ceph_zero_partial_object(struct inode *ino= de, struct ceph_inode_info *ci =3D ceph_inode(inode); struct ceph_fs_client *fsc =3D ceph_inode_to_fs_client(inode); struct ceph_osd_request *req; + struct ceph_snap_context *snapc; int ret =3D 0; loff_t zero =3D 0; int op; @@ -2482,12 +2483,25 @@ static int ceph_zero_partial_object(struct inode *i= node, op =3D CEPH_OSD_OP_ZERO; } =20 + spin_lock(&ci->i_ceph_lock); + if (__ceph_have_pending_cap_snap(ci)) { + struct ceph_cap_snap *capsnap =3D + list_last_entry(&ci->i_cap_snaps, + struct ceph_cap_snap, + ci_item); + snapc =3D ceph_get_snap_context(capsnap->context); + } else { + BUG_ON(!ci->i_head_snapc); + snapc =3D ceph_get_snap_context(ci->i_head_snapc); + } + spin_unlock(&ci->i_ceph_lock); + req =3D ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, ceph_vino(inode), offset, length, 0, 1, op, CEPH_OSD_FLAG_WRITE, - NULL, 0, 0, false); + snapc, 0, 0, false); if (IS_ERR(req)) { ret =3D PTR_ERR(req); goto out; @@ -2501,6 +2515,7 @@ static int ceph_zero_partial_object(struct inode *ino= de, ceph_osdc_put_request(req); =20 out: + ceph_put_snap_context(snapc); return ret; } =20 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a3d3c9fc6426..8d9cd6574d32 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3172,6 +3172,9 @@ static int ext4_split_extent_at(handle_t *handle, BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) =3D= =3D (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); =20 + /* Do not cache extents that are in the process of being modified. */ + flags |=3D EXT4_EX_NOCACHE; + ext_debug(inode, "logical block %llu\n", (unsigned long long)split); =20 ext4_ext_show_leaf(inode, path); @@ -3342,6 +3345,9 @@ static int ext4_split_extent(handle_t *handle, ee_len =3D ext4_ext_get_actual_len(ex); unwritten =3D ext4_ext_is_unwritten(ex); =20 + /* Do not cache extents that are in the process of being modified. */ + flags |=3D EXT4_EX_NOCACHE; + if (map->m_lblk + map->m_len < ee_block + ee_len) { split_flag1 =3D split_flag & EXT4_EXT_MAY_ZEROOUT; flags1 =3D flags | EXT4_GET_BLOCKS_PRE_IO; @@ -5252,7 +5258,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t = *handle, if (!extent) { EXT4_ERROR_INODE(inode, "unexpected hole at %lu", (unsigned long) *iterator); - return -EFSCORRUPTED; + ret =3D -EFSCORRUPTED; + goto out; } if (SHIFT =3D=3D SHIFT_LEFT && *iterator > le32_to_cpu(extent->ee_block)) { diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 4f931f80cb34..d34affd2075e 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -963,6 +963,7 @@ static long ext4_ioctl_group_add(struct file *file, =20 err =3D ext4_group_add(sb, input); if (EXT4_SB(sb)->s_journal) { + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL); jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); err2 =3D jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); @@ -1315,6 +1316,8 @@ static long __ext4_ioctl(struct file *filp, unsigned = int cmd, unsigned long arg) =20 err =3D ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); if (EXT4_SB(sb)->s_journal) { + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, + NULL); jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); err2 =3D jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 5ba161bd66a3..d095c4a218a3 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1090,8 +1090,6 @@ static inline int should_optimize_scan(struct ext4_al= location_context *ac) return 0; if (ac->ac_criteria >=3D CR_GOAL_LEN_SLOW) return 0; - if (!ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) - return 0; return 1; } =20 diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c5c6faa995e1..561f670768f9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5563,6 +5563,10 @@ static int __ext4_fill_super(struct fs_context *fc, = struct super_block *sb) clear_opt2(sb, MB_OPTIMIZE_SCAN); } =20 + err =3D ext4_percpu_param_init(sbi); + if (err) + goto failed_mount5; + err =3D ext4_mb_init(sb); if (err) { ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", @@ -5578,10 +5582,6 @@ static int __ext4_fill_super(struct fs_context *fc, = struct super_block *sb) sbi->s_journal->j_commit_callback =3D ext4_journal_commit_callback; =20 - err =3D ext4_percpu_param_init(sbi); - if (err) - goto failed_mount6; - if (ext4_has_feature_flex_bg(sb)) if (!ext4_fill_flex_info(sb)) { ext4_msg(sb, KERN_ERR, @@ -5661,8 +5661,8 @@ failed_mount8: __maybe_unused failed_mount6: ext4_mb_release(sb); ext4_flex_groups_free(sbi); - ext4_percpu_param_destroy(sbi); failed_mount5: + ext4_percpu_param_destroy(sbi); ext4_ext_release(sb); ext4_release_system_zone(sb); failed_mount4a: diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 2116c486843b..e189fbf95fca 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -325,7 +325,12 @@ static int msdos_rmdir(struct inode *dir, struct dentr= y *dentry) err =3D fat_remove_entries(dir, &sinfo); /* and releases bh */ if (err) goto out; - drop_nlink(dir); + if (dir->i_nlink >=3D 3) + drop_nlink(dir); + else { + fat_fs_error(sb, "parent dir link count too low (%u)", + dir->i_nlink); + } =20 clear_nlink(inode); fat_truncate_time(inode, NULL, S_CTIME); diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 3cf22a6727f1..7d7ac30c6eff 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -806,7 +806,12 @@ static int vfat_rmdir(struct inode *dir, struct dentry= *dentry) err =3D fat_remove_entries(dir, &sinfo); /* and releases bh */ if (err) goto out; - drop_nlink(dir); + if (dir->i_nlink >=3D 3) + drop_nlink(dir); + else { + fat_fs_error(sb, "parent dir link count too low (%u)", + dir->i_nlink); + } =20 clear_nlink(inode); fat_truncate_time(inode, NULL, S_ATIME|S_MTIME); diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 64c2d0814ed6..100bd3474476 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "internal.h" =20 /* diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 7ed276a8f599..bc0f7023adcf 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -317,6 +317,12 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, __= be64 *start, __be64 *end) } } =20 +static inline struct buffer_head * +metapath_dibh(struct metapath *mp) +{ + return mp->mp_bh[0]; +} + static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, unsigned int x, unsigned int h) { @@ -660,7 +666,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, stru= ct iomap *iomap, { struct gfs2_inode *ip =3D GFS2_I(inode); struct gfs2_sbd *sdp =3D GFS2_SB(inode); - struct buffer_head *dibh =3D mp->mp_bh[0]; + struct buffer_head *dibh =3D metapath_dibh(mp); u64 bn; unsigned n, i, blks, alloced =3D 0, iblks =3D 0, branch_start =3D 0; size_t dblks =3D iomap->length >> inode->i_blkbits; @@ -1120,10 +1126,18 @@ static int gfs2_iomap_begin(struct inode *inode, lo= ff_t pos, loff_t length, goto out_unlock; break; default: - goto out_unlock; + goto out; } =20 ret =3D gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp); + if (ret) + goto out_unlock; + +out: + if (iomap->type =3D=3D IOMAP_INLINE) { + iomap->private =3D metapath_dibh(&mp); + get_bh(iomap->private); + } =20 out_unlock: release_metapath(&mp); @@ -1137,6 +1151,9 @@ static int gfs2_iomap_end(struct inode *inode, loff_t= pos, loff_t length, struct gfs2_inode *ip =3D GFS2_I(inode); struct gfs2_sbd *sdp =3D GFS2_SB(inode); =20 + if (iomap->private) + brelse(iomap->private); + switch (flags & (IOMAP_WRITE | IOMAP_ZERO)) { case IOMAP_WRITE: if (flags & IOMAP_DIRECT) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index c4bc86c3535b..9265262807f0 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1396,31 +1396,45 @@ static int glocks_pending(unsigned int num_gh, stru= ct gfs2_holder *ghs) * gfs2_glock_async_wait - wait on multiple asynchronous glock acquisitions * @num_gh: the number of holders in the array * @ghs: the glock holder array + * @retries: number of retries attempted so far * * Returns: 0 on success, meaning all glocks have been granted and are hel= d. * -ESTALE if the request timed out, meaning all glocks were rele= ased, * and the caller should retry the operation. */ =20 -int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs) +int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, + unsigned int retries) { struct gfs2_sbd *sdp =3D ghs[0].gh_gl->gl_name.ln_sbd; - int i, ret =3D 0, timeout =3D 0; unsigned long start_time =3D jiffies; + int i, ret =3D 0; + long timeout; =20 might_sleep(); - /* - * Total up the (minimum hold time * 2) of all glocks and use that to - * determine the max amount of time we should wait. - */ - for (i =3D 0; i < num_gh; i++) - timeout +=3D ghs[i].gh_gl->gl_hold_time << 1; =20 - if (!wait_event_timeout(sdp->sd_async_glock_wait, + timeout =3D GL_GLOCK_MIN_HOLD; + if (retries) { + unsigned int max_shift; + long incr; + + /* Add a random delay and increase the timeout exponentially. */ + max_shift =3D BITS_PER_LONG - 2 - __fls(GL_GLOCK_HOLD_INCR); + incr =3D min(GL_GLOCK_HOLD_INCR << min(retries - 1, max_shift), + 10 * HZ - GL_GLOCK_MIN_HOLD); + schedule_timeout_interruptible(get_random_long() % (incr / 3)); + if (signal_pending(current)) + goto interrupted; + timeout +=3D (incr / 3) + get_random_long() % (incr / 3); + } + + if (!wait_event_interruptible_timeout(sdp->sd_async_glock_wait, !glocks_pending(num_gh, ghs), timeout)) { ret =3D -ESTALE; /* request timed out. */ goto out; } + if (signal_pending(current)) + goto interrupted; =20 for (i =3D 0; i < num_gh; i++) { struct gfs2_holder *gh =3D &ghs[i]; @@ -1444,6 +1458,10 @@ int gfs2_glock_async_wait(unsigned int num_gh, struc= t gfs2_holder *ghs) } } return ret; + +interrupted: + ret =3D -EINTR; + goto out; } =20 /** diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index aae9fabbb76c..e86dccdd6133 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -204,7 +204,8 @@ int gfs2_glock_poll(struct gfs2_holder *gh); int gfs2_instantiate(struct gfs2_holder *gh); int gfs2_glock_holder_ready(struct gfs2_holder *gh); int gfs2_glock_wait(struct gfs2_holder *gh); -int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs); +int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, + unsigned int retries); void gfs2_glock_dq(struct gfs2_holder *gh); void gfs2_glock_dq_wait(struct gfs2_holder *gh); void gfs2_glock_dq_uninit(struct gfs2_holder *gh); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 1cb5ce63fbf6..45040622d316 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1408,7 +1408,7 @@ static int gfs2_rename(struct inode *odir, struct den= try *odentry, unsigned int num_gh; int dir_rename =3D 0; struct gfs2_diradd da =3D { .nr_blocks =3D 0, .save_loc =3D 0, }; - unsigned int x; + unsigned int retries =3D 0, x; int error; =20 gfs2_holder_mark_uninitialized(&r_gh); @@ -1458,12 +1458,17 @@ static int gfs2_rename(struct inode *odir, struct d= entry *odentry, num_gh++; } =20 +again: for (x =3D 0; x < num_gh; x++) { error =3D gfs2_glock_nq(ghs + x); if (error) goto out_gunlock; } - error =3D gfs2_glock_async_wait(num_gh, ghs); + error =3D gfs2_glock_async_wait(num_gh, ghs, retries); + if (error =3D=3D -ESTALE) { + retries++; + goto again; + } if (error) goto out_gunlock; =20 @@ -1652,7 +1657,7 @@ static int gfs2_exchange(struct inode *odir, struct d= entry *odentry, struct gfs2_sbd *sdp =3D GFS2_SB(odir); struct gfs2_holder ghs[4], r_gh; unsigned int num_gh; - unsigned int x; + unsigned int retries =3D 0, x; umode_t old_mode =3D oip->i_inode.i_mode; umode_t new_mode =3D nip->i_inode.i_mode; int error; @@ -1696,13 +1701,18 @@ static int gfs2_exchange(struct inode *odir, struct= dentry *odentry, gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); num_gh++; =20 +again: for (x =3D 0; x < num_gh; x++) { error =3D gfs2_glock_nq(ghs + x); if (error) goto out_gunlock; } =20 - error =3D gfs2_glock_async_wait(num_gh, ghs); + error =3D gfs2_glock_async_wait(num_gh, ghs, retries); + if (error =3D=3D -ESTALE) { + retries++; + goto again; + } if (error) goto out_gunlock; =20 @@ -2095,6 +2105,14 @@ static int gfs2_getattr(struct mnt_idmap *idmap, return 0; } =20 +static bool fault_in_fiemap(struct fiemap_extent_info *fi) +{ + struct fiemap_extent __user *dest =3D fi->fi_extents_start; + size_t size =3D sizeof(*dest) * fi->fi_extents_max; + + return fault_in_safe_writeable((char __user *)dest, size) =3D=3D 0; +} + static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fie= info, u64 start, u64 len) { @@ -2104,14 +2122,22 @@ static int gfs2_fiemap(struct inode *inode, struct = fiemap_extent_info *fieinfo, =20 inode_lock_shared(inode); =20 +retry: ret =3D gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); if (ret) goto out; =20 + pagefault_disable(); ret =3D iomap_fiemap(inode, fieinfo, start, len, &gfs2_iomap_ops); + pagefault_enable(); =20 gfs2_glock_dq_uninit(&gh); =20 + if (ret =3D=3D -EFAULT && fault_in_fiemap(fieinfo)) { + fieinfo->fi_extents_mapped =3D 0; + goto retry; + } + out: inode_unlock_shared(inode); return ret; diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index c0089849be50..fb437598e262 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -629,7 +629,7 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tr= ee, u32 num) if (node) { pr_crit("new node %u already hashed?\n", num); WARN_ON(1); - return node; + return ERR_PTR(-EEXIST); } node =3D __hfs_bnode_create(tree, num); if (!node) diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 2619e5371ec9..2dd17192d11c 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -604,6 +604,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct = hfs_find_data *fd) int hfsplus_cat_write_inode(struct inode *inode) { struct inode *main_inode =3D inode; + struct hfs_btree *tree =3D HFSPLUS_SB(inode->i_sb)->cat_tree; struct hfs_find_data fd; hfsplus_cat_entry entry; int res =3D 0; @@ -614,7 +615,7 @@ int hfsplus_cat_write_inode(struct inode *inode) if (!main_inode->i_nlink) return 0; =20 - if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd)) + if (hfs_find_init(tree, &fd)) /* panic? */ return -EIO; =20 @@ -679,6 +680,15 @@ int hfsplus_cat_write_inode(struct inode *inode) set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags); out: hfs_find_exit(&fd); + + if (!res) { + res =3D hfs_btree_write(tree); + if (res) { + pr_err("b-tree write err: %d, ino %lu\n", + res, inode->i_ino); + } + } + return res; } =20 diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 7e889820a63d..954ceaa748e6 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -52,6 +52,12 @@ static int hfsplus_system_read_inode(struct inode *inode) return -EIO; } =20 + /* + * Assign a dummy file type, for may_open() requires that + * an inode has a valid file type. + */ + inode->i_mode =3D S_IFREG; + return 0; } =20 diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 8158ab18e1ae..ec6b019f087f 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -381,9 +381,13 @@ static loff_t iomap_dio_bio_iter(const struct iomap_it= er *iter, nr_pages =3D bio_iov_vecs_to_alloc(dio->submit.iter, BIO_MAX_VECS); do { size_t n; - if (dio->error) { - iov_iter_revert(dio->submit.iter, copied); - copied =3D ret =3D 0; + + /* + * If completions already occurred and reported errors, give up now and + * don't bother submitting more bios. + */ + if (unlikely(data_race(dio->error))) { + ret =3D 0; goto out; } =20 diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index cb6d1fda66a7..32e589bb663a 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2312,6 +2312,7 @@ int jfsIOWait(void *arg) { struct lbuf *bp; =20 + set_freezable(); do { spin_lock_irq(&log_redrive_lock); while ((bp =3D log_redrive_list)) { diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 57d7a4300210..649184d712ad 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1227,7 +1227,7 @@ static int jfs_rename(struct mnt_idmap *idmap, struct= inode *old_dir, jfs_err("jfs_rename: dtInsert returned -EIO"); goto out_tx; } - if (S_ISDIR(old_ip->i_mode)) + if (S_ISDIR(old_ip->i_mode) && old_dir !=3D new_dir) inc_nlink(new_dir); } /* @@ -1243,7 +1243,9 @@ static int jfs_rename(struct mnt_idmap *idmap, struct= inode *old_dir, goto out_tx; } if (S_ISDIR(old_ip->i_mode)) { - drop_nlink(old_dir); + if (new_ip || old_dir !=3D new_dir) + drop_nlink(old_dir); + if (old_dir !=3D new_dir) { /* * Change inode number of parent for moved directory diff --git a/fs/minix/inode.c b/fs/minix/inode.c index ee8a6fe360e7..820c7753bd10 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -153,10 +153,38 @@ static int minix_remount (struct super_block * sb, in= t * flags, char * data) static bool minix_check_superblock(struct super_block *sb) { struct minix_sb_info *sbi =3D minix_sb(sb); + unsigned long block; =20 - if (sbi->s_imap_blocks =3D=3D 0 || sbi->s_zmap_blocks =3D=3D 0) + if (sbi->s_log_zone_size !=3D 0) { + printk("minix-fs error: zone size must equal block size. " + "s_log_zone_size > 0 is not supported.\n"); + return false; + } + + if (sbi->s_ninodes < 1 || sbi->s_firstdatazone <=3D 4 || + sbi->s_firstdatazone >=3D sbi->s_nzones) return false; =20 + /* Apparently minix can create filesystems that allocate more blocks for + * the bitmaps than needed. We simply ignore that, but verify it didn't + * create one with not enough blocks and bail out if so. + */ + block =3D minix_blocks_needed(sbi->s_ninodes, sb->s_blocksize); + if (sbi->s_imap_blocks < block) { + printk("MINIX-fs: file system does not have enough " + "imap blocks allocated. Refusing to mount.\n"); + return false; + } + + block =3D minix_blocks_needed( + (sbi->s_nzones - sbi->s_firstdatazone + 1), + sb->s_blocksize); + if (sbi->s_zmap_blocks < block) { + printk("MINIX-fs: file system does not have enough " + "zmap blocks allocated. Refusing to mount.\n"); + return false; + } + /* * s_max_size must not exceed the block mapping limitation. This check * is only needed for V1 filesystems, since V2/V3 support an extra level @@ -275,26 +303,6 @@ static int minix_fill_super(struct super_block *s, voi= d *data, int silent) minix_set_bit(0,sbi->s_imap[0]->b_data); minix_set_bit(0,sbi->s_zmap[0]->b_data); =20 - /* Apparently minix can create filesystems that allocate more blocks for - * the bitmaps than needed. We simply ignore that, but verify it didn't - * create one with not enough blocks and bail out if so. - */ - block =3D minix_blocks_needed(sbi->s_ninodes, s->s_blocksize); - if (sbi->s_imap_blocks < block) { - printk("MINIX-fs: file system does not have enough " - "imap blocks allocated. Refusing to mount.\n"); - goto out_no_bitmap; - } - - block =3D minix_blocks_needed( - (sbi->s_nzones - sbi->s_firstdatazone + 1), - s->s_blocksize); - if (sbi->s_zmap_blocks < block) { - printk("MINIX-fs: file system does not have enough " - "zmap blocks allocated. Refusing to mount.\n"); - goto out_no_bitmap; - } - /* set up enough so that it can read an inode */ s->s_op =3D &minix_sops; s->s_time_min =3D 0; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 32e922a20d0d..46f53f40b741 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -70,7 +70,7 @@ const struct address_space_operations nfs_dir_aops =3D { .free_folio =3D nfs_readdir_clear_array, }; =20 -#define NFS_INIT_DTSIZE PAGE_SIZE +#define NFS_INIT_DTSIZE SZ_64K =20 static struct nfs_open_dir_context * alloc_nfs_open_dir_context(struct inode *dir) @@ -81,7 +81,7 @@ alloc_nfs_open_dir_context(struct inode *dir) ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); if (ctx !=3D NULL) { ctx->attr_gencount =3D nfsi->attr_gencount; - ctx->dtsize =3D NFS_INIT_DTSIZE; + ctx->dtsize =3D min(NFS_SERVER(dir)->dtsize, NFS_INIT_DTSIZE); spin_lock(&dir->i_lock); if (list_empty(&nfsi->open_files) && (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 0737d9a15d86..7dae2004c65f 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -464,7 +464,8 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr= *lo, }; struct pnfs_layout_segment *lseg, *next; =20 - set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); + if (test_and_set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) + return !list_empty(&lo->plh_segs); clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(lo->plh_inode)->flags); list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) pnfs_clear_lseg_state(lseg, lseg_list); diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 8cca1329f348..c319c31b0f64 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -643,34 +643,74 @@ static __be32 encode_name_from_id(struct xdr_stream *= xdr, return idmap_id_to_name(xdr, rqstp, type, id); } =20 -__be32 -nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t name= len, - kuid_t *uid) +/** + * nfsd_map_name_to_uid - Map user@domain to local UID + * @rqstp: RPC execution context + * @name: user@domain name to be mapped + * @namelen: length of name, in bytes + * @uid: OUT: mapped local UID value + * + * Returns nfs_ok on success or an NFSv4 status code on failure. + */ +__be32 nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, + size_t namelen, kuid_t *uid) { __be32 status; u32 id =3D -1; =20 + /* + * The idmap lookup below triggers an upcall that invokes + * cache_check(). RQ_USEDEFERRAL must be clear to prevent + * cache_check() from setting RQ_DROPME via svc_defer(). + * NFSv4 servers are not permitted to drop requests. Also + * RQ_DROPME will force NFSv4.1 session slot processing to + * be skipped. + */ + WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); + if (name =3D=3D NULL || namelen =3D=3D 0) return nfserr_inval; =20 status =3D do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, &id); + if (status) + return status; *uid =3D make_kuid(nfsd_user_namespace(rqstp), id); if (!uid_valid(*uid)) status =3D nfserr_badowner; return status; } =20 -__be32 -nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t name= len, - kgid_t *gid) +/** + * nfsd_map_name_to_gid - Map user@domain to local GID + * @rqstp: RPC execution context + * @name: user@domain name to be mapped + * @namelen: length of name, in bytes + * @gid: OUT: mapped local GID value + * + * Returns nfs_ok on success or an NFSv4 status code on failure. + */ +__be32 nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, + size_t namelen, kgid_t *gid) { __be32 status; u32 id =3D -1; =20 + /* + * The idmap lookup below triggers an upcall that invokes + * cache_check(). RQ_USEDEFERRAL must be clear to prevent + * cache_check() from setting RQ_DROPME via svc_defer(). + * NFSv4 servers are not permitted to drop requests. Also + * RQ_DROPME will force NFSv4.1 session slot processing to + * be skipped. + */ + WARN_ON_ONCE(test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)); + if (name =3D=3D NULL || namelen =3D=3D 0) return nfserr_inval; =20 status =3D do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, &id); + if (status) + return status; *gid =3D make_kgid(nfsd_user_namespace(rqstp), id); if (!gid_valid(*gid)) status =3D nfserr_badowner; diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a126fae2df56..5767080362e8 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2763,8 +2763,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) BUG_ON(cstate->replay_owner); out: cstate->status =3D status; - /* Reset deferral mechanism for RPC deferrals */ - set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); return rpc_success; } =20 diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 15189e683e83..d84eaae7cd0b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -5492,6 +5492,22 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, = struct xdr_stream *xdr) args->ops =3D args->iops; args->rqstp =3D rqstp; =20 + /* + * NFSv4 operation decoders can invoke svc cache lookups + * that trigger svc_defer() when RQ_USEDEFERRAL is set, + * setting RQ_DROPME. This creates two problems: + * + * 1. Non-idempotency: Compounds make it too hard to avoid + * problems if a request is deferred and replayed. + * + * 2. Session slot leakage (NFSv4.1+): If RQ_DROPME is set + * during decode but SEQUENCE executes successfully, the + * session slot will be marked INUSE. The request is then + * dropped before encoding, so the slot is never released, + * rendering it permanently unusable by the client. + */ + clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); + return nfsd4_decode_compound(args); } =20 diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index e25989dd2c6b..8f033e30e0d7 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -449,8 +449,10 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYP= E type, =20 is_ext =3D is_attr_ext(attr_b); align =3D sbi->cluster_size; - if (is_ext) + if (is_ext) { align <<=3D attr_b->nres.c_unit; + keep_prealloc =3D false; + } =20 old_valid =3D le64_to_cpu(attr_b->nres.valid_size); old_size =3D le64_to_cpu(attr_b->nres.data_size); @@ -1367,19 +1369,28 @@ int attr_load_runs_range(struct ntfs_inode *ni, enu= m ATTR_TYPE type, CLST vcn; CLST vcn_last =3D (to - 1) >> cluster_bits; CLST lcn, clen; - int err; + int err =3D 0; + int retry =3D 0; =20 for (vcn =3D from >> cluster_bits; vcn <=3D vcn_last; vcn +=3D clen) { if (!run_lookup_entry(run, vcn, &lcn, &clen, NULL)) { + if (retry !=3D 0) { /* Next run_lookup_entry(vcn) also failed. */ + err =3D -EINVAL; + break; + } err =3D attr_load_runs_vcn(ni, type, name, name_len, run, vcn); if (err) - return err; + break; + clen =3D 0; /* Next run_lookup_entry(vcn) must be success. */ + retry++; } + else + retry =3D 0; } =20 - return 0; + return err; } =20 #ifdef CONFIG_NTFS3_LZX_XPRESS diff --git a/fs/ntfs3/attrlist.c b/fs/ntfs3/attrlist.c index 9f4bd8d26090..9355b4416719 100644 --- a/fs/ntfs3/attrlist.c +++ b/fs/ntfs3/attrlist.c @@ -52,6 +52,11 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct AT= TRIB *attr) =20 if (!attr->non_res) { lsize =3D le32_to_cpu(attr->res.data_size); + if (!lsize) { + err =3D -EINVAL; + goto out; + } + /* attr is resident: lsize < record_size (1K or 4K) */ le =3D kvmalloc(al_aligned(lsize), GFP_KERNEL); if (!le) { @@ -66,6 +71,10 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct AT= TRIB *attr) u16 run_off =3D le16_to_cpu(attr->nres.run_off); =20 lsize =3D le64_to_cpu(attr->nres.data_size); + if (!lsize) { + err =3D -EINVAL; + goto out; + } =20 run_init(&ni->attr_list.run); =20 diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a7fe2e02c32e..212737a816d7 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb,= struct iov_iter *from) goto out; =20 if (lcn =3D=3D SPARSE_LCN) { - ni->i_valid =3D valid =3D - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid =3D frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid =3D=3D valid) { + err =3D -EINVAL; + goto out; + } + ni->i_valid =3D valid; continue; } =20 diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 2a1aeab53ea4..598b7f42b5e7 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -3431,6 +3431,9 @@ static int do_action(struct ntfs_log *log, struct OPE= N_ATTR_ENRTY *oe, =20 e1 =3D Add2Ptr(attr, le16_to_cpu(lrh->attr_off)); esize =3D le16_to_cpu(e1->size); + if (PtrOffset(e1, Add2Ptr(hdr, used)) < esize) + goto dirty_vol; + e2 =3D Add2Ptr(e1, esize); =20 memmove(e1, e2, PtrOffset(e2, Add2Ptr(hdr, used))); diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c index 446079b0866d..e17d4c1ba06f 100644 --- a/fs/ntfs3/fsntfs.c +++ b/fs/ntfs3/fsntfs.c @@ -1272,6 +1272,12 @@ int ntfs_read_run_nb(struct ntfs_sb_info *sbi, const= struct runs_tree *run, =20 } while (len32); =20 + if (!run) { + err =3D -EINVAL; + goto out; + } + + /* Get next fragment to read. */ vcn_next =3D vcn + clen; if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) || vcn !=3D vcn_next) { diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index f227db9f76c2..4330c2b39e50 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1192,7 +1192,12 @@ int indx_find(struct ntfs_index *indx, struct ntfs_i= node *ni, return -EINVAL; } =20 - fnd_push(fnd, node, e); + err =3D fnd_push(fnd, node, e); + + if (err) { + put_indx_node(node); + return err; + } } =20 *entry =3D e; diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index c2268b9e20a6..d0cb529b612a 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -6373,6 +6373,10 @@ static int ocfs2_reflink_xattr_header(handle_t *hand= le, (void *)last - (void *)xe); memset(last, 0, sizeof(struct ocfs2_xattr_entry)); + last =3D &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)] - 1; + } else { + memset(xe, 0, sizeof(struct ocfs2_xattr_entry)); + last =3D NULL; } =20 /* diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index de39e067ae65..0d667e953457 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -659,7 +659,7 @@ static bool ovl_fill_real(struct dir_context *ctx, cons= t char *name, container_of(ctx, struct ovl_readdir_translate, ctx); struct dir_context *orig_ctx =3D rdt->orig_ctx; =20 - if (rdt->parent_ino && strcmp(name, "..") =3D=3D 0) { + if (rdt->parent_ino && namelen =3D=3D 2 && !strncmp(name, "..", 2)) { ino =3D rdt->parent_ino; } else if (rdt->cache) { struct ovl_cache_entry *p; diff --git a/fs/proc/array.c b/fs/proc/array.c index 5e4f7b411fbd..363d9331216b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -531,7 +531,7 @@ static int do_task_stat(struct seq_file *m, struct pid_= namespace *ns, } =20 sid =3D task_session_nr_ns(task, ns); - ppid =3D task_tgid_nr_ns(task->real_parent, ns); + ppid =3D task_ppid_nr_ns(task, ns); pgid =3D task_pgrp_nr_ns(task, ns); =20 unlock_task_sighand(task, &flags); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index f1848cdd6d34..7b6d6378a3b8 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -298,6 +298,17 @@ void persistent_ram_save_old(struct persistent_ram_zon= e *prz) if (!size) return; =20 + /* + * If the existing buffer is differently sized, free it so a new + * one is allocated. This can happen when persistent_ram_save_old() + * is called early in boot and later for a timer-triggered + * survivable crash when the crash dumps don't match in size + * (which would be extremely unlikely given kmsg buffers usually + * exceed prz buffer sizes). + */ + if (prz->old_log && prz->old_log_size !=3D size) + persistent_ram_free_old(prz); + if (!prz->old_log) { persistent_ram_ecc_old(prz); prz->old_log =3D kvzalloc(size, GFP_KERNEL); @@ -446,6 +457,13 @@ static void *persistent_ram_vmap(phys_addr_t start, si= ze_t size, vaddr =3D vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot); kfree(pages); =20 + /* + * vmap() may fail and return NULL. Do not add the offset in this + * case, otherwise a NULL mapping would appear successful. + */ + if (!vaddr) + return NULL; + /* * Since vmap() uses page granularity, we must add the offset * into the page here, to get the byte granularity address diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 0e41fb84060f..5be53cae2c95 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -899,6 +899,7 @@ static struct super_block *quotactl_block(const char __= user *special, int cmd) sb_start_write(sb); sb_end_write(sb); put_super(sb); + cond_resched(); goto retry; } return sb; diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index e92a61e934e4..d83161285a17 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -769,11 +769,11 @@ static void cfids_laundromat_worker(struct work_struc= t *work) =20 dput(dentry); if (cfid->is_open) { - spin_lock(&cifs_tcp_ses_lock); + spin_lock(&cfid->tcon->tc_lock); ++cfid->tcon->tc_count; trace_smb3_tcon_ref(cfid->tcon->debug_id, cfid->tcon->tc_count, netfs_trace_tcon_ref_get_cached_laundromat); - spin_unlock(&cifs_tcp_ses_lock); + spin_unlock(&cfid->tcon->tc_lock); queue_work(serverclose_wq, &cfid->close_work); } else /* diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 86c89917f18e..59220ebd6ecc 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -4065,7 +4065,9 @@ cifs_setup_session(const unsigned int xid, struct cif= s_ses *ses, ses->ses_status =3D SES_IN_SETUP; =20 /* force iface_list refresh */ + spin_lock(&ses->iface_lock); ses->iface_last_update =3D 0; + spin_unlock(&ses->iface_lock); } spin_unlock(&ses->ses_lock); =20 diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index d436057ed77e..4e7d5c612256 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_= open_parms *oparms, __u32 &err_buftype); if (rc =3D=3D -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype =3D CIFS_NO_BUFFER; oparms->desired_access &=3D ~FILE_READ_ATTRIBUTES; rc =3D SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, = &err_iov, &err_buftype); diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index fadc5fc274eb..70a9536b03c6 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -807,14 +807,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, _= _u64 persistent_fid, int rc; =20 cifs_dbg(FYI, "%s: tc_count=3D%d\n", __func__, tcon->tc_count); - spin_lock(&cifs_tcp_ses_lock); + spin_lock(&tcon->tc_lock); if (tcon->tc_count <=3D 0) { struct TCP_Server_Info *server =3D NULL; =20 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_see_cancelled_close); WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); - spin_unlock(&cifs_tcp_ses_lock); + spin_unlock(&tcon->tc_lock); =20 if (tcon->ses) { server =3D tcon->ses->server; @@ -828,7 +828,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u= 64 persistent_fid, tcon->tc_count++; trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_get_cancelled_close); - spin_unlock(&cifs_tcp_ses_lock); + spin_unlock(&tcon->tc_lock); =20 rc =3D __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, persistent_fid, volatile_fid); diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 138b3ed08217..63752bd02aaf 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -595,13 +595,6 @@ parse_server_interfaces(struct network_interface_info_= ioctl_rsp *buf, p =3D buf; =20 spin_lock(&ses->iface_lock); - /* do not query too frequently, this time with lock held */ - if (ses->iface_last_update && - time_before(jiffies, ses->iface_last_update + - (SMB_INTERFACE_POLL_INTERVAL * HZ))) { - spin_unlock(&ses->iface_lock); - return 0; - } =20 /* * Go through iface_list and mark them as inactive @@ -624,7 +617,6 @@ parse_server_interfaces(struct network_interface_info_i= octl_rsp *buf, "Empty network interface list returned by server %s\n", ses->server->hostname); rc =3D -EOPNOTSUPP; - ses->iface_last_update =3D jiffies; goto out; } =20 @@ -753,8 +745,6 @@ parse_server_interfaces(struct network_interface_info_i= octl_rsp *buf, + sizeof(p->Next) && p->Next)) cifs_dbg(VFS, "%s: incomplete interface info\n", __func__); =20 - ses->iface_last_update =3D jiffies; - out: /* * Go through the list again and put the inactive entries @@ -783,10 +773,17 @@ SMB3_request_interfaces(const unsigned int xid, struc= t cifs_tcon *tcon, bool in_ struct TCP_Server_Info *pserver; =20 /* do not query too frequently */ + spin_lock(&ses->iface_lock); if (ses->iface_last_update && time_before(jiffies, ses->iface_last_update + - (SMB_INTERFACE_POLL_INTERVAL * HZ))) + (SMB_INTERFACE_POLL_INTERVAL * HZ))) { + spin_unlock(&ses->iface_lock); return 0; + } + + ses->iface_last_update =3D jiffies; + + spin_unlock(&ses->iface_lock); =20 rc =3D SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, FSCTL_QUERY_NETWORK_INTERFACE_INFO, @@ -1147,6 +1144,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon = *tcon, =20 replay_again: /* reinitialize for possible replay */ + used_len =3D 0; flags =3D CIFS_CP_CREATE_CLOSE_OP; oplock =3D SMB2_OPLOCK_LEVEL_NONE; server =3D cifs_pick_channel(ses); @@ -1545,6 +1543,7 @@ smb2_ioctl_query_info(const unsigned int xid, =20 replay_again: /* reinitialize for possible replay */ + buffer =3D NULL; flags =3D CIFS_CP_CREATE_CLOSE_OP; oplock =3D SMB2_OPLOCK_LEVEL_NONE; server =3D cifs_pick_channel(ses); @@ -2941,7 +2940,9 @@ smb2_get_dfs_refer(const unsigned int xid, struct cif= s_ses *ses, struct cifs_tcon, tcon_list); if (tcon) { + spin_lock(&tcon->tc_lock); tcon->tc_count++; + spin_unlock(&tcon->tc_lock); trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_get_dfs_refer); } @@ -3006,13 +3007,9 @@ smb2_get_dfs_refer(const unsigned int xid, struct ci= fs_ses *ses, out: if (tcon && !tcon->ipc) { /* ipc tcons are not refcounted */ - spin_lock(&cifs_tcp_ses_lock); - tcon->tc_count--; + cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer); trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_dec_dfs_refer); - /* tc_count can never go negative */ - WARN_ON(tcon->tc_count < 0); - spin_unlock(&cifs_tcp_ses_lock); } kfree(utf16_path); kfree(dfs_req); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index a8890ae21714..ea73fc5da603 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2850,6 +2850,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct= inode *inode, =20 replay_again: /* reinitialize for possible replay */ + pc_buf =3D NULL; flags =3D 0; n_iov =3D 2; server =3D cifs_pick_channel(ses); @@ -4174,7 +4175,9 @@ void smb2_reconnect_server(struct work_struct *work) =20 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { if (tcon->need_reconnect || tcon->need_reopen_files) { + spin_lock(&tcon->tc_lock); tcon->tc_count++; + spin_unlock(&tcon->tc_lock); trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_get_reconnect_server); list_add_tail(&tcon->rlist, &tmp_list); diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index be9be8f36331..359ab64e17d9 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -91,8 +91,23 @@ int smbd_send_credit_target =3D 255; /* The maximum single message size can be sent to remote peer */ int smbd_max_send_size =3D 1364; =20 -/* The maximum fragmented upper-layer payload receive size supported */ -int smbd_max_fragmented_recv_size =3D 1024 * 1024; +/* + * The maximum fragmented upper-layer payload receive size supported + * + * Assume max_payload_per_credit is + * smbd_max_receive_size - 24 =3D 1340 + * + * The maximum number would be + * smbd_receive_credit_max * max_payload_per_credit + * + * 1340 * 255 =3D 341700 (0x536C4) + * + * The minimum value from the spec is 131072 (0x20000) + * + * For now we use the logic we used in ksmbd before: + * (1364 * 255) / 2 =3D 173910 (0x2A756) + */ +int smbd_max_fragmented_recv_size =3D (1364 * 255) / 2; =20 /* The maximum single-message size which can be received */ int smbd_max_receive_size =3D 1364; diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 4dfdc521c5c9..17e7ce3b14af 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -42,6 +42,7 @@ EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \ EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \ EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \ + EM(netfs_trace_tcon_ref_put_dfs_refer, "PUT DfsRfr") \ EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \ EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \ EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \ diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 4e5ede2a296a..dcb09702cde2 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -1498,6 +1498,7 @@ xfs_attr3_leaf_add_work( struct xfs_attr_leaf_name_local *name_loc; struct xfs_attr_leaf_name_remote *name_rmt; struct xfs_mount *mp; + int old_end, new_end; int tmp; int i; =20 @@ -1590,17 +1591,49 @@ xfs_attr3_leaf_add_work( if (be16_to_cpu(entry->nameidx) < ichdr->firstused) ichdr->firstused =3D be16_to_cpu(entry->nameidx); =20 - ASSERT(ichdr->firstused >=3D ichdr->count * sizeof(xfs_attr_leaf_entry_t) - + xfs_attr3_leaf_hdr_size(leaf)); - tmp =3D (ichdr->count - 1) * sizeof(xfs_attr_leaf_entry_t) - + xfs_attr3_leaf_hdr_size(leaf); + new_end =3D ichdr->count * sizeof(struct xfs_attr_leaf_entry) + + xfs_attr3_leaf_hdr_size(leaf); + old_end =3D new_end - sizeof(struct xfs_attr_leaf_entry); + + ASSERT(ichdr->firstused >=3D new_end); =20 for (i =3D 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { - if (ichdr->freemap[i].base =3D=3D tmp) { - ichdr->freemap[i].base +=3D sizeof(xfs_attr_leaf_entry_t); + int diff =3D 0; + + if (ichdr->freemap[i].base =3D=3D old_end) { + /* + * This freemap entry starts at the old end of the + * leaf entry array, so we need to adjust its base + * upward to accomodate the larger array. + */ + diff =3D sizeof(struct xfs_attr_leaf_entry); + } else if (ichdr->freemap[i].size > 0 && + ichdr->freemap[i].base < new_end) { + /* + * This freemap entry starts in the space claimed by + * the new leaf entry. Adjust its base upward to + * reflect that. + */ + diff =3D new_end - ichdr->freemap[i].base; + } + + if (diff) { + ichdr->freemap[i].base +=3D diff; ichdr->freemap[i].size -=3D - min_t(uint16_t, ichdr->freemap[i].size, - sizeof(xfs_attr_leaf_entry_t)); + min_t(uint16_t, ichdr->freemap[i].size, diff); + } + + /* + * Don't leave zero-length freemaps with nonzero base lying + * around, because we don't want the code in _remove that + * matches on base address to get confused and create + * overlapping freemaps. If we end up with no freemap entries + * then the next _add will compact the leaf block and + * regenerate the freemaps. + */ + if (ichdr->freemap[i].size =3D=3D 0 && ichdr->freemap[i].base > 0) { + ichdr->freemap[i].base =3D 0; + ichdr->holes =3D 1; } } ichdr->usedbytes +=3D xfs_attr_leaf_entsize(leaf, args->index); diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c index 147babe738d2..c785d80bbfe5 100644 --- a/fs/xfs/scrub/attr.c +++ b/fs/xfs/scrub/attr.c @@ -343,7 +343,10 @@ xchk_xattr_entry( rentry =3D xfs_attr3_leaf_name_remote(leaf, idx); namesize =3D xfs_attr_leaf_entsize_remote(rentry->namelen); name_end =3D (char *)rentry + namesize; - if (rentry->namelen =3D=3D 0 || rentry->valueblk =3D=3D 0) + if (rentry->namelen =3D=3D 0) + xchk_da_set_corrupt(ds, level); + if (rentry->valueblk =3D=3D 0 && + !(ent->flags & XFS_ATTR_INCOMPLETE)) xchk_da_set_corrupt(ds, level); } if (name_end > buf_end) diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c index c3a9f33e5a8d..2afc7e5cc08f 100644 --- a/fs/xfs/scrub/btree.c +++ b/fs/xfs/scrub/btree.c @@ -42,6 +42,8 @@ __xchk_btree_process_error( break; case -EFSBADCRC: case -EFSCORRUPTED: + case -EIO: + case -ENODATA: /* Note the badness but don't abort. */ sc->sm->sm_flags |=3D errflag; *error =3D 0; diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index f10cd4fb0abd..36814c09bf10 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -83,6 +83,8 @@ __xchk_process_error( break; case -EFSBADCRC: case -EFSCORRUPTED: + case -EIO: + case -ENODATA: /* Note the badness but don't abort. */ sc->sm->sm_flags |=3D errflag; *error =3D 0; @@ -137,6 +139,8 @@ __xchk_fblock_process_error( break; case -EFSBADCRC: case -EFSCORRUPTED: + case -EIO: + case -ENODATA: /* Note the badness but don't abort. */ sc->sm->sm_flags |=3D errflag; *error =3D 0; diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c index 82b150d3b8b7..338199d7b841 100644 --- a/fs/xfs/scrub/dabtree.c +++ b/fs/xfs/scrub/dabtree.c @@ -45,6 +45,8 @@ xchk_da_process_error( break; case -EFSBADCRC: case -EFSCORRUPTED: + case -EIO: + case -ENODATA: /* Note the badness but don't abort. */ sc->sm->sm_flags |=3D XFS_SCRUB_OFLAG_CORRUPT; *error =3D 0; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index be1dd4c1a917..16646fdd1f84 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -21,6 +21,7 @@ struct ghes { struct acpi_hest_generic_v2 *generic_v2; }; struct acpi_hest_generic_status *estatus; + unsigned int estatus_length; unsigned long flags; union { struct list_head list; diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/= audit_change_attr.h index 331670807cf0..6c311d4d37f4 100644 --- a/include/asm-generic/audit_change_attr.h +++ b/include/asm-generic/audit_change_attr.h @@ -20,6 +20,9 @@ __NR_fremovexattr, __NR_fchownat, __NR_fchmodat, #endif +#ifdef __NR_fchmodat2 +__NR_fchmodat2, +#endif #ifdef __NR_chown32 __NR_chown32, __NR_fchown32, diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_r= ead.h index 7bb7b5a83ae2..fb9991f53fb6 100644 --- a/include/asm-generic/audit_read.h +++ b/include/asm-generic/audit_read.h @@ -4,9 +4,15 @@ __NR_readlink, #endif __NR_quotactl, __NR_listxattr, +#ifdef __NR_listxattrat +__NR_listxattrat, +#endif __NR_llistxattr, __NR_flistxattr, __NR_getxattr, +#ifdef __NR_getxattrat +__NR_getxattrat, +#endif __NR_lgetxattr, __NR_fgetxattr, #ifdef __NR_readlinkat diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 082a6e980d01..3e38a470c5cb 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -4,6 +4,7 @@ =20 #include #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) +#include #include #endif =20 @@ -163,6 +164,8 @@ static inline int drm_of_panel_bridge_remove(const stru= ct device_node *np, bridge =3D of_drm_find_bridge(remote); drm_panel_bridge_remove(bridge); =20 + of_node_put(remote); + return 0; #else return -EINVAL; diff --git a/include/linux/audit.h b/include/linux/audit.h index 7ca75f887379..517c665da259 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -125,12 +125,6 @@ enum audit_nfcfgop { extern int __init audit_register_class(int class, unsigned *list); extern int audit_classify_syscall(int abi, unsigned syscall); extern int audit_classify_arch(int arch); -/* only for compat system calls */ -extern unsigned compat_write_class[]; -extern unsigned compat_read_class[]; -extern unsigned compat_dir_class[]; -extern unsigned compat_chattr_class[]; -extern unsigned compat_signal_class[]; =20 /* audit_names->type values */ #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ diff --git a/include/linux/audit_arch.h b/include/linux/audit_arch.h index 0e34d673ef17..2b8153791e6a 100644 --- a/include/linux/audit_arch.h +++ b/include/linux/audit_arch.h @@ -23,4 +23,11 @@ enum auditsc_class_t { =20 extern int audit_classify_compat_syscall(int abi, unsigned syscall); =20 +/* only for compat system calls */ +extern unsigned compat_write_class[]; +extern unsigned compat_read_class[]; +extern unsigned compat_dir_class[]; +extern unsigned compat_chattr_class[]; +extern unsigned compat_signal_class[]; + #endif diff --git a/include/linux/cache.h b/include/linux/cache.h index 9900d20b76c2..ca2a05682a54 100644 --- a/include/linux/cache.h +++ b/include/linux/cache.h @@ -13,6 +13,32 @@ #define SMP_CACHE_BYTES L1_CACHE_BYTES #endif =20 +/** + * SMP_CACHE_ALIGN - align a value to the L2 cacheline size + * @x: value to align + * + * On some architectures, L2 ("SMP") CL size is bigger than L1, and someti= mes, + * this needs to be accounted. + * + * Return: aligned value. + */ +#ifndef SMP_CACHE_ALIGN +#define SMP_CACHE_ALIGN(x) ALIGN(x, SMP_CACHE_BYTES) +#endif + +/* + * ``__aligned_largest`` aligns a field to the value most optimal for the + * target architecture to perform memory operations. Get the actual value + * to be able to use it anywhere else. + */ +#ifndef __LARGEST_ALIGN +#define __LARGEST_ALIGN sizeof(struct { long x; } __aligned_largest) +#endif + +#ifndef LARGEST_ALIGN +#define LARGEST_ALIGN(x) ALIGN(x, __LARGEST_ALIGN) +#endif + /* * __read_mostly is used to keep rarely changing variables out of frequent= ly * updated cachelines. Its use should be reserved for data that is used @@ -85,6 +111,64 @@ #define cache_line_size() L1_CACHE_BYTES #endif =20 +#ifndef __cacheline_group_begin +#define __cacheline_group_begin(GROUP) \ + __u8 __cacheline_group_begin__##GROUP[0] +#endif + +#ifndef __cacheline_group_end +#define __cacheline_group_end(GROUP) \ + __u8 __cacheline_group_end__##GROUP[0] +#endif + +/** + * __cacheline_group_begin_aligned - declare an aligned group start + * @GROUP: name of the group + * @...: optional group alignment + * + * The following block inside a struct: + * + * __cacheline_group_begin_aligned(grp); + * field a; + * field b; + * __cacheline_group_end_aligned(grp); + * + * will always be aligned to either the specified alignment or + * ``SMP_CACHE_BYTES``. + */ +#define __cacheline_group_begin_aligned(GROUP, ...) \ + __cacheline_group_begin(GROUP) \ + __aligned((__VA_ARGS__ + 0) ? : SMP_CACHE_BYTES) + +/** + * __cacheline_group_end_aligned - declare an aligned group end + * @GROUP: name of the group + * @...: optional alignment (same as was in __cacheline_group_begin_aligne= d()) + * + * Note that the end marker is aligned to sizeof(long) to allow more preci= se + * size assertion. It also declares a padding at the end to avoid next fie= ld + * falling into this cacheline. + */ +#define __cacheline_group_end_aligned(GROUP, ...) \ + __cacheline_group_end(GROUP) __aligned(sizeof(long)); \ + struct { } __cacheline_group_pad__##GROUP \ + __aligned((__VA_ARGS__ + 0) ? : SMP_CACHE_BYTES) + +#ifndef CACHELINE_ASSERT_GROUP_MEMBER +#define CACHELINE_ASSERT_GROUP_MEMBER(TYPE, GROUP, MEMBER) \ + BUILD_BUG_ON(!(offsetof(TYPE, MEMBER) >=3D \ + offsetofend(TYPE, __cacheline_group_begin__##GROUP) && \ + offsetofend(TYPE, MEMBER) <=3D \ + offsetof(TYPE, __cacheline_group_end__##GROUP))) +#endif + +#ifndef CACHELINE_ASSERT_GROUP_SIZE +#define CACHELINE_ASSERT_GROUP_SIZE(TYPE, GROUP, SIZE) \ + BUILD_BUG_ON(offsetof(TYPE, __cacheline_group_end__##GROUP) - \ + offsetofend(TYPE, __cacheline_group_begin__##GROUP) > \ + SIZE) +#endif + /* * Helper to add padding within a struct to ensure data fall into separate * cachelines. diff --git a/include/linux/capability.h b/include/linux/capability.h index 0c356a517991..767c535dbd38 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -208,6 +208,12 @@ static inline bool checkpoint_restore_ns_capable(struc= t user_namespace *ns) ns_capable(ns, CAP_SYS_ADMIN); } =20 +static inline bool checkpoint_restore_ns_capable_noaudit(struct user_names= pace *ns) +{ + return ns_capable_noaudit(ns, CAP_CHECKPOINT_RESTORE) || + ns_capable_noaudit(ns, CAP_SYS_ADMIN); +} + /* audit system wants to get cap info from files as well */ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, const struct dentry *dentry, diff --git a/include/linux/clk.h b/include/linux/clk.h index 06f1b292f8a0..862ef29ee5f0 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -216,6 +216,23 @@ int clk_rate_exclusive_get(struct clk *clk); */ void clk_rate_exclusive_put(struct clk *clk); =20 +/** + * clk_save_context - save clock context for poweroff + * + * Saves the context of the clock register for powerstates in which the + * contents of the registers will be lost. Occurs deep within the suspend + * code so locking is not necessary. + */ +int clk_save_context(void); + +/** + * clk_restore_context - restore clock context after poweroff + * + * This occurs with all clocks enabled. Occurs deep within the resume code + * so locking is not necessary. + */ +void clk_restore_context(void); + #else =20 static inline int clk_notifier_register(struct clk *clk, @@ -276,6 +293,13 @@ static inline int clk_rate_exclusive_get(struct clk *c= lk) =20 static inline void clk_rate_exclusive_put(struct clk *clk) {} =20 +static inline int clk_save_context(void) +{ + return 0; +} + +static inline void clk_restore_context(void) {} + #endif =20 #ifdef CONFIG_HAVE_CLK_PREPARE @@ -872,23 +896,6 @@ struct clk *clk_get_parent(struct clk *clk); */ struct clk *clk_get_sys(const char *dev_id, const char *con_id); =20 -/** - * clk_save_context - save clock context for poweroff - * - * Saves the context of the clock register for powerstates in which the - * contents of the registers will be lost. Occurs deep within the suspend - * code so locking is not necessary. - */ -int clk_save_context(void); - -/** - * clk_restore_context - restore clock context after poweroff - * - * This occurs with all clocks enabled. Occurs deep within the resume code - * so locking is not necessary. - */ -void clk_restore_context(void); - #else /* !CONFIG_HAVE_CLK */ =20 static inline struct clk *clk_get(struct device *dev, const char *id) @@ -1055,13 +1062,6 @@ static inline struct clk *clk_get_sys(const char *de= v_id, const char *con_id) return NULL; } =20 -static inline int clk_save_context(void) -{ - return 0; -} - -static inline void clk_restore_context(void) {} - #endif =20 /* clk_prepare_enable helps cases using clk_enable in non-atomic context. = */ diff --git a/include/linux/cper.h b/include/linux/cper.h index ad1ed2473091..c588e5c2a96c 100644 --- a/include/linux/cper.h +++ b/include/linux/cper.h @@ -568,7 +568,8 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *, const char *cper_mem_err_unpack(struct trace_seq *, struct cper_mem_err_compact *); void cper_print_proc_arm(const char *pfx, - const struct cper_sec_proc_arm *proc); + const struct cper_sec_proc_arm *proc, + u32 length); void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc); int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg); diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index e8921871ef9a..5c3eaf9fc90c 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -89,11 +89,13 @@ struct ftrace_direct_func; defined(CONFIG_DYNAMIC_FTRACE) const char * ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, - unsigned long *off, char **modname, char *sym); + unsigned long *off, char **modname, + const unsigned char **modbuildid, char *sym); #else static inline const char * ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, - unsigned long *off, char **modname, char *sym) + unsigned long *off, char **modname, + const unsigned char **modbuildid, char *sym) { return NULL; } diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index ddb27fc0ee8c..b157ff4f727f 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -38,11 +38,11 @@ struct in_device { struct ip_mc_list *mc_tomb; unsigned long mr_v1_seen; unsigned long mr_v2_seen; - unsigned long mr_maxdelay; unsigned long mr_qi; /* Query Interval */ unsigned long mr_qri; /* Query Response Interval */ unsigned char mr_qrv; /* Query Robustness Variable */ unsigned char mr_gq_running; + u32 mr_maxdelay; u32 mr_ifc_count; struct timer_list mr_gq_timer; /* general query timer */ struct timer_list mr_ifc_timer; /* interface change timer */ diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/cor= e.h index a3241e4d7548..4816d4f47210 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h @@ -663,7 +663,7 @@ static inline int wm8350_register_irq(struct wm8350 *wm= 8350, int irq, return -ENODEV; =20 return request_threaded_irq(irq + wm8350->irq_base, NULL, - handler, flags, name, data); + handler, flags | IRQF_ONESHOT, name, data); } =20 static inline void wm8350_free_irq(struct wm8350 *wm8350, int irq, void *d= ata) diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index c0e0468b25a1..c29ecbfbf3da 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1288,12 +1288,12 @@ static inline bool mlx5_rl_is_supported(struct mlx5= _core_dev *dev) static inline int mlx5_core_is_mp_slave(struct mlx5_core_dev *dev) { return MLX5_CAP_GEN(dev, affiliate_nic_vport_criteria) && - MLX5_CAP_GEN(dev, num_vhca_ports) <=3D 1; + MLX5_CAP_GEN_MAX(dev, num_vhca_ports) <=3D 1; } =20 static inline int mlx5_core_is_mp_master(struct mlx5_core_dev *dev) { - return MLX5_CAP_GEN(dev, num_vhca_ports) > 1; + return MLX5_CAP_GEN_MAX(dev, num_vhca_ports) > 1; } =20 static inline int mlx5_core_mp_enabled(struct mlx5_core_dev *dev) diff --git a/include/linux/module.h b/include/linux/module.h index f58d1eb260fa..10603f725cae 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -735,6 +735,15 @@ static inline void __module_get(struct module *module) __mod ? __mod->name : "kernel"; \ }) =20 +static inline const unsigned char *module_buildid(struct module *mod) +{ +#ifdef CONFIG_STACKTRACE_BUILD_ID + return mod->build_id; +#else + return NULL; +#endif +} + /* Dereference module function descriptor */ void *dereference_module_function_descriptor(struct module *mod, void *ptr= ); =20 diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 5c2ccc649452..980e1fdf67ed 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -195,7 +195,7 @@ struct spinand_device; =20 /** * struct spinand_id - SPI NAND id structure - * @data: buffer containing the id bytes. Currently 4 bytes large, but can + * @data: buffer containing the id bytes. Currently 5 bytes large, but can * be extended if required * @len: ID length */ diff --git a/include/linux/psp.h b/include/linux/psp.h index 92e60aeef21e..b337dcce1e99 100644 --- a/include/linux/psp.h +++ b/include/linux/psp.h @@ -18,6 +18,7 @@ * and should include an appropriate local definition in their source file. */ #define PSP_CMDRESP_STS GENMASK(15, 0) +#define PSP_TEE_STS_RING_BUSY 0x0000000d /* Ring already initialized */ #define PSP_CMDRESP_CMD GENMASK(23, 16) #define PSP_CMDRESP_RESERVED GENMASK(29, 24) #define PSP_CMDRESP_RECOVERY BIT(30) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 69b392dc10aa..1a91645fa249 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1122,6 +1122,38 @@ static inline struct dst_entry *skb_dst(const struct= sk_buff *skb) return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK); } =20 +/** + * skb_dstref_steal() - return current dst_entry value and clear it + * @skb: buffer + * + * Resets skb dst_entry without adjusting its reference count. Useful in + * cases where dst_entry needs to be temporarily reset and restored. + * Note that the returned value cannot be used directly because it + * might contain SKB_DST_NOREF bit. + * + * When in doubt, prefer skb_dst_drop() over skb_dstref_steal() to correct= ly + * handle dst_entry reference counting. + * + * Returns: original skb dst_entry. + */ +static inline unsigned long skb_dstref_steal(struct sk_buff *skb) +{ + unsigned long refdst =3D skb->_skb_refdst; + + skb->_skb_refdst =3D 0; + return refdst; +} + +/** + * skb_dstref_restore() - restore skb dst_entry removed via skb_dstref_ste= al() + * @skb: buffer + * @refdst: dst entry from a call to skb_dstref_steal() + */ +static inline void skb_dstref_restore(struct sk_buff *skb, unsigned long r= efdst) +{ + skb->_skb_refdst =3D refdst; +} + /** * skb_dst_set - sets skb dst * @skb: buffer diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 32bbebf5b71e..e923f1c24ce4 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -93,6 +93,8 @@ struct sk_psock { struct sk_buff_head ingress_skb; struct list_head ingress_msg; spinlock_t ingress_lock; + /** @msg_tot_len: Total bytes queued in ingress_msg list. */ + u32 msg_tot_len; unsigned long state; struct list_head link; spinlock_t link_lock; @@ -132,6 +134,8 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct io= v_iter *from, struct sk_msg *msg, u32 bytes); int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr = *msg, int len, int flags); +int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghd= r *msg, + int len, int flags, int *copied_from_self); bool sk_msg_is_readable(struct sock *sk); =20 static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 byt= es) @@ -310,6 +314,27 @@ static inline void sock_drop(struct sock *sk, struct s= k_buff *skb) kfree_skb(skb); } =20 +static inline u32 sk_psock_get_msg_len_nolock(struct sk_psock *psock) +{ + /* Used by ioctl to read msg_tot_len only; lock-free for performance */ + return READ_ONCE(psock->msg_tot_len); +} + +static inline void sk_psock_msg_len_add_locked(struct sk_psock *psock, int= diff) +{ + /* Use WRITE_ONCE to ensure correct read in sk_psock_get_msg_len_nolock(). + * ingress_lock should be held to prevent concurrent updates to msg_tot_l= en + */ + WRITE_ONCE(psock->msg_tot_len, psock->msg_tot_len + diff); +} + +static inline void sk_psock_msg_len_add(struct sk_psock *psock, int diff) +{ + spin_lock_bh(&psock->ingress_lock); + sk_psock_msg_len_add_locked(psock, diff); + spin_unlock_bh(&psock->ingress_lock); +} + static inline bool sk_psock_queue_msg(struct sk_psock *psock, struct sk_msg *msg) { @@ -318,6 +343,7 @@ static inline bool sk_psock_queue_msg(struct sk_psock *= psock, spin_lock_bh(&psock->ingress_lock); if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { list_add_tail(&msg->list, &psock->ingress_msg); + sk_psock_msg_len_add_locked(psock, msg->sg.size); ret =3D true; } else { sk_msg_free(psock->sk, msg); @@ -334,18 +360,25 @@ static inline struct sk_msg *sk_psock_dequeue_msg(str= uct sk_psock *psock) =20 spin_lock_bh(&psock->ingress_lock); msg =3D list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list= ); - if (msg) + if (msg) { list_del(&msg->list); + sk_psock_msg_len_add_locked(psock, -msg->sg.size); + } spin_unlock_bh(&psock->ingress_lock); return msg; } =20 +static inline struct sk_msg *sk_psock_peek_msg_locked(struct sk_psock *pso= ck) +{ + return list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list); +} + static inline struct sk_msg *sk_psock_peek_msg(struct sk_psock *psock) { struct sk_msg *msg; =20 spin_lock_bh(&psock->ingress_lock); - msg =3D list_first_entry_or_null(&psock->ingress_msg, struct sk_msg, list= ); + msg =3D sk_psock_peek_msg_locked(psock); spin_unlock_bh(&psock->ingress_lock); return msg; } @@ -509,6 +542,39 @@ static inline bool sk_psock_strp_enabled(struct sk_pso= ck *psock) return !!psock->saved_data_ready; } =20 +/* for tcp only, sk is locked */ +static inline ssize_t sk_psock_msg_inq(struct sock *sk) +{ + struct sk_psock *psock; + ssize_t inq =3D 0; + + psock =3D sk_psock_get(sk); + if (likely(psock)) { + inq =3D sk_psock_get_msg_len_nolock(psock); + sk_psock_put(sk, psock); + } + return inq; +} + +/* for udp only, sk is not locked */ +static inline ssize_t sk_msg_first_len(struct sock *sk) +{ + struct sk_psock *psock; + struct sk_msg *msg; + ssize_t inq =3D 0; + + psock =3D sk_psock_get(sk); + if (likely(psock)) { + spin_lock_bh(&psock->ingress_lock); + msg =3D sk_psock_peek_msg_locked(psock); + if (msg) + inq =3D msg->sg.size; + spin_unlock_bh(&psock->ingress_lock); + sk_psock_put(sk, psock); + } + return inq; +} + #if IS_ENABLED(CONFIG_NET_SOCK_MSG) =20 #define BPF_F_STRPARSER (1UL << 1) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 9b371aa7c796..e15452df9804 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -471,15 +471,17 @@ enum tsq_enum { TCP_MTU_REDUCED_DEFERRED, /* tcp_v{4|6}_err() could not call * tcp_v{4|6}_mtu_reduced() */ + TCP_ACK_DEFERRED, /* TX pure ack is deferred */ }; =20 enum tsq_flags { - TSQF_THROTTLED =3D (1UL << TSQ_THROTTLED), - TSQF_QUEUED =3D (1UL << TSQ_QUEUED), - TCPF_TSQ_DEFERRED =3D (1UL << TCP_TSQ_DEFERRED), - TCPF_WRITE_TIMER_DEFERRED =3D (1UL << TCP_WRITE_TIMER_DEFERRED), - TCPF_DELACK_TIMER_DEFERRED =3D (1UL << TCP_DELACK_TIMER_DEFERRED), - TCPF_MTU_REDUCED_DEFERRED =3D (1UL << TCP_MTU_REDUCED_DEFERRED), + TSQF_THROTTLED =3D BIT(TSQ_THROTTLED), + TSQF_QUEUED =3D BIT(TSQ_QUEUED), + TCPF_TSQ_DEFERRED =3D BIT(TCP_TSQ_DEFERRED), + TCPF_WRITE_TIMER_DEFERRED =3D BIT(TCP_WRITE_TIMER_DEFERRED), + TCPF_DELACK_TIMER_DEFERRED =3D BIT(TCP_DELACK_TIMER_DEFERRED), + TCPF_MTU_REDUCED_DEFERRED =3D BIT(TCP_MTU_REDUCED_DEFERRED), + TCPF_ACK_DEFERRED =3D BIT(TCP_ACK_DEFERRED), }; =20 #define tcp_sk(ptr) container_of_const(ptr, struct tcp_sock, inet_conn.ics= k_inet.sk) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 63b1a24f406a..60436cd2b069 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -695,6 +695,11 @@ static inline void hist_poll_wakeup(void) =20 #define hist_poll_wait(file, wait) \ poll_wait(file, &hist_poll_wq, wait) + +#else +static inline void hist_poll_wakeup(void) +{ +} #endif =20 #define __TRACE_EVENT_FLAGS(name, value) \ diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index 457879938fc1..3366090a86bd 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -89,6 +89,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsigne= d long val) local64_add(val, &p->v); } =20 +static inline void u64_stats_sub(u64_stats_t *p, s64 val) +{ + local64_sub(val, &p->v); +} + static inline void u64_stats_inc(u64_stats_t *p) { local64_inc(&p->v); @@ -130,6 +135,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsig= ned long val) p->v +=3D val; } =20 +static inline void u64_stats_sub(u64_stats_t *p, s64 val) +{ + p->v -=3D val; +} + static inline void u64_stats_inc(u64_stats_t *p) { p->v++; diff --git a/include/media/dvb_vb2.h b/include/media/dvb_vb2.h index 8cb88452cd6c..0fbbfc65157e 100644 --- a/include/media/dvb_vb2.h +++ b/include/media/dvb_vb2.h @@ -124,7 +124,7 @@ static inline int dvb_vb2_release(struct dvb_vb2_ctx *c= tx) return 0; }; #define dvb_vb2_is_streaming(ctx) (0) -#define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0) +#define dvb_vb2_fill_buffer(ctx, file, wait, flags, flush) (0) =20 static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file, @@ -166,10 +166,12 @@ int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx); * @buffer_flags: * pointer to buffer flags as defined by &enum dmx_buffer_flags. * can be NULL. + * @flush: flush the buffer, even if it isn't full. */ int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, const unsigned char *src, int len, - enum dmx_buffer_flags *buffer_flags); + enum dmx_buffer_flags *buffer_flags, + bool flush); =20 /** * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 08574278645d..a57fd4573783 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -487,6 +487,8 @@ struct l2cap_ecred_reconf_req { #define L2CAP_RECONF_SUCCESS 0x0000 #define L2CAP_RECONF_INVALID_MTU 0x0001 #define L2CAP_RECONF_INVALID_MPS 0x0002 +#define L2CAP_RECONF_INVALID_CID 0x0003 +#define L2CAP_RECONF_INVALID_PARAMS 0x0004 =20 struct l2cap_ecred_reconf_rsp { __le16 result; diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connecti= on_sock.h index e85834722b8f..3eb715f66cbf 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -326,11 +326,10 @@ void inet_csk_update_fastreuse(struct inet_bind_bucke= t *tb, =20 struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); =20 -#define TCP_PINGPONG_THRESH 1 - static inline void inet_csk_enter_pingpong_mode(struct sock *sk) { - inet_csk(sk)->icsk_ack.pingpong =3D TCP_PINGPONG_THRESH; + inet_csk(sk)->icsk_ack.pingpong =3D + READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pingpong_thresh); } =20 static inline void inet_csk_exit_pingpong_mode(struct sock *sk) @@ -340,7 +339,16 @@ static inline void inet_csk_exit_pingpong_mode(struct = sock *sk) =20 static inline bool inet_csk_in_pingpong_mode(struct sock *sk) { - return inet_csk(sk)->icsk_ack.pingpong >=3D TCP_PINGPONG_THRESH; + return inet_csk(sk)->icsk_ack.pingpong >=3D + READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pingpong_thresh); +} + +static inline void inet_csk_inc_pingpong_cnt(struct sock *sk) +{ + struct inet_connection_sock *icsk =3D inet_csk(sk); + + if (icsk->icsk_ack.pingpong < U8_MAX) + icsk->icsk_ack.pingpong++; } =20 static inline bool inet_csk_has_ulp(const struct sock *sk) diff --git a/include/net/ioam6.h b/include/net/ioam6.h index 781d2d8b2f29..3f99eb445de6 100644 --- a/include/net/ioam6.h +++ b/include/net/ioam6.h @@ -59,6 +59,8 @@ void ioam6_fill_trace_data(struct sk_buff *skb, struct ioam6_trace_hdr *trace, bool is_input); =20 +u8 ioam6_trace_compute_nodelen(u32 trace_type); + int ioam6_init(void); void ioam6_exit(void); =20 diff --git a/include/net/ip.h b/include/net/ip.h index d8bf1f0a6919..bacdb4fecc89 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -790,11 +790,8 @@ static inline void ip_cmsg_recv(struct msghdr *msg, st= ruct sk_buff *skb) ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0); } =20 -bool icmp_global_allow(void); -void icmp_global_consume(void); - -extern int sysctl_icmp_msgs_per_sec; -extern int sysctl_icmp_msgs_burst; +bool icmp_global_allow(struct net *net); +void icmp_global_consume(struct net *net); =20 #ifdef CONFIG_PROC_FS int ip_misc_proc_init(void); diff --git a/include/net/ipv6.h b/include/net/ipv6.h index c6932d1a3fa8..d98f5390ffad 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -1017,11 +1017,11 @@ static inline int ip6_default_np_autolabel(struct n= et *net) #if IS_ENABLED(CONFIG_IPV6) static inline int ip6_multipath_hash_policy(const struct net *net) { - return net->ipv6.sysctl.multipath_hash_policy; + return READ_ONCE(net->ipv6.sysctl.multipath_hash_policy); } static inline u32 ip6_multipath_hash_fields(const struct net *net) { - return net->ipv6.sysctl.multipath_hash_fields; + return READ_ONCE(net->ipv6.sysctl.multipath_hash_fields); } #else static inline int ip6_multipath_hash_policy(const struct net *net) @@ -1293,12 +1293,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, =20 static inline int ip6_sock_set_v6only(struct sock *sk) { - if (inet_sk(sk)->inet_num) - return -EINVAL; + int ret =3D 0; + lock_sock(sk); - sk->sk_ipv6only =3D true; + if (inet_sk(sk)->inet_num) + ret =3D -EINVAL; + else + sk->sk_ipv6only =3D true; release_sock(sk); - return 0; + return ret; } =20 static inline void ip6_sock_set_recverr(struct sock *sk) diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfi= lter/nf_conntrack_count.h index 115bb7e572f7..bf22661925b8 100644 --- a/include/net/netfilter/nf_conntrack_count.h +++ b/include/net/netfilter/nf_conntrack_count.h @@ -13,6 +13,7 @@ struct nf_conncount_list { u32 last_gc; /* jiffies at most recent gc */ struct list_head head; /* connections with the same filtering key */ unsigned int count; /* length of list */ + unsigned int last_gc_count; /* length of list at most recent gc */ }; =20 struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int = family, diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 7a41c4791536..521529e61ae1 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -42,6 +42,44 @@ struct inet_timewait_death_row { struct tcp_fastopen_context; =20 struct netns_ipv4 { + /* Cacheline organization can be found documented in + * Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst. + * Please update the document when adding new fields. + */ + + /* TX readonly hotpath cache lines */ + __cacheline_group_begin(netns_ipv4_read_tx); + u8 sysctl_tcp_early_retrans; + u8 sysctl_tcp_tso_win_divisor; + u8 sysctl_tcp_tso_rtt_log; + u8 sysctl_tcp_autocorking; + int sysctl_tcp_min_snd_mss; + unsigned int sysctl_tcp_notsent_lowat; + int sysctl_tcp_limit_output_bytes; + int sysctl_tcp_min_rtt_wlen; + int sysctl_tcp_wmem[3]; + u8 sysctl_ip_fwd_use_pmtu; + __cacheline_group_end(netns_ipv4_read_tx); + + /* TXRX readonly hotpath cache lines */ + __cacheline_group_begin(netns_ipv4_read_txrx); + u8 sysctl_tcp_moderate_rcvbuf; + __cacheline_group_end(netns_ipv4_read_txrx); + + /* RX readonly hotpath cache line */ + __cacheline_group_begin(netns_ipv4_read_rx); + u8 sysctl_ip_early_demux; + u8 sysctl_tcp_early_demux; + int sysctl_tcp_reordering; + int sysctl_tcp_rmem[3]; + __cacheline_group_end(netns_ipv4_read_rx); + + /* ICMP rate limiter hot cache line. */ + __cacheline_group_begin_aligned(icmp); + atomic_t icmp_global_credit; + u32 icmp_global_stamp; + __cacheline_group_end_aligned(icmp); + struct inet_timewait_death_row tcp_death_row; struct udp_table *udp_table; =20 @@ -84,6 +122,8 @@ struct netns_ipv4 { u8 sysctl_icmp_errors_use_inbound_ifaddr; int sysctl_icmp_ratelimit; int sysctl_icmp_ratemask; + int sysctl_icmp_msgs_per_sec; + int sysctl_icmp_msgs_burst; =20 u32 ip_rt_min_pmtu; int ip_rt_mtu_expires; @@ -96,17 +136,14 @@ struct netns_ipv4 { =20 u8 sysctl_ip_default_ttl; u8 sysctl_ip_no_pmtu_disc; - u8 sysctl_ip_fwd_use_pmtu; u8 sysctl_ip_fwd_update_priority; u8 sysctl_ip_nonlocal_bind; u8 sysctl_ip_autobind_reuse; /* Shall we try to damage output packets if routing dev changes? */ u8 sysctl_ip_dynaddr; - u8 sysctl_ip_early_demux; #ifdef CONFIG_NET_L3_MASTER_DEV u8 sysctl_raw_l3mdev_accept; #endif - u8 sysctl_tcp_early_demux; u8 sysctl_udp_early_demux; =20 u8 sysctl_nexthop_compat_mode; @@ -119,7 +156,6 @@ struct netns_ipv4 { u8 sysctl_tcp_mtu_probing; int sysctl_tcp_mtu_probe_floor; int sysctl_tcp_base_mss; - int sysctl_tcp_min_snd_mss; int sysctl_tcp_probe_threshold; u32 sysctl_tcp_probe_interval; =20 @@ -132,17 +168,17 @@ struct netns_ipv4 { u8 sysctl_tcp_syncookies; u8 sysctl_tcp_migrate_req; u8 sysctl_tcp_comp_sack_nr; - int sysctl_tcp_reordering; + u8 sysctl_tcp_backlog_ack_defer; + u8 sysctl_tcp_pingpong_thresh; + u8 sysctl_tcp_retries1; u8 sysctl_tcp_retries2; u8 sysctl_tcp_orphan_retries; u8 sysctl_tcp_tw_reuse; int sysctl_tcp_fin_timeout; - unsigned int sysctl_tcp_notsent_lowat; u8 sysctl_tcp_sack; u8 sysctl_tcp_window_scaling; u8 sysctl_tcp_timestamps; - u8 sysctl_tcp_early_retrans; u8 sysctl_tcp_recovery; u8 sysctl_tcp_thin_linear_timeouts; u8 sysctl_tcp_slow_start_after_idle; @@ -158,21 +194,13 @@ struct netns_ipv4 { u8 sysctl_tcp_frto; u8 sysctl_tcp_nometrics_save; u8 sysctl_tcp_no_ssthresh_metrics_save; - u8 sysctl_tcp_moderate_rcvbuf; - u8 sysctl_tcp_tso_win_divisor; u8 sysctl_tcp_workaround_signed_windows; - int sysctl_tcp_limit_output_bytes; int sysctl_tcp_challenge_ack_limit; - int sysctl_tcp_min_rtt_wlen; u8 sysctl_tcp_min_tso_segs; - u8 sysctl_tcp_tso_rtt_log; - u8 sysctl_tcp_autocorking; u8 sysctl_tcp_reflect_tos; int sysctl_tcp_invalid_ratelimit; int sysctl_tcp_pacing_ss_ratio; int sysctl_tcp_pacing_ca_ratio; - int sysctl_tcp_wmem[3]; - int sysctl_tcp_rmem[3]; unsigned int sysctl_tcp_child_ehash_entries; unsigned long sysctl_tcp_comp_sack_delay_ns; unsigned long sysctl_tcp_comp_sack_slack_ns; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index de1d88d41270..038fa78835be 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -1096,7 +1096,7 @@ struct ib_qp_cap { =20 /* * Maximum number of rdma_rw_ctx structures in flight at a time. - * ib_create_qp() will calculate the right amount of neededed WRs + * ib_create_qp() will calculate the right amount of needed WRs * and MRs based on this. */ u32 max_rdma_ctxs; diff --git a/include/rdma/rw.h b/include/rdma/rw.h index d606cac48233..9a8f4b76ce58 100644 --- a/include/rdma/rw.h +++ b/include/rdma/rw.h @@ -66,6 +66,8 @@ int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_q= p *qp, u32 port_num, =20 unsigned int rdma_rw_mr_factor(struct ib_device *device, u32 port_num, unsigned int maxpages); +unsigned int rdma_rw_max_send_wr(struct ib_device *dev, u32 port_num, + unsigned int max_rdma_ctxs, u32 create_flags); void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr); int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr); void rdma_rw_cleanup_mrs(struct ib_qp *qp); diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index aaa502a7bff4..1749b35ab2c2 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -362,7 +362,7 @@ struct hv_kvp_exchg_msg_value { __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; __u32 value_u32; __u64 value_u64; - }; + } __attribute__((packed)); } __attribute__((packed)); =20 struct hv_kvp_msg_enumerate { diff --git a/include/uapi/linux/netfilter_bridge.h b/include/uapi/linux/net= filter_bridge.h index 1610fdbab98d..ad520d3e9df8 100644 --- a/include/uapi/linux/netfilter_bridge.h +++ b/include/uapi/linux/netfilter_bridge.h @@ -5,6 +5,10 @@ /* bridge-specific defines for netfilter.=20 */ =20 +#ifndef __KERNEL__ +#include /* for __UAPI_DEF_ETHHDR if defined */ +#endif + #include #include #include diff --git a/include/uapi/linux/vbox_vmmdev_types.h b/include/uapi/linux/vb= ox_vmmdev_types.h index f8a8d6b3c521..436678d4fb24 100644 --- a/include/uapi/linux/vbox_vmmdev_types.h +++ b/include/uapi/linux/vbox_vmmdev_types.h @@ -236,7 +236,7 @@ struct vmmdev_hgcm_function_parameter32 { /** Relative to the request header. */ __u32 offset; } page_list; - } u; + } __packed u; } __packed; VMMDEV_ASSERT_SIZE(vmmdev_hgcm_function_parameter32, 4 + 8); =20 @@ -251,7 +251,7 @@ struct vmmdev_hgcm_function_parameter64 { union { __u64 phys_addr; __u64 linear_addr; - } u; + } __packed u; } __packed pointer; struct { /** Size of the buffer described by the page list. */ diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 78380fc2374e..8d2efb9e5d66 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1329,17 +1329,13 @@ static inline void *ufshcd_get_variant(struct ufs_h= ba *hba) return hba->priv; } =20 -#ifdef CONFIG_PM extern int ufshcd_runtime_suspend(struct device *dev); extern int ufshcd_runtime_resume(struct device *dev); -#endif -#ifdef CONFIG_PM_SLEEP extern int ufshcd_system_suspend(struct device *dev); extern int ufshcd_system_resume(struct device *dev); extern int ufshcd_system_freeze(struct device *dev); extern int ufshcd_system_thaw(struct device *dev); extern int ufshcd_system_restore(struct device *dev); -#endif =20 extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba, int agreed_gear, diff --git a/include/xen/xen.h b/include/xen/xen.h index a1e5b3f18d69..86fe96fe5183 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -62,11 +62,13 @@ extern u64 xen_saved_max_mem_size; #endif =20 #ifdef CONFIG_XEN_UNPOPULATED_ALLOC +extern unsigned long xen_unpopulated_pages; int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages= ); void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages= ); #include int arch_xen_unpopulated_init(struct resource **res); #else +#define xen_unpopulated_pages 0UL #include static inline int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages) diff --git a/io_uring/cancel.h b/io_uring/cancel.h index fc98622e6166..7e6d0fca7db2 100644 --- a/io_uring/cancel.h +++ b/io_uring/cancel.h @@ -4,10 +4,8 @@ =20 struct io_cancel_data { struct io_ring_ctx *ctx; - union { - u64 data; - struct file *file; - }; + u64 data; + struct file *file; u8 opcode; u32 flags; int seq; diff --git a/io_uring/filetable.c b/io_uring/filetable.c index ff74d41d9e53..aa9f0abcd8ee 100644 --- a/io_uring/filetable.c +++ b/io_uring/filetable.c @@ -22,6 +22,10 @@ static int io_file_bitmap_get(struct io_ring_ctx *ctx) if (!table->bitmap) return -ENFILE; =20 + if (table->alloc_hint < ctx->file_alloc_start || + table->alloc_hint >=3D ctx->file_alloc_end) + table->alloc_hint =3D ctx->file_alloc_start; + do { ret =3D find_next_zero_bit(table->bitmap, nr, table->alloc_hint); if (ret !=3D nr) diff --git a/io_uring/sync.c b/io_uring/sync.c index 255f68c37e55..27bd0a26500b 100644 --- a/io_uring/sync.c +++ b/io_uring/sync.c @@ -62,6 +62,8 @@ int io_fsync_prep(struct io_kiocb *req, const struct io_u= ring_sqe *sqe) return -EINVAL; =20 sync->off =3D READ_ONCE(sqe->off); + if (sync->off < 0) + return -EINVAL; sync->len =3D READ_ONCE(sqe->len); req->flags |=3D REQ_F_FORCE_ASYNC; return 0; diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index b2f39a86f473..22b12a482ba9 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -215,7 +215,7 @@ static int ipc_permissions(struct ctl_table_header *hea= d, struct ctl_table *tabl if (((table->data =3D=3D &ns->ids[IPC_SEM_IDS].next_id) || (table->data =3D=3D &ns->ids[IPC_MSG_IDS].next_id) || (table->data =3D=3D &ns->ids[IPC_SHM_IDS].next_id)) && - checkpoint_restore_ns_capable(ns->user_ns)) + checkpoint_restore_ns_capable_noaudit(ns->user_ns)) mode =3D 0666; else #endif diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 45b2f06de452..4af7c96f6985 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -13136,21 +13136,17 @@ static void __scalar64_min_max_lsh(struct bpf_reg= _state *dst_reg, u64 umin_val, u64 umax_val) { /* Special case <<32 because it is a common compiler pattern to sign - * extend subreg by doing <<32 s>>32. In this case if 32bit bounds are - * positive we know this shift will also be positive so we can track - * bounds correctly. Otherwise we lose all sign bit information except - * what we can pick up from var_off. Perhaps we can generalize this - * later to shifts of any length. + * extend subreg by doing <<32 s>>32. smin/smax assignments are correct + * because s32 bounds don't flip sign when shifting to the left by + * 32bits. */ - if (umin_val =3D=3D 32 && umax_val =3D=3D 32 && dst_reg->s32_max_value >= =3D 0) + if (umin_val =3D=3D 32 && umax_val =3D=3D 32) { dst_reg->smax_value =3D (s64)dst_reg->s32_max_value << 32; - else - dst_reg->smax_value =3D S64_MAX; - - if (umin_val =3D=3D 32 && umax_val =3D=3D 32 && dst_reg->s32_min_value >= =3D 0) dst_reg->smin_value =3D (s64)dst_reg->s32_min_value << 32; - else + } else { + dst_reg->smax_value =3D S64_MAX; dst_reg->smin_value =3D S64_MIN; + } =20 /* If we might shift our top bit out, then we know nothing */ if (dst_reg->umax_value > 1ULL << (63 - umax_val)) { diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config index 4722b998a324..7471b4062b7a 100644 --- a/kernel/configs/debug.config +++ b/kernel/configs/debug.config @@ -29,7 +29,6 @@ CONFIG_SECTION_MISMATCH_WARN_ONLY=3Dy # CONFIG_UBSAN_ALIGNMENT is not set # CONFIG_UBSAN_DIV_ZERO is not set # CONFIG_UBSAN_TRAP is not set -# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set CONFIG_DEBUG_FS=3Dy CONFIG_DEBUG_FS_ALLOW_ALL=3Dy CONFIG_DEBUG_IRQFLAGS=3Dy diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 07f33601cac2..cd44e9c42753 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -431,8 +431,8 @@ static const char *kallsyms_lookup_buildid(unsigned lon= g addr, offset, modname, namebuf); =20 if (!ret) - ret =3D ftrace_mod_address_lookup(addr, symbolsize, - offset, modname, namebuf); + ret =3D ftrace_mod_address_lookup(addr, symbolsize, offset, + modname, modbuildid, namebuf); =20 found: cleanup_symbol_name(namebuf); diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 830344627e9f..92a169f0b2b5 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -797,6 +797,60 @@ static int kexec_calculate_store_digests(struct kimage= *image) } =20 #ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY +/* + * kexec_purgatory_find_symbol - find a symbol in the purgatory + * @pi: Purgatory to search in. + * @name: Name of the symbol. + * + * Return: pointer to symbol in read-only symtab on success, NULL on error. + */ +static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *p= i, + const char *name) +{ + const Elf_Shdr *sechdrs; + const Elf_Ehdr *ehdr; + const Elf_Sym *syms; + const char *strtab; + int i, k; + + if (!pi->ehdr) + return NULL; + + ehdr =3D pi->ehdr; + sechdrs =3D (void *)ehdr + ehdr->e_shoff; + + for (i =3D 0; i < ehdr->e_shnum; i++) { + if (sechdrs[i].sh_type !=3D SHT_SYMTAB) + continue; + + if (sechdrs[i].sh_link >=3D ehdr->e_shnum) + /* Invalid strtab section number */ + continue; + strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; + syms =3D (void *)ehdr + sechdrs[i].sh_offset; + + /* Go through symbols for a match */ + for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { + if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) + continue; + + if (strcmp(strtab + syms[k].st_name, name) !=3D 0) + continue; + + if (syms[k].st_shndx =3D=3D SHN_UNDEF || + syms[k].st_shndx >=3D ehdr->e_shnum) { + pr_debug("Symbol: %s has bad section index %d.\n", + name, syms[k].st_shndx); + return NULL; + } + + /* Found the symbol we are looking for */ + return &syms[k]; + } + } + + return NULL; +} /* * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory. * @pi: Purgatory to be loaded. @@ -875,6 +929,10 @@ static int kexec_purgatory_setup_sechdrs(struct purgat= ory_info *pi, unsigned long offset; size_t sechdrs_size; Elf_Shdr *sechdrs; + const Elf_Sym *entry_sym; + u16 entry_shndx =3D 0; + unsigned long entry_off =3D 0; + bool start_fixed =3D false; int i; =20 /* @@ -892,6 +950,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgat= ory_info *pi, bss_addr =3D kbuf->mem + kbuf->bufsz; kbuf->image->start =3D pi->ehdr->e_entry; =20 + entry_sym =3D kexec_purgatory_find_symbol(pi, "purgatory_start"); + if (entry_sym) { + entry_shndx =3D entry_sym->st_shndx; + entry_off =3D entry_sym->st_value; + } + for (i =3D 0; i < pi->ehdr->e_shnum; i++) { unsigned long align; void *src, *dst; @@ -909,6 +973,13 @@ static int kexec_purgatory_setup_sechdrs(struct purgat= ory_info *pi, =20 offset =3D ALIGN(offset, align); =20 + if (!start_fixed && entry_sym && i =3D=3D entry_shndx && + (sechdrs[i].sh_flags & SHF_EXECINSTR) && + entry_off < sechdrs[i].sh_size) { + kbuf->image->start =3D kbuf->mem + offset + entry_off; + start_fixed =3D true; + } + /* * Check if the segment contains the entry point, if so, * calculate the value of image->start based on it. @@ -919,13 +990,14 @@ static int kexec_purgatory_setup_sechdrs(struct purga= tory_info *pi, * is not set to the initial value, and warn the user so they * have a chance to fix their purgatory's linker script. */ - if (sechdrs[i].sh_flags & SHF_EXECINSTR && + if (!start_fixed && sechdrs[i].sh_flags & SHF_EXECINSTR && pi->ehdr->e_entry >=3D sechdrs[i].sh_addr && pi->ehdr->e_entry < (sechdrs[i].sh_addr + sechdrs[i].sh_size) && - !WARN_ON(kbuf->image->start !=3D pi->ehdr->e_entry)) { + kbuf->image->start =3D=3D pi->ehdr->e_entry) { kbuf->image->start -=3D sechdrs[i].sh_addr; kbuf->image->start +=3D kbuf->mem + offset; + start_fixed =3D true; } =20 src =3D (void *)pi->ehdr + sechdrs[i].sh_offset; @@ -1043,61 +1115,6 @@ int kexec_load_purgatory(struct kimage *image, struc= t kexec_buf *kbuf) return ret; } =20 -/* - * kexec_purgatory_find_symbol - find a symbol in the purgatory - * @pi: Purgatory to search in. - * @name: Name of the symbol. - * - * Return: pointer to symbol in read-only symtab on success, NULL on error. - */ -static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *p= i, - const char *name) -{ - const Elf_Shdr *sechdrs; - const Elf_Ehdr *ehdr; - const Elf_Sym *syms; - const char *strtab; - int i, k; - - if (!pi->ehdr) - return NULL; - - ehdr =3D pi->ehdr; - sechdrs =3D (void *)ehdr + ehdr->e_shoff; - - for (i =3D 0; i < ehdr->e_shnum; i++) { - if (sechdrs[i].sh_type !=3D SHT_SYMTAB) - continue; - - if (sechdrs[i].sh_link >=3D ehdr->e_shnum) - /* Invalid strtab section number */ - continue; - strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; - syms =3D (void *)ehdr + sechdrs[i].sh_offset; - - /* Go through symbols for a match */ - for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { - if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) - continue; - - if (strcmp(strtab + syms[k].st_name, name) !=3D 0) - continue; - - if (syms[k].st_shndx =3D=3D SHN_UNDEF || - syms[k].st_shndx >=3D ehdr->e_shnum) { - pr_debug("Symbol: %s has bad section index %d.\n", - name, syms[k].st_shndx); - return NULL; - } - - /* Found the symbol we are looking for */ - return &syms[k]; - } - } - - return NULL; -} - void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *na= me) { struct purgatory_info *pi =3D &image->purgatory_info; diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c index ef73ae7c8909..842808979113 100644 --- a/kernel/module/kallsyms.c +++ b/kernel/module/kallsyms.c @@ -336,13 +336,8 @@ const char *module_address_lookup(unsigned long addr, if (mod) { if (modname) *modname =3D mod->name; - if (modbuildid) { -#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) - *modbuildid =3D mod->build_id; -#else - *modbuildid =3D NULL; -#endif - } + if (modbuildid) + *modbuildid =3D module_buildid(mod); =20 ret =3D find_kallsyms_symbol(mod, addr, size, offset); } diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 607b2e68fa4c..81f0a730c54b 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -4379,6 +4379,54 @@ rcu_boot_init_percpu_data(int cpu) rcu_boot_init_nocb_percpu_data(rdp); } =20 +#ifdef CONFIG_RCU_EXP_KTHREAD +struct kthread_worker *rcu_exp_gp_kworker; +struct kthread_worker *rcu_exp_par_gp_kworker; + +static void __init rcu_start_exp_gp_kworkers(void) +{ + const char *par_gp_kworker_name =3D "rcu_exp_par_gp_kthread_worker"; + const char *gp_kworker_name =3D "rcu_exp_gp_kthread_worker"; + struct sched_param param =3D { .sched_priority =3D kthread_prio }; + + rcu_exp_gp_kworker =3D kthread_create_worker(0, gp_kworker_name); + if (IS_ERR_OR_NULL(rcu_exp_gp_kworker)) { + pr_err("Failed to create %s!\n", gp_kworker_name); + rcu_exp_gp_kworker =3D NULL; + return; + } + + rcu_exp_par_gp_kworker =3D kthread_create_worker(0, par_gp_kworker_name); + if (IS_ERR_OR_NULL(rcu_exp_par_gp_kworker)) { + pr_err("Failed to create %s!\n", par_gp_kworker_name); + rcu_exp_par_gp_kworker =3D NULL; + kthread_destroy_worker(rcu_exp_gp_kworker); + rcu_exp_gp_kworker =3D NULL; + return; + } + + sched_setscheduler_nocheck(rcu_exp_gp_kworker->task, SCHED_FIFO, ¶m); + sched_setscheduler_nocheck(rcu_exp_par_gp_kworker->task, SCHED_FIFO, + ¶m); +} + +static inline void rcu_alloc_par_gp_wq(void) +{ +} +#else /* !CONFIG_RCU_EXP_KTHREAD */ +struct workqueue_struct *rcu_par_gp_wq; + +static void __init rcu_start_exp_gp_kworkers(void) +{ +} + +static inline void rcu_alloc_par_gp_wq(void) +{ + rcu_par_gp_wq =3D alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); + WARN_ON(!rcu_par_gp_wq); +} +#endif /* CONFIG_RCU_EXP_KTHREAD */ + /* * Invoked early in the CPU-online process, when pretty much all services * are available. The incoming CPU is not present. @@ -4686,54 +4734,6 @@ static int rcu_pm_notify(struct notifier_block *self, return NOTIFY_OK; } =20 -#ifdef CONFIG_RCU_EXP_KTHREAD -struct kthread_worker *rcu_exp_gp_kworker; -struct kthread_worker *rcu_exp_par_gp_kworker; - -static void __init rcu_start_exp_gp_kworkers(void) -{ - const char *par_gp_kworker_name =3D "rcu_exp_par_gp_kthread_worker"; - const char *gp_kworker_name =3D "rcu_exp_gp_kthread_worker"; - struct sched_param param =3D { .sched_priority =3D kthread_prio }; - - rcu_exp_gp_kworker =3D kthread_create_worker(0, gp_kworker_name); - if (IS_ERR_OR_NULL(rcu_exp_gp_kworker)) { - pr_err("Failed to create %s!\n", gp_kworker_name); - rcu_exp_gp_kworker =3D NULL; - return; - } - - rcu_exp_par_gp_kworker =3D kthread_create_worker(0, par_gp_kworker_name); - if (IS_ERR_OR_NULL(rcu_exp_par_gp_kworker)) { - pr_err("Failed to create %s!\n", par_gp_kworker_name); - rcu_exp_par_gp_kworker =3D NULL; - kthread_destroy_worker(rcu_exp_gp_kworker); - rcu_exp_gp_kworker =3D NULL; - return; - } - - sched_setscheduler_nocheck(rcu_exp_gp_kworker->task, SCHED_FIFO, ¶m); - sched_setscheduler_nocheck(rcu_exp_par_gp_kworker->task, SCHED_FIFO, - ¶m); -} - -static inline void rcu_alloc_par_gp_wq(void) -{ -} -#else /* !CONFIG_RCU_EXP_KTHREAD */ -struct workqueue_struct *rcu_par_gp_wq; - -static void __init rcu_start_exp_gp_kworkers(void) -{ -} - -static inline void rcu_alloc_par_gp_wq(void) -{ - rcu_par_gp_wq =3D alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); - WARN_ON(!rcu_par_gp_wq); -} -#endif /* CONFIG_RCU_EXP_KTHREAD */ - /* * Spawn the kthreads that handle RCU's grace periods. */ @@ -4874,7 +4874,7 @@ static void __init rcu_init_one(void) init_waitqueue_head(&rnp->exp_wq[2]); init_waitqueue_head(&rnp->exp_wq[3]); spin_lock_init(&rnp->exp_lock); - mutex_init(&rnp->boost_kthread_mutex); + mutex_init(&rnp->kthread_mutex); raw_spin_lock_init(&rnp->exp_poll_lock); rnp->exp_seq_poll_rq =3D RCU_GET_STATE_COMPLETED; INIT_WORK(&rnp->exp_poll_wq, sync_rcu_do_polled_gp); diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index 71403d22a846..b79599b2059c 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -113,7 +113,7 @@ struct rcu_node { /* side effect, not as a lock. */ unsigned long boost_time; /* When to start boosting (jiffies). */ - struct mutex boost_kthread_mutex; + struct mutex kthread_mutex; /* Exclusion for thread spawning and affinity */ /* manipulation. */ struct task_struct *boost_kthread_task; @@ -203,7 +203,7 @@ struct rcu_data { /* during and after the last grace */ /* period it is aware of. */ struct irq_work defer_qs_iw; /* Obtain later scheduler attention. */ - int defer_qs_iw_pending; /* Scheduler attention pending? */ + int defer_qs_pending; /* irqwork or softirq pending? */ struct work_struct strict_work; /* Schedule readers for strict GPs. */ =20 /* 2) batch handling */ diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 8707f155afb6..8cf1adcd259b 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -475,8 +475,8 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *= t, unsigned long flags) union rcu_special special; =20 rdp =3D this_cpu_ptr(&rcu_data); - if (rdp->defer_qs_iw_pending =3D=3D DEFER_QS_PENDING) - rdp->defer_qs_iw_pending =3D DEFER_QS_IDLE; + if (rdp->defer_qs_pending =3D=3D DEFER_QS_PENDING) + rdp->defer_qs_pending =3D DEFER_QS_IDLE; =20 /* * If RCU core is waiting for this CPU to exit its critical section, @@ -615,11 +615,10 @@ notrace void rcu_preempt_deferred_qs(struct task_stru= ct *t) */ static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) { - unsigned long flags; struct rcu_data *rdp; =20 + lockdep_assert_irqs_disabled(); rdp =3D container_of(iwp, struct rcu_data, defer_qs_iw); - local_irq_save(flags); =20 /* * If the IRQ work handler happens to run in the middle of RCU read-side @@ -635,9 +634,76 @@ static void rcu_preempt_deferred_qs_handler(struct irq= _work *iwp) * 5. Deferred QS reporting does not happen. */ if (rcu_preempt_depth() > 0) - WRITE_ONCE(rdp->defer_qs_iw_pending, DEFER_QS_IDLE); + WRITE_ONCE(rdp->defer_qs_pending, DEFER_QS_IDLE); +} =20 - local_irq_restore(flags); +/* + * Check if expedited grace period processing during unlock is needed. + * + * This function determines whether expedited handling is required based o= n: + * 1. Task blocking an expedited grace period (based on a heuristic, could= be + * false-positive, see below.) + * 2. CPU participating in an expedited grace period + * 3. Strict grace period mode requiring expedited handling + * 4. RCU priority deboosting needs when interrupts were disabled + * + * @t: The task being checked + * @rdp: The per-CPU RCU data + * @rnp: The RCU node for this CPU + * @irqs_were_disabled: Whether interrupts were disabled before rcu_read_u= nlock() + * + * Returns true if expedited processing of the rcu_read_unlock() is needed. + */ +static bool rcu_unlock_needs_exp_handling(struct task_struct *t, + struct rcu_data *rdp, + struct rcu_node *rnp, + bool irqs_were_disabled) +{ + /* + * Check if this task is blocking an expedited grace period. If the + * task was preempted within an RCU read-side critical section and is + * on the expedited grace period blockers list (exp_tasks), we need + * expedited handling to unblock the expedited GP. This is not an exact + * check because 't' might not be on the exp_tasks list at all - its + * just a fast heuristic that can be false-positive sometimes. + */ + if (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) + return true; + + /* + * Check if this CPU is participating in an expedited grace period. + * The expmask bitmap tracks which CPUs need to check in for the + * current expedited GP. If our CPU's bit is set, we need expedited + * handling to help complete the expedited GP. + */ + if (rdp->grpmask & READ_ONCE(rnp->expmask)) + return true; + + /* + * In CONFIG_RCU_STRICT_GRACE_PERIOD=3Dy kernels, all grace periods + * are treated as short for testing purposes even if that means + * disturbing the system more. Check if either: + * - This CPU has not yet reported a quiescent state, or + * - This task was preempted within an RCU critical section + * In either case, require expedited handling for strict GP mode. + */ + if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && + ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) + return true; + + /* + * RCU priority boosting case: If a task is subject to RCU priority + * boosting and exits an RCU read-side critical section with interrupts + * disabled, we need expedited handling to ensure timely deboosting. + * Without this, a low-priority task could incorrectly run at high + * real-time priority for an extended period degrading real-time + * responsiveness. This applies to all CONFIG_RCU_BOOST=3Dy kernels, + * not just to PREEMPT_RT. + */ + if (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled && t->rcu_blocked_= node) + return true; + + return false; } =20 /* @@ -659,22 +725,21 @@ static void rcu_read_unlock_special(struct task_struc= t *t) local_irq_save(flags); irqs_were_disabled =3D irqs_disabled_flags(flags); if (preempt_bh_were_disabled || irqs_were_disabled) { - bool expboost; // Expedited GP in flight or possible boosting. + bool needs_exp; // Expedited handling needed. struct rcu_data *rdp =3D this_cpu_ptr(&rcu_data); struct rcu_node *rnp =3D rdp->mynode; =20 - expboost =3D (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_= tasks)) || - (rdp->grpmask & READ_ONCE(rnp->expmask)) || - (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && - ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) || - (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled && - t->rcu_blocked_node); + needs_exp =3D rcu_unlock_needs_exp_handling(t, rdp, rnp, irqs_were_disab= led); + // Need to defer quiescent state until everything is enabled. - if (use_softirq && (in_hardirq() || (expboost && !irqs_were_disabled))) { + if (use_softirq && (in_hardirq() || (needs_exp && !irqs_were_disabled)))= { // Using softirq, safe to awaken, and either the // wakeup is free or there is either an expedited // GP in flight or a potential need to deboost. - raise_softirq_irqoff(RCU_SOFTIRQ); + if (rdp->defer_qs_pending !=3D DEFER_QS_PENDING) { + rdp->defer_qs_pending =3D DEFER_QS_PENDING; + raise_softirq_irqoff(RCU_SOFTIRQ); + } } else { // Enabling BH or preempt does reschedule, so... // Also if no expediting and no possible deboosting, @@ -683,11 +748,11 @@ static void rcu_read_unlock_special(struct task_struc= t *t) set_tsk_need_resched(current); set_preempt_need_resched(); if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled && - expboost && rdp->defer_qs_iw_pending !=3D DEFER_QS_PENDING && + needs_exp && rdp->defer_qs_pending !=3D DEFER_QS_PENDING && cpu_online(rdp->cpu)) { // Get scheduler to re-evaluate and call hooks. // If !IRQ_WORK, FQS scan will eventually IPI. - rdp->defer_qs_iw_pending =3D DEFER_QS_PENDING; + rdp->defer_qs_pending =3D DEFER_QS_PENDING; irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu); } } @@ -1229,7 +1294,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_no= de *rnp) struct sched_param sp; struct task_struct *t; =20 - mutex_lock(&rnp->boost_kthread_mutex); + mutex_lock(&rnp->kthread_mutex); if (rnp->boost_kthread_task || !rcu_scheduler_fully_active) goto out; =20 @@ -1246,7 +1311,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_no= de *rnp) wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */ =20 out: - mutex_unlock(&rnp->boost_kthread_mutex); + mutex_unlock(&rnp->kthread_mutex); } =20 /* @@ -1258,7 +1323,7 @@ static void rcu_spawn_one_boost_kthread(struct rcu_no= de *rnp) * no outgoing CPU. If there are no CPUs left in the affinity set, * this function allows the kthread to execute on any CPU. * - * Any future concurrent calls are serialized via ->boost_kthread_mutex. + * Any future concurrent calls are serialized via ->kthread_mutex. */ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoi= ngcpu) { @@ -1271,7 +1336,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_= node *rnp, int outgoingcpu) return; if (!zalloc_cpumask_var(&cm, GFP_KERNEL)) return; - mutex_lock(&rnp->boost_kthread_mutex); + mutex_lock(&rnp->kthread_mutex); mask =3D rcu_rnp_online_cpus(rnp); for_each_leaf_node_possible_cpu(rnp, cpu) if ((mask & leaf_node_cpu_bit(rnp, cpu)) && @@ -1284,7 +1349,7 @@ static void rcu_boost_kthread_setaffinity(struct rcu_= node *rnp, int outgoingcpu) cpumask_clear_cpu(outgoingcpu, cm); } set_cpus_allowed_ptr(t, cm); - mutex_unlock(&rnp->boost_kthread_mutex); + mutex_unlock(&rnp->kthread_mutex); free_cpumask_var(cm); } =20 diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 005eaf41925c..20e1003a23c7 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -2219,6 +2219,7 @@ static void push_rt_tasks(struct rq *rq) */ static int rto_next_cpu(struct root_domain *rd) { + int this_cpu =3D smp_processor_id(); int next; int cpu; =20 @@ -2242,6 +2243,10 @@ static int rto_next_cpu(struct root_domain *rd) =20 rd->rto_cpu =3D cpu; =20 + /* Do not send IPI to self */ + if (cpu =3D=3D this_cpu) + continue; + if (cpu < nr_cpu_ids) { if (!has_pushable_tasks(cpu_rq(cpu))) continue; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index fbc2f30b4922..842e2831b6a4 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1715,7 +1715,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cp= u_base, =20 lockdep_assert_held(&cpu_base->lock); =20 - debug_deactivate(timer); + debug_hrtimer_deactivate(timer); base->running =3D timer; =20 /* diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8f2d44e74151..94f7ed57d43e 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -7046,7 +7046,8 @@ ftrace_func_address_lookup(struct ftrace_mod_map *mod= _map, =20 const char * ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, - unsigned long *off, char **modname, char *sym) + unsigned long *off, char **modname, + const unsigned char **modbuildid, char *sym) { struct ftrace_mod_map *mod_map; const char *ret =3D NULL; @@ -7058,6 +7059,8 @@ ftrace_mod_address_lookup(unsigned long addr, unsigne= d long *size, if (ret) { if (modname) *modname =3D mod_map->mod->name; + if (modbuildid) + *modbuildid =3D module_buildid(mod_map->mod); break; } } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9ab46a9d0aa6..b0ff1a4e352b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -8833,7 +8833,7 @@ tracing_init_tracefs_percpu(struct trace_array *tr, l= ong cpu) trace_create_cpu_file("stats", TRACE_MODE_READ, d_cpu, tr, cpu, &tracing_stats_fops); =20 - trace_create_cpu_file("buffer_size_kb", TRACE_MODE_READ, d_cpu, + trace_create_cpu_file("buffer_size_kb", TRACE_MODE_WRITE, d_cpu, tr, cpu, &tracing_entries_fops); =20 #ifdef CONFIG_TRACER_SNAPSHOT diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 382e07cd49f9..106ae22f0464 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1169,6 +1169,9 @@ static void remove_event_file_dir(struct trace_event_= file *file) free_event_filter(file->filter); file->flags |=3D EVENT_FILE_FL_FREED; event_file_put(file); + + /* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */ + hist_poll_wakeup(); } =20 /* @@ -3575,11 +3578,6 @@ void trace_put_event_file(struct trace_event_file *f= ile) EXPORT_SYMBOL_GPL(trace_put_event_file); =20 #ifdef CONFIG_DYNAMIC_FTRACE - -/* Avoid typos */ -#define ENABLE_EVENT_STR "enable_event" -#define DISABLE_EVENT_STR "disable_event" - struct event_probe_data { struct trace_event_file *file; unsigned long count; diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_h= ist.c index 99d1e8b57f85..19b3d388fbc6 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5760,7 +5760,7 @@ static __poll_t event_hist_poll(struct file *file, st= ruct poll_table_struct *wai =20 guard(mutex)(&event_mutex); =20 - event_file =3D event_file_data(file); + event_file =3D event_file_file(file); if (!event_file) return EPOLLERR; =20 @@ -5798,7 +5798,7 @@ static int event_hist_open(struct inode *inode, struc= t file *file) =20 guard(mutex)(&event_mutex); =20 - event_file =3D event_file_data(file); + event_file =3D event_file_file(file); if (!event_file) { ret =3D -ENODEV; goto err; @@ -6889,7 +6889,7 @@ static int event_hist_trigger_parse(struct event_comm= and *cmd_ops, =20 remove_hist_vars(hist_data); =20 - kfree(trigger_data); + trigger_data_free(trigger_data); =20 destroy_hist_data(hist_data); goto out; diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index 3bd6071441ad..bc437b6ce896 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -102,9 +102,9 @@ struct hwlat_sample { /* keep the global state somewhere. */ static struct hwlat_data { =20 - struct mutex lock; /* protect changes */ + struct mutex lock; /* protect changes */ =20 - u64 count; /* total since reset */ + atomic64_t count; /* total since reset */ =20 u64 sample_window; /* total sampling window (on+off) */ u64 sample_width; /* active sampling portion of window */ @@ -195,8 +195,7 @@ void trace_hwlat_callback(bool enter) * get_sample - sample the CPU TSC and look for likely hardware latencies * * Used to repeatedly capture the CPU TSC (or similar), looking for potent= ial - * hardware-induced latency. Called with interrupts disabled and with - * hwlat_data.lock held. + * hardware-induced latency. Called with interrupts disabled. */ static int get_sample(void) { @@ -206,6 +205,7 @@ static int get_sample(void) time_type start, t1, t2, last_t2; s64 diff, outer_diff, total, last_total =3D 0; u64 sample =3D 0; + u64 sample_width =3D READ_ONCE(hwlat_data.sample_width); u64 thresh =3D tracing_thresh; u64 outer_sample =3D 0; int ret =3D -1; @@ -269,7 +269,7 @@ static int get_sample(void) if (diff > sample) sample =3D diff; /* only want highest value */ =20 - } while (total <=3D hwlat_data.sample_width); + } while (total <=3D sample_width); =20 barrier(); /* finish the above in the view for NMIs */ trace_hwlat_callback_enabled =3D false; @@ -287,8 +287,7 @@ static int get_sample(void) if (kdata->nmi_total_ts) do_div(kdata->nmi_total_ts, NSEC_PER_USEC); =20 - hwlat_data.count++; - s.seqnum =3D hwlat_data.count; + s.seqnum =3D atomic64_inc_return(&hwlat_data.count); s.duration =3D sample; s.outer_duration =3D outer_sample; s.nmi_total_ts =3D kdata->nmi_total_ts; @@ -837,7 +836,7 @@ static int hwlat_tracer_init(struct trace_array *tr) =20 hwlat_trace =3D tr; =20 - hwlat_data.count =3D 0; + atomic64_set(&hwlat_data.count, 0); tr->max_latency =3D 0; save_tracing_thresh =3D tracing_thresh; =20 diff --git a/kernel/ucount.c b/kernel/ucount.c index a7fd89693bd2..44ede7a6b805 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -45,7 +45,7 @@ static int set_permissions(struct ctl_table_header *head, int mode; =20 /* Allow users with CAP_SYS_RESOURCE unrestrained access */ - if (ns_capable(user_ns, CAP_SYS_RESOURCE)) + if (ns_capable_noaudit(user_ns, CAP_SYS_RESOURCE)) mode =3D (table->mode & S_IRWXU) >> 6; else /* Allow all others at most read-only access */ diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 59b6efb2a11c..641914d86154 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -101,6 +101,8 @@ enum { MAYDAY_INTERVAL =3D HZ / 10, /* and then every 100ms */ CREATE_COOLDOWN =3D HZ, /* time to breath after fail */ =20 + RESCUER_BATCH =3D 16, /* process items per turn */ + /* * Rescue workers are used only on emergencies and shared by * all cpus. Give MIN_NICE. @@ -254,6 +256,7 @@ struct pool_workqueue { struct list_head inactive_works; /* L: inactive works */ struct list_head pwqs_node; /* WR: node on wq->pwqs */ struct list_head mayday_node; /* MD: node on wq->maydays */ + struct work_struct mayday_cursor; /* L: cursor on pool->worklist */ =20 u64 stats[PWQ_NR_STATS]; =20 @@ -1015,6 +1018,12 @@ static struct worker *find_worker_executing_work(str= uct worker_pool *pool, return NULL; } =20 +static void mayday_cursor_func(struct work_struct *work) +{ + /* should not be processed, only for marking position */ + BUG(); +} + /** * move_linked_works - move linked works to a list * @work: start of series of works to be scheduled @@ -1077,6 +1086,16 @@ static bool assign_work(struct work_struct *work, st= ruct worker *worker, =20 lockdep_assert_held(&pool->lock); =20 + /* The cursor work should not be processed */ + if (unlikely(work->func =3D=3D mayday_cursor_func)) { + /* only worker_thread() can possibly take this branch */ + WARN_ON_ONCE(worker->rescue_wq); + if (nextp) + *nextp =3D list_next_entry(work, entry); + list_del_init(&work->entry); + return false; + } + /* * A single work shouldn't be executed concurrently by multiple workers. * __queue_work() ensures that @work doesn't jump to a different pool @@ -2808,6 +2827,35 @@ static int worker_thread(void *__worker) goto woke_up; } =20 +static bool assign_rescuer_work(struct pool_workqueue *pwq, struct worker = *rescuer) +{ + struct worker_pool *pool =3D pwq->pool; + struct work_struct *cursor =3D &pwq->mayday_cursor; + struct work_struct *work, *n; + + /* need rescue? */ + if (!pwq->nr_active || !need_to_create_worker(pool)) + return false; + + /* search from the start or cursor if available */ + if (list_empty(&cursor->entry)) + work =3D list_first_entry(&pool->worklist, struct work_struct, entry); + else + work =3D list_next_entry(cursor, entry); + + /* find the next work item to rescue */ + list_for_each_entry_safe_from(work, n, &pool->worklist, entry) { + if (get_work_pwq(work) =3D=3D pwq && assign_work(work, rescuer, &n)) { + pwq->stats[PWQ_STAT_RESCUED]++; + /* put the cursor for next search */ + list_move_tail(&cursor->entry, &n->entry); + return true; + } + } + + return false; +} + /** * rescuer_thread - the rescuer thread function * @__rescuer: self @@ -2862,7 +2910,7 @@ static int rescuer_thread(void *__rescuer) struct pool_workqueue *pwq =3D list_first_entry(&wq->maydays, struct pool_workqueue, mayday_node); struct worker_pool *pool =3D pwq->pool; - struct work_struct *work, *n; + unsigned int count =3D 0; =20 __set_current_state(TASK_RUNNING); list_del_init(&pwq->mayday_node); @@ -2873,30 +2921,18 @@ static int rescuer_thread(void *__rescuer) =20 raw_spin_lock_irq(&pool->lock); =20 - /* - * Slurp in all works issued via this workqueue and - * process'em. - */ WARN_ON_ONCE(!list_empty(&rescuer->scheduled)); - list_for_each_entry_safe(work, n, &pool->worklist, entry) { - if (get_work_pwq(work) =3D=3D pwq && - assign_work(work, rescuer, &n)) - pwq->stats[PWQ_STAT_RESCUED]++; - } =20 - if (!list_empty(&rescuer->scheduled)) { + while (assign_rescuer_work(pwq, rescuer)) { process_scheduled_works(rescuer); =20 /* - * The above execution of rescued work items could - * have created more to rescue through - * pwq_activate_first_inactive() or chained - * queueing. Let's put @pwq back on mayday list so - * that such back-to-back work items, which may be - * being used to relieve memory pressure, don't - * incur MAYDAY_INTERVAL delay inbetween. + * If the per-turn work item limit is reached and other + * PWQs are in mayday, requeue mayday for this PWQ and + * let the rescuer handle the other PWQs first. */ - if (pwq->nr_active && need_to_create_worker(pool)) { + if (++count > RESCUER_BATCH && !list_empty(&pwq->wq->maydays) && + pwq->nr_active && need_to_create_worker(pool)) { raw_spin_lock(&wq_mayday_lock); /* * Queue iff we aren't racing destruction @@ -2907,9 +2943,14 @@ static int rescuer_thread(void *__rescuer) list_add_tail(&pwq->mayday_node, &wq->maydays); } raw_spin_unlock(&wq_mayday_lock); + break; } } =20 + /* The cursor can not be left behind without the rescuer watching it. */ + if (!list_empty(&pwq->mayday_cursor.entry) && list_empty(&pwq->mayday_no= de)) + list_del_init(&pwq->mayday_cursor.entry); + /* * Put the reference grabbed by send_mayday(). @pool won't * go away while we're still attached to it. @@ -4222,6 +4263,19 @@ static void init_pwq(struct pool_workqueue *pwq, str= uct workqueue_struct *wq, INIT_LIST_HEAD(&pwq->pwqs_node); INIT_LIST_HEAD(&pwq->mayday_node); kthread_init_work(&pwq->release_work, pwq_release_workfn); + + /* + * Set the dummy cursor work with valid function and get_work_pwq(). + * + * The cursor work should only be in the pwq->pool->worklist, and + * should not be treated as a processable work item. + * + * WORK_STRUCT_PENDING and WORK_STRUCT_INACTIVE just make it less + * surprise for kernel debugging tools and reviewers. + */ + INIT_WORK(&pwq->mayday_cursor, mayday_cursor_func); + atomic_long_set(&pwq->mayday_cursor.data, (unsigned long)pwq | + WORK_STRUCT_PENDING | WORK_STRUCT_PWQ | WORK_STRUCT_INACTIVE); } =20 /* sync @pwq with the current state of its associated wq and link it */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1aae81c57b2c..e56f9e1b18fd 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1619,33 +1619,6 @@ config STACKTRACE It is also used by various kernel debugging features that require stack trace generation. =20 -config WARN_ALL_UNSEEDED_RANDOM - bool "Warn for all uses of unseeded randomness" - default n - help - Some parts of the kernel contain bugs relating to their use of - cryptographically secure random numbers before it's actually possible - to generate those numbers securely. This setting ensures that these - flaws don't go unnoticed, by enabling a message, should this ever - occur. This will allow people with obscure setups to know when things - are going wrong, so that they might contact developers about fixing - it. - - Unfortunately, on some models of some architectures getting - a fully seeded CRNG is extremely difficult, and so this can - result in dmesg getting spammed for a surprisingly long - time. This is really bad from a security perspective, and - so architecture maintainers really need to do what they can - to get the CRNG seeded sooner after the system is booted. - However, since users cannot do anything actionable to - address this, by default this option is disabled. - - Say Y here if you want to receive warnings for all uses of - unseeded randomness. This will be of use primarily for - those developers interested in improving the security of - Linux kernels running on their architecture (or - subarchitecture). - config DEBUG_KOBJECT bool "kobject debugging" depends on DEBUG_KERNEL diff --git a/localversion-rt b/localversion-rt index 65189810797f..f36b5d418dd8 100644 --- a/localversion-rt +++ b/localversion-rt @@ -1 +1 @@ --rt69 +-rt70 diff --git a/mm/highmem.c b/mm/highmem.c index e19269093a93..87c2fe3d2f3d 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -169,12 +169,13 @@ struct page *__kmap_to_page(void *vaddr) for (i =3D 0; i < kctrl->idx; i++) { unsigned long base_addr; int idx; + pte_t pteval =3D kctrl->pteval[i]; =20 idx =3D arch_kmap_local_map_idx(i, pte_pfn(pteval)); base_addr =3D __fix_to_virt(FIX_KMAP_BEGIN + idx); =20 if (base_addr =3D=3D base) - return pte_page(kctrl->pteval[i]); + return pte_page(pteval); } } =20 diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6c042f7796e4..b617fb364b15 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4057,6 +4057,20 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int = order, compact_result =3D=3D COMPACT_DEFERRED) goto nopage; =20 + /* + * THP page faults may attempt local node only first, + * but are then allowed to only compact, not reclaim, + * see alloc_pages_mpol(). + * + * Compaction can fail for other reasons than those + * checked above and we don't want such THP allocations + * to put reclaim pressure on a single node in a + * situation where other nodes might have plenty of + * available memory. + */ + if (gfp_mask & __GFP_THISNODE) + goto nopage; + /* * Looks like reclaim/compaction is worth trying, but * sync compaction could be very expensive, so keep diff --git a/net/atm/signaling.c b/net/atm/signaling.c index e70ae2c113f9..358fbe5e4d1d 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -22,6 +22,36 @@ =20 struct atm_vcc *sigd =3D NULL; =20 +/* + * find_get_vcc - validate and get a reference to a vcc pointer + * @vcc: the vcc pointer to validate + * + * This function validates that @vcc points to a registered VCC in vcc_has= h. + * If found, it increments the socket reference count and returns the vcc. + * The caller must call sock_put(sk_atm(vcc)) when done. + * + * Returns the vcc pointer if valid, NULL otherwise. + */ +static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc) +{ + int i; + + read_lock(&vcc_sklist_lock); + for (i =3D 0; i < VCC_HTABLE_SIZE; i++) { + struct sock *s; + + sk_for_each(s, &vcc_hash[i]) { + if (atm_sk(s) =3D=3D vcc) { + sock_hold(s); + read_unlock(&vcc_sklist_lock); + return vcc; + } + } + } + read_unlock(&vcc_sklist_lock); + return NULL; +} + static void sigd_put_skb(struct sk_buff *skb) { if (!sigd) { @@ -69,7 +99,14 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff= *skb) =20 msg =3D (struct atmsvc_msg *) skb->data; WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc)= ); - vcc =3D *(struct atm_vcc **) &msg->vcc; + + vcc =3D find_get_vcc(*(struct atm_vcc **)&msg->vcc); + if (!vcc) { + pr_debug("invalid vcc pointer in msg\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc); sk =3D sk_atm(vcc); =20 @@ -100,7 +137,16 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_bu= ff *skb) clear_bit(ATM_VF_WAITING, &vcc->flags); break; case as_indicate: - vcc =3D *(struct atm_vcc **)&msg->listen_vcc; + /* Release the reference from msg->vcc, we'll use msg->listen_vcc instea= d */ + sock_put(sk); + + vcc =3D find_get_vcc(*(struct atm_vcc **)&msg->listen_vcc); + if (!vcc) { + pr_debug("invalid listen_vcc pointer in msg\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + sk =3D sk_atm(vcc); pr_debug("as_indicate!!!\n"); lock_sock(sk); @@ -115,6 +161,8 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buf= f *skb) sk->sk_state_change(sk); as_indicate_complete: release_sock(sk); + /* Paired with find_get_vcc(msg->listen_vcc) above */ + sock_put(sk); return 0; case as_close: set_bit(ATM_VF_RELEASED, &vcc->flags); @@ -131,11 +179,15 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_b= uff *skb) break; default: pr_alert("bad message type %d\n", (int)msg->type); + /* Paired with find_get_vcc(msg->vcc) above */ + sock_put(sk); return -EINVAL; } sk->sk_state_change(sk); out: dev_kfree_skb(skb); + /* Paired with find_get_vcc(msg->vcc) above */ + sock_put(sk); return 0; } =20 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ff9d2520ba74..30feeaf7e642 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -951,6 +951,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *= hdev, int type, bdaddr_t switch (type) { case ACL_LINK: conn->pkt_type =3D hdev->pkt_type & ACL_PTYPE_MASK; + conn->link_policy =3D hdev->link_policy; conn->mtu =3D hdev->acl_mtu; break; case LE_LINK: @@ -2517,8 +2518,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn= , __u8 force_active) =20 timer: if (hdev->idle_timeout > 0) - queue_delayed_work(hdev->workqueue, &conn->idle_work, - msecs_to_jiffies(hdev->idle_timeout)); + mod_delayed_work(hdev->workqueue, &conn->idle_work, + msecs_to_jiffies(hdev->idle_timeout)); } =20 /* Drop all connection on the device */ diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index f0eb52d5c058..6a14f7607107 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -6860,8 +6860,6 @@ static int hci_acl_create_conn_sync(struct hci_dev *h= dev, void *data) =20 conn->attempt++; =20 - conn->link_policy =3D hdev->link_policy; - memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode =3D 0x02; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ad46112cb596..0cbd6c292123 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -4863,6 +4863,13 @@ static int l2cap_le_connect_req(struct l2cap_conn *c= onn, goto response_unlock; } =20 + /* Check if Key Size is sufficient for the security level */ + if (!l2cap_check_enc_key_size(conn->hcon, pchan)) { + result =3D L2CAP_CR_LE_BAD_KEY_SIZE; + chan =3D NULL; + goto response_unlock; + } + /* Check for valid dynamic CID range */ if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) { result =3D L2CAP_CR_LE_INVALID_SCID; @@ -5059,7 +5066,16 @@ static inline int l2cap_ecred_conn_req(struct l2cap_= conn *conn, =20 if (!smp_sufficient_security(conn->hcon, pchan->sec_level, SMP_ALLOW_STK)) { - result =3D L2CAP_CR_LE_AUTHENTICATION; + result =3D pchan->sec_level =3D=3D BT_SECURITY_MEDIUM ? + L2CAP_CR_LE_ENCRYPTION : L2CAP_CR_LE_AUTHENTICATION; + goto unlock; + } + + /* Check if the listening channel has set an output MTU then the + * requested MTU shall be less than or equal to that value. + */ + if (pchan->omtu && mtu < pchan->omtu) { + result =3D L2CAP_CR_LE_UNACCEPT_PARAMS; goto unlock; } =20 @@ -5260,14 +5276,14 @@ static inline int l2cap_ecred_reconf_req(struct l2c= ap_conn *conn, struct l2cap_ecred_reconf_req *req =3D (void *) data; struct l2cap_ecred_reconf_rsp rsp; u16 mtu, mps, result; - struct l2cap_chan *chan; + struct l2cap_chan *chan[L2CAP_ECRED_MAX_CID] =3D {}; int i, num_scid; =20 if (!enable_ecred) return -EINVAL; =20 - if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) { - result =3D L2CAP_CR_LE_INVALID_PARAMS; + if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) { + result =3D L2CAP_RECONF_INVALID_CID; goto respond; } =20 @@ -5277,42 +5293,69 @@ static inline int l2cap_ecred_reconf_req(struct l2c= ap_conn *conn, BT_DBG("mtu %u mps %u", mtu, mps); =20 if (mtu < L2CAP_ECRED_MIN_MTU) { - result =3D L2CAP_RECONF_INVALID_MTU; + result =3D L2CAP_RECONF_INVALID_PARAMS; goto respond; } =20 if (mps < L2CAP_ECRED_MIN_MPS) { - result =3D L2CAP_RECONF_INVALID_MPS; + result =3D L2CAP_RECONF_INVALID_PARAMS; goto respond; } =20 cmd_len -=3D sizeof(*req); num_scid =3D cmd_len / sizeof(u16); + + if (num_scid > L2CAP_ECRED_MAX_CID) { + result =3D L2CAP_RECONF_INVALID_PARAMS; + goto respond; + } + result =3D L2CAP_RECONF_SUCCESS; =20 + /* Check if each SCID, MTU and MPS are valid */ for (i =3D 0; i < num_scid; i++) { u16 scid; =20 scid =3D __le16_to_cpu(req->scid[i]); - if (!scid) - return -EPROTO; + if (!scid) { + result =3D L2CAP_RECONF_INVALID_CID; + goto respond; + } =20 - chan =3D __l2cap_get_chan_by_dcid(conn, scid); - if (!chan) - continue; + chan[i] =3D __l2cap_get_chan_by_dcid(conn, scid); + if (!chan[i]) { + result =3D L2CAP_RECONF_INVALID_CID; + goto respond; + } =20 - /* If the MTU value is decreased for any of the included - * channels, then the receiver shall disconnect all - * included channels. + /* The MTU field shall be greater than or equal to the greatest + * current MTU size of these channels. */ - if (chan->omtu > mtu) { - BT_ERR("chan %p decreased MTU %u -> %u", chan, - chan->omtu, mtu); + if (chan[i]->omtu > mtu) { + BT_ERR("chan %p decreased MTU %u -> %u", chan[i], + chan[i]->omtu, mtu); result =3D L2CAP_RECONF_INVALID_MTU; + goto respond; } =20 - chan->omtu =3D mtu; - chan->remote_mps =3D mps; + /* If more than one channel is being configured, the MPS field + * shall be greater than or equal to the current MPS size of + * each of these channels. If only one channel is being + * configured, the MPS field may be less than the current MPS + * of that channel. + */ + if (chan[i]->remote_mps >=3D mps && i) { + BT_ERR("chan %p decreased MPS %u -> %u", chan[i], + chan[i]->remote_mps, mps); + result =3D L2CAP_RECONF_INVALID_MPS; + goto respond; + } + } + + /* Commit the new MTU and MPS values after checking they are valid */ + for (i =3D 0; i < num_scid; i++) { + chan[i]->omtu =3D mtu; + chan[i]->remote_mps =3D mps; } =20 respond: diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 59630dbeda20..250cc0bc552e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1027,10 +1027,17 @@ static int l2cap_sock_setsockopt(struct socket *soc= k, int level, int optname, break; } =20 - /* Setting is not supported as it's the remote side that - * decides this. - */ - err =3D -EPERM; + /* Only allow setting output MTU when not connected */ + if (sk->sk_state =3D=3D BT_CONNECTED) { + err =3D -EISCONN; + break; + } + + err =3D copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen); + if (err) + break; + + chan->omtu =3D mtu; break; =20 case BT_RCVMTU: diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 4a2d94e8717e..4e75ec75c702 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -243,14 +243,11 @@ br_multicast_port_vid_to_port_ctx(struct net_bridge_p= ort *port, u16 vid) =20 lockdep_assert_held_once(&port->br->multicast_lock); =20 - if (!br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) - return NULL; - /* Take RCU to access the vlan. */ rcu_read_lock(); =20 vlan =3D br_vlan_find(nbp_vlan_group_rcu(port), vid); - if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx)) + if (vlan) pmctx =3D &vlan->port_mcast_ctx; =20 rcu_read_unlock(); @@ -700,7 +697,10 @@ br_multicast_port_ngroups_inc_one(struct net_bridge_mc= ast_port *pmctx, u32 max =3D READ_ONCE(pmctx->mdb_max_entries); u32 n =3D READ_ONCE(pmctx->mdb_n_entries); =20 - if (max && n >=3D max) { + /* enforce the max limit when it's a port pmctx or a port-vlan pmctx + * with snooping enabled + */ + if (!br_multicast_port_ctx_vlan_disabled(pmctx) && max && n >=3D max) { NL_SET_ERR_MSG_FMT_MOD(extack, "%s is already in %u groups, and mcast_ma= x_groups=3D%u", what, n, max); return -E2BIG; @@ -735,9 +735,7 @@ static int br_multicast_port_ngroups_inc(struct net_bri= dge_port *port, return err; } =20 - /* Only count on the VLAN context if VID is given, and if snooping on - * that VLAN is enabled. - */ + /* Only count on the VLAN context if VID is given */ if (!group->vid) return 0; =20 @@ -2009,6 +2007,18 @@ void br_multicast_port_ctx_init(struct net_bridge_po= rt *port, timer_setup(&pmctx->ip6_own_query.timer, br_ip6_multicast_port_query_expired, 0); #endif + /* initialize mdb_n_entries if a new port vlan is being created */ + if (vlan) { + struct net_bridge_port_group *pg; + u32 n =3D 0; + + spin_lock_bh(&port->br->multicast_lock); + hlist_for_each_entry(pg, &port->mglist, mglist) + if (pg->key.addr.vid =3D=3D vlan->vid) + n++; + WRITE_ONCE(pmctx->mdb_n_entries, n); + spin_unlock_bh(&port->br->multicast_lock); + } } =20 void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) @@ -2092,25 +2102,6 @@ static void __br_multicast_enable_port_ctx(struct ne= t_bridge_mcast_port *pmctx) br_ip4_multicast_add_router(brmctx, pmctx); br_ip6_multicast_add_router(brmctx, pmctx); } - - if (br_multicast_port_ctx_is_vlan(pmctx)) { - struct net_bridge_port_group *pg; - u32 n =3D 0; - - /* The mcast_n_groups counter might be wrong. First, - * BR_VLFLAG_MCAST_ENABLED is toggled before temporary entries - * are flushed, thus mcast_n_groups after the toggle does not - * reflect the true values. And second, permanent entries added - * while BR_VLFLAG_MCAST_ENABLED was disabled, are not reflected - * either. Thus we have to refresh the counter. - */ - - hlist_for_each_entry(pg, &pmctx->port->mglist, mglist) { - if (pg->key.addr.vid =3D=3D pmctx->vlan->vid) - n++; - } - WRITE_ONCE(pmctx->mdb_n_entries, n); - } } =20 static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmc= tx) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 051d22c0e4ad..3397d105f74f 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -37,9 +37,6 @@ static int set_secret(struct ceph_crypto_key *key, void *= buf) return -ENOTSUPP; } =20 - if (!key->len) - return -EINVAL; - key->key =3D kmemdup(buf, key->len, GFP_NOIO); if (!key->key) { ret =3D -ENOMEM; @@ -95,6 +92,11 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, = void **p, void *end) ceph_decode_copy(p, &key->created, sizeof(key->created)); key->len =3D ceph_decode_16(p); ceph_decode_need(p, end, key->len, bad); + if (key->len > CEPH_MAX_KEY_LEN) { + pr_err("secret too big %d\n", key->len); + return -EINVAL; + } + ret =3D set_secret(key, *p); memzero_explicit(*p, key->len); *p +=3D key->len; diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 13bd526349fa..0d32f1649f3d 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -5,7 +5,7 @@ #include #include =20 -#define CEPH_KEY_LEN 16 +#define CEPH_MAX_KEY_LEN 16 #define CEPH_MAX_CON_SECRET_LEN 64 =20 /* diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c index 858198724439..f82029bd33db 100644 --- a/net/ceph/messenger_v2.c +++ b/net/ceph/messenger_v2.c @@ -2393,7 +2393,7 @@ static int process_auth_reply_more(struct ceph_connec= tion *con, */ static int process_auth_done(struct ceph_connection *con, void *p, void *e= nd) { - u8 session_key_buf[CEPH_KEY_LEN + 16]; + u8 session_key_buf[CEPH_MAX_KEY_LEN + 16]; u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16]; u8 *session_key =3D PTR_ALIGN(&session_key_buf[0], 16); u8 *con_secret =3D PTR_ALIGN(&con_secret_buf[0], 16); diff --git a/net/core/dev.c b/net/core/dev.c index 5b53496b2666..7c78d074cb70 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -701,7 +701,7 @@ static struct net_device_path *dev_fwd_path(struct net_= device_path_stack *stack) { int k =3D stack->num_paths++; =20 - if (WARN_ON_ONCE(k >=3D NET_DEVICE_PATH_STACK_MAX)) + if (k >=3D NET_DEVICE_PATH_STACK_MAX) return NULL; =20 return &stack->path[k]; @@ -4424,6 +4424,8 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_= device *sb_dev) * to -1 or to their cpu id, but not to our id. */ if (READ_ONCE(txq->xmit_lock_owner) !=3D cpu) { + bool is_list =3D false; + if (dev_xmit_recursion()) goto recursion_alert; =20 @@ -4434,17 +4436,28 @@ int __dev_queue_xmit(struct sk_buff *skb, struct ne= t_device *sb_dev) HARD_TX_LOCK(dev, txq, cpu); =20 if (!netif_xmit_stopped(txq)) { + is_list =3D !!skb->next; + dev_xmit_recursion_inc(); skb =3D dev_hard_start_xmit(skb, dev, txq, &rc); dev_xmit_recursion_dec(); - if (dev_xmit_complete(rc)) { - HARD_TX_UNLOCK(dev, txq); - goto out; - } + + /* GSO segments a single SKB into + * a list of frames. TCP expects error + * to mean none of the data was sent. + */ + if (is_list) + rc =3D NETDEV_TX_OK; } HARD_TX_UNLOCK(dev, txq); + if (!skb) /* xmit completed */ + goto out; + net_crit_ratelimited("Virtual device %s asks to queue packet!\n", dev->name); + /* NETDEV_TX_BUSY or queue was stopped */ + if (!is_list) + rc =3D -ENETDOWN; } else { /* Recursion is detected! It is possible, * unfortunately @@ -4452,10 +4465,10 @@ int __dev_queue_xmit(struct sk_buff *skb, struct ne= t_device *sb_dev) recursion_alert: net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\= n", dev->name); + rc =3D -ENETDOWN; } } =20 - rc =3D -ENETDOWN; rcu_read_unlock_bh(); =20 dev_core_stats_tx_dropped_inc(dev); diff --git a/net/core/filter.c b/net/core/filter.c index ddb6d3dd34de..e5dc1f699297 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4118,7 +4118,7 @@ static const struct bpf_func_proto bpf_xdp_store_byte= s_proto =3D { .ret_type =3D RET_INTEGER, .arg1_type =3D ARG_PTR_TO_CTX, .arg2_type =3D ARG_ANYTHING, - .arg3_type =3D ARG_PTR_TO_UNINIT_MEM, + .arg3_type =3D ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type =3D ARG_CONST_SIZE, }; =20 diff --git a/net/core/gro.c b/net/core/gro.c index 87889cb75d21..92cb86d4ce50 100644 --- a/net/core/gro.c +++ b/net/core/gro.c @@ -386,7 +386,7 @@ static void gro_pull_from_frag0(struct sk_buff *skb, in= t grow) { struct skb_shared_info *pinfo =3D skb_shinfo(skb); =20 - BUG_ON(skb->end - skb->tail < grow); + DEBUG_NET_WARN_ON_ONCE(skb->end - skb->tail < grow); =20 memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow); =20 diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 20829e0c36cd..b99fdca441f3 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -1144,11 +1144,56 @@ static void rtnl_net_notifyid(struct net *net, int = cmd, int id, u32 portid, rtnl_set_sk_err(net, RTNLGRP_NSID, err); } =20 +#ifdef CONFIG_NET_NS +static void __init netns_ipv4_struct_check(void) +{ + /* TX readonly hotpath cache lines */ + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_early_retrans); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_tso_win_divisor); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_tso_rtt_log); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_autocorking); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_min_snd_mss); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_notsent_lowat); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_limit_output_bytes); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_min_rtt_wlen); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_tcp_wmem); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_tx, + sysctl_ip_fwd_use_pmtu); + CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_tx, 33); + + /* TXRX readonly hotpath cache lines */ + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_txrx, + sysctl_tcp_moderate_rcvbuf); + CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_txrx, 1); + + /* RX readonly hotpath cache line */ + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, + sysctl_ip_early_demux); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, + sysctl_tcp_early_demux); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, + sysctl_tcp_reordering); + CACHELINE_ASSERT_GROUP_MEMBER(struct netns_ipv4, netns_ipv4_read_rx, + sysctl_tcp_rmem); + CACHELINE_ASSERT_GROUP_SIZE(struct netns_ipv4, netns_ipv4_read_rx, 18); +} +#endif + void __init net_ns_init(void) { struct net_generic *ng; =20 #ifdef CONFIG_NET_NS + netns_ipv4_struct_check(); net_cachep =3D kmem_cache_create("net_namespace", sizeof(struct net), SMP_CACHE_BYTES, SLAB_PANIC|SLAB_ACCOUNT, NULL); diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 6225547808a6..5d557ba9c0cb 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -408,22 +408,26 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct = iov_iter *from, } EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter); =20 -/* Receive sk_msg from psock->ingress_msg to @msg. */ -int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr = *msg, - int len, int flags) +int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghd= r *msg, + int len, int flags, int *copied_from_self) { struct iov_iter *iter =3D &msg->msg_iter; int peek =3D flags & MSG_PEEK; struct sk_msg *msg_rx; int i, copied =3D 0; + bool from_self; =20 msg_rx =3D sk_psock_peek_msg(psock); + if (copied_from_self) + *copied_from_self =3D 0; + while (copied !=3D len) { struct scatterlist *sge; =20 if (unlikely(!msg_rx)) break; =20 + from_self =3D msg_rx->sk =3D=3D sk; i =3D msg_rx->sg.start; do { struct page *page; @@ -442,6 +446,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *ps= ock, struct msghdr *msg, } =20 copied +=3D copy; + if (from_self && copied_from_self) + *copied_from_self +=3D copy; + if (likely(!peek)) { sge->offset +=3D copy; sge->length -=3D copy; @@ -450,6 +457,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *ps= ock, struct msghdr *msg, atomic_sub(copy, &sk->sk_rmem_alloc); } msg_rx->sg.size -=3D copy; + sk_psock_msg_len_add(psock, -copy); =20 if (!sge->length) { sk_msg_iter_var_next(i); @@ -486,6 +494,13 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *p= sock, struct msghdr *msg, out: return copied; } + +/* Receive sk_msg from psock->ingress_msg to @msg. */ +int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr = *msg, + int len, int flags) +{ + return __sk_msg_recvmsg(sk, psock, msg, len, flags, NULL); +} EXPORT_SYMBOL_GPL(sk_msg_recvmsg); =20 bool sk_msg_is_readable(struct sock *sk) @@ -615,6 +630,12 @@ static int sk_psock_skb_ingress_self(struct sk_psock *= psock, struct sk_buff *skb if (unlikely(!msg)) return -EAGAIN; skb_set_owner_r(skb, sk); + + /* This is used in tcp_bpf_recvmsg_parser() to determine whether the + * data originates from the socket's own protocol stack. No need to + * refcount sk because msg's lifetime is bound to sk via the ingress_msg. + */ + msg->sk =3D sk; err =3D sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, take_= ref); if (err < 0) kfree(msg); @@ -800,9 +821,11 @@ static void __sk_psock_purge_ingress_msg(struct sk_pso= ck *psock) list_del(&msg->list); if (!msg->skb) atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc); + sk_psock_msg_len_add(psock, -msg->sg.size); sk_msg_free(psock->sk, msg); kfree(msg); } + WARN_ON_ONCE(psock->msg_tot_len); } =20 static void __sk_psock_zap_ingress(struct sk_psock *psock) @@ -908,6 +931,7 @@ int sk_psock_msg_verdict(struct sock *sk, struct sk_pso= ck *psock, sk_msg_compute_data_pointers(msg); msg->sk =3D sk; ret =3D bpf_prog_run_pin_on_cpu(prog, msg); + msg->sk =3D NULL; ret =3D sk_psock_map_verd(ret, msg->sk_redir); psock->apply_bytes =3D msg->apply_bytes; if (ret =3D=3D __SK_REDIRECT) { diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h index f9b9e26c32c1..0b72796dd1ad 100644 --- a/net/ipv4/fib_lookup.h +++ b/net/ipv4/fib_lookup.h @@ -28,8 +28,10 @@ struct fib_alias { /* Don't write on fa_state unless needed, to keep it shared on all cpus */ static inline void fib_alias_accessed(struct fib_alias *fa) { - if (!(fa->fa_state & FA_S_ACCESSED)) - fa->fa_state |=3D FA_S_ACCESSED; + u8 fa_state =3D READ_ONCE(fa->fa_state); + + if (!(fa_state & FA_S_ACCESSED)) + WRITE_ONCE(fa->fa_state, fa_state | FA_S_ACCESSED); } =20 /* Exported by fib_semantics.c */ diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 4d148d089232..c9e1526e749b 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1285,7 +1285,7 @@ int fib_table_insert(struct net *net, struct fib_tabl= e *tb, new_fa->fa_dscp =3D fa->fa_dscp; new_fa->fa_info =3D fi; new_fa->fa_type =3D cfg->fc_type; - state =3D fa->fa_state; + state =3D READ_ONCE(fa->fa_state); new_fa->fa_state =3D state & ~FA_S_ACCESSED; new_fa->fa_slen =3D fa->fa_slen; new_fa->tb_id =3D tb->tb_id; @@ -1751,7 +1751,7 @@ int fib_table_delete(struct net *net, struct fib_tabl= e *tb, =20 fib_remove_alias(t, tp, l, fa_to_delete); =20 - if (fa_to_delete->fa_state & FA_S_ACCESSED) + if (READ_ONCE(fa_to_delete->fa_state) & FA_S_ACCESSED) rt_cache_flush(cfg->fc_nlinfo.nl_net); =20 fib_release_info(fa_to_delete->fa_info); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index b17549c4e5de..784591ed5bb7 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -221,22 +221,15 @@ static inline void icmp_xmit_unlock(struct sock *sk) spin_unlock(&sk->sk_lock.slock); } =20 -int sysctl_icmp_msgs_per_sec __read_mostly =3D 1000; -int sysctl_icmp_msgs_burst __read_mostly =3D 50; - -static struct { - atomic_t credit; - u32 stamp; -} icmp_global; - /** * icmp_global_allow - Are we allowed to send one more ICMP message ? + * @net: network namespace * * Uses a token bucket to limit our ICMP messages to ~sysctl_icmp_msgs_per= _sec. * Returns false if we reached the limit and can not send another packet. * Works in tandem with icmp_global_consume(). */ -bool icmp_global_allow(void) +bool icmp_global_allow(struct net *net) { u32 delta, now, oldstamp; int incr, new, old; @@ -245,36 +238,37 @@ bool icmp_global_allow(void) * Then later icmp_global_consume() could consume more credits, * this is an acceptable race. */ - if (atomic_read(&icmp_global.credit) > 0) + if (atomic_read(&net->ipv4.icmp_global_credit) > 0) return true; =20 now =3D jiffies; - oldstamp =3D READ_ONCE(icmp_global.stamp); + oldstamp =3D READ_ONCE(net->ipv4.icmp_global_stamp); delta =3D min_t(u32, now - oldstamp, HZ); if (delta < HZ / 50) return false; =20 - incr =3D READ_ONCE(sysctl_icmp_msgs_per_sec) * delta / HZ; + incr =3D READ_ONCE(net->ipv4.sysctl_icmp_msgs_per_sec); + incr =3D div_u64((u64)incr * delta, HZ); if (!incr) return false; =20 - if (cmpxchg(&icmp_global.stamp, oldstamp, now) =3D=3D oldstamp) { - old =3D atomic_read(&icmp_global.credit); + if (cmpxchg(&net->ipv4.icmp_global_stamp, oldstamp, now) =3D=3D oldstamp)= { + old =3D atomic_read(&net->ipv4.icmp_global_credit); do { - new =3D min(old + incr, READ_ONCE(sysctl_icmp_msgs_burst)); - } while (!atomic_try_cmpxchg(&icmp_global.credit, &old, new)); + new =3D min(old + incr, READ_ONCE(net->ipv4.sysctl_icmp_msgs_burst)); + } while (!atomic_try_cmpxchg(&net->ipv4.icmp_global_credit, &old, new)); } return true; } EXPORT_SYMBOL(icmp_global_allow); =20 -void icmp_global_consume(void) +void icmp_global_consume(struct net *net) { int credits =3D get_random_u32_below(3); =20 /* Note: this might make icmp_global.credit negative. */ if (credits) - atomic_sub(credits, &icmp_global.credit); + atomic_sub(credits, &net->ipv4.icmp_global_credit); } EXPORT_SYMBOL(icmp_global_consume); =20 @@ -300,7 +294,7 @@ static bool icmpv4_global_allow(struct net *net, int ty= pe, int code, if (icmpv4_mask_allow(net, type, code)) return true; =20 - if (icmp_global_allow()) { + if (icmp_global_allow(net)) { *apply_ratelimit =3D true; return true; } @@ -337,7 +331,7 @@ static bool icmpv4_xrlim_allow(struct net *net, struct = rtable *rt, if (!rc) __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST); else - icmp_global_consume(); + icmp_global_consume(net); return rc; } =20 @@ -546,14 +540,30 @@ static struct rtable *icmp_route_lookup(struct net *n= et, struct flowi4 *fl4, goto relookup_failed; } /* Ugh! */ - orefdst =3D skb_in->_skb_refdst; /* save old refdst */ - skb_dst_set(skb_in, NULL); + orefdst =3D skb_dstref_steal(skb_in); err =3D ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, dscp, rt2->dst.dev); =20 dst_release(&rt2->dst); rt2 =3D skb_rtable(skb_in); - skb_in->_skb_refdst =3D orefdst; /* restore old refdst */ + /* steal dst entry from skb_in, don't drop refcnt */ + skb_dstref_steal(skb_in); + skb_dstref_restore(skb_in, orefdst); + + /* + * At this point, fl4_dec.daddr should NOT be local (we + * checked fl4_dec.saddr above). However, a race condition + * may occur if the address is added to the interface + * concurrently. In that case, ip_route_input() returns a + * LOCAL route with dst.output=3Dip_rt_bug, which must not + * be used for output. + */ + if (!err && rt2 && rt2->rt_type =3D=3D RTN_LOCAL) { + net_warn_ratelimited("detected local route for %pI4 during ICMP sending= , src %pI4\n", + &fl4_dec.daddr, &fl4_dec.saddr); + dst_release(&rt2->dst); + err =3D -EINVAL; + } } =20 if (err) @@ -840,16 +850,22 @@ static void icmp_socket_deliver(struct sk_buff *skb, = u32 info) /* Checkin full IP header plus 8 bytes of protocol to * avoid additional coding at protocol handlers. */ - if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { - __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); - return; - } + if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) + goto out; + + /* IPPROTO_RAW sockets are not supposed to receive anything. */ + if (protocol =3D=3D IPPROTO_RAW) + goto out; =20 raw_icmp_error(skb, protocol, info); =20 ipprot =3D rcu_dereference(inet_protos[protocol]); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, info); + return; + +out: + __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS); } =20 static bool icmp_tag_validation(int proto) @@ -1498,6 +1514,8 @@ static int __net_init icmp_sk_init(struct net *net) net->ipv4.sysctl_icmp_ratelimit =3D 1 * HZ; net->ipv4.sysctl_icmp_ratemask =3D 0x1818; net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr =3D 0; + net->ipv4.sysctl_icmp_msgs_per_sec =3D 1000; + net->ipv4.sysctl_icmp_msgs_burst =3D 50; =20 return 0; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d515881d02a6..2836020bf12d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -224,7 +224,7 @@ static void igmp_start_timer(struct ip_mc_list *im, int= max_delay) =20 static void igmp_gq_start_timer(struct in_device *in_dev) { - int tv =3D get_random_u32_below(in_dev->mr_maxdelay); + int tv =3D get_random_u32_below(READ_ONCE(in_dev->mr_maxdelay)); unsigned long exp =3D jiffies + tv + 2; =20 if (in_dev->mr_gq_running && @@ -1006,7 +1006,7 @@ static bool igmp_heard_query(struct in_device *in_dev= , struct sk_buff *skb, max_delay =3D IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); if (!max_delay) max_delay =3D 1; /* can't mod w/ 0 */ - in_dev->mr_maxdelay =3D max_delay; + WRITE_ONCE(in_dev->mr_maxdelay, max_delay); =20 /* RFC3376, 4.1.6. QRV and 4.1.7. QQIC, when the most recently * received value was zero, use the default or statically diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index b4c59708fc09..d898e1523a45 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -615,14 +615,13 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct ne= t_device *dev) } memcpy(&nexthop, &optptr[srrptr-1], 4); =20 - orefdst =3D skb->_skb_refdst; - skb_dst_set(skb, NULL); + orefdst =3D skb_dstref_steal(skb); err =3D ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph), dev); rt2 =3D skb_rtable(skb); if (err || (rt2->rt_type !=3D RTN_UNICAST && rt2->rt_type !=3D RTN_LOCAL= )) { skb_dst_drop(skb); - skb->_skb_refdst =3D orefdst; + skb_dstref_restore(skb, orefdst); return -EINVAL; } refdst_drop(orefdst); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 47f2e7dd554a..fa13cfa2fa00 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -159,7 +159,7 @@ void ping_unhash(struct sock *sk) pr_debug("ping_unhash(isk=3D%p,isk->num=3D%u)\n", isk, isk->inet_num); spin_lock(&ping_table.lock); if (sk_del_node_init_rcu(sk)) { - isk->inet_num =3D 0; + WRITE_ONCE(isk->inet_num, 0); isk->inet_sport =3D 0; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); } @@ -192,31 +192,35 @@ static struct sock *ping_lookup(struct net *net, stru= ct sk_buff *skb, u16 ident) } =20 sk_for_each_rcu(sk, hslot) { + int bound_dev_if; + if (!net_eq(sock_net(sk), net)) continue; isk =3D inet_sk(sk); =20 pr_debug("iterate\n"); - if (isk->inet_num !=3D ident) + if (READ_ONCE(isk->inet_num) !=3D ident) continue; =20 + bound_dev_if =3D READ_ONCE(sk->sk_bound_dev_if); if (skb->protocol =3D=3D htons(ETH_P_IP) && sk->sk_family =3D=3D AF_INET) { + __be32 rcv_saddr =3D READ_ONCE(isk->inet_rcv_saddr); + pr_debug("found: %p: num=3D%d, daddr=3D%pI4, dif=3D%d\n", sk, - (int) isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); + ident, &rcv_saddr, + bound_dev_if); =20 - if (isk->inet_rcv_saddr && - isk->inet_rcv_saddr !=3D ip_hdr(skb)->daddr) + if (rcv_saddr && rcv_saddr !=3D ip_hdr(skb)->daddr) continue; #if IS_ENABLED(CONFIG_IPV6) } else if (skb->protocol =3D=3D htons(ETH_P_IPV6) && sk->sk_family =3D=3D AF_INET6) { =20 pr_debug("found: %p: num=3D%d, daddr=3D%pI6c, dif=3D%d\n", sk, - (int) isk->inet_num, + ident, &sk->sk_v6_rcv_saddr, - sk->sk_bound_dev_if); + bound_dev_if); =20 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, @@ -227,8 +231,8 @@ static struct sock *ping_lookup(struct net *net, struct= sk_buff *skb, u16 ident) continue; } =20 - if (sk->sk_bound_dev_if && sk->sk_bound_dev_if !=3D dif && - sk->sk_bound_dev_if !=3D sdif) + if (bound_dev_if && bound_dev_if !=3D dif && + bound_dev_if !=3D sdif) continue; =20 goto exit; @@ -403,7 +407,9 @@ static void ping_set_saddr(struct sock *sk, struct sock= addr *saddr) if (saddr->sa_family =3D=3D AF_INET) { struct inet_sock *isk =3D inet_sk(sk); struct sockaddr_in *addr =3D (struct sockaddr_in *) saddr; - isk->inet_rcv_saddr =3D isk->inet_saddr =3D addr->sin_addr.s_addr; + + isk->inet_saddr =3D addr->sin_addr.s_addr; + WRITE_ONCE(isk->inet_rcv_saddr, addr->sin_addr.s_addr); #if IS_ENABLED(CONFIG_IPV6) } else if (saddr->sa_family =3D=3D AF_INET6) { struct sockaddr_in6 *addr =3D (struct sockaddr_in6 *) saddr; @@ -860,7 +866,8 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, s= ize_t len, int flags, struct sk_buff *skb; int copied, err; =20 - pr_debug("ping_recvmsg(sk=3D%p,sk->num=3D%u)\n", isk, isk->inet_num); + pr_debug("ping_recvmsg(sk=3D%p,sk->num=3D%u)\n", isk, + READ_ONCE(isk->inet_num)); =20 err =3D -EOPNOTSUPP; if (flags & MSG_OOB) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 6ac890b4073f..96f1b8d39fac 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -547,22 +547,6 @@ static struct ctl_table ipv4_table[] =3D { .mode =3D 0444, .proc_handler =3D proc_tcp_available_ulp, }, - { - .procname =3D "icmp_msgs_per_sec", - .data =3D &sysctl_icmp_msgs_per_sec, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D SYSCTL_ZERO, - }, - { - .procname =3D "icmp_msgs_burst", - .data =3D &sysctl_icmp_msgs_burst, - .maxlen =3D sizeof(int), - .mode =3D 0644, - .proc_handler =3D proc_dointvec_minmax, - .extra1 =3D SYSCTL_ZERO, - }, { .procname =3D "udp_mem", .data =3D &sysctl_udp_mem, @@ -649,6 +633,22 @@ static struct ctl_table ipv4_net_table[] =3D { .mode =3D 0644, .proc_handler =3D proc_dointvec }, + { + .procname =3D "icmp_msgs_per_sec", + .data =3D &init_net.ipv4.sysctl_icmp_msgs_per_sec, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D SYSCTL_ZERO, + }, + { + .procname =3D "icmp_msgs_burst", + .data =3D &init_net.ipv4.sysctl_icmp_msgs_burst, + .maxlen =3D sizeof(int), + .mode =3D 0644, + .proc_handler =3D proc_dointvec_minmax, + .extra1 =3D SYSCTL_ZERO, + }, { .procname =3D "ping_group_range", .data =3D &init_net.ipv4.ping_group_range.range, @@ -1366,6 +1366,15 @@ static struct ctl_table ipv4_net_table[] =3D { .proc_handler =3D proc_dou8vec_minmax, .extra1 =3D SYSCTL_ZERO, }, + { + .procname =3D "tcp_backlog_ack_defer", + .data =3D &init_net.ipv4.sysctl_tcp_backlog_ack_defer, + .maxlen =3D sizeof(u8), + .mode =3D 0644, + .proc_handler =3D proc_dou8vec_minmax, + .extra1 =3D SYSCTL_ZERO, + .extra2 =3D SYSCTL_ONE, + }, { .procname =3D "tcp_reflect_tos", .data =3D &init_net.ipv4.sysctl_tcp_reflect_tos, @@ -1489,6 +1498,14 @@ static struct ctl_table ipv4_net_table[] =3D { .extra1 =3D SYSCTL_ZERO, .extra2 =3D SYSCTL_ONE, }, + { + .procname =3D "tcp_pingpong_thresh", + .data =3D &init_net.ipv4.sysctl_tcp_pingpong_thresh, + .maxlen =3D sizeof(u8), + .mode =3D 0644, + .proc_handler =3D proc_dou8vec_minmax, + .extra1 =3D SYSCTL_ONE, + }, { } }; =20 diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5dde0aed3144..2bae34d63c3d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -468,6 +468,9 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsfla= gs) { struct sk_buff *skb =3D tcp_write_queue_tail(sk); =20 + if (unlikely(!skb)) + skb =3D skb_rb_last(&sk->tcp_rtx_queue); + if (tsflags && skb) { struct skb_shared_info *shinfo =3D skb_shinfo(skb); struct tcp_skb_cb *tcb =3D TCP_SKB_CB(skb); diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 7518d2af6308..06a185bb1e35 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -10,6 +10,7 @@ =20 #include #include +#include =20 void tcp_eat_skb(struct sock *sk, struct sk_buff *skb) { @@ -226,6 +227,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, int peek =3D flags & MSG_PEEK; struct sk_psock *psock; struct tcp_sock *tcp; + int copied_from_self =3D 0; int copied =3D 0; u32 seq; =20 @@ -262,7 +264,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, } =20 msg_bytes_ready: - copied =3D sk_msg_recvmsg(sk, psock, msg, len, flags); + copied =3D __sk_msg_recvmsg(sk, psock, msg, len, flags, &copied_from_self= ); /* The typical case for EFAULT is the socket was gracefully * shutdown with a FIN pkt. So check here the other case is * some error on copy_page_to_iter which would be unexpected. @@ -277,7 +279,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, goto out; } } - seq +=3D copied; + seq +=3D copied_from_self; if (!copied) { long timeo; int data; @@ -331,6 +333,24 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, return copied; } =20 +static int tcp_bpf_ioctl(struct sock *sk, int cmd, int *karg) +{ + bool slow; + + if (cmd !=3D SIOCINQ) + return tcp_ioctl(sk, cmd, karg); + + /* works similar as tcp_ioctl */ + if (sk->sk_state =3D=3D TCP_LISTEN) + return -EINVAL; + + slow =3D lock_sock_fast(sk); + *karg =3D sk_psock_msg_inq(sk); + unlock_sock_fast(sk, slow); + + return 0; +} + static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, int *addr_len) { @@ -609,6 +629,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TC= P_BPF_NUM_CFGS], prot[TCP_BPF_BASE].close =3D sock_map_close; prot[TCP_BPF_BASE].recvmsg =3D tcp_bpf_recvmsg; prot[TCP_BPF_BASE].sock_is_readable =3D sk_msg_is_readable; + prot[TCP_BPF_BASE].ioctl =3D tcp_bpf_ioctl; =20 prot[TCP_BPF_TX] =3D prot[TCP_BPF_BASE]; prot[TCP_BPF_TX].sendmsg =3D tcp_bpf_sendmsg; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8834cd41b384..f67967c75771 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5678,6 +5678,14 @@ static void __tcp_ack_snd_check(struct sock *sk, int= ofo_possible) tcp_in_quickack_mode(sk) || /* Protocol state mandates a one-time immediate ACK */ inet_csk(sk)->icsk_ack.pending & ICSK_ACK_NOW) { + /* If we are running from __release_sock() in user context, + * Defer the ack until tcp_release_cb(). + */ + if (sock_owned_by_user_nocheck(sk) && + READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_backlog_ack_defer)) { + set_bit(TCP_ACK_DEFERRED, &sk->sk_tsq_flags); + return; + } send_now: tcp_send_ack(sk); return; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2f49a504c9d3..ab4be34e58bb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -3279,6 +3279,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_comp_sack_delay_ns =3D NSEC_PER_MSEC; net->ipv4.sysctl_tcp_comp_sack_slack_ns =3D 100 * NSEC_PER_USEC; net->ipv4.sysctl_tcp_comp_sack_nr =3D 44; + net->ipv4.sysctl_tcp_backlog_ack_defer =3D 1; net->ipv4.sysctl_tcp_fastopen =3D TFO_CLIENT_ENABLE; net->ipv4.sysctl_tcp_fastopen_blackhole_timeout =3D 0; atomic_set(&net->ipv4.tfo_active_disable_times, 0); @@ -3302,6 +3303,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_syn_linear_timeouts =3D 4; net->ipv4.sysctl_tcp_shrink_window =3D 0; =20 + net->ipv4.sysctl_tcp_pingpong_thresh =3D 1; + return 0; } =20 diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 88551db62ca2..db8f2830c67b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -170,10 +170,10 @@ static void tcp_event_data_sent(struct tcp_sock *tp, tp->lsndtime =3D now; =20 /* If it is a reply for ato after last received - * packet, enter pingpong mode. + * packet, increase pingpong count. */ if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato) - inet_csk_enter_pingpong_mode(sk); + inet_csk_inc_pingpong_cnt(sk); } =20 /* Account for an ACK we sent. */ @@ -1083,7 +1083,8 @@ static void tcp_tasklet_func(struct tasklet_struct *t) #define TCP_DEFERRED_ALL (TCPF_TSQ_DEFERRED | \ TCPF_WRITE_TIMER_DEFERRED | \ TCPF_DELACK_TIMER_DEFERRED | \ - TCPF_MTU_REDUCED_DEFERRED) + TCPF_MTU_REDUCED_DEFERRED | \ + TCPF_ACK_DEFERRED) /** * tcp_release_cb - tcp release_sock() callback * @sk: socket @@ -1130,6 +1131,8 @@ void tcp_release_cb(struct sock *sk) inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); __sock_put(sk); } + if ((flags & TCPF_ACK_DEFERRED) && inet_csk_ack_scheduled(sk)) + tcp_send_ack(sk); } EXPORT_SYMBOL(tcp_release_cb); =20 diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c index 0735d820e413..91233e37cd97 100644 --- a/net/ipv4/udp_bpf.c +++ b/net/ipv4/udp_bpf.c @@ -5,6 +5,7 @@ #include #include #include +#include =20 #include "udp_impl.h" =20 @@ -111,12 +112,26 @@ enum { static DEFINE_SPINLOCK(udpv6_prot_lock); static struct proto udp_bpf_prots[UDP_BPF_NUM_PROTS]; =20 +static int udp_bpf_ioctl(struct sock *sk, int cmd, int *karg) +{ + if (cmd !=3D SIOCINQ) + return udp_ioctl(sk, cmd, karg); + + /* Since we don't hold a lock, sk_receive_queue may contain data. + * BPF might only be processing this data at the moment. We only + * care about the data in the ingress_msg here. + */ + *karg =3D sk_msg_first_len(sk); + return 0; +} + static void udp_bpf_rebuild_protos(struct proto *prot, const struct proto = *base) { - *prot =3D *base; - prot->close =3D sock_map_close; - prot->recvmsg =3D udp_bpf_recvmsg; - prot->sock_is_readable =3D sk_msg_is_readable; + *prot =3D *base; + prot->close =3D sock_map_close; + prot->recvmsg =3D udp_bpf_recvmsg; + prot->sock_is_readable =3D sk_msg_is_readable; + prot->ioctl =3D udp_bpf_ioctl; } =20 static void udp_bpf_check_v6_needs_rebuild(struct proto *ops) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 02e9ffb63af1..676284b6efe8 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -313,7 +313,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) } =20 extlen =3D (skb_transport_header(skb)[1] + 1) << 3; - if (extlen > net->ipv6.sysctl.max_dst_opts_len) + if (extlen > READ_ONCE(net->ipv6.sysctl.max_dst_opts_len)) goto fail_and_free; =20 opt->lastopt =3D opt->dst1 =3D skb_network_header_len(skb); @@ -321,7 +321,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) dstbuf =3D opt->dst1; #endif =20 - if (ip6_parse_tlv(false, skb, net->ipv6.sysctl.max_dst_opts_cnt)) { + if (ip6_parse_tlv(false, skb, + READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) { skb->transport_header +=3D extlen; opt =3D IP6CB(skb); #if IS_ENABLED(CONFIG_IPV6_MIP6) @@ -937,6 +938,11 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int opt= off) if (hdr->opt_len < 2 + sizeof(*trace) + trace->remlen * 4) goto drop; =20 + /* Inconsistent Pre-allocated Trace header */ + if (trace->nodelen !=3D + ioam6_trace_compute_nodelen(be32_to_cpu(trace->type_be32))) + goto drop; + /* Ignore if the IOAM namespace is unknown */ ns =3D ioam6_namespace(ipv6_skb_net(skb), trace->namespace_id); if (!ns) @@ -1053,11 +1059,12 @@ int ipv6_parse_hopopts(struct sk_buff *skb) } =20 extlen =3D (skb_transport_header(skb)[1] + 1) << 3; - if (extlen > net->ipv6.sysctl.max_hbh_opts_len) + if (extlen > READ_ONCE(net->ipv6.sysctl.max_hbh_opts_len)) goto fail_and_free; =20 opt->flags |=3D IP6SKB_HOPBYHOP; - if (ip6_parse_tlv(true, skb, net->ipv6.sysctl.max_hbh_opts_cnt)) { + if (ip6_parse_tlv(true, skb, + READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) { skb->transport_header +=3D extlen; opt =3D IP6CB(skb); opt->nhoff =3D sizeof(struct ipv6hdr); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index c7e815b7ca08..1d1c56e0e246 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -181,7 +181,7 @@ static bool icmpv6_global_allow(struct net *net, int ty= pe, if (icmpv6_mask_allow(net, type)) return true; =20 - if (icmp_global_allow()) { + if (icmp_global_allow(net)) { *apply_ratelimit =3D true; return true; } @@ -231,7 +231,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, __ICMP6_INC_STATS(net, ip6_dst_idev(dst), ICMP6_MIB_RATELIMITHOST); else - icmp_global_consume(); + icmp_global_consume(net); dst_release(dst); return res; } @@ -869,6 +869,12 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb= , u8 type, if (reason !=3D SKB_NOT_DROPPED_YET) goto out; =20 + if (nexthdr =3D=3D IPPROTO_RAW) { + /* Add a more specific reason later ? */ + reason =3D SKB_DROP_REASON_NOT_SPECIFIED; + goto out; + } + /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. Without this we will not able f.e. to make source routed pmtu discovery. diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c index 571f0e4d9cf3..a35b6fdbc93e 100644 --- a/net/ipv6/ioam6.c +++ b/net/ipv6/ioam6.c @@ -630,6 +630,20 @@ struct ioam6_namespace *ioam6_namespace(struct net *ne= t, __be16 id) return rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params); } =20 +#define IOAM6_MASK_SHORT_FIELDS 0xff1ffc00 +#define IOAM6_MASK_WIDE_FIELDS 0x00e00000 + +u8 ioam6_trace_compute_nodelen(u32 trace_type) +{ + u8 nodelen =3D hweight32(trace_type & IOAM6_MASK_SHORT_FIELDS) + * (sizeof(__be32) / 4); + + nodelen +=3D hweight32(trace_type & IOAM6_MASK_WIDE_FIELDS) + * (sizeof(__be64) / 4); + + return nodelen; +} + static void __ioam6_fill_trace_data(struct sk_buff *skb, struct ioam6_namespace *ns, struct ioam6_trace_hdr *trace, diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c index a5cfc5b0b206..3a6065faaf9b 100644 --- a/net/ipv6/ioam6_iptunnel.c +++ b/net/ipv6/ioam6_iptunnel.c @@ -22,9 +22,6 @@ #include #include =20 -#define IOAM6_MASK_SHORT_FIELDS 0xff100000 -#define IOAM6_MASK_WIDE_FIELDS 0xe00000 - struct ioam6_lwt_encap { struct ipv6_hopopt_hdr eh; u8 pad[2]; /* 2-octet padding for 4n-alignment */ @@ -88,13 +85,8 @@ static bool ioam6_validate_trace_hdr(struct ioam6_trace_= hdr *trace) trace->type.bit21) return false; =20 - trace->nodelen =3D 0; fields =3D be32_to_cpu(trace->type_be32); - - trace->nodelen +=3D hweight32(fields & IOAM6_MASK_SHORT_FIELDS) - * (sizeof(__be32) / 4); - trace->nodelen +=3D hweight32(fields & IOAM6_MASK_WIDE_FIELDS) - * (sizeof(__be64) / 4); + trace->nodelen =3D ioam6_trace_compute_nodelen(fields); =20 return true; } diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index fe57884ca723..6fe867579118 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1137,7 +1137,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, str= uct fib6_info *rt, fib6_add_gc_list(iter); } if (!(rt->fib6_flags & (RTF_ADDRCONF | RTF_PREFIX_RT)) && - !iter->fib6_nh->fib_nh_gw_family) { + (iter->nh || !iter->fib6_nh->fib_nh_gw_family)) { iter->fib6_flags &=3D ~RTF_ADDRCONF; iter->fib6_flags &=3D ~RTF_PREFIX_RT; } diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index f24faa78ee82..e5d76e782b96 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -57,6 +57,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, struct dst_entry *dst; struct net_device *dev; struct inet6_dev *idev; + int err; =20 dst =3D xfrm6_dst_lookup(params); if (IS_ERR(dst)) @@ -68,9 +69,11 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, return -EHOSTUNREACH; } dev =3D idev->dev; - ipv6_dev_get_saddr(dev_net(dev), dev, ¶ms->daddr->in6, 0, - &saddr->in6); + err =3D ipv6_dev_get_saddr(dev_net(dev), dev, ¶ms->daddr->in6, 0, + &saddr->in6); dst_release(dst); + if (err) + return -EHOSTUNREACH; return 0; } =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f3856856aa44..85ef9042873b 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2048,8 +2048,8 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock = *msk, int copied) =20 msk->rcvq_space.copied +=3D copied; =20 - mstamp =3D div_u64(tcp_clock_ns(), NSEC_PER_USEC); - time =3D tcp_stamp_us_delta(mstamp, msk->rcvq_space.time); + mstamp =3D mptcp_stamp(); + time =3D tcp_stamp_us_delta(mstamp, READ_ONCE(msk->rcvq_space.time)); =20 rtt_us =3D msk->rcvq_space.rtt_us; if (rtt_us && time < (rtt_us >> 3)) @@ -3451,6 +3451,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *s= k, __mptcp_propagate_sndbuf(nsk, ssk); =20 mptcp_rcv_space_init(msk, ssk); + msk->rcvq_space.time =3D mptcp_stamp(); =20 if (mp_opt->suboptions & OPTION_MPTCP_MPC_ACK) __mptcp_subflow_fully_established(msk, subflow, mp_opt); @@ -3468,8 +3469,6 @@ void mptcp_rcv_space_init(struct mptcp_sock *msk, con= st struct sock *ssk) msk->rcvq_space.copied =3D 0; msk->rcvq_space.rtt_us =3D 0; =20 - msk->rcvq_space.time =3D tp->tcp_mstamp; - /* initial rcv_space offering made to peer */ msk->rcvq_space.space =3D min_t(u32, tp->rcv_wnd, TCP_INIT_CWND * tp->advmss); @@ -3688,6 +3687,7 @@ void mptcp_finish_connect(struct sock *ssk) * accessing the field below */ WRITE_ONCE(msk->local_key, subflow->local_key); + WRITE_ONCE(msk->rcvq_space.time, mptcp_stamp()); =20 mptcp_pm_new_connection(msk, ssk, 0); } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 0fbc1f13bd2d..58805fbf1f96 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -786,6 +786,11 @@ static inline bool mptcp_is_fully_established(struct s= ock *sk) READ_ONCE(mptcp_sk(sk)->fully_established); } =20 +static inline u64 mptcp_stamp(void) +{ + return div_u64(tcp_clock_ns(), NSEC_PER_USEC); +} + void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk); void mptcp_data_ready(struct sock *sk, struct sock *ssk); bool mptcp_finish_join(struct sock *sk); diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index a2c5a7ba0c6f..ae9ad439449f 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -34,8 +34,9 @@ =20 #define CONNCOUNT_SLOTS 256U =20 -#define CONNCOUNT_GC_MAX_NODES 8 -#define MAX_KEYLEN 5 +#define CONNCOUNT_GC_MAX_NODES 8 +#define CONNCOUNT_GC_MAX_COLLECT 64 +#define MAX_KEYLEN 5 =20 /* we will save the tuples of all connections we care about */ struct nf_conncount_tuple { @@ -178,16 +179,28 @@ static int __nf_conncount_add(struct net *net, return -ENOENT; =20 if (ct && nf_ct_is_confirmed(ct)) { - err =3D -EEXIST; - goto out_put; + /* local connections are confirmed in postrouting so confirmation + * might have happened before hitting connlimit + */ + if (skb->skb_iif !=3D LOOPBACK_IFINDEX) { + err =3D -EEXIST; + goto out_put; + } + + /* this is likely a local connection, skip optimization to avoid + * adding duplicates from a 'packet train' + */ + goto check_connections; } =20 - if ((u32)jiffies =3D=3D list->last_gc) + if ((u32)jiffies =3D=3D list->last_gc && + (list->count - list->last_gc_count) < CONNCOUNT_GC_MAX_COLLECT) goto add_new_node; =20 +check_connections: /* check the saved connections */ list_for_each_entry_safe(conn, conn_n, &list->head, node) { - if (collect > CONNCOUNT_GC_MAX_NODES) + if (collect > CONNCOUNT_GC_MAX_COLLECT) break; =20 found =3D find_or_evict(net, list, conn); @@ -230,6 +243,7 @@ static int __nf_conncount_add(struct net *net, nf_ct_put(found_ct); } list->last_gc =3D (u32)jiffies; + list->last_gc_count =3D list->count; =20 add_new_node: if (WARN_ON_ONCE(list->count > INT_MAX)) { @@ -277,13 +291,14 @@ void nf_conncount_list_init(struct nf_conncount_list = *list) spin_lock_init(&list->list_lock); INIT_LIST_HEAD(&list->head); list->count =3D 0; + list->last_gc_count =3D 0; list->last_gc =3D (u32)jiffies; } EXPORT_SYMBOL_GPL(nf_conncount_list_init); =20 /* Return true if the list is empty. Must be called with BH disabled. */ -bool nf_conncount_gc_list(struct net *net, - struct nf_conncount_list *list) +static bool __nf_conncount_gc_list(struct net *net, + struct nf_conncount_list *list) { const struct nf_conntrack_tuple_hash *found; struct nf_conncount_tuple *conn, *conn_n; @@ -295,10 +310,6 @@ bool nf_conncount_gc_list(struct net *net, if ((u32)jiffies =3D=3D READ_ONCE(list->last_gc)) return false; =20 - /* don't bother if other cpu is already doing GC */ - if (!spin_trylock(&list->list_lock)) - return false; - list_for_each_entry_safe(conn, conn_n, &list->head, node) { found =3D find_or_evict(net, list, conn); if (IS_ERR(found)) { @@ -320,14 +331,29 @@ bool nf_conncount_gc_list(struct net *net, } =20 nf_ct_put(found_ct); - if (collected > CONNCOUNT_GC_MAX_NODES) + if (collected > CONNCOUNT_GC_MAX_COLLECT) break; } =20 if (!list->count) ret =3D true; list->last_gc =3D (u32)jiffies; - spin_unlock(&list->list_lock); + list->last_gc_count =3D list->count; + + return ret; +} + +bool nf_conncount_gc_list(struct net *net, + struct nf_conncount_list *list) +{ + bool ret; + + /* don't bother if other cpu is already doing GC */ + if (!spin_trylock_bh(&list->list_lock)) + return false; + + ret =3D __nf_conncount_gc_list(net, list); + spin_unlock_bh(&list->list_lock); =20 return ret; } diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conn= track_h323_asn1.c index 540d97715bd2..62aa22a07876 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c @@ -796,7 +796,7 @@ static int decode_choice(struct bitstr *bs, const struc= t field_t *f, =20 if (ext || (son->attr & OPEN)) { BYTE_ALIGN(bs); - if (nf_h323_error_boundary(bs, len, 0)) + if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len =3D get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conn= track_h323_main.c index 5a9bce24f3c3..ed983421e2eb 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -1186,13 +1186,13 @@ static struct nf_conntrack_expect *find_expect(stru= ct nf_conn *ct, { struct net *net =3D nf_ct_net(ct); struct nf_conntrack_expect *exp; - struct nf_conntrack_tuple tuple; + struct nf_conntrack_tuple tuple =3D { + .src.l3num =3D nf_ct_l3num(ct), + .dst.protonum =3D IPPROTO_TCP, + .dst.u.tcp.port =3D port, + }; =20 - memset(&tuple.src.u3, 0, sizeof(tuple.src.u3)); - tuple.src.u.tcp.port =3D 0; memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3)); - tuple.dst.u.tcp.port =3D port; - tuple.dst.protonum =3D IPPROTO_TCP; =20 exp =3D __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); if (exp && exp->master =3D=3D ct) diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_= conntrack_proto_generic.c index e831637bc8ca..cb260eb3d012 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -67,6 +67,7 @@ void nf_conntrack_generic_init_net(struct net *net) const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =3D { .l4proto =3D 255, + .allow_clash =3D true, #ifdef CONFIG_NF_CONNTRACK_TIMEOUT .ctnl_timeout =3D { .nlattr_to_obj =3D generic_timeout_nlattr_to_obj, diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index a0a5d19fa850..41614e897ec8 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2581,6 +2581,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8= family, u8 genmask, =20 err_register_hook: nft_chain_del(chain); + synchronize_rcu(); err_chain_add: nft_trans_destroy(trans); err_trans: @@ -10824,6 +10825,13 @@ static int nf_tables_abort(struct net *net, struct= sk_buff *skb, ret =3D __nf_tables_abort(net, action); nft_gc_seq_end(nft_net, gc_seq); =20 + if (action =3D=3D NFNL_ABORT_NONE) { + struct nft_table *table; + + list_for_each_entry(table, &nft_net->tables, list) + table->validate_state =3D NFT_VALIDATE_SKIP; + } + WARN_ON_ONCE(!list_empty(&nft_net->commit_list)); =20 /* module autoload needs to happen after GC sequence update because it diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 7ca4f0d21fe2..1e8142e64e80 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -134,7 +134,8 @@ static void nft_target_eval_bridge(const struct nft_exp= r *expr, } =20 static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] =3D { - [NFTA_TARGET_NAME] =3D { .type =3D NLA_NUL_STRING }, + [NFTA_TARGET_NAME] =3D { .type =3D NLA_NUL_STRING, + .len =3D XT_EXTENSION_MAXNAMELEN, }, [NFTA_TARGET_REV] =3D NLA_POLICY_MAX(NLA_BE32, 255), [NFTA_TARGET_INFO] =3D { .type =3D NLA_BINARY }, }; @@ -434,7 +435,8 @@ static void nft_match_eval(const struct nft_expr *expr, } =20 static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] =3D { - [NFTA_MATCH_NAME] =3D { .type =3D NLA_NUL_STRING }, + [NFTA_MATCH_NAME] =3D { .type =3D NLA_NUL_STRING, + .len =3D XT_EXTENSION_MAXNAMELEN }, [NFTA_MATCH_REV] =3D NLA_POLICY_MAX(NLA_BE32, 255), [NFTA_MATCH_INFO] =3D { .type =3D NLA_BINARY }, }; @@ -693,7 +695,12 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb, =20 name =3D nla_data(tb[NFTA_COMPAT_NAME]); rev =3D ntohl(nla_get_be32(tb[NFTA_COMPAT_REV])); - target =3D ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE])); + /* x_tables api checks for 'target =3D=3D 1' to mean target, + * everything else means 'match'. + * In x_tables world, the number is set by kernel, not + * userspace. + */ + target =3D nla_get_be32(tb[NFTA_COMPAT_TYPE]) =3D=3D htonl(1); =20 switch(family) { case AF_INET: diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c index 83a7d5769396..5dd50b3ab5a4 100644 --- a/net/netfilter/nft_connlimit.c +++ b/net/netfilter/nft_connlimit.c @@ -232,13 +232,8 @@ static void nft_connlimit_destroy_clone(const struct n= ft_ctx *ctx, static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr) { struct nft_connlimit *priv =3D nft_expr_priv(expr); - bool ret; =20 - local_bh_disable(); - ret =3D nf_conncount_gc_list(net, priv->list); - local_bh_enable(); - - return ret; + return nf_conncount_gc_list(net, priv->list); } =20 static struct nft_expr_type nft_connlimit_type; diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c index cc7325329496..0d70325280cc 100644 --- a/net/netfilter/nft_counter.c +++ b/net/netfilter/nft_counter.c @@ -117,8 +117,8 @@ static void nft_counter_reset(struct nft_counter_percpu= _priv *priv, nft_sync =3D this_cpu_ptr(&nft_counter_sync); =20 u64_stats_update_begin(nft_sync); - u64_stats_add(&this_cpu->packets, -total->packets); - u64_stats_add(&this_cpu->bytes, -total->bytes); + u64_stats_sub(&this_cpu->packets, total->packets); + u64_stats_sub(&this_cpu->bytes, total->bytes); u64_stats_update_end(nft_sync); =20 local_bh_enable(); diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 2f1012bde1f3..5a74ee4b7dfb 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -525,15 +525,20 @@ bool nft_hash_lookup(const struct net *net, const str= uct nft_set *set, static void *nft_hash_get(const struct net *net, const struct nft_set *set, const struct nft_set_elem *elem, unsigned int flags) { + const u32 *key =3D (const u32 *)&elem->key.val; struct nft_hash *priv =3D nft_set_priv(set); u8 genmask =3D nft_genmask_cur(net); struct nft_hash_elem *he; u32 hash; =20 - hash =3D jhash(elem->key.val.data, set->klen, priv->seed); + if (set->klen =3D=3D 4) + hash =3D jhash_1word(*key, priv->seed); + else + hash =3D jhash(key, set->klen, priv->seed); + hash =3D reciprocal_scale(hash, priv->buckets); hlist_for_each_entry_rcu(he, &priv->table[hash], node) { - if (!memcmp(nft_set_ext_key(&he->ext), elem->key.val.data, set->klen) && + if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) && nft_set_elem_active(&he->ext, genmask)) return he; } diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 04672238e17d..9c9b07f2def1 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_= set *set, return false; } =20 +/* Only for anonymous sets which do not allow updates, all element are act= ive. */ +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_el= em *rbe) +{ + struct rb_node *node; + + node =3D rb_prev(&rbe->node); + if (!node) + return NULL; + + return rb_entry(node, struct nft_rbtree_elem, node); +} + static int __nft_rbtree_insert(const struct net *net, const struct nft_set= *set, struct nft_rbtree_elem *new, struct nft_set_ext **ext) { - struct nft_rbtree_elem *rbe, *rbe_le =3D NULL, *rbe_ge =3D NULL; + struct nft_rbtree_elem *rbe, *rbe_le =3D NULL, *rbe_ge =3D NULL, *rbe_pre= v; struct rb_node *node, *next, *parent, **p, *first =3D NULL; struct nft_rbtree *priv =3D nft_set_priv(set); u8 cur_genmask =3D nft_genmask_cur(net); @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net,= const struct nft_set *set, /* - new start element with existing closest, less or equal key value * being a start element: partial overlap, reported as -ENOTEMPTY. * Anonymous sets allow for two consecutive start element since they - * are constant, skip them to avoid bogus overlap reports. + * are constant, but validate that this new start element does not + * sit in between an existing start and end elements: partial overlap, + * reported as -ENOTEMPTY. */ - if (!nft_set_is_anonymous(set) && rbe_le && - nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) - return -ENOTEMPTY; + if (rbe_le && + nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) { + if (!nft_set_is_anonymous(set)) + return -ENOTEMPTY; + + rbe_prev =3D nft_rbtree_prev_active(rbe_le); + if (rbe_prev && nft_rbtree_interval_end(rbe_prev)) + return -ENOTEMPTY; + } =20 /* - new end element with existing closest, less or equal key value * being a end element: partial overlap, reported as -ENOTEMPTY. diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 37704ab01799..0d32d4841cb3 100644 --- a/net/netfilter/xt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c @@ -61,7 +61,7 @@ tcpmss_mt(const struct sk_buff *skb, struct xt_action_par= am *par) return (mssval >=3D info->mss_min && mssval <=3D info->mss_max) ^ info->invert; } - if (op[i] < 2) + if (op[i] < 2 || i =3D=3D optlen - 1) i++; else i +=3D op[i+1] ? : 1; diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index e90f70385813..a106f4352356 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c @@ -762,6 +762,14 @@ static void llc_shdlc_deinit(struct nfc_llc *llc) { struct llc_shdlc *shdlc =3D nfc_llc_get_data(llc); =20 + timer_shutdown_sync(&shdlc->connect_timer); + timer_shutdown_sync(&shdlc->t1_timer); + timer_shutdown_sync(&shdlc->t2_timer); + shdlc->t1_active =3D false; + shdlc->t2_active =3D false; + + cancel_work_sync(&shdlc->sm_work); + skb_queue_purge(&shdlc->rcv_q); skb_queue_purge(&shdlc->send_q); skb_queue_purge(&shdlc->ack_pending_q); diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index cb2a672105dc..df0f1200082c 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -58,7 +58,7 @@ static int nci_core_conn_credits_ntf_packet(struct nci_de= v *ndev, struct nci_conn_info *conn_info; int i; =20 - if (skb->len < sizeof(struct nci_core_conn_credit_ntf)) + if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries)) return -EINVAL; =20 ntf =3D (struct nci_core_conn_credit_ntf *)skb->data; @@ -68,6 +68,10 @@ static int nci_core_conn_credits_ntf_packet(struct nci_d= ev *ndev, if (ntf->num_entries > NCI_MAX_NUM_CONN) ntf->num_entries =3D NCI_MAX_NUM_CONN; =20 + if (skb->len < offsetofend(struct nci_core_conn_credit_ntf, num_entries) + + ntf->num_entries * sizeof(struct conn_credit_entry)) + return -EINVAL; + /* update the credits */ for (i =3D 0; i < ntf->num_entries; i++) { ntf->conn_entries[i].conn_id =3D @@ -138,23 +142,48 @@ static int nci_core_conn_intf_error_ntf_packet(struct= nci_dev *ndev, static const __u8 * nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfca_poll *nfca_poll, - const __u8 *data) + const __u8 *data, ssize_t data_len) { + /* Check if we have enough data for sens_res (2 bytes) */ + if (data_len < 2) + return ERR_PTR(-EINVAL); + nfca_poll->sens_res =3D __le16_to_cpu(*((__le16 *)data)); data +=3D 2; + data_len -=3D 2; + + /* Check if we have enough data for nfcid1_len (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); =20 nfca_poll->nfcid1_len =3D min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); + data_len--; =20 pr_debug("sens_res 0x%x, nfcid1_len %d\n", nfca_poll->sens_res, nfca_poll->nfcid1_len); =20 + /* Check if we have enough data for nfcid1 */ + if (data_len < nfca_poll->nfcid1_len) + return ERR_PTR(-EINVAL); + memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); data +=3D nfca_poll->nfcid1_len; + data_len -=3D nfca_poll->nfcid1_len; + + /* Check if we have enough data for sel_res_len (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); =20 nfca_poll->sel_res_len =3D *data++; + data_len--; + + if (nfca_poll->sel_res_len !=3D 0) { + /* Check if we have enough data for sel_res (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); =20 - if (nfca_poll->sel_res_len !=3D 0) nfca_poll->sel_res =3D *data++; + } =20 pr_debug("sel_res_len %d, sel_res 0x%x\n", nfca_poll->sel_res_len, @@ -166,12 +195,21 @@ nci_extract_rf_params_nfca_passive_poll(struct nci_de= v *ndev, static const __u8 * nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfcb_poll *nfcb_poll, - const __u8 *data) + const __u8 *data, ssize_t data_len) { + /* Check if we have enough data for sensb_res_len (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + nfcb_poll->sensb_res_len =3D min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE); + data_len--; =20 pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len); =20 + /* Check if we have enough data for sensb_res */ + if (data_len < nfcb_poll->sensb_res_len) + return ERR_PTR(-EINVAL); + memcpy(nfcb_poll->sensb_res, data, nfcb_poll->sensb_res_len); data +=3D nfcb_poll->sensb_res_len; =20 @@ -181,14 +219,29 @@ nci_extract_rf_params_nfcb_passive_poll(struct nci_de= v *ndev, static const __u8 * nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfcf_poll *nfcf_poll, - const __u8 *data) + const __u8 *data, ssize_t data_len) { + /* Check if we have enough data for bit_rate (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + nfcf_poll->bit_rate =3D *data++; + data_len--; + + /* Check if we have enough data for sensf_res_len (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + nfcf_poll->sensf_res_len =3D min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE); + data_len--; =20 pr_debug("bit_rate %d, sensf_res_len %d\n", nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); =20 + /* Check if we have enough data for sensf_res */ + if (data_len < nfcf_poll->sensf_res_len) + return ERR_PTR(-EINVAL); + memcpy(nfcf_poll->sensf_res, data, nfcf_poll->sensf_res_len); data +=3D nfcf_poll->sensf_res_len; =20 @@ -198,22 +251,49 @@ nci_extract_rf_params_nfcf_passive_poll(struct nci_de= v *ndev, static const __u8 * nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfcv_poll *nfcv_poll, - const __u8 *data) + const __u8 *data, ssize_t data_len) { + /* Skip 1 byte (reserved) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + ++data; + data_len--; + + /* Check if we have enough data for dsfid (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + nfcv_poll->dsfid =3D *data++; + data_len--; + + /* Check if we have enough data for uid (8 bytes) */ + if (data_len < NFC_ISO15693_UID_MAXSIZE) + return ERR_PTR(-EINVAL); + memcpy(nfcv_poll->uid, data, NFC_ISO15693_UID_MAXSIZE); data +=3D NFC_ISO15693_UID_MAXSIZE; + return data; } =20 static const __u8 * nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev, struct rf_tech_specific_params_nfcf_listen *nfcf_listen, - const __u8 *data) + const __u8 *data, ssize_t data_len) { + /* Check if we have enough data for local_nfcid2_len (1 byte) */ + if (data_len < 1) + return ERR_PTR(-EINVAL); + nfcf_listen->local_nfcid2_len =3D min_t(__u8, *data++, NFC_NFCID2_MAXSIZE); + data_len--; + + /* Check if we have enough data for local_nfcid2 */ + if (data_len < nfcf_listen->local_nfcid2_len) + return ERR_PTR(-EINVAL); + memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len); data +=3D nfcf_listen->local_nfcid2_len; =20 @@ -364,7 +444,7 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *n= dev, const __u8 *data; bool add_target =3D true; =20 - if (skb->len < sizeof(struct nci_rf_discover_ntf)) + if (skb->len < offsetofend(struct nci_rf_discover_ntf, rf_tech_specific_p= arams_len)) return -EINVAL; =20 data =3D skb->data; @@ -380,26 +460,42 @@ static int nci_rf_discover_ntf_packet(struct nci_dev = *ndev, pr_debug("rf_tech_specific_params_len %d\n", ntf.rf_tech_specific_params_len); =20 + if (skb->len < (data - skb->data) + + ntf.rf_tech_specific_params_len + sizeof(ntf.ntf_type)) + return -EINVAL; + if (ntf.rf_tech_specific_params_len > 0) { switch (ntf.rf_tech_and_mode) { case NCI_NFC_A_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfca_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfca_poll), data); + &(ntf.rf_tech_specific_params.nfca_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return PTR_ERR(data); break; =20 case NCI_NFC_B_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcb_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcb_poll), data); + &(ntf.rf_tech_specific_params.nfcb_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return PTR_ERR(data); break; =20 case NCI_NFC_F_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcf_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcf_poll), data); + &(ntf.rf_tech_specific_params.nfcf_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return PTR_ERR(data); break; =20 case NCI_NFC_V_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcv_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcv_poll), data); + &(ntf.rf_tech_specific_params.nfcv_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return PTR_ERR(data); break; =20 default: @@ -574,7 +670,7 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_= dev *ndev, const __u8 *data; int err =3D NCI_STATUS_OK; =20 - if (skb->len < sizeof(struct nci_rf_intf_activated_ntf)) + if (skb->len < offsetofend(struct nci_rf_intf_activated_ntf, rf_tech_spec= ific_params_len)) return -EINVAL; =20 data =3D skb->data; @@ -606,26 +702,41 @@ static int nci_rf_intf_activated_ntf_packet(struct nc= i_dev *ndev, if (ntf.rf_interface =3D=3D NCI_RF_INTERFACE_NFCEE_DIRECT) goto listen; =20 + if (skb->len < (data - skb->data) + ntf.rf_tech_specific_params_len) + return -EINVAL; + if (ntf.rf_tech_specific_params_len > 0) { switch (ntf.activation_rf_tech_and_mode) { case NCI_NFC_A_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfca_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfca_poll), data); + &(ntf.rf_tech_specific_params.nfca_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return -EINVAL; break; =20 case NCI_NFC_B_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcb_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcb_poll), data); + &(ntf.rf_tech_specific_params.nfcb_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return -EINVAL; break; =20 case NCI_NFC_F_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcf_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcf_poll), data); + &(ntf.rf_tech_specific_params.nfcf_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return -EINVAL; break; =20 case NCI_NFC_V_PASSIVE_POLL_MODE: data =3D nci_extract_rf_params_nfcv_passive_poll(ndev, - &(ntf.rf_tech_specific_params.nfcv_poll), data); + &(ntf.rf_tech_specific_params.nfcv_poll), data, + ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return -EINVAL; break; =20 case NCI_NFC_A_PASSIVE_LISTEN_MODE: @@ -635,7 +746,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_= dev *ndev, case NCI_NFC_F_PASSIVE_LISTEN_MODE: data =3D nci_extract_rf_params_nfcf_passive_listen(ndev, &(ntf.rf_tech_specific_params.nfcf_listen), - data); + data, ntf.rf_tech_specific_params_len); + if (IS_ERR(data)) + return -EINVAL; break; =20 default: @@ -646,6 +759,13 @@ static int nci_rf_intf_activated_ntf_packet(struct nci= _dev *ndev, } } =20 + if (skb->len < (data - skb->data) + + sizeof(ntf.data_exch_rf_tech_and_mode) + + sizeof(ntf.data_exch_tx_bit_rate) + + sizeof(ntf.data_exch_rx_bit_rate) + + sizeof(ntf.activation_params_len)) + return -EINVAL; + ntf.data_exch_rf_tech_and_mode =3D *data++; ntf.data_exch_tx_bit_rate =3D *data++; ntf.data_exch_rx_bit_rate =3D *data++; @@ -657,6 +777,9 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_= dev *ndev, pr_debug("data_exch_rx_bit_rate 0x%x\n", ntf.data_exch_rx_bit_rate); pr_debug("activation_params_len %d\n", ntf.activation_params_len); =20 + if (skb->len < (data - skb->data) + ntf.activation_params_len) + return -EINVAL; + if (ntf.activation_params_len > 0) { switch (ntf.rf_interface) { case NCI_RF_INTERFACE_ISO_DEP: diff --git a/net/rds/connection.c b/net/rds/connection.c index b4cc699c5fad..98c0d5ff9de9 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c @@ -381,6 +381,8 @@ void rds_conn_shutdown(struct rds_conn_path *cp) if (!rds_conn_path_transition(cp, RDS_CONN_UP, RDS_CONN_DISCONNECTING) && !rds_conn_path_transition(cp, RDS_CONN_ERROR, + RDS_CONN_DISCONNECTING) && + !rds_conn_path_transition(cp, RDS_CONN_RESETTING, RDS_CONN_DISCONNECTING)) { rds_conn_path_error(cp, "shutdown called in state %d\n", @@ -426,6 +428,8 @@ void rds_conn_shutdown(struct rds_conn_path *cp) * to the conn hash, so we never trigger a reconnect on this * conn - the reconnect is always triggered by the active peer. */ cancel_delayed_work_sync(&cp->cp_conn_w); + + clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); rcu_read_lock(); if (!hlist_unhashed(&conn->c_hash_node)) { rcu_read_unlock(); diff --git a/net/rds/send.c b/net/rds/send.c index 09a280110654..4a24ee9c22d7 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1382,9 +1382,11 @@ int rds_sendmsg(struct socket *sock, struct msghdr *= msg, size_t payload_len) else queue_delayed_work(rds_wq, &cpath->cp_send_w, 1); rcu_read_unlock(); + + if (ret) + goto out; } - if (ret) - goto out; + rds_message_put(rm); =20 for (ind =3D 0; ind < vct.indx; ind++) diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 53b3535a1e4a..2e2f1a675049 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -59,9 +59,6 @@ void rds_tcp_keepalive(struct socket *sock) * socket and force a reconneect from smaller -> larger ip addr. The reason * we special case cp_index 0 is to allow the rds probe ping itself to its= elf * get through efficiently. - * Since reconnects are only initiated from the node with the numerically - * smaller ip address, we recycle conns in RDS_CONN_ERROR on the passive s= ide - * by moving them to CONNECTING in this function. */ static struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *= conn) @@ -86,8 +83,6 @@ struct rds_tcp_connection *rds_tcp_accept_one_path(struct= rds_connection *conn) struct rds_conn_path *cp =3D &conn->c_path[i]; =20 if (rds_conn_path_transition(cp, RDS_CONN_DOWN, - RDS_CONN_CONNECTING) || - rds_conn_path_transition(cp, RDS_CONN_ERROR, RDS_CONN_CONNECTING)) { return cp->cp_transport_data; } diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index ce7008cf291c..8675be6b1a2d 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -128,7 +128,7 @@ static int tcf_skbedit_init(struct net *net, struct nla= ttr *nla, struct tcf_skbedit *d; u32 flags =3D 0, *priority =3D NULL, *mark =3D NULL, *mask =3D NULL; u16 *queue_mapping =3D NULL, *ptype =3D NULL; - u16 mapping_mod =3D 1; + u32 mapping_mod =3D 1; bool exists =3D false; int ret =3D 0, err; u32 index; @@ -196,6 +196,10 @@ static int tcf_skbedit_init(struct net *net, struct nl= attr *nla, } =20 mapping_mod =3D *queue_mapping_max - *queue_mapping + 1; + if (mapping_mod > U16_MAX) { + NL_SET_ERR_MSG_MOD(extack, "The range of queue_mapping is invalid."); + return -EINVAL; + } flags |=3D SKBEDIT_F_TXQ_SKBHASH; } if (*pure_flags & SKBEDIT_F_INHERITDSFIELD) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 00753bc5f1b1..13a948e2f83d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -39,6 +39,8 @@ static const struct rpc_authops authgss_ops; static const struct rpc_credops gss_credops; static const struct rpc_credops gss_nullops; =20 +static void gss_free_callback(struct kref *kref); + #define GSS_RETRY_EXPIRED 5 static unsigned int gss_expired_cred_retry_delay =3D GSS_RETRY_EXPIRED; =20 @@ -551,6 +553,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, } return gss_msg; err_put_pipe_version: + kref_put(&gss_auth->kref, gss_free_callback); put_pipe_version(gss_auth->net); err_free_msg: kfree(gss_msg); diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rp= c_xdr.c index cb32ab9a8395..ee91f4d641e6 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c @@ -320,29 +320,47 @@ static int gssx_dec_status(struct xdr_stream *xdr, =20 /* status->minor_status */ p =3D xdr_inline_decode(xdr, 8); - if (unlikely(p =3D=3D NULL)) - return -ENOSPC; + if (unlikely(p =3D=3D NULL)) { + err =3D -ENOSPC; + goto out_free_mech; + } p =3D xdr_decode_hyper(p, &status->minor_status); =20 /* status->major_status_string */ err =3D gssx_dec_buffer(xdr, &status->major_status_string); if (err) - return err; + goto out_free_mech; =20 /* status->minor_status_string */ err =3D gssx_dec_buffer(xdr, &status->minor_status_string); if (err) - return err; + goto out_free_major_status_string; =20 /* status->server_ctx */ err =3D gssx_dec_buffer(xdr, &status->server_ctx); if (err) - return err; + goto out_free_minor_status_string; =20 /* we assume we have no options for now, so simply consume them */ /* status->options */ err =3D dummy_dec_opt_array(xdr, &status->options); + if (err) + goto out_free_server_ctx; =20 + return 0; + +out_free_server_ctx: + kfree(status->server_ctx.data); + status->server_ctx.data =3D NULL; +out_free_minor_status_string: + kfree(status->minor_status_string.data); + status->minor_status_string.data =3D NULL; +out_free_major_status_string: + kfree(status->major_status_string.data); + status->major_status_string.data =3D NULL; +out_free_mech: + kfree(status->mech.data); + status->mech.data =3D NULL; return err; } =20 @@ -505,28 +523,35 @@ static int gssx_dec_name(struct xdr_stream *xdr, /* name->name_type */ err =3D gssx_dec_buffer(xdr, &dummy_netobj); if (err) - return err; + goto out_free_display_name; =20 /* name->exported_name */ err =3D gssx_dec_buffer(xdr, &dummy_netobj); if (err) - return err; + goto out_free_display_name; =20 /* name->exported_composite_name */ err =3D gssx_dec_buffer(xdr, &dummy_netobj); if (err) - return err; + goto out_free_display_name; =20 /* we assume we have no attributes for now, so simply consume them */ /* name->name_attributes */ err =3D dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); if (err) - return err; + goto out_free_display_name; =20 /* we assume we have no options for now, so simply consume them */ /* name->extensions */ err =3D dummy_dec_opt_array(xdr, &dummy_option_array); + if (err) + goto out_free_display_name; =20 + return 0; + +out_free_display_name: + kfree(name->display_name.data); + name->display_name.data =3D NULL; return err; } =20 @@ -649,32 +674,34 @@ static int gssx_dec_ctx(struct xdr_stream *xdr, /* ctx->state */ err =3D gssx_dec_buffer(xdr, &ctx->state); if (err) - return err; + goto out_free_exported_context_token; =20 /* ctx->need_release */ err =3D gssx_dec_bool(xdr, &ctx->need_release); if (err) - return err; + goto out_free_state; =20 /* ctx->mech */ err =3D gssx_dec_buffer(xdr, &ctx->mech); if (err) - return err; + goto out_free_state; =20 /* ctx->src_name */ err =3D gssx_dec_name(xdr, &ctx->src_name); if (err) - return err; + goto out_free_mech; =20 /* ctx->targ_name */ err =3D gssx_dec_name(xdr, &ctx->targ_name); if (err) - return err; + goto out_free_src_name; =20 /* ctx->lifetime */ p =3D xdr_inline_decode(xdr, 8+8); - if (unlikely(p =3D=3D NULL)) - return -ENOSPC; + if (unlikely(p =3D=3D NULL)) { + err =3D -ENOSPC; + goto out_free_targ_name; + } p =3D xdr_decode_hyper(p, &ctx->lifetime); =20 /* ctx->ctx_flags */ @@ -683,17 +710,36 @@ static int gssx_dec_ctx(struct xdr_stream *xdr, /* ctx->locally_initiated */ err =3D gssx_dec_bool(xdr, &ctx->locally_initiated); if (err) - return err; + goto out_free_targ_name; =20 /* ctx->open */ err =3D gssx_dec_bool(xdr, &ctx->open); if (err) - return err; + goto out_free_targ_name; =20 /* we assume we have no options for now, so simply consume them */ /* ctx->options */ err =3D dummy_dec_opt_array(xdr, &ctx->options); + if (err) + goto out_free_targ_name; + + return 0; =20 +out_free_targ_name: + kfree(ctx->targ_name.display_name.data); + ctx->targ_name.display_name.data =3D NULL; +out_free_src_name: + kfree(ctx->src_name.display_name.data); + ctx->src_name.display_name.data =3D NULL; +out_free_mech: + kfree(ctx->mech.data); + ctx->mech.data =3D NULL; +out_free_state: + kfree(ctx->state.data); + ctx->state.data =3D NULL; +out_free_exported_context_token: + kfree(ctx->exported_context_token.data); + ctx->exported_context_token.data =3D NULL; return err; } =20 diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma= /svc_rdma_transport.c index 2abd895046ee..b8d13b522298 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -363,12 +363,12 @@ static struct svc_xprt *svc_rdma_create(struct svc_se= rv *serv, */ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) { + unsigned int ctxts, rq_depth, maxpayload; struct svcxprt_rdma *listen_rdma; struct svcxprt_rdma *newxprt =3D NULL; struct rdma_conn_param conn_param; struct rpcrdma_connect_private pmsg; struct ib_qp_init_attr qp_attr; - unsigned int ctxts, rq_depth; struct ib_device *dev; int ret =3D 0; RPC_IFDEBUG(struct sockaddr *sap); @@ -391,37 +391,46 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xp= rt *xprt) dev =3D newxprt->sc_cm_id->device; newxprt->sc_port_num =3D newxprt->sc_cm_id->port_num; =20 - /* Qualify the transport resource defaults with the - * capabilities of this particular device */ + newxprt->sc_max_req_size =3D svcrdma_max_req_size; + newxprt->sc_max_requests =3D svcrdma_max_requests; + newxprt->sc_max_bc_requests =3D svcrdma_max_bc_requests; + newxprt->sc_recv_batch =3D RPCRDMA_MAX_RECV_BATCH; + newxprt->sc_fc_credits =3D cpu_to_be32(newxprt->sc_max_requests); + + /* Qualify the transport's resource defaults with the + * capabilities of this particular device. + */ + /* Transport header, head iovec, tail iovec */ newxprt->sc_max_send_sges =3D 3; /* Add one SGE per page list entry */ newxprt->sc_max_send_sges +=3D (svcrdma_max_req_size / PAGE_SIZE) + 1; if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) newxprt->sc_max_send_sges =3D dev->attrs.max_send_sge; - newxprt->sc_max_req_size =3D svcrdma_max_req_size; - newxprt->sc_max_requests =3D svcrdma_max_requests; - newxprt->sc_max_bc_requests =3D svcrdma_max_bc_requests; - newxprt->sc_recv_batch =3D RPCRDMA_MAX_RECV_BATCH; rq_depth =3D newxprt->sc_max_requests + newxprt->sc_max_bc_requests + newxprt->sc_recv_batch; if (rq_depth > dev->attrs.max_qp_wr) { - pr_warn("svcrdma: reducing receive depth to %d\n", - dev->attrs.max_qp_wr); rq_depth =3D dev->attrs.max_qp_wr; newxprt->sc_recv_batch =3D 1; newxprt->sc_max_requests =3D rq_depth - 2; newxprt->sc_max_bc_requests =3D 2; } - newxprt->sc_fc_credits =3D cpu_to_be32(newxprt->sc_max_requests); - ctxts =3D rdma_rw_mr_factor(dev, newxprt->sc_port_num, RPCSVC_MAXPAGES); - ctxts *=3D newxprt->sc_max_requests; - newxprt->sc_sq_depth =3D rq_depth + ctxts; - if (newxprt->sc_sq_depth > dev->attrs.max_qp_wr) { - pr_warn("svcrdma: reducing send depth to %d\n", - dev->attrs.max_qp_wr); + + /* Estimate the needed number of rdma_rw contexts. The maximum + * Read and Write chunks have one segment each. Each request + * can involve one Read chunk and either a Write chunk or Reply + * chunk; thus a factor of three. + */ + maxpayload =3D min(xprt->xpt_server->sv_max_payload, + RPCSVC_MAXPAYLOAD_RDMA); + ctxts =3D newxprt->sc_max_requests * 3 * + rdma_rw_mr_factor(dev, newxprt->sc_port_num, + maxpayload >> PAGE_SHIFT); + + newxprt->sc_sq_depth =3D rq_depth + + rdma_rw_max_send_wr(dev, newxprt->sc_port_num, ctxts, 0); + if (newxprt->sc_sq_depth > dev->attrs.max_qp_wr) newxprt->sc_sq_depth =3D dev->attrs.max_qp_wr; - } atomic_set(&newxprt->sc_sq_avail, newxprt->sc_sq_depth); =20 newxprt->sc_pd =3D ib_alloc_pd(dev, 0); diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c index 2721baf9fd2b..d7736d900271 100644 --- a/net/tipc/crypto.c +++ b/net/tipc/crypto.c @@ -460,7 +460,7 @@ static void tipc_aead_users_dec(struct tipc_aead __rcu = *aead, int lim) rcu_read_lock(); tmp =3D rcu_dereference(aead); if (tmp) - atomic_add_unless(&rcu_dereference(aead)->users, -1, lim); + atomic_add_unless(&tmp->users, -1, lim); rcu_read_unlock(); } =20 diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index d1180370fdf4..e6555254ddb8 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -348,7 +348,8 @@ static bool tipc_service_insert_publ(struct net *net, =20 /* Return if the publication already exists */ list_for_each_entry(_p, &sr->all_publ, all_publ) { - if (_p->key =3D=3D key && (!_p->sk.node || _p->sk.node =3D=3D node)) { + if (_p->key =3D=3D key && _p->sk.ref =3D=3D p->sk.ref && + (!_p->sk.node || _p->sk.node =3D=3D node)) { pr_debug("Failed to bind duplicate %u,%u,%u/%u:%u/%u\n", p->sr.type, p->sr.lower, p->sr.upper, node, p->sk.ref, key); @@ -388,7 +389,8 @@ static struct publication *tipc_service_remove_publ(str= uct service_range *r, u32 node =3D sk->node; =20 list_for_each_entry(p, &r->all_publ, all_publ) { - if (p->key !=3D key || (node && node !=3D p->sk.node)) + if (p->key !=3D key || p->sk.ref !=3D sk->ref || + (node && node !=3D p->sk.node)) continue; list_del(&p->all_publ); list_del(&p->local_publ); diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 7eccd6708d66..aca3132689cf 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -161,7 +161,7 @@ vmci_transport_packet_init(struct vmci_transport_packet= *pkt, =20 case VMCI_TRANSPORT_PACKET_TYPE_WAITING_READ: case VMCI_TRANSPORT_PACKET_TYPE_WAITING_WRITE: - memcpy(&pkt->u.wait, wait, sizeof(pkt->u.wait)); + pkt->u.wait =3D *wait; break; =20 case VMCI_TRANSPORT_PACKET_TYPE_REQUEST2: diff --git a/net/wireless/core.c b/net/wireless/core.c index f6693983b5e9..0baa4c6ab169 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1331,8 +1331,10 @@ void __cfg80211_leave(struct cfg80211_registered_dev= ice *rdev, __cfg80211_leave_ocb(rdev, dev); break; case NL80211_IFTYPE_P2P_DEVICE: + cfg80211_stop_p2p_device(rdev, wdev); + break; case NL80211_IFTYPE_NAN: - /* cannot happen, has no netdev */ + cfg80211_stop_nan(rdev, wdev); break; case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_MONITOR: diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index e3acfac7430a..52abda40dfb3 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -735,7 +735,7 @@ static int cfg80211_wext_siwencodeext(struct net_device= *dev, =20 idx =3D erq->flags & IW_ENCODE_INDEX; if (cipher =3D=3D WLAN_CIPHER_SUITE_AES_CMAC) { - if (idx < 4 || idx > 5) { + if (idx < 5 || idx > 6) { idx =3D wdev->wext.default_mgmt_key; if (idx < 0) return -EINVAL; diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 7188d3592dde..a73b3c9d7e4d 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -515,6 +515,14 @@ static int xfrm_dev_down(struct net_device *dev) return NOTIFY_DONE; } =20 +static int xfrm_dev_unregister(struct net_device *dev) +{ + xfrm_dev_state_flush(dev_net(dev), dev, true); + xfrm_dev_policy_flush(dev_net(dev), dev, true); + + return NOTIFY_DONE; +} + static int xfrm_dev_event(struct notifier_block *this, unsigned long event= , void *ptr) { struct net_device *dev =3D netdev_notifier_info_to_dev(ptr); @@ -527,8 +535,10 @@ static int xfrm_dev_event(struct notifier_block *this,= unsigned long event, void return xfrm_api_check(dev); =20 case NETDEV_DOWN: - case NETDEV_UNREGISTER: return xfrm_dev_down(dev); + + case NETDEV_UNREGISTER: + return xfrm_dev_unregister(dev); } return NOTIFY_DONE; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2edb0f868c57..b516dd15113e 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3734,8 +3734,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, str= uct sk_buff *skb, struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; struct xfrm_tmpl *stp[XFRM_MAX_DEPTH]; struct xfrm_tmpl **tpp =3D tp; + int i, k =3D 0; int ti =3D 0; - int i, k; =20 sp =3D skb_sec_path(skb); if (!sp) @@ -3761,6 +3761,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, st= ruct sk_buff *skb, tpp =3D stp; } =20 + if (pol->xdo.type =3D=3D XFRM_DEV_OFFLOAD_PACKET && sp =3D=3D &dummy) + /* This policy template was already checked by HW + * and secpath was removed in __xfrm_policy_check2. + */ + goto out; + /* For each tunnel xfrm, find the first matching tmpl. * For each tmpl before that, find corresponding xfrm. * Order is _important_. Later we will implement @@ -3770,7 +3776,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, str= uct sk_buff *skb, * verified to allow them to be skipped in future policy * checks (e.g. nested tunnels). */ - for (i =3D xfrm_nr-1, k =3D 0; i >=3D 0; i--) { + for (i =3D xfrm_nr - 1; i >=3D 0; i--) { k =3D xfrm_policy_ok(tpp[i], sp, k, family, if_id); if (k < 0) { if (k < -1) @@ -3786,6 +3792,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, str= uct sk_buff *skb, goto reject; } =20 +out: xfrm_pols_put(pols, npols); sp->verified_cnt =3D k; =20 diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 6e199a745ccb..d963fdf40e90 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1592,6 +1592,11 @@ sub push_parameter($$$$$) { $parameterdescs{$param} =3D "anonymous\n"; $anon_struct_union =3D 1; } + elsif ($param =3D~ "__cacheline_group" ) + # handle cache group enforcing variables: they do not need be described i= n header files + { + return; # ignore __cacheline_group_begin and __cacheline_group_end + } =20 # warn if parameter has no description # (but ignore ones starting with # as these are not parameters diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3eb7fda8a98f..96a6e6873098 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -608,6 +608,10 @@ static int ignore_undef_symbol(struct elf_info *info, = const char *symname) /* Special register function linked on all modules during final link of = .ko */ if (strstarts(symname, "_restgpr0_") || strstarts(symname, "_savegpr0_") || + strstarts(symname, "_restgpr1_") || + strstarts(symname, "_savegpr1_") || + strstarts(symname, "_restfpr_") || + strstarts(symname, "_savefpr_") || strstarts(symname, "_restvr_") || strstarts(symname, "_savevr_") || strcmp(symname, ".TOC.") =3D=3D 0) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 23b2853ce3c4..6885ecd4afdd 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -619,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profi= le, struct aa_perms *perms, =20 if (profile_unconfined(profile)) return; - if (rules->file.dfa && *match_str =3D=3D AA_CLASS_FILE) { - state =3D aa_dfa_match_len(rules->file.dfa, - rules->file.start[AA_CLASS_FILE], + if (rules->file->dfa && *match_str =3D=3D AA_CLASS_FILE) { + state =3D aa_dfa_match_len(rules->file->dfa, + rules->file->start[AA_CLASS_FILE], match_str + 1, match_len - 1); if (state) { struct path_cond cond =3D { }; =20 - tmp =3D *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp =3D *(aa_lookup_fperms(rules->file, state, &cond)); } - } else if (rules->policy.dfa) { + } else if (rules->policy->dfa) { if (!RULE_MEDIATES(rules, *match_str)) return; /* no change to current perms */ - state =3D aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], + state =3D aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], match_str, match_len); if (state) - tmp =3D *aa_lookup_perms(&rules->policy, state); + tmp =3D *aa_lookup_perms(rules->policy, state); } aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum_raw(perms, &tmp); @@ -1096,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *s= eq, void *v) struct aa_profile *profile =3D labels_profile(label); if (profile->attach.xmatch_str) seq_printf(seq, "%s\n", profile->attach.xmatch_str); - else if (profile->attach.xmatch.dfa) + else if (profile->attach.xmatch->dfa) seq_puts(seq, "\n"); else seq_printf(seq, "%s\n", profile->base.name); @@ -1637,6 +1637,15 @@ static const char *rawdata_get_link_base(struct dent= ry *dentry, =20 label =3D aa_get_label_rcu(&proxy->label); profile =3D labels_profile(label); + + /* rawdata can be null when aa_g_export_binary is unset during + * runtime and a profile is replaced + */ + if (!profile->rawdata) { + aa_put_label(label); + return ERR_PTR(-ENOENT); + } + depth =3D profile_depth(profile); target =3D gen_symlink_name(depth, profile->rawdata->name, name); aa_put_label(label); diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 543105cf7e33..d6500ec4f6b6 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -77,7 +77,7 @@ static int may_change_ptraced_domain(const struct cred *t= o_cred, /**** TODO: dedup to aa_label_match - needs perm and dfa, merging * specifically this is an exact copy of aa_label_match except * aa_compute_perms is replaced with aa_compute_fperms - * and policy.dfa with file.dfa + * and policy->dfa with file->dfa ****/ /* match a profile and its associated ns component if needed * Assumes visibility test has already been done. @@ -93,16 +93,16 @@ static inline aa_state_t match_component(struct aa_prof= ile *profile, const char *ns_name; =20 if (stack) - state =3D aa_dfa_match(rules->file.dfa, state, "&"); + state =3D aa_dfa_match(rules->file->dfa, state, "&"); if (profile->ns =3D=3D tp->ns) - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); =20 /* try matching with namespace name and then profile */ ns_name =3D aa_ns_name(profile->ns, tp->ns, true); - state =3D aa_dfa_match_len(rules->file.dfa, state, ":", 1); - state =3D aa_dfa_match(rules->file.dfa, state, ns_name); - state =3D aa_dfa_match_len(rules->file.dfa, state, ":", 1); - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + state =3D aa_dfa_match_len(rules->file->dfa, state, ":", 1); + state =3D aa_dfa_match(rules->file->dfa, state, ns_name); + state =3D aa_dfa_match_len(rules->file->dfa, state, ":", 1); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); } =20 /** @@ -150,12 +150,12 @@ static int label_compound_match(struct aa_profile *pr= ofile, label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state =3D aa_dfa_match(rules->file.dfa, state, "//&"); + state =3D aa_dfa_match(rules->file->dfa, state, "//&"); state =3D match_component(profile, tp, false, state); if (!state) goto fail; } - *perms =3D *(aa_lookup_fperms(&(rules->file), state, &cond)); + *perms =3D *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, perms); if ((perms->allow & request) !=3D request) return -EACCES; @@ -210,7 +210,7 @@ static int label_components_match(struct aa_profile *pr= ofile, return 0; =20 next: - tmp =3D *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp =3D *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { @@ -219,7 +219,7 @@ static int label_components_match(struct aa_profile *pr= ofile, state =3D match_component(profile, tp, stack, start); if (!state) goto fail; - tmp =3D *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp =3D *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); } @@ -316,7 +316,7 @@ static int aa_xattrs_match(const struct linux_binprm *b= prm, might_sleep(); =20 /* transition from exec match to xattr set */ - state =3D aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state =3D aa_dfa_outofband_transition(attach->xmatch->dfa, state); d =3D bprm->file->f_path.dentry; =20 for (i =3D 0; i < attach->xattr_count; i++) { @@ -330,20 +330,20 @@ static int aa_xattrs_match(const struct linux_binprm = *bprm, * that not present xattr can be distinguished from a 0 * length value or rule that matches any value */ - state =3D aa_dfa_null_transition(attach->xmatch.dfa, + state =3D aa_dfa_null_transition(attach->xmatch->dfa, state); /* Check xattr value */ - state =3D aa_dfa_match_len(attach->xmatch.dfa, state, + state =3D aa_dfa_match_len(attach->xmatch->dfa, state, value, size); - index =3D ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm =3D attach->xmatch.perms[index].allow; + index =3D ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm =3D attach->xmatch->perms[index].allow; if (!(perm & MAY_EXEC)) { ret =3D -EINVAL; goto out; } } /* transition to next element */ - state =3D aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state =3D aa_dfa_outofband_transition(attach->xmatch->dfa, state); if (size < 0) { /* * No xattr match, so verify if transition to @@ -412,16 +412,16 @@ static struct aa_label *find_attach(const struct linu= x_binprm *bprm, * as another profile, signal a conflict and refuse to * match. */ - if (attach->xmatch.dfa) { + if (attach->xmatch->dfa) { unsigned int count; aa_state_t state; u32 index, perm; =20 - state =3D aa_dfa_leftmatch(attach->xmatch.dfa, - attach->xmatch.start[AA_CLASS_XMATCH], + state =3D aa_dfa_leftmatch(attach->xmatch->dfa, + attach->xmatch->start[AA_CLASS_XMATCH], name, &count); - index =3D ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm =3D attach->xmatch.perms[index].allow; + index =3D ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm =3D attach->xmatch->perms[index].allow; /* any accepting state means a valid match. */ if (perm & MAY_EXEC) { int ret =3D 0; @@ -524,7 +524,7 @@ struct aa_label *x_table_lookup(struct aa_profile *prof= ile, u32 xindex, /* TODO: move lookup parsing to unpack time so this is a straight * index into the resultant label */ - for (*name =3D rules->file.trans.table[index]; !label && *name; + for (*name =3D rules->file->trans.table[index]; !label && *name; *name =3D next_name(xtype, *name)) { if (xindex & AA_X_CHILD) { struct aa_profile *new_profile; @@ -577,7 +577,7 @@ static struct aa_label *x_to_label(struct aa_profile *p= rofile, break; case AA_X_TABLE: /* TODO: fix when perm mapping done at unload */ - stack =3D rules->file.trans.table[xindex & AA_X_INDEX_MASK]; + stack =3D rules->file->trans.table[xindex & AA_X_INDEX_MASK]; if (*stack !=3D '&') { /* released by caller */ new =3D x_table_lookup(profile, xindex, lookupname); @@ -636,7 +636,7 @@ static struct aa_label *profile_transition(const struct= cred *subj_cred, typeof(*rules), list); struct aa_label *new =3D NULL; const char *info =3D NULL, *name =3D NULL, *target =3D NULL; - aa_state_t state =3D rules->file.start[AA_CLASS_FILE]; + aa_state_t state =3D rules->file->start[AA_CLASS_FILE]; struct aa_perms perms =3D {}; bool nonewprivs =3D false; int error =3D 0; @@ -670,7 +670,7 @@ static struct aa_label *profile_transition(const struct= cred *subj_cred, } =20 /* find exec permissions for name */ - state =3D aa_str_perms(&(rules->file), state, name, cond, &perms); + state =3D aa_str_perms(rules->file, state, name, cond, &perms); if (perms.allow & MAY_EXEC) { /* exec permission determine how to transition */ new =3D x_to_label(profile, bprm, name, perms.xindex, &target, @@ -736,7 +736,7 @@ static int profile_onexec(const struct cred *subj_cred, { struct aa_ruleset *rules =3D list_first_entry(&profile->rules, typeof(*rules), list); - aa_state_t state =3D rules->file.start[AA_CLASS_FILE]; + aa_state_t state =3D rules->file->start[AA_CLASS_FILE]; struct aa_perms perms =3D {}; const char *xname =3D NULL, *info =3D "change_profile onexec"; int error =3D -EACCES; @@ -769,7 +769,7 @@ static int profile_onexec(const struct cred *subj_cred, } =20 /* find exec permissions for name */ - state =3D aa_str_perms(&(rules->file), state, xname, cond, &perms); + state =3D aa_str_perms(rules->file, state, xname, cond, &perms); if (!(perms.allow & AA_MAY_ONEXEC)) { info =3D "no change_onexec valid for executable"; goto audit; @@ -778,7 +778,7 @@ static int profile_onexec(const struct cred *subj_cred, * onexec permission is linked to exec with a standard pairing * exec\0change_profile */ - state =3D aa_dfa_null_transition(rules->file.dfa, state); + state =3D aa_dfa_null_transition(rules->file->dfa, state); error =3D change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, state, &perms); if (error) { @@ -1298,7 +1298,7 @@ static int change_profile_perms_wrapper(const char *o= p, const char *name, =20 if (!error) error =3D change_profile_perms(profile, target, stack, request, - rules->file.start[AA_CLASS_FILE], + rules->file->start[AA_CLASS_FILE], perms); if (error) error =3D aa_audit_file(subj_cred, profile, perms, op, request, diff --git a/security/apparmor/file.c b/security/apparmor/file.c index a51b83cf6968..e9e71d7bdcb6 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -236,7 +236,7 @@ static int __aa_path_perm(const char *op, const struct = cred *subj_cred, =20 if (profile_unconfined(profile)) return 0; - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], name, cond, perms); if (request & ~perms->allow) e =3D -EACCES; @@ -353,16 +353,16 @@ static int profile_path_link(const struct cred *subj_= cred, =20 error =3D -EACCES; /* aa_str_perms - handles the case of the dfa being NULL */ - state =3D aa_str_perms(&(rules->file), - rules->file.start[AA_CLASS_FILE], lname, + state =3D aa_str_perms(rules->file, + rules->file->start[AA_CLASS_FILE], lname, cond, &lperms); =20 if (!(lperms.allow & AA_MAY_LINK)) goto audit; =20 /* test to see if target can be paired with link */ - state =3D aa_dfa_null_transition(rules->file.dfa, state); - aa_str_perms(&(rules->file), state, tname, cond, &perms); + state =3D aa_dfa_null_transition(rules->file->dfa, state); + aa_str_perms(rules->file, state, tname, cond, &perms); =20 /* force audit/quiet masks for link are stored in the second entry * in the link pair. @@ -384,7 +384,7 @@ static int profile_path_link(const struct cred *subj_cr= ed, /* Do link perm subset test requiring allowed permission on link are * a subset of the allowed permissions on target. */ - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], tname, cond, &perms); =20 /* AA_MAY_LINK is not considered in the subset test */ diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/li= b.h index 6e88e99da80f..1ec00113a056 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -16,6 +16,8 @@ =20 #include "match.h" =20 +extern struct aa_dfa *stacksplitdfa; + /* * DEBUG remains global (no per profile flag) since it is mostly used in s= ysctl * which is not related to profile accesses. diff --git a/security/apparmor/include/match.h b/security/apparmor/include/= match.h index e59305abb85a..ae31a8a631fc 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -102,9 +102,6 @@ struct aa_dfa { struct table_header *tables[YYTD_ID_TSIZE]; }; =20 -extern struct aa_dfa *nulldfa; -extern struct aa_dfa *stacksplitdfa; - #define byte_to_byte(X) (X) =20 #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ @@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_s= ize) return ALIGN(sizeof(struct table_header) + len * el_size, 8); } =20 -int aa_setup_dfa_engine(void); -void aa_teardown_dfa_engine(void); - #define aa_state_t unsigned int =20 struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); diff --git a/security/apparmor/include/policy.h b/security/apparmor/include= /policy.h index fa15a5c7febb..bb682d513412 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -74,12 +74,14 @@ enum profile_mode { =20 =20 /* struct aa_policydb - match engine for a policy + * count: refcount for the pdb * dfa: dfa pattern match * perms: table of permissions * strs: table of strings, index by x * start: set of start states for the different classes of data */ struct aa_policydb { + struct kref count; struct aa_dfa *dfa; struct { struct aa_perms *perms; @@ -89,13 +91,36 @@ struct aa_policydb { aa_state_t start[AA_CLASS_LAST + 1]; }; =20 -static inline void aa_destroy_policydb(struct aa_policydb *policy) +extern struct aa_policydb *nullpdb; + +struct aa_policydb *aa_alloc_pdb(gfp_t gfp); +void aa_pdb_free_kref(struct kref *kref); + +/** + * aa_get_pdb - increment refcount on @pdb + * @pdb: policydb (MAYBE NULL) + * + * Returns: pointer to @pdb if @pdb is NULL will return NULL + * Requires: @pdb must be held with valid refcount when called + */ +static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) { - aa_put_dfa(policy->dfa); - if (policy->perms) - kvfree(policy->perms); - aa_free_str_table(&policy->trans); + if (pdb) + kref_get(&(pdb->count)); =20 + return pdb; +} + +/** + * aa_put_pdb - put a pdb refcount + * @pdb: pdb to put refcount (MAYBE NULL) + * + * Requires: if @pdb !=3D NULL that a valid refcount be held + */ +static inline void aa_put_pdb(struct aa_policydb *pdb) +{ + if (pdb) + kref_put(&pdb->count, aa_pdb_free_kref); } =20 static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, @@ -139,8 +164,8 @@ struct aa_ruleset { int size; =20 /* TODO: merge policy and file */ - struct aa_policydb policy; - struct aa_policydb file; + struct aa_policydb *policy; + struct aa_policydb *file; struct aa_caps caps; =20 struct aa_rlimit rlimits; @@ -159,7 +184,7 @@ struct aa_ruleset { */ struct aa_attachment { const char *xmatch_str; - struct aa_policydb xmatch; + struct aa_policydb *xmatch; unsigned int xmatch_len; int xattr_count; char **xattrs; @@ -276,10 +301,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_rule= set *rules, unsigned char class) { if (class <=3D AA_CLASS_LAST) - return rules->policy.start[class]; + return rules->policy->start[class]; else - return aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], &class, 1); + return aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], &class, 1); } =20 static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) @@ -289,7 +314,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_rul= eset *rules, u16 AF) =20 if (!state) return DFA_NOMATCH; - return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); + return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); } =20 static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index c0d0dbd7b4c4..0cdf4340b02d 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -92,8 +92,8 @@ static int profile_signal_perm(const struct cred *cred, ad->subj_cred =3D cred; ad->peer =3D peer; /* TODO: secondary cache check */ - state =3D aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_SIGNAL], + state =3D aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_SIGNAL], ad->signal); aa_label_match(profile, rules, peer, state, false, request, &perms); aa_apply_modes_to_perms(profile, &perms); diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 8a2af96f4da5..d64c838f5d84 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -1269,14 +1269,14 @@ static inline aa_state_t match_component(struct aa_= profile *profile, const char *ns_name; =20 if (profile->ns =3D=3D tp->ns) - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); =20 /* try matching with namespace name and then profile */ ns_name =3D aa_ns_name(profile->ns, tp->ns, true); - state =3D aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - state =3D aa_dfa_match(rules->policy.dfa, state, ns_name); - state =3D aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + state =3D aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + state =3D aa_dfa_match(rules->policy->dfa, state, ns_name); + state =3D aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); } =20 /** @@ -1288,7 +1288,7 @@ static inline aa_state_t match_component(struct aa_pr= ofile *profile, * @request: permissions to request * @perms: perms struct to set * - * Returns: 0 on success else ERROR + * Returns: state match stopped at or DFA_NOMATCH if aborted early * * For the label A//&B//&C this does the perm match for A//&B//&C * @perms should be preinitialized with allperms OR a previous permission @@ -1315,27 +1315,23 @@ static int label_compound_match(struct aa_profile *= profile, =20 /* no component visible */ *perms =3D allperms; - return 0; + return state; =20 next: label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state =3D aa_dfa_match(rules->policy.dfa, state, "//&"); + state =3D aa_dfa_match(rules->policy->dfa, state, "//&"); state =3D match_component(profile, rules, tp, state); if (!state) goto fail; } - *perms =3D *aa_lookup_perms(&rules->policy, state); - aa_apply_modes_to_perms(profile, perms); - if ((perms->allow & request) !=3D request) - return -EACCES; - - return 0; + *perms =3D *aa_lookup_perms(rules->policy, state); + return state; =20 fail: *perms =3D nullperms; - return state; + return DFA_NOMATCH; } =20 /** @@ -1348,7 +1344,7 @@ static int label_compound_match(struct aa_profile *pr= ofile, * @request: permissions to request * @perms: an initialized perms struct to add accumulation to * - * Returns: 0 on success else ERROR + * Returns: the state the match finished in, may be the none matching state * * For the label A//&B//&C this does the perm match for each of A and B an= d C * @perms should be preinitialized with allperms OR a previous permission @@ -1376,11 +1372,10 @@ static int label_components_match(struct aa_profile= *profile, } =20 /* no subcomponents visible - no change in perms */ - return 0; + return state; =20 next: - tmp =3D *aa_lookup_perms(&rules->policy, state); - aa_apply_modes_to_perms(profile, &tmp); + tmp =3D *aa_lookup_perms(rules->policy, state); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) @@ -1388,19 +1383,18 @@ static int label_components_match(struct aa_profile= *profile, state =3D match_component(profile, rules, tp, start); if (!state) goto fail; - tmp =3D *aa_lookup_perms(&rules->policy, state); - aa_apply_modes_to_perms(profile, &tmp); + tmp =3D *aa_lookup_perms(rules->policy, state); aa_perms_accum(perms, &tmp); } =20 if ((perms->allow & request) !=3D request) - return -EACCES; + return DFA_NOMATCH; =20 - return 0; + return state; =20 fail: *perms =3D nullperms; - return -EACCES; + return DFA_NOMATCH; } =20 /** @@ -1419,11 +1413,12 @@ int aa_label_match(struct aa_profile *profile, stru= ct aa_ruleset *rules, struct aa_label *label, aa_state_t state, bool subns, u32 request, struct aa_perms *perms) { - int error =3D label_compound_match(profile, rules, label, state, subns, - request, perms); - if (!error) - return error; + aa_state_t tmp =3D label_compound_match(profile, rules, label, state, sub= ns, + request, perms); + if ((perms->allow & request) =3D=3D request) + return tmp; =20 + /* failed compound_match try component matches */ *perms =3D allperms; return label_components_match(profile, rules, label, state, subns, request, perms); diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 7182a8b821fb..cd569fbbfe36 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -342,8 +342,8 @@ void aa_profile_match_label(struct aa_profile *profile, /* TODO: doesn't yet handle extended types */ aa_state_t state; =20 - state =3D aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_LABEL], + state =3D aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_LABEL], type); aa_label_match(profile, rules, label, state, false, request, perms); } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 5303a51eff9c..641f6510d7cb 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1909,6 +1909,69 @@ static int __init apparmor_nf_ip_init(void) __initcall(apparmor_nf_ip_init); #endif =20 +static char nulldfa_src[] =3D { + #include "nulldfa.in" +}; +struct aa_dfa *nulldfa; + +static char stacksplitdfa_src[] =3D { + #include "stacksplitdfa.in" +}; +struct aa_dfa *stacksplitdfa; +struct aa_policydb *nullpdb; + +static int __init aa_setup_dfa_engine(void) +{ + int error =3D -ENOMEM; + + nullpdb =3D aa_alloc_pdb(GFP_KERNEL); + if (!nullpdb) + return -ENOMEM; + + nulldfa =3D aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(nulldfa)) { + error =3D PTR_ERR(nulldfa); + goto fail; + } + nullpdb->dfa =3D aa_get_dfa(nulldfa); + nullpdb->perms =3D kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); + if (!nullpdb->perms) + goto fail; + nullpdb->size =3D 2; + + stacksplitdfa =3D aa_dfa_unpack(stacksplitdfa_src, + sizeof(stacksplitdfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(stacksplitdfa)) { + error =3D PTR_ERR(stacksplitdfa); + goto fail; + } + + return 0; + +fail: + aa_put_pdb(nullpdb); + aa_put_dfa(nulldfa); + nullpdb =3D NULL; + nulldfa =3D NULL; + stacksplitdfa =3D NULL; + + return error; +} + +static void __init aa_teardown_dfa_engine(void) +{ + aa_put_dfa(stacksplitdfa); + aa_put_dfa(nulldfa); + aa_put_pdb(nullpdb); + nullpdb =3D NULL; + stacksplitdfa =3D NULL; + nulldfa =3D NULL; +} + static int __init apparmor_init(void) { int error; diff --git a/security/apparmor/match.c b/security/apparmor/match.c index 3667b79e9366..6f6cdb86f32b 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -21,50 +21,6 @@ =20 #define base_idx(X) ((X) & 0xffffff) =20 -static char nulldfa_src[] =3D { - #include "nulldfa.in" -}; -struct aa_dfa *nulldfa; - -static char stacksplitdfa_src[] =3D { - #include "stacksplitdfa.in" -}; -struct aa_dfa *stacksplitdfa; - -int __init aa_setup_dfa_engine(void) -{ - int error; - - nulldfa =3D aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(nulldfa)) { - error =3D PTR_ERR(nulldfa); - nulldfa =3D NULL; - return error; - } - - stacksplitdfa =3D aa_dfa_unpack(stacksplitdfa_src, - sizeof(stacksplitdfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(stacksplitdfa)) { - aa_put_dfa(nulldfa); - nulldfa =3D NULL; - error =3D PTR_ERR(stacksplitdfa); - stacksplitdfa =3D NULL; - return error; - } - - return 0; -} - -void __init aa_teardown_dfa_engine(void) -{ - aa_put_dfa(stacksplitdfa); - aa_put_dfa(nulldfa); -} - /** * unpack_table - unpack a dfa table (one of accept, default, base, next c= heck) * @blob: data to unpack (NOT NULL) diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index cb0fdbdb82d9..49fe8da6fea4 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -332,8 +332,8 @@ static int match_mnt_path_str(const struct cred *subj_c= red, } =20 error =3D -EACCES; - pos =3D do_match_mnt(&rules->policy, - rules->policy.start[AA_CLASS_MOUNT], + pos =3D do_match_mnt(rules->policy, + rules->policy->start[AA_CLASS_MOUNT], mntpnt, devname, type, flags, data, binary, &perms); if (pos) { info =3D mnt_info_table[pos]; @@ -620,10 +620,10 @@ static int profile_umount(const struct cred *subj_cre= d, if (error) goto audit; =20 - state =3D aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state =3D aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], name); - perms =3D *aa_lookup_perms(&rules->policy, state); + perms =3D *aa_lookup_perms(rules->policy, state); if (AA_MAY_UMOUNT & ~perms.allow) error =3D -EACCES; =20 @@ -694,12 +694,12 @@ static struct aa_label *build_pivotroot(const struct = cred *subj_cred, goto audit; =20 error =3D -EACCES; - state =3D aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state =3D aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], new_name); - state =3D aa_dfa_null_transition(rules->policy.dfa, state); - state =3D aa_dfa_match(rules->policy.dfa, state, old_name); - perms =3D *aa_lookup_perms(&rules->policy, state); + state =3D aa_dfa_null_transition(rules->policy->dfa, state); + state =3D aa_dfa_match(rules->policy->dfa, state, old_name); + perms =3D *aa_lookup_perms(rules->policy, state); =20 if (AA_MAY_PIVOTROOT & perms.allow) error =3D 0; diff --git a/security/apparmor/net.c b/security/apparmor/net.c index 704c171232ab..3e632700d06f 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -127,9 +127,9 @@ int aa_profile_af_perm(struct aa_profile *profile, =20 buffer[0] =3D cpu_to_be16(family); buffer[1] =3D cpu_to_be16((u16) type); - state =3D aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, + state =3D aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer, 4); - perms =3D *aa_lookup_perms(&rules->policy, state); + perms =3D *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &perms); =20 return aa_check_perms(profile, &perms, request, ad, audit_net_cb); @@ -190,8 +190,10 @@ int aa_sock_file_perm(const struct cred *subj_cred, st= ruct aa_label *label, const char *op, u32 request, struct socket *sock) { AA_BUG(!label); - AA_BUG(!sock); - AA_BUG(!sock->sk); + + /* sock && sock->sk can be NULL for sockets being set up or torn down */ + if (!sock || !sock->sk) + return 0; =20 return aa_label_sk_perm(subj_cred, label, op, request, sock->sk); } diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index d9d3b3d776e1..009fa7cfb668 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -98,6 +98,41 @@ const char *const aa_profile_mode_names[] =3D { }; =20 =20 +static void aa_free_pdb(struct aa_policydb *policy) +{ + if (policy) { + aa_put_dfa(policy->dfa); + if (policy->perms) + kvfree(policy->perms); + aa_free_str_table(&policy->trans); + } +} + +/** + * aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb) + * @kr: kref callback for freeing of a dfa (NOT NULL) + */ +void aa_pdb_free_kref(struct kref *kref) +{ + struct aa_policydb *pdb =3D container_of(kref, struct aa_policydb, count); + + aa_free_pdb(pdb); +} + + +struct aa_policydb *aa_alloc_pdb(gfp_t gfp) +{ + struct aa_policydb *pdb =3D kzalloc(sizeof(struct aa_policydb), gfp); + + if (!pdb) + return NULL; + + kref_init(&pdb->count); + + return pdb; +} + + /** * __add_profile - add a profiles to list and label tree * @list: list to add it to (NOT NULL) @@ -200,15 +235,15 @@ static void free_attachment(struct aa_attachment *att= ach) for (i =3D 0; i < attach->xattr_count; i++) kfree_sensitive(attach->xattrs[i]); kfree_sensitive(attach->xattrs); - aa_destroy_policydb(&attach->xmatch); + aa_put_pdb(attach->xmatch); } =20 static void free_ruleset(struct aa_ruleset *rules) { int i; =20 - aa_destroy_policydb(&rules->file); - aa_destroy_policydb(&rules->policy); + aa_put_pdb(rules->file); + aa_put_pdb(rules->policy); aa_free_cap_rules(&rules->caps); aa_free_rlimit_rules(&rules->rlimits); =20 @@ -590,16 +625,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *pa= rent, const char *name, /* TODO: ideally we should inherit abi from parent */ profile->label.flags |=3D FLAG_NULL; rules =3D list_first_entry(&profile->rules, typeof(*rules), list); - rules->file.dfa =3D aa_get_dfa(nulldfa); - rules->file.perms =3D kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); - if (!rules->file.perms) - goto fail; - rules->file.size =3D 2; - rules->policy.dfa =3D aa_get_dfa(nulldfa); - rules->policy.perms =3D kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); - if (!rules->policy.perms) - goto fail; - rules->policy.size =3D 2; + rules->file =3D aa_get_pdb(nullpdb); + rules->policy =3D aa_get_pdb(nullpdb); =20 if (parent) { profile->path_flags =3D parent->path_flags; @@ -610,11 +637,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *pa= rent, const char *name, } =20 return profile; - -fail: - aa_free_profile(profile); - - return NULL; } =20 /** diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_u= npack.c index d752bfa9b3f3..9b25624285e6 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -683,8 +683,10 @@ static ssize_t unpack_perms_table(struct aa_ext *e, st= ruct aa_perms **perms) if (!aa_unpack_array(e, NULL, &size)) goto fail_reset; *perms =3D kcalloc(size, sizeof(struct aa_perms), GFP_KERNEL); - if (!*perms) - goto fail_reset; + if (!*perms) { + e->pos =3D pos; + return -ENOMEM; + } for (i =3D 0; i < size; i++) { if (!unpack_perm(e, version, &(*perms)[i])) goto fail; @@ -705,24 +707,29 @@ static ssize_t unpack_perms_table(struct aa_ext *e, s= truct aa_perms **perms) return -EPROTO; } =20 -static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, +static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, bool required_dfa, bool required_trans, const char **info) { + struct aa_policydb *pdb; void *pos =3D e->pos; int i, flags, error =3D -EPROTO; ssize_t size; =20 - size =3D unpack_perms_table(e, &policy->perms); + pdb =3D aa_alloc_pdb(GFP_KERNEL); + if (!pdb) + return -ENOMEM; + + size =3D unpack_perms_table(e, &pdb->perms); if (size < 0) { error =3D size; - policy->perms =3D NULL; + pdb->perms =3D NULL; *info =3D "failed to unpack - perms"; goto fail; } - policy->size =3D size; + pdb->size =3D size; =20 - if (policy->perms) { + if (pdb->perms) { /* perms table present accept is index */ flags =3D TO_ACCEPT1_FLAG(YYTD_DATA32); } else { @@ -731,13 +738,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_pol= icydb *policy, TO_ACCEPT2_FLAG(YYTD_DATA32); } =20 - policy->dfa =3D unpack_dfa(e, flags); - if (IS_ERR(policy->dfa)) { - error =3D PTR_ERR(policy->dfa); - policy->dfa =3D NULL; + pdb->dfa =3D unpack_dfa(e, flags); + if (IS_ERR(pdb->dfa)) { + error =3D PTR_ERR(pdb->dfa); + pdb->dfa =3D NULL; *info =3D "failed to unpack - dfa"; goto fail; - } else if (!policy->dfa) { + } else if (!pdb->dfa) { if (required_dfa) { *info =3D "missing required dfa"; goto fail; @@ -751,18 +758,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_pol= icydb *policy, * sadly start was given different names for file and policydb * but since it is optional we can try both */ - if (!aa_unpack_u32(e, &policy->start[0], "start")) + if (!aa_unpack_u32(e, &pdb->start[0], "start")) /* default start state */ - policy->start[0] =3D DFA_START; - if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { + pdb->start[0] =3D DFA_START; + if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) { /* default start state for xmatch and file dfa */ - policy->start[AA_CLASS_FILE] =3D DFA_START; + pdb->start[AA_CLASS_FILE] =3D DFA_START; } /* setup class index */ for (i =3D AA_CLASS_FILE + 1; i <=3D AA_CLASS_LAST; i++) { - policy->start[i] =3D aa_dfa_next(policy->dfa, policy->start[0], + pdb->start[i] =3D aa_dfa_next(pdb->dfa, pdb->start[0], i); } - if (!unpack_trans_table(e, &policy->trans) && required_trans) { + if (!unpack_trans_table(e, &pdb->trans) && required_trans) { *info =3D "failed to unpack profile transition table"; goto fail; } @@ -770,9 +777,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_poli= cydb *policy, /* TODO: move compat mapping here, requires dfa merging first */ /* TODO: move verify here, it has to be done after compat mappings */ out: + *policy =3D pdb; return 0; =20 fail: + aa_put_pdb(pdb); e->pos =3D pos; return error; } @@ -860,15 +869,15 @@ static struct aa_profile *unpack_profile(struct aa_ex= t *e, char **ns_name) } =20 /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ - if (profile->attach.xmatch.dfa) { + if (profile->attach.xmatch->dfa) { if (!aa_unpack_u32(e, &tmp, NULL)) { info =3D "missing xmatch len"; goto fail; } profile->attach.xmatch_len =3D tmp; - profile->attach.xmatch.start[AA_CLASS_XMATCH] =3D DFA_START; - if (!profile->attach.xmatch.perms) { - error =3D aa_compat_map_xmatch(&profile->attach.xmatch); + profile->attach.xmatch->start[AA_CLASS_XMATCH] =3D DFA_START; + if (!profile->attach.xmatch->perms) { + error =3D aa_compat_map_xmatch(profile->attach.xmatch); if (error) { info =3D "failed to convert xmatch permission table"; goto fail; @@ -985,16 +994,16 @@ static struct aa_profile *unpack_profile(struct aa_ex= t *e, char **ns_name) if (error) goto fail; /* Fixup: drop when we get rid of start array */ - if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], + if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0], AA_CLASS_FILE)) - rules->policy.start[AA_CLASS_FILE] =3D - aa_dfa_next(rules->policy.dfa, - rules->policy.start[0], + rules->policy->start[AA_CLASS_FILE] =3D + aa_dfa_next(rules->policy->dfa, + rules->policy->start[0], AA_CLASS_FILE); if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; - if (!rules->policy.perms) { - error =3D aa_compat_map_policy(&rules->policy, + if (!rules->policy->perms) { + error =3D aa_compat_map_policy(rules->policy, e->version); if (error) { info =3D "failed to remap policydb permission table"; @@ -1002,44 +1011,25 @@ static struct aa_profile *unpack_profile(struct aa_= ext *e, char **ns_name) } } } else { - rules->policy.dfa =3D aa_get_dfa(nulldfa); - rules->policy.perms =3D kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->policy.perms) - goto fail; - rules->policy.size =3D 2; + rules->policy =3D aa_get_pdb(nullpdb); } /* get file rules */ error =3D unpack_pdb(e, &rules->file, false, true, &info); if (error) { goto fail; - } else if (rules->file.dfa) { - if (!rules->file.perms) { - error =3D aa_compat_map_file(&rules->file); + } else if (rules->file->dfa) { + if (!rules->file->perms) { + error =3D aa_compat_map_file(rules->file); if (error) { info =3D "failed to remap file permission table"; goto fail; } } - } else if (rules->policy.dfa && - rules->policy.start[AA_CLASS_FILE]) { - rules->file.dfa =3D aa_get_dfa(rules->policy.dfa); - rules->file.start[AA_CLASS_FILE] =3D rules->policy.start[AA_CLASS_FILE]; - rules->file.perms =3D kcalloc(rules->policy.size, - sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - memcpy(rules->file.perms, rules->policy.perms, - rules->policy.size * sizeof(struct aa_perms)); - rules->file.size =3D rules->policy.size; + } else if (rules->policy->dfa && + rules->policy->start[AA_CLASS_FILE]) { + rules->file =3D aa_get_pdb(rules->policy); } else { - rules->file.dfa =3D aa_get_dfa(nulldfa); - rules->file.perms =3D kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - rules->file.size =3D 2; + rules->file =3D aa_get_pdb(nullpdb); } error =3D -EPROTO; if (aa_unpack_nameX(e, AA_STRUCT, "data")) { @@ -1247,26 +1237,32 @@ static int verify_profile(struct aa_profile *profil= e) if (!rules) return 0; =20 - if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, - rules->file.size)) || - (rules->policy.dfa && - !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) { + if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa, + rules->file->size)) { + audit_iface(profile, NULL, NULL, + "Unpack: file Invalid named transition", NULL, + -EPROTO); + return -EPROTO; + } + if (rules->policy->dfa && + !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) { audit_iface(profile, NULL, NULL, - "Unpack: Invalid named transition", NULL, -EPROTO); + "Unpack: policy Invalid named transition", NULL, + -EPROTO); return -EPROTO; } =20 - if (!verify_perms(&rules->file)) { + if (!verify_perms(rules->file)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&rules->policy)) { + if (!verify_perms(rules->policy)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&profile->attach.xmatch)) { + if (!verify_perms(profile->attach.xmatch)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index dcc94c3153d5..a7eee815f121 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -201,6 +201,11 @@ void __aa_transition_rlimits(struct aa_label *old_l, s= truct aa_label *new_l) rules->rlimits.limits[j].rlim_max); /* soft limit should not exceed hard limit */ rlim->rlim_cur =3D min(rlim->rlim_cur, rlim->rlim_max); + if (j =3D=3D RLIMIT_CPU && + rlim->rlim_cur !=3D RLIM_INFINITY && + IS_ENABLED(CONFIG_POSIX_TIMERS)) + (void) update_rlimit_cpu(current->group_leader, + rlim->rlim_cur); } } } diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 1e35c9f807b2..109ad155ffc2 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -68,6 +68,7 @@ enum smk_inos { static DEFINE_MUTEX(smack_cipso_lock); static DEFINE_MUTEX(smack_ambient_lock); static DEFINE_MUTEX(smk_net4addr_lock); +static DEFINE_MUTEX(smk_cipso_doi_lock); #if IS_ENABLED(CONFIG_IPV6) static DEFINE_MUTEX(smk_net6addr_lock); #endif /* CONFIG_IPV6 */ @@ -139,7 +140,7 @@ struct smack_parsed_rule { int smk_access2; }; =20 -static int smk_cipso_doi_value =3D SMACK_CIPSO_DOI_DEFAULT; +static u32 smk_cipso_doi_value =3D CIPSO_V4_DOI_UNKNOWN; =20 /* * Values for parsing cipso rules @@ -679,43 +680,60 @@ static const struct file_operations smk_load_ops =3D { }; =20 /** - * smk_cipso_doi - initialize the CIPSO domain + * smk_cipso_doi - set netlabel maps + * @ndoi: new value for our CIPSO DOI + * @gfp_flags: kmalloc allocation context */ -static void smk_cipso_doi(void) +static int +smk_cipso_doi(u32 ndoi, gfp_t gfp_flags) { - int rc; + int rc =3D 0; struct cipso_v4_doi *doip; struct netlbl_audit nai; =20 - smk_netlabel_audit_set(&nai); + mutex_lock(&smk_cipso_doi_lock); =20 - rc =3D netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); - if (rc !=3D 0) - printk(KERN_WARNING "%s:%d remove rc =3D %d\n", - __func__, __LINE__, rc); + if (smk_cipso_doi_value =3D=3D ndoi) + goto clr_doi_lock; + + smk_netlabel_audit_set(&nai); =20 - doip =3D kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL); + doip =3D kmalloc(sizeof(struct cipso_v4_doi), gfp_flags); + if (!doip) { + rc =3D -ENOMEM; + goto clr_doi_lock; + } doip->map.std =3D NULL; - doip->doi =3D smk_cipso_doi_value; + doip->doi =3D ndoi; doip->type =3D CIPSO_V4_MAP_PASS; doip->tags[0] =3D CIPSO_V4_TAG_RBITMAP; for (rc =3D 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) doip->tags[rc] =3D CIPSO_V4_TAG_INVALID; =20 rc =3D netlbl_cfg_cipsov4_add(doip, &nai); - if (rc !=3D 0) { - printk(KERN_WARNING "%s:%d cipso add rc =3D %d\n", - __func__, __LINE__, rc); + if (rc) { kfree(doip); - return; + goto clr_doi_lock; } - rc =3D netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai); - if (rc !=3D 0) { - printk(KERN_WARNING "%s:%d map add rc =3D %d\n", - __func__, __LINE__, rc); - netlbl_cfg_cipsov4_del(doip->doi, &nai); - return; + + if (smk_cipso_doi_value !=3D CIPSO_V4_DOI_UNKNOWN) { + rc =3D netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); + if (rc && rc !=3D -ENOENT) + goto clr_ndoi_def; + + netlbl_cfg_cipsov4_del(smk_cipso_doi_value, &nai); } + + rc =3D netlbl_cfg_cipsov4_map_add(ndoi, NULL, NULL, NULL, &nai); + if (rc) { + smk_cipso_doi_value =3D CIPSO_V4_DOI_UNKNOWN; // no default map +clr_ndoi_def: netlbl_cfg_cipsov4_del(ndoi, &nai); + } else + smk_cipso_doi_value =3D ndoi; + +clr_doi_lock: + mutex_unlock(&smk_cipso_doi_lock); + return rc; } =20 /** @@ -1580,7 +1598,7 @@ static ssize_t smk_read_doi(struct file *filp, char _= _user *buf, if (*ppos !=3D 0) return 0; =20 - sprintf(temp, "%d", smk_cipso_doi_value); + sprintf(temp, "%lu", (unsigned long)smk_cipso_doi_value); rc =3D simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); =20 return rc; @@ -1599,7 +1617,7 @@ static ssize_t smk_write_doi(struct file *file, const= char __user *buf, size_t count, loff_t *ppos) { char temp[80]; - int i; + unsigned long u; =20 if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; @@ -1612,14 +1630,13 @@ static ssize_t smk_write_doi(struct file *file, con= st char __user *buf, =20 temp[count] =3D '\0'; =20 - if (sscanf(temp, "%d", &i) !=3D 1) + if (kstrtoul(temp, 10, &u)) return -EINVAL; =20 - smk_cipso_doi_value =3D i; - - smk_cipso_doi(); + if (u =3D=3D CIPSO_V4_DOI_UNKNOWN || u > U32_MAX) + return -EINVAL; =20 - return count; + return smk_cipso_doi(u, GFP_KERNEL) ? : count; } =20 static const struct file_operations smk_doi_ops =3D { @@ -2996,6 +3013,7 @@ static int __init init_smk_fs(void) { int err; int rc; + struct netlbl_audit nai; =20 if (smack_enabled =3D=3D 0) return 0; @@ -3014,7 +3032,10 @@ static int __init init_smk_fs(void) } } =20 - smk_cipso_doi(); + smk_netlabel_audit_set(&nai); + (void) netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai); + (void) smk_cipso_doi(SMACK_CIPSO_DOI_DEFAULT, + GFP_KERNEL | __GFP_NOFAIL); smk_unlbl_ambient(NULL); =20 rc =3D smack_populate_secattr(&smack_known_floor); diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 157efd1530fb..fd141185ce2b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1127,6 +1127,7 @@ static const struct hda_quirk cxt5066_fixups[] =3D { SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI), SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004), SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205), + SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET= _MIC), HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER), HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER), {} diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index b6068d289f5f..5aeacbcb1f6a 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -689,7 +689,13 @@ static const struct dmi_system_id yc_acp_quirk_table[]= =3D { DMI_MATCH(DMI_BOARD_NAME, "XyloD5_RBU"), } }, - + { + .driver_data =3D &acp6x_card, + .matches =3D { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vivobook_ASUSLaptop M6501RR_M6501RR"), + } + }, {} }; =20 diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c index a697b5006b45..f2a9c33ff4a6 100644 --- a/sound/soc/codecs/aw88261.c +++ b/sound/soc/codecs/aw88261.c @@ -424,9 +424,10 @@ static int aw88261_dev_reg_update(struct aw88261 *aw88= 261, if (ret) break; =20 + /* keep all three bits from current hw status */ read_val &=3D (~AW88261_AMPPD_MASK) | (~AW88261_PWDN_MASK) | (~AW88261_HMUTE_MASK); - reg_val &=3D (AW88261_AMPPD_MASK | AW88261_PWDN_MASK | AW88261_HMUTE_MA= SK); + reg_val &=3D (AW88261_AMPPD_MASK & AW88261_PWDN_MASK & AW88261_HMUTE_MA= SK); reg_val |=3D read_val; =20 /* enable uls hmute */ diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 43792e175d75..864c6a858628 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -750,17 +750,23 @@ static int es8328_resume(struct snd_soc_component *co= mponent) es8328->supplies); if (ret) { dev_err(component->dev, "unable to enable regulators\n"); - return ret; + goto err_clk; } =20 regcache_mark_dirty(regmap); ret =3D regcache_sync(regmap); if (ret) { dev_err(component->dev, "unable to sync regcache\n"); - return ret; + goto err_regulators; } =20 return 0; + +err_regulators: + regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), es8328->supplies); +err_clk: + clk_disable_unprepare(es8328->clk); + return ret; } =20 static int es8328_component_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 5b8e78e51630..f2a1306d042b 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -1076,6 +1076,9 @@ static int max98390_i2c_probe(struct i2c_client *i2c) =20 reset_gpio =3D devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return dev_err_probe(&i2c->dev, PTR_ERR(reset_gpio), + "Failed to get reset gpio\n"); =20 /* Power on device */ if (reset_gpio) { diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 48ed75c3a7db..3cf531258911 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -1067,20 +1067,24 @@ static void nau8821_eject_jack(struct nau8821 *nau8= 821) snd_soc_component_disable_pin(component, "MICBIAS"); snd_soc_dapm_sync(dapm); =20 + /* Disable & mask both insertion & ejection IRQs */ + regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, + NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS, + NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS); + regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, + NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN, + NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN); + /* Clear all interruption status */ nau8821_irq_status_clear(regmap, 0); =20 - /* Enable the insertion interruption, disable the ejection inter- - * ruption, and then bypass de-bounce circuit. - */ + /* Enable & unmask the insertion IRQ */ regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, - NAU8821_IRQ_EJECT_DIS | NAU8821_IRQ_INSERT_DIS, - NAU8821_IRQ_EJECT_DIS); - /* Mask unneeded IRQs: 1 - disable, 0 - enable */ + NAU8821_IRQ_INSERT_DIS, 0); regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, - NAU8821_IRQ_EJECT_EN | NAU8821_IRQ_INSERT_EN, - NAU8821_IRQ_EJECT_EN); + NAU8821_IRQ_INSERT_EN, 0); =20 + /* Bypass de-bounce circuit */ regmap_update_bits(regmap, NAU8821_R0D_JACK_DET_CTRL, NAU8821_JACK_DET_DB_BYPASS, NAU8821_JACK_DET_DB_BYPASS); =20 @@ -1104,22 +1108,17 @@ static void nau8821_eject_jack(struct nau8821 *nau8= 821) NAU8821_IRQ_KEY_RELEASE_DIS | NAU8821_IRQ_KEY_PRESS_DIS); } - } =20 static void nau8821_jdet_work(struct work_struct *work) { struct nau8821 *nau8821 =3D - container_of(work, struct nau8821, jdet_work); + container_of(work, struct nau8821, jdet_work.work); struct snd_soc_dapm_context *dapm =3D nau8821->dapm; struct snd_soc_component *component =3D snd_soc_dapm_to_component(dapm); struct regmap *regmap =3D nau8821->regmap; int jack_status_reg, mic_detected, event =3D 0, event_mask =3D 0; =20 - snd_soc_component_force_enable_pin(component, "MICBIAS"); - snd_soc_dapm_sync(dapm); - msleep(20); - regmap_read(regmap, NAU8821_R58_I2C_DEVICE_ID, &jack_status_reg); mic_detected =3D !(jack_status_reg & NAU8821_KEYDET); if (mic_detected) { @@ -1149,6 +1148,7 @@ static void nau8821_jdet_work(struct work_struct *wor= k) snd_soc_component_disable_pin(component, "MICBIAS"); snd_soc_dapm_sync(dapm); } + event_mask |=3D SND_JACK_HEADSET; snd_soc_jack_report(nau8821->jack, event, event_mask); } @@ -1158,6 +1158,15 @@ static void nau8821_setup_inserted_irq(struct nau882= 1 *nau8821) { struct regmap *regmap =3D nau8821->regmap; =20 + /* Disable & mask insertion IRQ */ + regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, + NAU8821_IRQ_INSERT_DIS, NAU8821_IRQ_INSERT_DIS); + regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, + NAU8821_IRQ_INSERT_EN, NAU8821_IRQ_INSERT_EN); + + /* Clear insert IRQ status */ + nau8821_irq_status_clear(regmap, NAU8821_JACK_INSERT_DETECTED); + /* Enable internal VCO needed for interruptions */ if (nau8821->dapm->bias_level < SND_SOC_BIAS_PREPARE) nau8821_configure_sysclk(nau8821, NAU8821_CLK_INTERNAL, 0); @@ -1177,17 +1186,19 @@ static void nau8821_setup_inserted_irq(struct nau88= 21 *nau8821) regmap_update_bits(regmap, NAU8821_R0D_JACK_DET_CTRL, NAU8821_JACK_DET_DB_BYPASS, 0); =20 + /* Unmask & enable the ejection IRQs */ regmap_update_bits(regmap, NAU8821_R0F_INTERRUPT_MASK, - NAU8821_IRQ_EJECT_EN, 0); + NAU8821_IRQ_EJECT_EN, 0); regmap_update_bits(regmap, NAU8821_R12_INTERRUPT_DIS_CTRL, - NAU8821_IRQ_EJECT_DIS, 0); + NAU8821_IRQ_EJECT_DIS, 0); } =20 static irqreturn_t nau8821_interrupt(int irq, void *data) { struct nau8821 *nau8821 =3D (struct nau8821 *)data; struct regmap *regmap =3D nau8821->regmap; - int active_irq, clear_irq =3D 0, event =3D 0, event_mask =3D 0; + struct snd_soc_component *component; + int active_irq, event =3D 0, event_mask =3D 0; =20 if (regmap_read(regmap, NAU8821_R10_IRQ_STATUS, &active_irq)) { dev_err(nau8821->dev, "failed to read irq status\n"); @@ -1198,49 +1209,41 @@ static irqreturn_t nau8821_interrupt(int irq, void = *data) =20 if ((active_irq & NAU8821_JACK_EJECT_IRQ_MASK) =3D=3D NAU8821_JACK_EJECT_DETECTED) { - cancel_work_sync(&nau8821->jdet_work); + cancel_delayed_work_sync(&nau8821->jdet_work); regmap_update_bits(regmap, NAU8821_R71_ANALOG_ADC_1, NAU8821_MICDET_MASK, NAU8821_MICDET_DIS); nau8821_eject_jack(nau8821); event_mask |=3D SND_JACK_HEADSET; - clear_irq =3D NAU8821_JACK_EJECT_IRQ_MASK; } else if (active_irq & NAU8821_KEY_SHORT_PRESS_IRQ) { event |=3D NAU8821_BUTTON; event_mask |=3D NAU8821_BUTTON; - clear_irq =3D NAU8821_KEY_SHORT_PRESS_IRQ; + nau8821_irq_status_clear(regmap, NAU8821_KEY_SHORT_PRESS_IRQ); } else if (active_irq & NAU8821_KEY_RELEASE_IRQ) { event_mask =3D NAU8821_BUTTON; - clear_irq =3D NAU8821_KEY_RELEASE_IRQ; + nau8821_irq_status_clear(regmap, NAU8821_KEY_RELEASE_IRQ); } else if ((active_irq & NAU8821_JACK_INSERT_IRQ_MASK) =3D=3D NAU8821_JACK_INSERT_DETECTED) { - cancel_work_sync(&nau8821->jdet_work); + cancel_delayed_work_sync(&nau8821->jdet_work); regmap_update_bits(regmap, NAU8821_R71_ANALOG_ADC_1, NAU8821_MICDET_MASK, NAU8821_MICDET_EN); if (nau8821_is_jack_inserted(regmap)) { - /* detect microphone and jack type */ - schedule_work(&nau8821->jdet_work); + /* Detect microphone and jack type */ + component =3D snd_soc_dapm_to_component(nau8821->dapm); + snd_soc_component_force_enable_pin(component, "MICBIAS"); + snd_soc_dapm_sync(nau8821->dapm); + schedule_delayed_work(&nau8821->jdet_work, msecs_to_jiffies(20)); /* Turn off insertion interruption at manual mode */ - regmap_update_bits(regmap, - NAU8821_R12_INTERRUPT_DIS_CTRL, - NAU8821_IRQ_INSERT_DIS, - NAU8821_IRQ_INSERT_DIS); - regmap_update_bits(regmap, - NAU8821_R0F_INTERRUPT_MASK, - NAU8821_IRQ_INSERT_EN, - NAU8821_IRQ_INSERT_EN); nau8821_setup_inserted_irq(nau8821); } else { dev_warn(nau8821->dev, "Inserted IRQ fired but not connected\n"); nau8821_eject_jack(nau8821); } + } else { + /* Clear the rightmost interrupt */ + nau8821_irq_status_clear(regmap, active_irq); } =20 - if (!clear_irq) - clear_irq =3D active_irq; - /* clears the rightmost interruption */ - regmap_write(regmap, NAU8821_R11_INT_CLR_KEY_STATUS, clear_irq); - if (event_mask) snd_soc_jack_report(nau8821->jack, event, event_mask); =20 @@ -1664,8 +1667,14 @@ int nau8821_enable_jack_detect(struct snd_soc_compon= ent *component, int ret; =20 nau8821->jack =3D jack; + + if (nau8821->jdet_active) + return 0; + /* Initiate jack detection work queue */ - INIT_WORK(&nau8821->jdet_work, nau8821_jdet_work); + INIT_DELAYED_WORK(&nau8821->jdet_work, nau8821_jdet_work); + nau8821->jdet_active =3D true; + ret =3D devm_request_threaded_irq(nau8821->dev, nau8821->irq, NULL, nau8821_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "nau8821", nau8821); diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h index 00a888ed07ce..ce0880cdd189 100644 --- a/sound/soc/codecs/nau8821.h +++ b/sound/soc/codecs/nau8821.h @@ -559,7 +559,8 @@ struct nau8821 { struct regmap *regmap; struct snd_soc_dapm_context *dapm; struct snd_soc_jack *jack; - struct work_struct jdet_work; + struct delayed_work jdet_work; + bool jdet_active; int irq; int clk_id; int micbias_voltage; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 4f50b07848fd..68a5ca176d6f 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -67,6 +67,8 @@ struct wm8962_priv { struct mutex dsp2_ena_lock; u16 dsp2_ena; =20 + int mic_status; + struct delayed_work mic_work; struct snd_soc_jack *jack; =20 @@ -1759,7 +1761,7 @@ SND_SOC_BYTES("EQR Coefficients", WM8962_EQ24, 18), =20 =20 SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0), -SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA= ), +SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA= | WM8962_ADC_MONOMIX), =20 SOC_SINGLE("DF1 Switch", WM8962_DF1, 0, 1, 0), SND_SOC_BYTES_MASK("DF1 Coefficients", WM8962_DF1, 7, WM8962_DF1_ENA), @@ -3073,8 +3075,16 @@ static void wm8962_mic_work(struct work_struct *work) if (reg & WM8962_MICSHORT_STS) { status |=3D SND_JACK_BTN_0; irq_pol |=3D WM8962_MICSCD_IRQ_POL; + + /* Don't report a microphone if it's shorted right after + * plugging in, as this may be a TRS plug in a TRRS socket. + */ + if (!(wm8962->mic_status & WM8962_MICDET_STS)) + status =3D 0; } =20 + wm8962->mic_status =3D status; + snd_soc_jack_report(wm8962->jack, status, SND_JACK_MICROPHONE | SND_JACK_BTN_0); =20 diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 3a5ab8b53672..90a0a24c05d8 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -206,13 +206,10 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kco= ntrol, =20 xcvr->mode =3D snd_soc_enum_item_to_val(e, item[0]); =20 - down_read(&card->snd_card->controls_rwsem); fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, (xcvr->mode =3D=3D FSL_XCVR_MODE_ARC)); fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, (xcvr->mode =3D=3D FSL_XCVR_MODE_EARC)); - up_read(&card->snd_card->controls_rwsem); - /* Allow playback for SPDIF only */ rtd =3D snd_soc_get_pcm_runtime(card, card->dai_link); rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =3D diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/roc= kchip_i2s_tdm.c index 7ae93cbaea9a..15ef6b6bec2b 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -24,6 +24,7 @@ =20 #define DRV_NAME "rockchip-i2s-tdm" =20 +#define DEFAULT_MCLK_FS 256 #define CH_GRP_MAX 4 /* The max channel 8 / 2 */ #define MULTIPLEX_CH_MAX 10 =20 @@ -695,6 +696,15 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_s= ubstream *substream, mclk_rate =3D i2s_tdm->mclk_rx_freq; } =20 + /* + * When the dai/component driver doesn't need to set mclk-fs for a speci= fic + * clock, it can skip the call to set_sysclk() for that clock. + * In that case, simply use the clock rate from the params and multiply = it by + * the default mclk-fs value. + */ + if (!mclk_rate) + mclk_rate =3D DEFAULT_MCLK_FS * params_rate(params); + err =3D clk_set_rate(mclk, mclk_rate); if (err) return err; diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 84145209dec4..3835179b22b4 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -66,7 +66,7 @@ static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_= control *scontrol, * configuration */ memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data, - scontrol->max_size); + scontrol->size); kfree(scontrol->old_ipc_control_data); scontrol->old_ipc_control_data =3D NULL; /* Send the last known good configuration to firmware */ @@ -364,19 +364,35 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof= _dev *sdev, int ret =3D 0; =20 /* Send the new data to the firmware only if it is powered up */ - if (set && !pm_runtime_active(sdev->dev)) - return 0; + if (set) { + if (!pm_runtime_active(sdev->dev)) + return 0; + + if (!data->size) { + dev_dbg(sdev->dev, "%s: No data to be sent.\n", + scontrol->name); + return 0; + } + } =20 msg->extension =3D SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); =20 msg->data_ptr =3D data->data; - msg->data_size =3D data->size; + if (set) + msg->data_size =3D data->size; + else + msg->data_size =3D scontrol->max_size - sizeof(*data); =20 ret =3D sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); - if (ret < 0) + if (ret < 0) { dev_err(sdev->dev, "Failed to %s for %s\n", set ? "set bytes update" : "get bytes", scontrol->name); + } else if (!set) { + /* Update the sizes according to the received payload data */ + data->size =3D msg->data_size; + scontrol->size =3D sizeof(*cdata) + sizeof(*data) + data->size; + } =20 msg->data_ptr =3D NULL; msg->data_size =3D 0; @@ -392,6 +408,7 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *s= control, struct snd_sof_dev *sdev =3D snd_soc_component_get_drvdata(scomp); struct sof_abi_hdr *data =3D cdata->data; size_t size; + int ret; =20 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { dev_err_ratelimited(scomp->dev, @@ -413,9 +430,12 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *= scontrol, /* copy from kcontrol */ memcpy(data, ucontrol->value.bytes.data, size); =20 - sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + ret =3D sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); + if (!ret) + /* Update the cdata size */ + scontrol->size =3D sizeof(*cdata) + size; =20 - return 0; + return ret; } =20 static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol, @@ -511,7 +531,7 @@ static int sof_ipc4_bytes_ext_put(struct snd_sof_contro= l *scontrol, if (!scontrol->old_ipc_control_data) { /* Create a backup of the current, valid bytes control */ scontrol->old_ipc_control_data =3D kmemdup(scontrol->ipc_control_data, - scontrol->max_size, GFP_KERNEL); + scontrol->size, GFP_KERNEL); if (!scontrol->old_ipc_control_data) return -ENOMEM; } @@ -519,12 +539,15 @@ static int sof_ipc4_bytes_ext_put(struct snd_sof_cont= rol *scontrol, /* Copy the whole binary data which includes the ABI header and the paylo= ad */ if (copy_from_user(data, tlvd->tlv, header.length)) { memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data, - scontrol->max_size); + scontrol->size); kfree(scontrol->old_ipc_control_data); scontrol->old_ipc_control_data =3D NULL; return -EFAULT; } =20 + /* Update the cdata size */ + scontrol->size =3D sizeof(*cdata) + header.length; + return sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); } =20 diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c380ddf68a58..cc17d4e74c82 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2184,22 +2184,41 @@ static int sof_ipc4_control_load_bytes(struct snd_s= of_dev *sdev, struct snd_sof_ struct sof_ipc4_msg *msg; int ret; =20 - if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_h= dr))) { - dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", + /* + * The max_size is coming from topology and indicates the maximum size + * of sof_abi_hdr plus the payload, which excludes the local only + * 'struct sof_ipc4_control_data' + */ + if (scontrol->max_size < sizeof(struct sof_abi_hdr)) { + dev_err(sdev->dev, + "insufficient maximum size for a bytes control %s: %zu.\n", scontrol->name, scontrol->max_size); return -EINVAL; } =20 - if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { - dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", - scontrol->name, scontrol->priv_size, - scontrol->max_size - sizeof(*control_data)); + if (scontrol->priv_size > scontrol->max_size) { + dev_err(sdev->dev, + "bytes control %s initial data size %zu exceeds max %zu.\n", + scontrol->name, scontrol->priv_size, scontrol->max_size); + return -EINVAL; + } + + if (scontrol->priv_size < sizeof(struct sof_abi_hdr)) { + dev_err(sdev->dev, + "bytes control %s initial data size %zu is insufficient.\n", + scontrol->name, scontrol->priv_size); return -EINVAL; } =20 - scontrol->size =3D sizeof(struct sof_ipc4_control_data) + scontrol->priv_= size; + /* + * The used size behind the cdata pointer, which can be smaller than + * the maximum size + */ + scontrol->size =3D sizeof(*control_data) + scontrol->priv_size; =20 - scontrol->ipc_control_data =3D kzalloc(scontrol->max_size, GFP_KERNEL); + /* Allocate the cdata: local struct size + maximum payload size */ + scontrol->ipc_control_data =3D kzalloc(sizeof(*control_data) + scontrol->= max_size, + GFP_KERNEL); if (!scontrol->ipc_control_data) return -ENOMEM; =20 diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index 2599683a582d..9071bc483575 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -324,6 +324,9 @@ static int sun50i_dmic_probe(struct platform_device *pd= ev) =20 host->regmap =3D devm_regmap_init_mmio(&pdev->dev, base, &sun50i_dmic_regmap_config); + if (IS_ERR(host->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(host->regmap), + "failed to initialise regmap\n"); =20 /* Clocks */ host->bus_clk =3D devm_clk_get(&pdev->dev, "bus"); diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 17ae74b067c5..1092b964167e 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -278,8 +278,8 @@ static inline bool has_tx_length_quirk(struct snd_usb_a= udio *chip) return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH; } =20 -static void prepare_silent_urb(struct snd_usb_endpoint *ep, - struct snd_urb_ctx *ctx) +static int prepare_silent_urb(struct snd_usb_endpoint *ep, + struct snd_urb_ctx *ctx) { struct urb *urb =3D ctx->urb; unsigned int offs =3D 0; @@ -292,28 +292,34 @@ static void prepare_silent_urb(struct snd_usb_endpoin= t *ep, extra =3D sizeof(packet_length); =20 for (i =3D 0; i < ctx->packets; ++i) { - unsigned int offset; - unsigned int length; - int counts; - - counts =3D snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); - length =3D counts * ep->stride; /* number of silent bytes */ - offset =3D offs * ep->stride + extra * i; - urb->iso_frame_desc[i].offset =3D offset; + int length; + + length =3D snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); + if (length < 0) + return length; + length *=3D ep->stride; /* number of silent bytes */ + if (offs + length + extra > ctx->buffer_size) + break; + urb->iso_frame_desc[i].offset =3D offs; urb->iso_frame_desc[i].length =3D length + extra; if (extra) { packet_length =3D cpu_to_le32(length); - memcpy(urb->transfer_buffer + offset, + memcpy(urb->transfer_buffer + offs, &packet_length, sizeof(packet_length)); + offs +=3D extra; } - memset(urb->transfer_buffer + offset + extra, + memset(urb->transfer_buffer + offs, ep->silence_value, length); - offs +=3D counts; + offs +=3D length; } =20 - urb->number_of_packets =3D ctx->packets; - urb->transfer_buffer_length =3D offs * ep->stride + ctx->packets * extra; + if (!offs) + return -EPIPE; + + urb->number_of_packets =3D i; + urb->transfer_buffer_length =3D offs; ctx->queued =3D 0; + return 0; } =20 /* @@ -335,8 +341,7 @@ static int prepare_outbound_urb(struct snd_usb_endpoint= *ep, if (data_subs && ep->prepare_data_urb) return ep->prepare_data_urb(data_subs, urb, in_stream_lock); /* no data provider, so send silence */ - prepare_silent_urb(ep, ctx); - break; + return prepare_silent_urb(ep, ctx); =20 case SND_USB_ENDPOINT_TYPE_SYNC: if (snd_usb_get_speed(ep->chip->dev) >=3D USB_SPEED_HIGH) { @@ -489,6 +494,7 @@ int snd_usb_queue_pending_output_urbs(struct snd_usb_en= dpoint *ep, =20 /* copy over the length information */ if (implicit_fb) { + ctx->packets =3D packet->packets; for (i =3D 0; i < packet->packets; i++) ctx->packet_size[i] =3D packet->packet_size[i]; } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index cde5b5c16509..ff2bbe761ee3 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2047,6 +2047,8 @@ struct usb_audio_quirk_flags_table { =20 static const struct usb_audio_quirk_flags_table quirk_flags_table[] =3D { /* Device matches */ + DEVICE_FLG(0x001f, 0x0b21, /* AB13X USB Audio */ + QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */ diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c index c2ca82fc21e2..225d3678b4ed 100644 --- a/tools/bpf/bpftool/net.c +++ b/tools/bpf/bpftool/net.c @@ -150,7 +150,7 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 s= eq, bool multipart =3D true; struct nlmsgerr *err; struct nlmsghdr *nh; - char buf[4096]; + char buf[8192]; int len, ret; =20 while (multipart) { @@ -195,6 +195,9 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 s= eq, return ret; } } + + if (len) + p_err("Invalid message or trailing data in Netlink response: %d bytes l= eft", len); } ret =3D 0; done: diff --git a/tools/include/linux/bitfield.h b/tools/include/linux/bitfield.h index 6093fa6db260..ddf81f24956b 100644 --- a/tools/include/linux/bitfield.h +++ b/tools/include/linux/bitfield.h @@ -8,6 +8,7 @@ #define _LINUX_BITFIELD_H =20 #include +#include #include =20 /* diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index cf4db51b99eb..beb91c78ca7a 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -1758,9 +1758,18 @@ static int btf_dump_get_bitfield_value(struct btf_du= mp *d, __u16 left_shift_bits, right_shift_bits; const __u8 *bytes =3D data; __u8 nr_copy_bits; + __u8 start_bit, nr_bytes; __u64 num =3D 0; int i; =20 + /* Calculate how many bytes cover the bitfield */ + start_bit =3D bits_offset % 8; + nr_bytes =3D (start_bit + bit_sz + 7) / 8; + + /* Bound check */ + if (data + nr_bytes > d->typed_dump->data_end) + return -E2BIG; + /* Maximum supported bitfield size is 64 bits */ if (t->size > 8) { pr_warn("unexpected bitfield size %d\n", t->size); diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c index 68a2def17175..6f16c4f7b3a4 100644 --- a/tools/lib/bpf/netlink.c +++ b/tools/lib/bpf/netlink.c @@ -143,7 +143,7 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, = int seq, struct nlmsghdr *nh; int len, ret; =20 - ret =3D alloc_iov(&iov, 4096); + ret =3D alloc_iov(&iov, 8192); if (ret) goto done; =20 @@ -212,6 +212,8 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, = int seq, } } } + if (len) + pr_warn("Invalid message or trailing data in Netlink response: %d bytes= left\n", len); } ret =3D 0; done: diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile index 3a9b2140aa04..703a8ff0b343 100644 --- a/tools/lib/perf/Makefile +++ b/tools/lib/perf/Makefile @@ -54,13 +54,6 @@ endif =20 TEST_ARGS :=3D $(if $(V),-v) =20 -# Set compile option CFLAGS -ifdef EXTRA_CFLAGS - CFLAGS :=3D $(EXTRA_CFLAGS) -else - CFLAGS :=3D -g -Wall -endif - INCLUDES =3D \ -I$(srctree)/tools/lib/perf/include \ -I$(srctree)/tools/lib/ \ @@ -70,11 +63,12 @@ INCLUDES =3D \ -I$(srctree)/tools/include/uapi =20 # Append required CFLAGS -override CFLAGS +=3D $(EXTRA_WARNINGS) -override CFLAGS +=3D -Werror -Wall +override CFLAGS :=3D $(INCLUDES) $(CFLAGS) +override CFLAGS +=3D -g -Werror -Wall override CFLAGS +=3D -fPIC -override CFLAGS +=3D $(INCLUDES) override CFLAGS +=3D -fvisibility=3Dhidden +override CFLAGS +=3D $(EXTRA_WARNINGS) +override CFLAGS +=3D $(EXTRA_CFLAGS) =20 all: =20 diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c index ddaeb4eb3e24..db94aa685b73 100644 --- a/tools/lib/subcmd/help.c +++ b/tools/lib/subcmd/help.c @@ -97,11 +97,13 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdname= s *excludes) ei++; } } - if (ci !=3D cj) { - while (ci < cmds->cnt) { - cmds->names[cj++] =3D cmds->names[ci]; - cmds->names[ci++] =3D NULL; + while (ci < cmds->cnt) { + if (ci !=3D cj) { + cmds->names[cj] =3D cmds->names[ci]; + cmds->names[ci] =3D NULL; } + ci++; + cj++; } for (ci =3D cj; ci < cmds->cnt; ci++) assert(cmds->names[ci] =3D=3D NULL); diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 83b100c1e7f6..e9a0f89e9c39 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -7,6 +7,8 @@ srctree :=3D $(patsubst %/,%,$(dir $(CURDIR))) srctree :=3D $(patsubst %/,%,$(dir $(srctree))) endif =20 +RM ?=3D rm -f + LIBSUBCMD_DIR =3D $(srctree)/tools/lib/subcmd/ ifneq ($(OUTPUT),) LIBSUBCMD_OUTPUT =3D $(abspath $(OUTPUT))/libsubcmd diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh index 62f13dfeae8e..a76ccf2deb56 100755 --- a/tools/perf/tests/shell/stat.sh +++ b/tools/perf/tests/shell/stat.sh @@ -18,7 +18,7 @@ test_default_stat() { =20 test_stat_record_report() { echo "stat record and report test" - if ! perf stat record -o - true | perf stat report -i - 2>&1 | \ + if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>= &1 | \ grep -E -q "Performance counter stats for 'pipe':" then echo "stat record and report test [Failed]" @@ -30,7 +30,7 @@ test_stat_record_report() { =20 test_stat_record_script() { echo "stat record and script test" - if ! perf stat record -o - true | perf script -i - 2>&1 | \ + if ! perf stat record -e task-clock -o - true | perf script -i - 2>&1 | \ grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:spac= e:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT" then echo "stat record and script test [Failed]" @@ -159,7 +159,7 @@ test_hybrid() { fi =20 # Run default Perf stat - cycles_events=3D$(perf stat -- true 2>&1 | grep -E "/cycles/[uH]*| cycl= es[:uH]* " -c) + cycles_events=3D$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/= [uH]*| cpu-cycles[:uH]* " | wc -l) =20 # The expectation is that default output will have a cycles events on ea= ch # hybrid PMU. In situations with no cycles PMU events, like virtualized,= this diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprint= f.c index 8719b3cb5646..99310f842396 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -181,8 +181,12 @@ int sample__fprintf_callchain(struct perf_sample *samp= le, int left_alignment, if (print_dso && (!sym || !sym->inlined)) printed +=3D map__fprintf_dsoname_dsoff(map, print_dsoff, addr, fp); =20 - if (print_srcline) - printed +=3D map__fprintf_srcline(map, addr, "\n ", fp); + if (print_srcline) { + if (node->srcline) + printed +=3D fprintf(fp, "\n %s", node->srcline); + else + printed +=3D map__fprintf_srcline(map, addr, "\n ", fp); + } =20 if (sym && sym->inlined) printed +=3D fprintf(fp, " (inlined)"); diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 6013335a8dae..bd027fdf6af1 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -133,8 +133,8 @@ static int entry(u64 ip, struct unwind_info *ui) } =20 e->ip =3D ip; - e->ms.maps =3D al.maps; - e->ms.map =3D al.map; + e->ms.maps =3D maps__get(al.maps); + e->ms.map =3D map__get(al.map); e->ms.sym =3D al.sym; =20 pr_debug("unwind: %s:ip =3D 0x%" PRIx64 " (0x%" PRIx64 ")\n", @@ -319,6 +319,9 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, if (err) pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1)); =20 + for (i =3D 0; i < ui->idx; i++) + map_symbol__exit(&ui->entries[i].ms); + dwfl_end(ui->dwfl); free(ui); return 0; diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/= cpuidle.c index c15d0de12357..e7b8c5663837 100644 --- a/tools/power/cpupower/lib/cpuidle.c +++ b/tools/power/cpupower/lib/cpuidle.c @@ -148,6 +148,7 @@ unsigned long long cpuidle_state_get_one_value(unsigned= int cpu, if (len =3D=3D 0) return 0; =20 + errno =3D 0; value =3D strtoull(linebuf, &endp, 0); =20 if (endp =3D=3D linebuf || errno =3D=3D ERANGE) diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power= /x86/intel-speed-select/isst-config.c index 5fcc2a92957e..a5d512866a94 100644 --- a/tools/power/x86/intel-speed-select/isst-config.c +++ b/tools/power/x86/intel-speed-select/isst-config.c @@ -936,9 +936,11 @@ int isolate_cpus(struct isst_id *id, int mask_size, cp= u_set_t *cpu_mask, int lev ret =3D write(fd, "member", strlen("member")); if (ret =3D=3D -1) { printf("Can't update to member\n"); + close(fd); return ret; } =20 + close(fd); return 0; } =20 diff --git a/tools/spi/.gitignore b/tools/spi/.gitignore index 14ddba3d2195..038261b34ed8 100644 --- a/tools/spi/.gitignore +++ b/tools/spi/.gitignore @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only spidev_fdx spidev_test +include/ diff --git a/tools/testing/selftests/bpf/veristat.c b/tools/testing/selftes= ts/bpf/veristat.c index 611b5a0a6f7e..fab89a84119f 100644 --- a/tools/testing/selftests/bpf/veristat.c +++ b/tools/testing/selftests/bpf/veristat.c @@ -1372,7 +1372,7 @@ static void output_stats(const struct verif_stats *s,= enum resfmt fmt, bool last if (last && fmt =3D=3D RESFMT_TABLE) { output_header_underlines(); printf("Done. Processed %d files, %d programs. Skipped %d files, %d prog= rams.\n", - env.files_processed, env.files_skipped, env.progs_processed, env.= progs_skipped); + env.files_processed, env.progs_processed, env.files_skipped, env.= progs_skipped); } } =20 diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh b= /tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh index 0441a18f098b..aac8ef490feb 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh @@ -317,7 +317,7 @@ police_limits_test() =20 tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ flower skip_sw \ - action police rate 0.5kbit burst 1m conform-exceed drop/ok + action police rate 0.5kbit burst 2k conform-exceed drop/ok check_fail $? "Incorrect success to add police action with too low rate" =20 tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ @@ -327,7 +327,7 @@ police_limits_test() =20 tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ flower skip_sw \ - action police rate 1.5kbit burst 1m conform-exceed drop/ok + action police rate 1.5kbit burst 2k conform-exceed drop/ok check_err $? "Failed to add police action with low rate" =20 tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/sel= ftests/memfd/memfd_test.c index 9c9c82fd18a7..f2042de4bab8 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include #include =20 @@ -39,14 +42,26 @@ F_SEAL_EXEC) =20 #define MFD_NOEXEC_SEAL 0x0008U +union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; + +/* + * we use semaphores on nested wait tasks due the use of CLONE_NEWPID: the + * child will be PID 1 and can't send SIGSTOP to themselves due special + * treatment of the init task, so the SIGSTOP/SIGCONT synchronization + * approach can't be used here. + */ +#define SEM_KEY 0xdeadbeef =20 /* * Default is not to test hugetlbfs */ static size_t mfd_def_size =3D MFD_DEF_SIZE; static const char *memfd_str =3D MEMFD_STR; -static int newpid_thread_fn2(void *arg); -static void join_newpid_thread(pid_t pid); =20 static ssize_t fd2name(int fd, char *buf, size_t bufsize) { @@ -195,7 +210,6 @@ static unsigned int mfd_assert_get_seals(int fd) static void mfd_assert_has_seals(int fd, unsigned int seals) { char buf[PATH_MAX]; - int nbytes; unsigned int s; fd2name(fd, buf, PATH_MAX); =20 @@ -715,7 +729,6 @@ static void mfd_assert_mode(int fd, int mode) { struct stat st; char buf[PATH_MAX]; - int nbytes; =20 fd2name(fd, buf, PATH_MAX); =20 @@ -734,7 +747,6 @@ static void mfd_assert_mode(int fd, int mode) static void mfd_assert_chmod(int fd, int mode) { char buf[PATH_MAX]; - int nbytes; =20 fd2name(fd, buf, PATH_MAX); =20 @@ -750,7 +762,6 @@ static void mfd_fail_chmod(int fd, int mode) { struct stat st; char buf[PATH_MAX]; - int nbytes; =20 fd2name(fd, buf, PATH_MAX); =20 @@ -1297,9 +1308,6 @@ static void test_sysctl_set_sysctl2(void) =20 static int sysctl_simple_child(void *arg) { - int fd; - int pid; - printf("%s sysctl 0\n", memfd_str); test_sysctl_set_sysctl0(); =20 @@ -1342,8 +1350,22 @@ static int sysctl_nested(void *arg) =20 static int sysctl_nested_wait(void *arg) { - /* Wait for a SIGCONT. */ - kill(getpid(), SIGSTOP); + int sem =3D semget(SEM_KEY, 1, 0600); + struct sembuf sembuf; + + if (sem < 0) { + perror("semget:"); + abort(); + } + sembuf.sem_num =3D 0; + sembuf.sem_flg =3D 0; + sembuf.sem_op =3D 0; + + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + abort(); + } + return sysctl_nested(arg); } =20 @@ -1364,8 +1386,9 @@ static void test_sysctl_sysctl2_failset(void) =20 static int sysctl_nested_child(void *arg) { - int fd; - int pid; + int pid, sem; + union semun semun; + struct sembuf sembuf; =20 printf("%s nested sysctl 0\n", memfd_str); sysctl_assert_write("0"); @@ -1399,23 +1422,53 @@ static int sysctl_nested_child(void *arg) test_sysctl_sysctl2_failset); join_thread(pid); =20 + sem =3D semget(SEM_KEY, 1, IPC_CREAT | 0600); + if (sem < 0) { + perror("semget:"); + return 1; + } + semun.val =3D 1; + sembuf.sem_op =3D -1; + sembuf.sem_flg =3D 0; + sembuf.sem_num =3D 0; + /* Verify that the rules are actually inherited after fork. */ printf("%s nested sysctl 0 -> 1 after fork\n", memfd_str); sysctl_assert_write("0"); =20 + if (semctl(sem, 0, SETVAL, semun) < 0) { + perror("semctl:"); + return 1; + } + pid =3D spawn_thread(CLONE_NEWPID, sysctl_nested_wait, test_sysctl_sysctl1_failset); sysctl_assert_write("1"); - kill(pid, SIGCONT); + + /* Allow child to continue */ + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + return 1; + } join_thread(pid); =20 printf("%s nested sysctl 0 -> 2 after fork\n", memfd_str); sysctl_assert_write("0"); =20 + if (semctl(sem, 0, SETVAL, semun) < 0) { + perror("semctl:"); + return 1; + } + pid =3D spawn_thread(CLONE_NEWPID, sysctl_nested_wait, test_sysctl_sysctl2_failset); sysctl_assert_write("2"); - kill(pid, SIGCONT); + + /* Allow child to continue */ + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + return 1; + } join_thread(pid); =20 /* @@ -1425,28 +1478,62 @@ static int sysctl_nested_child(void *arg) */ printf("%s nested sysctl 2 -> 1 after fork\n", memfd_str); sysctl_assert_write("2"); + + if (semctl(sem, 0, SETVAL, semun) < 0) { + perror("semctl:"); + return 1; + } + pid =3D spawn_thread(CLONE_NEWPID, sysctl_nested_wait, test_sysctl_sysctl2); sysctl_assert_write("1"); - kill(pid, SIGCONT); + + /* Allow child to continue */ + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + return 1; + } join_thread(pid); =20 printf("%s nested sysctl 2 -> 0 after fork\n", memfd_str); sysctl_assert_write("2"); + + if (semctl(sem, 0, SETVAL, semun) < 0) { + perror("semctl:"); + return 1; + } + pid =3D spawn_thread(CLONE_NEWPID, sysctl_nested_wait, test_sysctl_sysctl2); sysctl_assert_write("0"); - kill(pid, SIGCONT); + + /* Allow child to continue */ + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + return 1; + } join_thread(pid); =20 printf("%s nested sysctl 1 -> 0 after fork\n", memfd_str); sysctl_assert_write("1"); + + if (semctl(sem, 0, SETVAL, semun) < 0) { + perror("semctl:"); + return 1; + } + pid =3D spawn_thread(CLONE_NEWPID, sysctl_nested_wait, test_sysctl_sysctl1); sysctl_assert_write("0"); - kill(pid, SIGCONT); + /* Allow child to continue */ + if (semop(sem, &sembuf, 1) < 0) { + perror("semop:"); + return 1; + } join_thread(pid); =20 + semctl(sem, 0, IPC_RMID); + return 0; } =20 diff --git a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh b/tools/= testing/selftests/mm/charge_reserved_hugetlb.sh index dc3fc438b3d9..7cf581f4f44f 100755 --- a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh +++ b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh @@ -288,7 +288,7 @@ function run_test() { setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit" =20 mkdir -p /mnt/huge - mount -t hugetlbfs -o pagesize=3D${MB}M,size=3D256M none /mnt/huge + mount -t hugetlbfs -o pagesize=3D${MB}M none /mnt/huge =20 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \ "$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \ @@ -342,7 +342,7 @@ function run_multiple_cgroup_test() { setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit= 2" =20 mkdir -p /mnt/huge - mount -t hugetlbfs -o pagesize=3D${MB}M,size=3D256M none /mnt/huge + mount -t hugetlbfs -o pagesize=3D${MB}M none /mnt/huge =20 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \ "$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \ diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh b/to= ols/testing/selftests/net/forwarding/vxlan_bridge_1d.sh index eb307ca37bfa..002551451a72 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh @@ -559,6 +559,21 @@ vxlan_encapped_ping_do() local inner_tos=3D$1; shift local outer_tos=3D$1; shift =20 + local ipv4hdr=3D$(: + )"45:"$( : IP version + IHL + )"$inner_tos:"$( : IP TOS + )"00:54:"$( : IP total length + )"99:83:"$( : IP identification + )"40:00:"$( : IP flags + frag off + )"40:"$( : IP TTL + )"01:"$( : IP proto + )"CHECKSUM:"$( : IP header csum + )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 + )"c0:00:02:01"$( : IP daddr: 192.0.2.1 + ) + local checksum=3D$(payload_template_calc_checksum "$ipv4hdr") + ipv4hdr=3D$(payload_template_expand_checksum "$ipv4hdr" $checksum) + $MZ $dev -c $count -d 100msec -q \ -b $next_hop_mac -B $dest_ip \ -t udp tos=3D$outer_tos,sp=3D23456,dp=3D$VXPORT,p=3D$(: @@ -569,16 +584,7 @@ vxlan_encapped_ping_do() )"$dest_mac:"$( : ETH daddr )"$(mac_get w2):"$( : ETH saddr )"08:00:"$( : ETH type - )"45:"$( : IP version + IHL - )"$inner_tos:"$( : IP TOS - )"00:54:"$( : IP total length - )"99:83:"$( : IP identification - )"40:00:"$( : IP flags + frag off - )"40:"$( : IP TTL - )"01:"$( : IP proto - )"00:00:"$( : IP header csum - )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 - )"c0:00:02:01:"$( : IP daddr: 192.0.2.1 + )"$ipv4hdr:"$( : IPv4 header )"08:"$( : ICMP type )"00:"$( : ICMP code )"8b:f2:"$( : ICMP csum diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh= b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh index bd3f7d492af2..28284a5aa07a 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh @@ -695,7 +695,7 @@ vxlan_encapped_ping_do() )"6"$( : IP version )"$inner_tos"$( : Traffic class )"0:00:00:"$( : Flow label - )"00:08:"$( : Payload length + )"00:03:"$( : Payload length )"3a:"$( : Next header )"04:"$( : Hop limit )"$saddr:"$( : IP saddr