This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.12.5-rc1
Kuninori Morimoto kuninori.morimoto.gx@renesas.com ASoC: rsnd: check all BUSIF status when error
Christoph Hellwig hch@lst.de nvme: do not try to reconfigure APST when the controller is not live
Arnd Bergmann arnd@arndb.de ext4: fix debug format string warning
Kees Cook keescook@chromium.org debugfs: Make debugfs_allow RO after init
Geert Uytterhoeven geert+renesas@glider.be dt-bindings: PCI: rcar-pci-host: Document missing R-Car H1 support
Zhen Lei thunder.leizhen@huawei.com dt-bindings: serial: 8250: Remove duplicated compatible strings
Dmitry Baryshkov dmitry.baryshkov@linaro.org dt-bindings: phy: qcom,qmp-usb3-dp-phy: move usb3 compatibles back to qcom,qmp-phy.yaml
Geert Uytterhoeven geert+renesas@glider.be arm64: dts: renesas: falcon: Move console config to CPU board DTS
Niklas Söderlund niklas.soderlund+renesas@ragnatech.se dt-bindings: thermal: rcar-gen3-thermal: Support five TSC nodes on r8a779a0
Geert Uytterhoeven geert+renesas@glider.be dt-bindings: media: renesas,vin: Make resets optional on R-Car Gen1
Qii Wang qii.wang@mediatek.com i2c: mediatek: Fix send master code at more than 1MHz
Fabio Estevam festevam@gmail.com media: rkvdec: Remove of_match_ptr()
Enric Balletbo i Serra enric.balletbo@collabora.com soc: mediatek: pm-domains: Add a power domain names for mt8192
Enric Balletbo i Serra enric.balletbo@collabora.com soc: mediatek: pm-domains: Add a power domain names for mt8183
Enric Balletbo i Serra enric.balletbo@collabora.com soc: mediatek: pm-domains: Add a meaningful power domain name
Paweł Chmiel pawel.mikolaj.chmiel@gmail.com clk: exynos7: Mark aclk_fsys1_200 as critical
Stéphane Marchesin marcheu@chromium.org drm/i915: Fix crash in auto_retire
Tvrtko Ursulin tvrtko.ursulin@intel.com drm/i915/overlay: Fix active retire callback alignment
Ville Syrjälä ville.syrjala@linux.intel.com drm/i915: Read C0DRB3/C1DRB3 as 16 bits again
Kuogee Hsieh khsieh@codeaurora.org drm/msm/dp: check sink_count before update is_connected status
Lv Yunlong lyl2019@mail.ustc.edu.cn drm/i915/gt: Fix a double free in gen8_preallocate_top_level_pdp
Greg Kroah-Hartman gregkh@linuxfoundation.org kobject_uevent: remove warning in init_uevent_argv()
Badhri Jagan Sridharan badhri@google.com usb: typec: tcpm: Fix error while calculating PPS out values
Tony Lindgren tony@atomide.com clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940
Tony Lindgren tony@atomide.com clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue
Maciej W. Rozycki macro@orcam.me.uk MIPS: Avoid handcoded DIVU in `__div64_32' altogether
Maciej W. Rozycki macro@orcam.me.uk MIPS: Avoid DIVU in `__div64_32' is result would be zero
Maciej W. Rozycki macro@orcam.me.uk MIPS: Reinstate platform `__div64_32' handler
Matthew Wilcox (Oracle) willy@infradead.org mm: fix struct page layout on 32-bit systems
Sean Christopherson seanjc@google.com KVM: VMX: Disable preemption when probing user return MSRs
Sean Christopherson seanjc@google.com KVM: VMX: Do not advertise RDPID if ENABLE_RDTSCP control is unsupported
Vitaly Kuznetsov vkuznets@redhat.com KVM: nVMX: Always make an attempt to map eVMCS after migration
Sean Christopherson seanjc@google.com KVM: x86: Add support for RDPID without RDTSCP
Sean Christopherson seanjc@google.com KVM: x86: Move RDPID emulation intercept to its own enum
Sean Christopherson seanjc@google.com KVM: x86: Emulate RDPID only if RDTSCP is supported
Juergen Gross jgross@suse.com xen/gntdev: fix gntdev_mmap() error exit path
Alexandre Belloni alexandre.belloni@bootlin.com alarmtimer: Check RTC features instead of ops
Oliver Neukum oneukum@suse.com cdc-wdm: untangle a circular dependency between callback and softint
Colin Ian King colin.king@canonical.com iio: tsl2583: Fix division by a zero lux_val
Dmitry Osipenko digetx@gmail.com iio: gyro: mpu3050: Fix reported temperature value
Tomasz Duszynski tomasz.duszynski@octakon.com iio: core: fix ioctl handlers removal
Sandeep Singh sandeep.singh@amd.com xhci: Add reset resume quirk for AMD xhci controller.
Christophe JAILLET christophe.jaillet@wanadoo.fr xhci: Do not use GFP_KERNEL in (potentially) atomic context
Mathias Nyman mathias.nyman@linux.intel.com xhci: Fix giving back cancelled URBs even if halted endpoint can't reset
Abhijeet Rao abhijeet.rao@intel.com xhci-pci: Allow host runtime PM as default for Intel Alder Lake xHCI
Andy Shevchenko andy.shevchenko@gmail.com usb: typec: ucsi: Put fwnode in any case during ->probe()
Jack Pham jackp@codeaurora.org usb: typec: ucsi: Retrieve all the PDOs instead of just the first 4
Kyle Tso kyletso@google.com usb: typec: tcpm: Fix wrong handling in GET_SINK_CAP
Wesley Cheng wcheng@codeaurora.org usb: dwc3: gadget: Return success always for kick transfer in ep queue
Jack Pham jackp@codeaurora.org usb: dwc3: gadget: Enable suspend events
Zhen Lei thunder.leizhen@huawei.com usb: dwc3: imx8mp: fix error return code in dwc3_imx8mp_probe()
Chunfeng Yun chunfeng.yun@mediatek.com usb: core: hub: fix race condition about TRSMRCY of resume
Phil Elwell phil@raspberrypi.com usb: dwc2: Fix gadget DMA unmap direction
Maximilian Luz luzmaximilian@gmail.com usb: xhci: Increase timeout for HC halt
Ferry Toth ftoth@exalondelft.nl usb: dwc3: pci: Enable usb2-gadget-lpm-disable for Intel Merrifield
Marcel Hamer marcel@solidxs.se usb: dwc3: omap: improve extcon initialization
Bart Van Assche bvanassche@acm.org blk-mq: Swap two calls in blk_mq_exit_queue()
Ming Lei ming.lei@redhat.com blk-mq: plug request for shared sbitmap
Nicholas Piggin npiggin@gmail.com powerpc/64s: Make NMI record implicitly soft-masked code as irqs disabled
Sun Ke sunke32@huawei.com nbd: Fix NULL pointer in flush_workqueue
Gautham R. Shenoy ego@linux.vnet.ibm.com sched/fair: Fix clearing of has_idle_cores flag in select_idle_cpu()
Chao Yu chao@kernel.org f2fs: compress: fix to assign cc.cluster_idx correctly
Chao Yu chao@kernel.org f2fs: compress: fix race condition of overwrite vs truncate
Chao Yu chao@kernel.org f2fs: compress: fix to free compress page correctly
Michal Kalderon michal.kalderon@marvell.com nvmet-rdma: Fix NULL deref when SEND is completed with error
Chaitanya Kulkarni chaitanya.kulkarni@wdc.com nvmet: fix inline bio check for passthru
Chaitanya Kulkarni chaitanya.kulkarni@wdc.com nvmet: fix inline bio check for bdev-ns
Omar Sandoval osandov@fb.com kyber: fix out of bounds access when preempted
Christophe JAILLET christophe.jaillet@wanadoo.fr ACPI: scan: Fix a memory leak in an error handling path
Andy Shevchenko andy.shevchenko@gmail.com hwmon: (ltc2992) Put fwnode in error case during ->probe()
Christophe JAILLET christophe.jaillet@wanadoo.fr usb: musb: Fix an error message
Kyle Tso kyletso@google.com usb: typec: tcpm: Fix wrong handling for Not_Supported in VDM AMS
Eddie James eajames@linux.ibm.com hwmon: (occ) Fix poll rate limiting
Christophe JAILLET christophe.jaillet@wanadoo.fr usb: fotg210-hcd: Fix an error message
Alexandru Ardelean aardelean@deviqon.com iio: core: return ENODEV if ioctl is unknown
Alexandru Ardelean aardelean@deviqon.com iio: hid-sensors: select IIO_TRIGGERED_BUFFER under HID_SENSOR_IIO_TRIGGER
Dinghao Liu dinghao.liu@zju.edu.cn iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
Dinghao Liu dinghao.liu@zju.edu.cn iio: light: gp2ap002: Fix rumtime PM imbalance on error
Jack Pham jackp@codeaurora.org usb: dwc3: gadget: Free gadget structure only after freeing endpoints
Jiri Olsa jolsa@kernel.org perf tools: Fix dynamic libbpf link
Zhen Lei thunder.leizhen@huawei.com xen/unpopulated-alloc: fix error return code in fill_list()
Vivek Goyal vgoyal@redhat.com dax: Wake up all waiters after invalidating dax entry
Vivek Goyal vgoyal@redhat.com dax: Add a wakeup mode parameter to put_unlocked_entry()
Vivek Goyal vgoyal@redhat.com dax: Add an enum for specifying dax wakup mode
Tom Lendacky thomas.lendacky@amd.com KVM: SVM: Move GHCB unmapping to fix RCU warning
Thomas Gleixner tglx@linutronix.de KVM: x86: Prevent deadlock against tk_core.seq
Thomas Gleixner tglx@linutronix.de KVM: x86: Cancel pvclock_gtod_work on module removal
Kuogee Hsieh khsieh@codeaurora.org drm/msm/dp: initialize audio_comp when audio starts
Wanpeng Li wanpengli@tencent.com KVM: LAPIC: Accurately guarantee busy wait for timer to expire when using hv_timer
Jonathan Marek jonathan@marek.ca drm/msm: fix LLC not being enabled for mmu500 targets
Benjamin Segall bsegall@google.com kvm: exit halt polling on need_resched() as well
Kai-Heng Feng kai.heng.feng@canonical.com drm/i915/dp: Use slow and wide link training for everything
Ville Syrjälä ville.syrjala@linux.intel.com drm/i915: Avoid div-by-zero on gen2
David Ward david.ward@gatech.edu drm/amd/display: Initialize attribute for hdcp_srm sysfs file
Kai-Heng Feng kai.heng.feng@canonical.com drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors are connected
Naohiro Aota naohiro.aota@wdc.com btrfs: zoned: sanity check zone type
Tom Rix trix@redhat.com btrfs: initialize return variable in cleanup_free_space_cache_v1
Filipe Manana fdmanana@suse.com btrfs: fix race leading to unpersisted data and metadata on fsync
Filipe Manana fdmanana@suse.com btrfs: zoned: fix silent data loss after failure splitting ordered extent
Filipe Manana fdmanana@suse.com btrfs: fix deadlock when cloning inline extents and using qgroups
Catalin Marinas catalin.marinas@arm.com arm64: Fix race condition on PG_dcache_clean in __sync_icache_dcache()
Peter Collingbourne pcc@google.com arm64: mte: initialize RGSR_EL1.SEED in __cpu_setup
Huang Rui ray.huang@amd.com x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations
Tejun Heo tj@kernel.org blk-iocost: fix weight updates of inner active iocgs
Peter Xu peterx@redhat.com mm/hugetlb: fix cow where page writtable in child
Peter Xu peterx@redhat.com mm/hugetlb: fix F_SEAL_FUTURE_WRITE
Peter Collingbourne pcc@google.com kasan: fix unit tests with CONFIG_UBSAN_LOCAL_BOUNDS enabled
Axel Rasmussen axelrasmussen@google.com userfaultfd: release page in error path to avoid BUG_ON
Phillip Lougher phillip@squashfs.org.uk squashfs: fix divide error in calculate_skip()
Jouni Roivas jouni.roivas@tuxera.com hfsplus: prevent corruption in shrinking truncate
Michael Ellerman mpe@ellerman.id.au powerpc/64s: Fix crashes when toggling entry flush barrier
Michael Ellerman mpe@ellerman.id.au powerpc/64s: Fix crashes when toggling stf barrier
Eric Dumazet edumazet@google.com sh: Remove unused variable
Vladimir Isaev isaev@synopsys.com ARC: mm: Use max_high_pfn as a HIGHMEM zone border
Vladimir Isaev isaev@synopsys.com ARC: mm: PAE: use 40-bit physical page mask
Vineet Gupta vgupta@synopsys.com ARC: entry: fix off-by-one error in syscall number validation
Paolo Abeni pabeni@redhat.com mptcp: fix splat when closing unaccepted socket
Arkadiusz Kubalewski arkadiusz.kubalewski@intel.com i40e: Remove LLDP frame filters
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Fix PHY type identifiers for 2.5G and 5G adapters
Jaroslaw Gawin jaroslawx.gawin@intel.com i40e: fix the restart auto-negotiation after FEC modified
Yunjian Wang wangyunjian@huawei.com i40e: Fix use-after-free in i40e_client_subtask()
Magnus Karlsson magnus.karlsson@intel.com i40e: fix broken XDP support
Eric Dumazet edumazet@google.com netfilter: nftables: avoid overflows in nft_hash_buckets()
David Hildenbrand david@redhat.com kernel/resource: make walk_mem_res() find all busy IORESOURCE_MEM resources
David Hildenbrand david@redhat.com kernel/resource: make walk_system_ram_res() find all busy IORESOURCE_SYSTEM_RAM resources
Jia-Ju Bai baijiaju1990@gmail.com kernel: kexec_file: fix error return code of kexec_calculate_store_digests()
Colin Ian King colin.king@canonical.com fs/proc/generic.c: fix incorrect pde_is_permanent check
Alex Elder elder@linaro.org net: ipa: fix inter-EE IRQ register definitions
Odin Ugedal odin@uged.al sched/fair: Fix unfairness caused by missing load decay
Quentin Perret qperret@google.com sched: Fix out-of-bound access in uclamp
Marc Kleine-Budde mkl@pengutronix.de can: m_can: m_can_tx_work_queue(): fix tx_skb race condition
Frieder Schrempf frieder.schrempf@kontron.de can: mcp251x: fix resume from sleep before interface was brought up
Marc Kleine-Budde mkl@pengutronix.de can: mcp251xfd: mcp251xfd_probe(): add missing can_rx_offload_del() in error path
Dan Carpenter dan.carpenter@oracle.com can: mcp251xfd: mcp251xfd_probe(): fix an error pointer dereference in probe
Pablo Neira Ayuso pablo@netfilter.org netfilter: nftables: Fix a memleak from userdata error path in new objects
Pablo Neira Ayuso pablo@netfilter.org netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL check
Cong Wang cong.wang@bytedance.com smc: disallow TCP_ULP in smc_setsockopt()
Maciej Żenczykowski maze@google.com net: fix nla_strcmp to handle more then one trailing null character
Fernando Fernandez Mancera ffmancera@riseup.net ethtool: fix missing NLM_F_MULTI flag when dumping
Marco Elver elver@google.com kfence: await for allocation using wait_event
Pavel Tatashin pasha.tatashin@soleen.com mm/gup: check for isolation errors
Pavel Tatashin pasha.tatashin@soleen.com mm/gup: return an error on migration failure
Pavel Tatashin pasha.tatashin@soleen.com mm/gup: check every subpage of a compound page during isolation
Miaohe Lin linmiaohe@huawei.com ksm: fix potential missing rmap_item for stable_node
Miaohe Lin linmiaohe@huawei.com mm/migrate.c: fix potential indeterminate pte entry in migrate_vma_insert_page()
Miaohe Lin linmiaohe@huawei.com mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts()
Miaohe Lin linmiaohe@huawei.com khugepaged: fix wrong result value for trace_mm_collapse_huge_page_isolate()
Sasha Levin sashal@kernel.org arm64: entry: always set GIC_PRIO_PSR_I_SET during entry
Marc Zyngier maz@kernel.org arm64: entry: factor irq triage logic into macros
Kees Cook keescook@chromium.org drm/radeon: Avoid power table parsing memory leaks
Kees Cook keescook@chromium.org drm/radeon: Fix off-by-one power_state index heap overwrite
Ramesh Babu B ramesh.babu.b@intel.com net: stmmac: Clear receive all(RA) bit when promiscuous mode is off
Sandipan Das sandipan@linux.ibm.com powerpc/powernv/memtrace: Fix dcache flushing
Xuan Zhuo xuanzhuo@linux.alibaba.com xsk: Fix for xp_aligned_validate_desc() when len == chunk_size
Pablo Neira Ayuso pablo@netfilter.org netfilter: xt_SECMARK: add new revision to fix structure layout
Xin Long lucien.xin@gmail.com sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b
Lv Yunlong lyl2019@mail.ustc.edu.cn ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
Jim Quinlan jim2101024@gmail.com PCI: brcmstb: Use reset/rearm instead of deassert/assert
Jim Quinlan jim2101024@gmail.com ata: ahci_brcm: Fix use of BCM7216 reset controller
Md Haris Iqbal haris.iqbal@cloud.ionos.com block/rnbd-clt: Check the return value of the function rtrs_clt_query
Md Haris Iqbal haris.iqbal@cloud.ionos.com block/rnbd-clt: Change queue_depth type in rnbd_clt_session to size_t
Brendan Jackman jackmanb@google.com libbpf: Fix signed overflow in ringbuf_process_ring
Baptiste Lepers baptiste.lepers@gmail.com sunrpc: Fix misplaced barrier in call_decode
Anup Patel anup.patel@wdc.com RISC-V: Fix error code returned by riscv_hartid_to_cpuid()
Xin Long lucien.xin@gmail.com sctp: do asoc update earlier in sctp_sf_do_dupcook_a
Yufeng Mo moyufeng@huawei.com net: hns3: disable phy loopback setting in hclge_mac_start_phy
Peng Li lipeng321@huawei.com net: hns3: use netif_tx_disable to stop the transmit queue
Hao Chen chenhao288@hisilicon.com net: hns3: fix for vxlan gpe tx checksum bug
Mark Rutland mark.rutland@arm.com arm64: stacktrace: restore terminal records
Jian Shen shenjian15@huawei.com net: hns3: add check for HNS3_NIC_STATE_INITED in hns3_reset_notify_up_enet()
Yufeng Mo moyufeng@huawei.com net: hns3: initialize the message content in hclge_get_link_mode()
Yufeng Mo moyufeng@huawei.com net: hns3: fix incorrect configuration for igu_egu_hw_err
Nobuhiro Iwamatsu nobuhiro1.iwamatsu@toshiba.co.jp rtc: ds1307: Fix wday settings for rx8130
Can Guo cang@codeaurora.org scsi: ufs: core: Narrow down fast path in system suspend path
Can Guo cang@codeaurora.org scsi: ufs: core: Cancel rpm_dev_flush_recheck_work during system suspend
Can Guo cang@codeaurora.org scsi: ufs: core: Do not put UFS power into LPM if link is broken
Anastasia Kovaleva a.kovaleva@yadro.com scsi: qla2xxx: Prevent PRLI in target mode
Jeff Layton jlayton@kernel.org ceph: fix inode leak on getattr error in __fh_to_dentry
Claire Chang tientzu@chromium.org swiotlb: Fix the type of index
Nathan Chancellor nathan@kernel.org riscv: Select HAVE_DYNAMIC_FTRACE when -fpatchable-function-entry is available
Chuck Lever chuck.lever@oracle.com xprtrdma: rpcrdma_mr_pop() already does list_del_init()
Chuck Lever chuck.lever@oracle.com xprtrdma: Fix cwnd update ordering
Chuck Lever chuck.lever@oracle.com xprtrdma: Avoid Receive Queue wrapping
Uwe Kleine-König u.kleine-koenig@pengutronix.de pwm: atmel: Fix duty cycle calculation in .get_state()
Yunjian Wang wangyunjian@huawei.com SUNRPC: Fix null pointer dereference in svc_rqst_free()
Dan Carpenter dan.carpenter@oracle.com SUNRPC: fix ternary sign expansion bug in tracing
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix cdev setup and free device lifetime issues
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix group conf_dev lifetime
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix engine conf_dev lifetime
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix wq conf_dev 'struct device' lifetime
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix idxd conf_dev 'struct device' lifetime
Dave Jiang dave.jiang@intel.com dmaengine: idxd: use ida for device instance enumeration
Dave Jiang dave.jiang@intel.com dmaengine: idxd: removal of pcim managed mmio mapping
Dave Jiang dave.jiang@intel.com dmaengine: idxd: cleanup pci interrupt vector allocation management
Dave Jiang dave.jiang@intel.com dmaengine: idxd: fix dma device lifetime
Colin Ian King colin.king@canonical.com dmaengine: idxd: Fix potential null dereference on pointer status
Michael Walle michael@walle.cc rtc: fsl-ftm-alarm: add MODULE_TABLE()
J. Bruce Fields bfields@redhat.com nfsd: ensure new clients break delegations
Trond Myklebust trond.myklebust@hammerspace.com NFSv4.x: Don't return NFS4ERR_NOMATCHING_LAYOUT if we're unmounting
Guangqing Zhu zhuguangqing83@gmail.com thermal/drivers/tsens: Fix missing put_device error
Trond Myklebust trond.myklebust@hammerspace.com NFSv42: Copy offload should update the file size when appropriate
Chris Dion Christopher.Dion@dell.com SUNRPC: Handle major timeout in xprt_adjust_timeout()
Chuck Lever chuck.lever@oracle.com SUNRPC: Remove trace_xprt_transmit_queued
Chuck Lever chuck.lever@oracle.com SUNRPC: Move fault injection call sites
Olga Kornievskaia kolga@netapp.com NFSv4.2 fix handling of sr_eof in SEEK's reply
Nikola Livic nlivic@gmail.com pNFS/flexfiles: fix incorrect size check in decode_nfs_fh()
Suman Anna s-anna@ti.com remoteproc: pru: Fix and cleanup firmware interrupt mapping logic
Suman Anna s-anna@ti.com remoteproc: pru: Fix wrong success return value for fw events
Suman Anna s-anna@ti.com remoteproc: pru: Fixup interrupt-parent logic for fw events
Yang Yingliang yangyingliang@huawei.com PCI: endpoint: Fix missing destroy_workqueue()
Trond Myklebust trond.myklebust@hammerspace.com NFS: Deal correctly with attribute generation counter overflow
Trond Myklebust trond.myklebust@hammerspace.com NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
Trond Myklebust trond.myklebust@hammerspace.com NFS: Fix attribute bitmask in _nfs42_proc_fallocate()
Trond Myklebust trond.myklebust@hammerspace.com NFS: nfs4_bitmask_adjust() must not change the server global bitmasks
Jia-Ju Bai baijiaju1990@gmail.com rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
Chao Yu chao@kernel.org f2fs: fix to avoid accessing invalid fio in f2fs_allocate_data_block()
Trond Myklebust trond.myklebust@hammerspace.com NFS: Only change the cookie verifier if the directory page cache is empty
Trond Myklebust trond.myklebust@hammerspace.com NFS: Fix handling of cookie verifier in uncached_readdir()
Nagendra S Tomar natomar@microsoft.com nfs: Subsequent READDIR calls should carry non-zero cookieverifier
Yi Zhuang zhuangyi1@huawei.com f2fs: Fix a hungtask problem in atomic write
Chao Yu chao@kernel.org f2fs: fix to restrict mount condition on readonly block device
Yang Yingliang yangyingliang@huawei.com fs: 9p: fix v9fs_file_open writeback fid error check
Chao Yu chao@kernel.org f2fs: fix to cover __allocate_new_section() with curseg_lock
Chao Yu chao@kernel.org f2fs: fix to avoid touching checkpointed data in get_victim()
Shradha Todi shradha.t@samsung.com PCI: endpoint: Fix NULL pointer dereference for ->get_features()
Chao Yu chao@kernel.org f2fs: fix to update last i_size if fallocate partially succeeds
Chao Yu chao@kernel.org f2fs: fix to align to section for fallocate() on pinned file
Zhen Lei thunder.leizhen@huawei.com ARM: 9064/1: hw_breakpoint: Do not directly check the event's overflow_handler hook
Dmitry Baryshkov dmitry.baryshkov@linaro.org PCI: Release OF node in pci_scan_device()'s error path
Wei Yongjun weiyongjun1@huawei.com PCI: brcmstb: Fix error return code in brcm_pcie_probe()
Pali Rohár pali@kernel.org PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc()
Bjorn Andersson bjorn.andersson@linaro.org remoteproc: qcom_q6v5_mss: Validate p_filesz in ELF loader
Arnd Bergmann arnd@arndb.de rtc: tps65910: include linux/property.h
Colin Ian King colin.king@canonical.com f2fs: fix a redundant call to f2fs_balance_fs if an error occurs
Chao Yu chao@kernel.org f2fs: fix panic during f2fs_resize_fs()
Chao Yu chao@kernel.org f2fs: fix to allow migrating fully valid segment
Qiuxu Zhuo qiuxu.zhuo@intel.com PCI/RCEC: Fix RCiEP device to RCEC association
Jia-Ju Bai baijiaju1990@gmail.com thermal: thermal_of: Fix error return code of thermal_of_populate_bind_params()
Arnd Bergmann arnd@arndb.de leds: lgm: fix gpiolib dependency
David Ward david.ward@gatech.edu ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
Petr Mladek pmladek@suse.com watchdog: cleanup handling of false positives
Petr Mladek pmladek@suse.com watchdog: fix barriers when printing backtraces from all CPUs
Petr Mladek pmladek@suse.com watchdog/softlockup: remove logic that tried to prevent repeated reports
Petr Mladek pmladek@suse.com watchdog/softlockup: report the overall time of softlockups
Petr Mladek pmladek@suse.com watchdog: explicitly update timestamp when reporting softlockup
Petr Mladek pmladek@suse.com watchdog: rename __touch_watchdog() to a better descriptive name
Sergei Trofimovich slyfox@gentoo.org ia64: module: fix symbolizer crash on fdescr
Michael Chan michael.chan@broadcom.com bnxt_en: Add PCI IDs for Hyper-V VF devices.
Masahiro Yamada masahiroy@kernel.org kbuild: generate Module.symvers only when vmlinux exists
Petr Machata petrm@nvidia.com selftests: mlxsw: Fix mausezahn invocation in ERSPAN scale test
Petr Machata petrm@nvidia.com selftests: mlxsw: Increase the tolerance of backlog buildup
Felix Fietkau nbd@nbd.name net: ethernet: mtk_eth_soc: fix RX VLAN offload
Stefan Assmann sassmann@kpanic.de iavf: remove duplicate free resources calls
Alexey Kardashevskiy aik@ozlabs.ru powerpc/iommu: Annotate nested lock for lockdep
Lee Gibson leegib@gmail.com qtnfmac: Fix possible buffer overflow in qtnf_event_handle_external_auth
Gustavo A. R. Silva gustavoars@kernel.org wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join
Gustavo A. R. Silva gustavoars@kernel.org wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
Sean Christopherson seanjc@google.com crypto: ccp: Free SEV device if SEV init fails
Felix Fietkau nbd@nbd.name mt76: mt7615: fix entering driver-own state on mt7663
Jinzhou Su Jinzhou.Su@amd.com drm/amdgpu: Add mem sync flag for IB allocated by SA
Dingchen (David) Zhang dingchen.zhang@amd.com drm/amd/display: add handling for hdcp2 rx id list validation
Robin Singh robin.singh@amd.com drm/amd/display: fixed divide by zero kernel crash during dsc enablement
Michael Ellerman mpe@ellerman.id.au powerpc/pseries: Stop calling printk in rtas_stop_self()
Yaqi Chen chendotjs@gmail.com samples/bpf: Fix broken tracex1 due to kprobe argument change
Du Cheng ducheng2@gmail.com net: sched: tapr: prevent cycle_time == 0 in parse_taprio_schedule
Gustavo A. R. Silva gustavoars@kernel.org ethtool: ioctl: Fix out-of-bounds warning in store_link_ksettings_for_user()
David Ward david.ward@gatech.edu ASoC: rt286: Generalize support for ALC3263 codec
Emmanuel Grumbach emmanuel.grumbach@intel.com mac80211: properly drop the connection in case of invalid CSA IE
David Mosberger-Tang davidm@egauge.net wilc1000: Bring MAC address setting in line with typical Linux behavior
Srikar Dronamraju srikar@linux.vnet.ibm.com powerpc/smp: Set numa node before updating mask
Cédric Le Goater clg@kaod.org powerpc/xive: Use the "ibm, chip-id" property only under PowerNV
Gustavo A. R. Silva gustavoars@kernel.org flow_dissector: Fix out-of-bounds warning in __skb_flow_bpf_to_target()
Gustavo A. R. Silva gustavoars@kernel.org sctp: Fix out-of-bounds warning in sctp_process_asconf_param()
Jarkko Nikula jarkko.nikula@linux.intel.com i2c: i801: Add support for Intel Alder Lake PCH-M
Kai Vehmanen kai.vehmanen@linux.intel.com ALSA: hda/hdmi: fix race in handling acomp ELD notification at resume
Vamshi Krishna Gopal vamshi.krishna.gopal@intel.com ASoC: Intel: sof_sdw: add quirk for new ADL-P Rvp
Takashi Iwai tiwai@suse.de ALSA: hda/realtek: Add quirk for Lenovo Ideapad S740
Mihai Moldovan ionic@ionic.de kconfig: nconf: stop endless search loops
Yonghong Song yhs@fb.com selftests: Set CC to clang in lib.mk if LLVM is set
Anthony Wang anthony1.wang@amd.com drm/amd/display: Force vsync flip when reconfiguring MPCC
Suravee Suthikulpanit suravee.suthikulpanit@amd.com iommu/amd: Remove performance counter pre-initialization test
Paul Menzel pmenzel@molgen.mpg.de Revert "iommu/amd: Fix performance counter initialization"
Florian Fainelli f.fainelli@gmail.com net: bridge: propagate error code and extack from br_mc_disabled_update
Kuninori Morimoto kuninori.morimoto.gx@renesas.com ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init()
Vaibhav Jain vaibhav@linux.ibm.com powerpc/mm: Add cond_resched() while removing hpte mappings
Johannes Berg johannes.berg@intel.com iwlwifi: trans/pcie: defer transport initialisation
Mordechay Goodstein mordechay.goodstein@intel.com iwlwifi: queue: avoid memory leak in reset flow
Johannes Berg johannes.berg@intel.com iwlwifi: pcie: make cfg vs. trans_cfg more robust
Miklos Szeredi mszeredi@redhat.com cuse: prevent clone
Miklos Szeredi mszeredi@redhat.com virtiofs: fix userns
Vivek Goyal vgoyal@redhat.com fuse: invalidate attrs when page writeback completes
Ye Weihua yeweihua4@huawei.com i2c: imx: Fix PM reference leak in i2c_imx_reg_slave()
Ryder Lee ryder.lee@mediatek.com mt76: mt7915: add wifi subsystem reset
Lorenzo Bianconi lorenzo@kernel.org mt76: mt7921: fix key set/delete issue
Shayne Chen shayne.chen@mediatek.com mt76: mt7915: fix txpower init for TSSI off chips
Felix Fietkau nbd@nbd.name mt76: mt7915: fix key set/delete issue
Lorenzo Bianconi lorenzo@kernel.org mt76: mt7915: always check return value from mt7915_mcu_alloc_wtbl_req
Lorenzo Bianconi lorenzo@kernel.org mt76: connac: always check return value from mt76_connac_mcu_alloc_wtbl_req
David Bauer mail@david-bauer.net mt76: mt76x0: disable GTK offloading
Sander Vanheule sander@svanheule.net mt76: mt7615: support loading EEPROM for MT7613BE
Felix Fietkau nbd@nbd.name mt76: mt7615: fix key set/delete issues
Po-Hao Huang phhuang@realtek.com rtw88: 8822c: add LC calibration for RTL8822C
Krzysztof Kozlowski krzysztof.kozlowski@canonical.com pinctrl: samsung: use 'int' for register masks in Exynos
Heiner Kallweit hkallweit1@gmail.com net: fec: use mac-managed PHY PM
Heiner Kallweit hkallweit1@gmail.com net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM
Gyeongtaek Lee gt82.lee@samsung.com ASoC: soc-compress: lock pcm_mutex to resolve lockdep error
Emmanuel Grumbach emmanuel.grumbach@intel.com mac80211: clear the beacon's CRC after channel switch
Johan Almbladh johan.almbladh@anyfinetworks.com mac80211: Set priority and queue mapping for injected frames
Mike Marciniszyn mike.marciniszyn@cornelisnetworks.com IB/hfi1: Correct oversized ring allocation
Suzuki K Poulose suzuki.poulose@arm.com coresight: Do not scan for graph if none is present
Tiezhu Yang yangtiezhu@loongson.cn MIPS: Loongson64: Use _CACHE_UNCACHED instead of _CACHE_UNCACHED_ACCELERATED
Daniel Winkler danielwinkler@google.com Bluetooth: Do not set cur_adv_instance in adv param MGMT request
Bence Csókás bence98@sch.bme.hu i2c: Add I2C_AQ_NO_REP_START adapter quirk
Matthieu Baerts matthieu.baerts@tessares.net selftests: mptcp: launch mptcp_connect with timeout
Hans de Goede hdegoede@redhat.com ASoC: rt5670: Add a quirk for the Dell Venue 10 Pro 5055
mark-yw.chen mark-yw.chen@mediatek.com Bluetooth: btusb: Enable quirk boolean flag for Mediatek Chip.
Paul M Stillwell Jr paul.m.stillwell.jr@intel.com ice: handle increasing Tx or Rx ring sizes
Hans de Goede hdegoede@redhat.com ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet
Xiang Chen chenxiang66@hisilicon.com iommu/arm-smmu-v3: Add a check to avoid invalid iotlb sync
Marc Kleine-Budde mkl@pengutronix.de can: dev: can_free_echo_skb(): don't crash the kernel if can_priv::echo_skb is accessed out of bounds
Eric Dumazet edumazet@google.com ip6_vti: proper dev_{hold|put} in ndo_[un]init methods
Yunsheng Lin linyunsheng@huawei.com net: hns3: add handling for xmit skb with recursive fraglist
Guangbin Huang huangguangbin2@huawei.com net: hns3: remediate a potential overflow risk of bd_num_list
Christophe Leroy christophe.leroy@csgroup.eu powerpc/32: Statically initialise first emergency context
Kai Vehmanen kai.vehmanen@linux.intel.com ALSA: hda/hdmi: fix max DP-MST dev_num for Intel TGL+ platforms
Russell Currey ruscur@russell.cc selftests/powerpc: Fix L1D flushing tests for Power10
Archie Pusaka apusaka@chromium.org Bluetooth: check for zapped sk before connecting
Nikolay Aleksandrov nikolay@nvidia.com net: bridge: when suppression is enabled exclude RARP packets
Vladimir Oltean vladimir.oltean@nxp.com net/sched: cls_flower: use ntohs for struct flow_dissector_key_ports
Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp Bluetooth: initialize skb_queue_head at l2cap_chan_create()
Archie Pusaka apusaka@chromium.org Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default
Takashi Sakamoto o-takashi@sakamocchi.jp ALSA: bebob: enable to deliver MIDI messages for multiple ports
Tong Zhang ztong0001@gmail.com ALSA: rme9652: don't disable if not enabled
Tong Zhang ztong0001@gmail.com ALSA: hdspm: don't disable if not enabled
Tong Zhang ztong0001@gmail.com ALSA: hdsp: don't disable if not enabled
Wolfram Sang wsa+renesas@sang-engineering.com i2c: bail out early when RDWR parameters are wrong
Ayush Garg ayush.garg@samsung.com Bluetooth: Fix incorrect status handling in LE PHY UPDATE event
Mikhail Durnev mikhail_durnev@mentor.com ASoC: rsnd: core: Check convert rate in rsnd_hw_params
Jonathan McDowell noodles@earth.li net: stmmac: Set FIFO sizes for ipq806x
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: Use net_prefetchw instead of prefetchw in MPWQE TX datapath
Hans de Goede hdegoede@redhat.com ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF
Hoang Le hoang.h.le@dektech.com.au tipc: convert dest node's address to network order
Alexander Aring aahringo@redhat.com fs: dlm: add shutdown hook
Alexander Aring aahringo@redhat.com fs: dlm: flush swork on shutdown
Alexander Aring aahringo@redhat.com fs: dlm: check on minimum msglen size
Alexander Aring aahringo@redhat.com fs: dlm: change allocation limits
Alexander Aring aahringo@redhat.com fs: dlm: add check if dlm is currently running
Alexander Aring aahringo@redhat.com fs: dlm: add errno handling to check callback
Alexander Aring aahringo@redhat.com fs: dlm: fix mark setting deadlock
Alexander Aring aahringo@redhat.com fs: dlm: fix debugfs dump
Nicolas MURE nicolas.mure2019@gmail.com ALSA: usb-audio: Add Pioneer DJM-850 to quirks-table
Pradeep Kumar Chitrapu pradeepc@codeaurora.org ath11k: fix thermal temperature read
David Matlack dmatlack@google.com kvm: Cap halt polling at kvm->max_halt_poll_ns
Rafael J. Wysocki rafael.j.wysocki@intel.com cpufreq: intel_pstate: Use HWP if enabled by platform firmware
Tony Lindgren tony@atomide.com PM: runtime: Fix unpaired parent child_count for force_resume
Sumeet Pawnikar sumeet.r.pawnikar@intel.com ACPI: PM: Add ACPI ID of Alder Lake Fan
Lai Jiangshan laijs@linux.alibaba.com KVM/VMX: Invoke NMI non-IST entry instead of IST entry
Tom Lendacky thomas.lendacky@amd.com KVM: SVM: Make sure GHCB is mapped before updating
Anand Jain anand.jain@oracle.com btrfs: fix unmountable seed device after fstrim
Jarkko Sakkinen jarkko@kernel.org tpm, tpm_tis: Reserve locality in tpm_tis_resume()
Jarkko Sakkinen jarkko@kernel.org tpm, tpm_tis: Extend locality handling to TPM2 in tpm_tis_gen_interrupt()
Zhen Lei thunder.leizhen@huawei.com tpm: fix error return code in tpm2_get_cc_attrs_tbl()
Colin Ian King colin.king@canonical.com KEYS: trusted: Fix memory leak on object td
-------------
Diffstat:
.gitignore | 1 + .../devicetree/bindings/media/renesas,vin.yaml | 46 +- .../devicetree/bindings/pci/rcar-pci-host.yaml | 12 +- .../devicetree/bindings/phy/qcom,qmp-phy.yaml | 2 + .../bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 2 - Documentation/devicetree/bindings/serial/8250.yaml | 5 - .../bindings/thermal/rcar-gen3-thermal.yaml | 43 +- Documentation/dontdiff | 1 + Makefile | 6 +- arch/arc/include/asm/page.h | 12 + arch/arc/include/asm/pgtable.h | 12 +- arch/arc/include/uapi/asm/page.h | 1 - arch/arc/kernel/entry.S | 4 +- arch/arc/mm/init.c | 11 +- arch/arc/mm/ioremap.c | 5 +- arch/arc/mm/tlb.c | 2 +- arch/arm/boot/dts/dra7-l4.dtsi | 4 +- arch/arm/boot/dts/dra7.dtsi | 20 + arch/arm/kernel/hw_breakpoint.c | 2 +- .../boot/dts/renesas/r8a779a0-falcon-cpu.dtsi | 8 + arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts | 5 - arch/arm64/include/asm/daifflags.h | 3 + arch/arm64/kernel/entry-common.c | 17 - arch/arm64/kernel/entry.S | 91 ++-- arch/arm64/kernel/stacktrace.c | 10 +- arch/arm64/mm/flush.c | 4 +- arch/arm64/mm/proc.S | 12 + arch/ia64/include/asm/module.h | 6 +- arch/ia64/kernel/module.c | 29 +- arch/mips/include/asm/div64.h | 55 ++- arch/mips/kernel/cpu-probe.c | 3 - arch/powerpc/include/asm/interrupt.h | 7 + arch/powerpc/kernel/head_32.h | 6 +- arch/powerpc/kernel/iommu.c | 4 +- arch/powerpc/kernel/setup_32.c | 2 +- arch/powerpc/kernel/smp.c | 6 +- arch/powerpc/lib/feature-fixups.c | 35 +- arch/powerpc/mm/book3s64/hash_utils.c | 13 +- arch/powerpc/platforms/powernv/memtrace.c | 4 +- arch/powerpc/platforms/pseries/hotplug-cpu.c | 3 - arch/powerpc/sysdev/xive/common.c | 9 +- arch/powerpc/sysdev/xive/native.c | 6 + arch/powerpc/sysdev/xive/xive-internal.h | 1 + arch/riscv/Kconfig | 2 +- arch/riscv/kernel/smp.c | 2 +- arch/sh/kernel/traps.c | 1 - arch/x86/include/asm/idtentry.h | 15 + arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/processor.h | 2 + arch/x86/kernel/cpu/amd.c | 16 + arch/x86/kernel/nmi.c | 10 + arch/x86/kernel/smpboot.c | 2 +- arch/x86/kvm/cpuid.c | 3 +- arch/x86/kvm/emulate.c | 2 +- arch/x86/kvm/kvm_emulate.h | 1 + arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/svm/sev.c | 8 +- arch/x86/kvm/svm/svm.c | 11 +- arch/x86/kvm/svm/svm.h | 1 + arch/x86/kvm/vmx/nested.c | 29 +- arch/x86/kvm/vmx/vmx.c | 57 ++- arch/x86/kvm/x86.c | 42 +- block/bfq-iosched.c | 3 +- block/blk-iocost.c | 14 +- block/blk-mq-sched.c | 8 +- block/blk-mq.c | 11 +- block/kyber-iosched.c | 5 +- block/mq-deadline.c | 3 +- drivers/acpi/device_pm.c | 1 + drivers/acpi/scan.c | 1 + drivers/ata/ahci_brcm.c | 46 +- drivers/base/power/runtime.c | 10 +- drivers/block/nbd.c | 3 +- drivers/block/rnbd/rnbd-clt.c | 12 +- drivers/block/rnbd/rnbd-clt.h | 2 +- drivers/bluetooth/btusb.c | 4 +- drivers/char/tpm/tpm2-cmd.c | 1 + drivers/char/tpm/tpm_tis_core.c | 22 +- drivers/clk/samsung/clk-exynos7.c | 7 +- drivers/clocksource/timer-ti-dm-systimer.c | 144 +++++- drivers/cpufreq/acpi-cpufreq.c | 6 +- drivers/cpufreq/intel_pstate.c | 14 +- drivers/crypto/ccp/sev-dev.c | 4 +- drivers/dma/idxd/cdev.c | 129 ++---- drivers/dma/idxd/device.c | 25 +- drivers/dma/idxd/dma.c | 77 +++- drivers/dma/idxd/idxd.h | 89 +++- drivers/dma/idxd/init.c | 349 ++++++++++----- drivers/dma/idxd/irq.c | 10 +- drivers/dma/idxd/sysfs.c | 324 ++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 4 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 15 +- .../gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 2 + drivers/gpu/drm/i915/display/intel_dp.c | 59 +-- drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 1 - drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 4 +- drivers/gpu/drm/i915/i915_active.c | 3 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 9 +- drivers/gpu/drm/msm/dp/dp_audio.c | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 26 +- drivers/gpu/drm/msm/dp/dp_display.h | 1 + drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 26 +- drivers/gpu/drm/radeon/radeon_pm.c | 8 + drivers/gpu/drm/radeon/si_dpm.c | 3 + drivers/hwmon/ltc2992.c | 8 +- drivers/hwmon/occ/common.c | 5 +- drivers/hwmon/occ/common.h | 2 +- drivers/hwtracing/coresight/coresight-platform.c | 6 + drivers/i2c/busses/i2c-i801.c | 4 + drivers/i2c/busses/i2c-imx.c | 2 +- drivers/i2c/busses/i2c-mt65xx.c | 9 +- drivers/i2c/i2c-dev.c | 9 +- drivers/iio/accel/Kconfig | 1 - drivers/iio/common/hid-sensors/Kconfig | 1 + drivers/iio/gyro/Kconfig | 1 - drivers/iio/gyro/mpu3050-core.c | 13 +- drivers/iio/humidity/Kconfig | 1 - drivers/iio/industrialio-core.c | 9 +- drivers/iio/light/Kconfig | 2 - drivers/iio/light/gp2ap002.c | 5 +- drivers/iio/light/tsl2583.c | 8 + drivers/iio/magnetometer/Kconfig | 1 - drivers/iio/orientation/Kconfig | 2 - drivers/iio/pressure/Kconfig | 1 - drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 1 + drivers/iio/temperature/Kconfig | 1 - drivers/infiniband/hw/hfi1/ipoib.h | 3 +- drivers/infiniband/hw/hfi1/ipoib_tx.c | 14 +- drivers/iommu/amd/init.c | 49 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 + drivers/leds/blink/Kconfig | 1 + drivers/net/can/dev/skb.c | 6 +- drivers/net/can/m_can/m_can.c | 3 +- drivers/net/can/spi/mcp251x.c | 35 +- drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 8 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 +- drivers/net/ethernet/cisco/enic/enic_main.c | 7 +- drivers/net/ethernet/freescale/fec_main.c | 3 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 127 ++++-- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 + drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 3 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 3 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 27 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 + drivers/net/ethernet/intel/i40e/i40e.h | 1 - drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 6 +- drivers/net/ethernet/intel/i40e/i40e_client.c | 1 + drivers/net/ethernet/intel/i40e/i40e_common.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 42 -- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 +- drivers/net/ethernet/intel/i40e/i40e_type.h | 7 +- drivers/net/ethernet/intel/iavf/iavf_main.c | 2 - drivers/net/ethernet/intel/ice/ice_lib.c | 123 ++++-- drivers/net/ethernet/intel/ice/ice_txrx.h | 2 + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- .../net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 + drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 1 + drivers/net/ipa/gsi.c | 4 +- drivers/net/ipa/gsi_reg.h | 18 +- drivers/net/phy/phy_device.c | 6 + drivers/net/wireless/ath/ath11k/wmi.c | 53 +-- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 91 ++-- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 39 +- .../net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 4 +- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 30 +- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 3 +- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 1 + drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 97 ++-- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 18 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 15 +- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 + drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 + drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 19 +- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 58 ++- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 25 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 27 +- drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 13 + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 25 +- drivers/net/wireless/microchip/wilc1000/netdev.c | 25 +- drivers/net/wireless/quantenna/qtnfmac/event.c | 6 +- drivers/net/wireless/realtek/rtw88/main.h | 2 + drivers/net/wireless/realtek/rtw88/phy.c | 14 + drivers/net/wireless/realtek/rtw88/phy.h | 1 + drivers/net/wireless/realtek/rtw88/reg.h | 5 + drivers/net/wireless/realtek/rtw88/rtw8822c.c | 27 +- drivers/net/wireless/wl3501.h | 47 +- drivers/net/wireless/wl3501_cs.c | 54 +-- drivers/nvme/host/core.c | 3 +- drivers/nvme/target/io-cmd-bdev.c | 2 +- drivers/nvme/target/nvmet.h | 6 + drivers/nvme/target/passthru.c | 2 +- drivers/nvme/target/rdma.c | 4 +- drivers/pci/controller/pcie-brcmstb.c | 20 +- drivers/pci/controller/pcie-iproc-msi.c | 2 +- drivers/pci/endpoint/functions/pci-epf-test.c | 20 +- drivers/pci/pcie/rcec.c | 2 +- drivers/pci/probe.c | 1 + drivers/pinctrl/samsung/pinctrl-exynos.c | 10 +- drivers/pwm/pwm-atmel.c | 2 +- drivers/remoteproc/pru_rproc.c | 41 +- drivers/remoteproc/qcom_q6v5_mss.c | 18 + drivers/rpmsg/qcom_glink_native.c | 1 + drivers/rtc/rtc-ds1307.c | 12 +- drivers/rtc/rtc-fsl-ftm-alarm.c | 1 + drivers/rtc/rtc-tps65910.c | 1 + drivers/scsi/qla2xxx/qla_init.c | 3 + drivers/scsi/ufs/ufshcd.c | 7 +- drivers/soc/mediatek/mt8173-pm-domains.h | 10 + drivers/soc/mediatek/mt8183-pm-domains.h | 15 + drivers/soc/mediatek/mt8192-pm-domains.h | 21 + drivers/soc/mediatek/mtk-pm-domains.c | 6 +- drivers/soc/mediatek/mtk-pm-domains.h | 2 + drivers/staging/media/rkvdec/rkvdec.c | 2 +- drivers/thermal/qcom/tsens.c | 6 +- drivers/thermal/thermal_of.c | 7 +- drivers/usb/class/cdc-wdm.c | 30 +- drivers/usb/core/hub.c | 6 +- drivers/usb/dwc2/core.h | 2 + drivers/usb/dwc2/gadget.c | 3 +- drivers/usb/dwc3/dwc3-imx8mp.c | 1 + drivers/usb/dwc3/dwc3-omap.c | 5 + drivers/usb/dwc3/dwc3-pci.c | 1 + drivers/usb/dwc3/gadget.c | 11 +- drivers/usb/host/fotg210-hcd.c | 4 +- drivers/usb/host/xhci-ext-caps.h | 5 +- drivers/usb/host/xhci-pci.c | 8 +- drivers/usb/host/xhci-ring.c | 16 +- drivers/usb/host/xhci.c | 6 +- drivers/usb/musb/mediatek.c | 2 +- drivers/usb/typec/tcpm/tcpm.c | 22 +- drivers/usb/typec/ucsi/ucsi.c | 46 +- drivers/usb/typec/ucsi/ucsi.h | 6 +- drivers/xen/gntdev.c | 4 +- drivers/xen/unpopulated-alloc.c | 4 +- fs/9p/vfs_file.c | 4 +- fs/btrfs/ctree.h | 2 +- fs/btrfs/extent-tree.c | 6 +- fs/btrfs/file.c | 35 +- fs/btrfs/free-space-cache.c | 2 +- fs/btrfs/inode.c | 4 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/ordered-data.c | 2 +- fs/btrfs/qgroup.c | 2 +- fs/btrfs/send.c | 4 +- fs/btrfs/tree-log.c | 3 +- fs/btrfs/zoned.c | 5 + fs/ceph/export.c | 4 +- fs/dax.c | 35 +- fs/debugfs/inode.c | 2 +- fs/dlm/config.c | 86 ++-- fs/dlm/config.h | 1 - fs/dlm/debug_fs.c | 1 + fs/dlm/lockspace.c | 20 +- fs/dlm/lowcomms.c | 104 +++-- fs/dlm/lowcomms.h | 5 + fs/dlm/midcomms.c | 7 +- fs/ext4/fast_commit.c | 2 +- fs/f2fs/compress.c | 55 +-- fs/f2fs/data.c | 6 +- fs/f2fs/f2fs.h | 7 +- fs/f2fs/file.c | 42 +- fs/f2fs/gc.c | 62 ++- fs/f2fs/inline.c | 3 +- fs/f2fs/segment.c | 86 ++-- fs/f2fs/segment.h | 14 +- fs/f2fs/super.c | 18 +- fs/fuse/cuse.c | 2 + fs/fuse/file.c | 9 + fs/fuse/virtio_fs.c | 3 +- fs/hfsplus/extents.c | 7 +- fs/hugetlbfs/inode.c | 5 + fs/jbd2/recovery.c | 5 +- fs/nfs/callback_proc.c | 17 +- fs/nfs/dir.c | 22 +- fs/nfs/flexfilelayout/flexfilelayout.c | 2 +- fs/nfs/inode.c | 8 +- fs/nfs/nfs42proc.c | 72 ++- fs/nfs/nfs4proc.c | 56 ++- fs/nfsd/nfs4state.c | 24 +- fs/proc/generic.c | 2 +- fs/squashfs/file.c | 6 +- include/linux/cpuhotplug.h | 1 + include/linux/elevator.h | 2 +- include/linux/i2c.h | 2 + include/linux/mm.h | 32 ++ include/linux/mm_types.h | 4 +- include/linux/nfs_xdr.h | 11 +- include/linux/phy.h | 2 + include/linux/pm.h | 1 + include/net/page_pool.h | 12 +- include/trace/events/sunrpc.h | 1 - include/uapi/linux/netfilter/xt_SECMARK.h | 6 + kernel/dma/swiotlb.c | 3 +- kernel/kexec_file.c | 4 +- kernel/resource.c | 4 +- kernel/sched/core.c | 2 +- kernel/sched/fair.c | 14 +- kernel/time/alarmtimer.c | 2 +- kernel/watchdog.c | 88 ++-- lib/Kconfig.kfence | 1 + lib/kobject_uevent.c | 9 +- lib/nlattr.c | 2 +- lib/test_kasan.c | 29 +- mm/gup.c | 94 ++-- mm/hugetlb.c | 12 +- mm/kfence/core.c | 45 +- mm/khugepaged.c | 18 +- mm/ksm.c | 1 + mm/migrate.c | 7 + mm/shmem.c | 34 +- net/bluetooth/hci_event.c | 2 +- net/bluetooth/l2cap_core.c | 4 + net/bluetooth/l2cap_sock.c | 8 + net/bluetooth/mgmt.c | 1 - net/bridge/br_arp_nd_proxy.c | 4 +- net/bridge/br_multicast.c | 28 +- net/bridge/br_netlink.c | 4 +- net/bridge/br_private.h | 3 +- net/bridge/br_sysfs_br.c | 8 +- net/core/flow_dissector.c | 6 +- net/core/page_pool.c | 12 +- net/ethtool/ioctl.c | 2 +- net/ethtool/netlink.c | 3 +- net/ipv6/ip6_vti.c | 2 +- net/mac80211/mlme.c | 12 +- net/mac80211/tx.c | 20 +- net/mptcp/subflow.c | 3 +- net/netfilter/nf_tables_api.c | 4 +- net/netfilter/nfnetlink_osf.c | 2 + net/netfilter/nft_set_hash.c | 10 +- net/netfilter/xt_SECMARK.c | 88 +++- net/sched/cls_flower.c | 36 +- net/sched/sch_taprio.c | 6 + net/sctp/sm_make_chunk.c | 2 +- net/sctp/sm_statefuns.c | 28 +- net/smc/af_smc.c | 4 +- net/sunrpc/clnt.c | 12 +- net/sunrpc/svc.c | 3 +- net/sunrpc/svcsock.c | 2 +- net/sunrpc/xprt.c | 12 +- net/sunrpc/xprtrdma/frwr_ops.c | 2 +- net/sunrpc/xprtrdma/rpc_rdma.c | 3 +- net/sunrpc/xprtrdma/transport.c | 6 +- net/sunrpc/xprtrdma/verbs.c | 10 +- net/sunrpc/xprtrdma/xprt_rdma.h | 2 +- net/tipc/netlink_compat.c | 2 +- net/xdp/xsk_queue.h | 7 +- samples/bpf/tracex1_kern.c | 4 +- scripts/Makefile.modpost | 15 +- scripts/kconfig/nconf.c | 2 +- scripts/mod/modpost.c | 15 +- security/keys/trusted-keys/trusted_tpm1.c | 8 +- sound/firewire/bebob/bebob_stream.c | 12 +- sound/pci/hda/ideapad_s740_helper.c | 492 +++++++++++++++++++++ sound/pci/hda/patch_hdmi.c | 29 +- sound/pci/hda/patch_realtek.c | 11 + sound/pci/rme9652/hdsp.c | 3 +- sound/pci/rme9652/hdspm.c | 3 +- sound/pci/rme9652/rme9652.c | 3 +- sound/soc/codecs/rt286.c | 23 +- sound/soc/codecs/rt5670.c | 12 + sound/soc/intel/boards/bytcr_rt5640.c | 20 + sound/soc/intel/boards/sof_sdw.c | 11 + sound/soc/sh/rcar/core.c | 69 ++- sound/soc/sh/rcar/ssi.c | 16 +- sound/soc/soc-compress.c | 4 + sound/usb/quirks-table.h | 63 +++ tools/lib/bpf/ringbuf.c | 30 +- tools/perf/Makefile.config | 1 + tools/perf/util/Build | 7 + .../drivers/net/mlxsw/mirror_gre_scale.sh | 3 +- .../selftests/drivers/net/mlxsw/sch_red_core.sh | 4 +- tools/testing/selftests/lib.mk | 4 + .../testing/selftests/net/forwarding/mirror_lib.sh | 19 +- tools/testing/selftests/net/mptcp/diag.sh | 55 ++- tools/testing/selftests/net/mptcp/mptcp_connect.sh | 15 +- tools/testing/selftests/net/mptcp/mptcp_join.sh | 22 +- tools/testing/selftests/net/mptcp/simult_flows.sh | 13 +- .../selftests/powerpc/security/entry_flush.c | 2 +- .../selftests/powerpc/security/flush_utils.h | 4 + .../testing/selftests/powerpc/security/rfi_flush.c | 2 +- virt/kvm/kvm_main.c | 7 +- 394 files changed, 4512 insertions(+), 2167 deletions(-)
From: Colin Ian King colin.king@canonical.com
commit 83a775d5f9bfda95b1c295f95a3a041a40c7f321 upstream.
Two error return paths are neglecting to free allocated object td, causing a memory leak. Fix this by returning via the error return path that securely kfree's td.
Fixes clang scan-build warning: security/keys/trusted-keys/trusted_tpm1.c:496:10: warning: Potential memory leak [unix.Malloc]
Cc: stable@vger.kernel.org Fixes: 5df16caada3f ("KEYS: trusted: Fix incorrect handling of tpm_get_random()") Signed-off-by: Colin Ian King colin.king@canonical.com Reviewed-by: Nick Desaulniers ndesaulniers@google.com Reviewed-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/keys/trusted-keys/trusted_tpm1.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
--- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -500,10 +500,12 @@ static int tpm_seal(struct tpm_buf *tb,
ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); if (ret < 0) - return ret; + goto out;
- if (ret != TPM_NONCE_SIZE) - return -EIO; + if (ret != TPM_NONCE_SIZE) { + ret = -EIO; + goto out; + }
ordinal = htonl(TPM_ORD_SEAL); datsize = htonl(datalen);
From: Zhen Lei thunder.leizhen@huawei.com
commit 1df83992d977355177810c2b711afc30546c81ce upstream.
If the total number of commands queried through TPM2_CAP_COMMANDS is different from that queried through TPM2_CC_GET_CAPABILITY, it indicates an unknown error. In this case, an appropriate error code -EFAULT should be returned. However, we currently do not explicitly assign this error code to 'rc'. As a result, 0 was incorrectly returned.
Cc: stable@vger.kernel.org Fixes: 58472f5cd4f6("tpm: validate TPM 2.0 commands") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhen Lei thunder.leizhen@huawei.com Reviewed-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm2-cmd.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -656,6 +656,7 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chi
if (nr_commands != be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) { + rc = -EFAULT; tpm_buf_destroy(&buf); goto out; }
From: Jarkko Sakkinen jarkko@kernel.org
commit e630af7dfb450d1c00c30077314acf33032ff9e4 upstream.
The earlier fix (linked) only partially fixed the locality handling bug in tpm_tis_gen_interrupt(), i.e. only for TPM 1.x.
Extend the locality handling to cover TPM2.
Cc: Hans de Goede hdegoede@redhat.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-integrity/20210220125534.20707-1-jarkko@kernel... Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()") Reported-by: Lino Sanfilippo LinoSanfilippo@gmx.de Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Tested-by: Lino Sanfilippo LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm_tis_core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
--- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -709,16 +709,14 @@ static int tpm_tis_gen_interrupt(struct cap_t cap; int ret;
- /* TPM 2.0 */ - if (chip->flags & TPM_CHIP_FLAG_TPM2) - return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); - - /* TPM 1.2 */ ret = request_locality(chip, 0); if (ret < 0) return ret;
- ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0); + if (chip->flags & TPM_CHIP_FLAG_TPM2) + ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); + else + ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
release_locality(chip, 0);
From: Jarkko Sakkinen jarkko@kernel.org
commit 8a2d296aaebadd68d9c1f6908667df1d1c84c051 upstream.
Reserve locality in tpm_tis_resume(), as it could be unsert after waking up from a sleep state.
Cc: stable@vger.kernel.org Cc: Lino Sanfilippo LinoSanfilippo@gmx.de Reported-by: Hans de Goede hdegoede@redhat.com Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()") Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm_tis_core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
--- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -1125,12 +1125,20 @@ int tpm_tis_resume(struct device *dev) if (ret) return ret;
- /* TPM 1.2 requires self-test on resume. This function actually returns + /* + * TPM 1.2 requires self-test on resume. This function actually returns * an error code but for unknown reason it isn't handled. */ - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { + ret = request_locality(chip, 0); + if (ret < 0) + return ret; + tpm1_do_selftest(chip);
+ release_locality(chip, 0); + } + return 0; } EXPORT_SYMBOL_GPL(tpm_tis_resume);
From: Anand Jain anand.jain@oracle.com
commit 5e753a817b2d5991dfe8a801b7b1e8e79a1c5a20 upstream.
The following test case reproduces an issue of wrongly freeing in-use blocks on the readonly seed device when fstrim is called on the rw sprout device. As shown below.
Create a seed device and add a sprout device to it:
$ mkfs.btrfs -fq -dsingle -msingle /dev/loop0 $ btrfstune -S 1 /dev/loop0 $ mount /dev/loop0 /btrfs $ btrfs dev add -f /dev/loop1 /btrfs BTRFS info (device loop0): relocating block group 290455552 flags system BTRFS info (device loop0): relocating block group 1048576 flags system BTRFS info (device loop0): disk added /dev/loop1 $ umount /btrfs
Mount the sprout device and run fstrim:
$ mount /dev/loop1 /btrfs $ fstrim /btrfs $ umount /btrfs
Now try to mount the seed device, and it fails:
$ mount /dev/loop0 /btrfs mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
Block 5292032 is missing on the readonly seed device:
$ dmesg -kt | tail <snip> BTRFS error (device loop0): bad tree block start, want 5292032 have 0 BTRFS warning (device loop0): couldn't read-tree root BTRFS error (device loop0): open_ctree failed
From the dump-tree of the seed device (taken before the fstrim). Block
5292032 belonged to the block group starting at 5242880:
$ btrfs inspect dump-tree -e /dev/loop0 | grep -A1 BLOCK_GROUP <snip> item 3 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16169 itemsize 24 block group used 114688 chunk_objectid 256 flags METADATA <snip>
From the dump-tree of the sprout device (taken before the fstrim).
fstrim used block-group 5242880 to find the related free space to free:
$ btrfs inspect dump-tree -e /dev/loop1 | grep -A1 BLOCK_GROUP <snip> item 1 key (5242880 BLOCK_GROUP_ITEM 8388608) itemoff 16226 itemsize 24 block group used 32768 chunk_objectid 256 flags METADATA <snip>
BPF kernel tracing the fstrim command finds the missing block 5292032 within the range of the discarded blocks as below:
kprobe:btrfs_discard_extent { printf("freeing start %llu end %llu num_bytes %llu:\n", arg1, arg1+arg2, arg2); }
freeing start 5259264 end 5406720 num_bytes 147456 <snip>
Fix this by avoiding the discard command to the readonly seed device.
Reported-by: Chris Murphy lists@colorremedies.com CC: stable@vger.kernel.org # 4.4+ Reviewed-by: Filipe Manana fdmanana@suse.com Signed-off-by: Anand Jain anand.jain@oracle.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/extent-tree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1340,12 +1340,16 @@ int btrfs_discard_extent(struct btrfs_fs stripe = bbio->stripes; for (i = 0; i < bbio->num_stripes; i++, stripe++) { u64 bytes; + struct btrfs_device *device = stripe->dev;
- if (!stripe->dev->bdev) { + if (!device->bdev) { ASSERT(btrfs_test_opt(fs_info, DEGRADED)); continue; }
+ if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) + continue; + ret = do_discard_extent(stripe, &bytes); if (!ret) { discarded_bytes += bytes;
From: Tom Lendacky thomas.lendacky@amd.com
commit a3ba26ecfb569f4aa3f867e80c02aa65f20aadad upstream.
Access to the GHCB is mainly in the VMGEXIT path and it is known that the GHCB will be mapped. But there are two paths where it is possible the GHCB might not be mapped.
The sev_vcpu_deliver_sipi_vector() routine will update the GHCB to inform the caller of the AP Reset Hold NAE event that a SIPI has been delivered. However, if a SIPI is performed without a corresponding AP Reset Hold, then the GHCB might not be mapped (depending on the previous VMEXIT), which will result in a NULL pointer dereference.
The svm_complete_emulated_msr() routine will update the GHCB to inform the caller of a RDMSR/WRMSR operation about any errors. While it is likely that the GHCB will be mapped in this situation, add a safe guard in this path to be certain a NULL pointer dereference is not encountered.
Fixes: f1c6366e3043 ("KVM: SVM: Add required changes to support intercepts under SEV-ES") Fixes: 647daca25d24 ("KVM: SVM: Add support for booting APs in an SEV-ES guest") Signed-off-by: Tom Lendacky thomas.lendacky@amd.com Cc: stable@vger.kernel.org Message-Id: a5d3ebb600a91170fc88599d5a575452b3e31036.1617979121.git.thomas.lendacky@amd.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/svm/sev.c | 3 +++ arch/x86/kvm/svm/svm.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
--- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2106,5 +2106,8 @@ void sev_vcpu_deliver_sipi_vector(struct * the guest will set the CS and RIP. Set SW_EXIT_INFO_2 to a * non-zero value. */ + if (!svm->ghcb) + return; + ghcb_set_sw_exit_info_2(svm->ghcb, 1); } --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2811,7 +2811,7 @@ static int svm_get_msr(struct kvm_vcpu * static int svm_complete_emulated_msr(struct kvm_vcpu *vcpu, int err) { struct vcpu_svm *svm = to_svm(vcpu); - if (!sev_es_guest(svm->vcpu.kvm) || !err) + if (!err || !sev_es_guest(vcpu->kvm) || WARN_ON_ONCE(!svm->ghcb)) return kvm_complete_insn_gp(&svm->vcpu, err);
ghcb_set_sw_exit_info_1(svm->ghcb, 1);
From: Lai Jiangshan laijs@linux.alibaba.com
commit a217a6593cec8b315d4c2f344bae33660b39b703 upstream.
In VMX, the host NMI handler needs to be invoked after NMI VM-Exit. Before commit 1a5488ef0dcf6 ("KVM: VMX: Invoke NMI handler via indirect call instead of INTn"), this was done by INTn ("int $2"). But INTn microcode is relatively expensive, so the commit reworked NMI VM-Exit handling to invoke the kernel handler by function call.
But this missed a detail. The NMI entry point for direct invocation is fetched from the IDT table and called on the kernel stack. But on 64-bit the NMI entry installed in the IDT expects to be invoked on the IST stack. It relies on the "NMI executing" variable on the IST stack to work correctly, which is at a fixed position in the IST stack. When the entry point is unexpectedly called on the kernel stack, the RSP-addressed "NMI executing" variable is obviously also on the kernel stack and is "uninitialized" and can cause the NMI entry code to run in the wrong way.
Provide a non-ist entry point for VMX which shares the C-function with the regular NMI entry and invoke the new asm entry point instead.
On 32-bit this just maps to the regular NMI entry point as 32-bit has no ISTs and is not affected.
[ tglx: Made it independent for backporting, massaged changelog ]
Fixes: 1a5488ef0dcf6 ("KVM: VMX: Invoke NMI handler via indirect call instead of INTn") Signed-off-by: Lai Jiangshan laijs@linux.alibaba.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Tested-by: Lai Jiangshan laijs@linux.alibaba.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/87r1imi8i1.ffs@nanos.tec.linutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/idtentry.h | 15 +++++++++++++++ arch/x86/kernel/nmi.c | 10 ++++++++++ arch/x86/kvm/vmx/vmx.c | 16 +++++++++------- 3 files changed, 34 insertions(+), 7 deletions(-)
--- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -588,6 +588,21 @@ DECLARE_IDTENTRY_RAW(X86_TRAP_MC, xenpv_ #endif
/* NMI */ + +#if defined(CONFIG_X86_64) && IS_ENABLED(CONFIG_KVM_INTEL) +/* + * Special NOIST entry point for VMX which invokes this on the kernel + * stack. asm_exc_nmi() requires an IST to work correctly vs. the NMI + * 'executing' marker. + * + * On 32bit this just uses the regular NMI entry point because 32-bit does + * not have ISTs. + */ +DECLARE_IDTENTRY(X86_TRAP_NMI, exc_nmi_noist); +#else +#define asm_exc_nmi_noist asm_exc_nmi +#endif + DECLARE_IDTENTRY_NMI(X86_TRAP_NMI, exc_nmi); #ifdef CONFIG_XEN_PV DECLARE_IDTENTRY_RAW(X86_TRAP_NMI, xenpv_exc_nmi); --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -524,6 +524,16 @@ nmi_restart: mds_user_clear_cpu_buffers(); }
+#if defined(CONFIG_X86_64) && IS_ENABLED(CONFIG_KVM_INTEL) +DEFINE_IDTENTRY_RAW(exc_nmi_noist) +{ + exc_nmi(regs); +} +#endif +#if IS_MODULE(CONFIG_KVM_INTEL) +EXPORT_SYMBOL_GPL(asm_exc_nmi_noist); +#endif + void stop_nmi(void) { ignore_nmis++; --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -36,6 +36,7 @@ #include <asm/debugreg.h> #include <asm/desc.h> #include <asm/fpu/internal.h> +#include <asm/idtentry.h> #include <asm/io.h> #include <asm/irq_remapping.h> #include <asm/kexec.h> @@ -6394,18 +6395,17 @@ static void vmx_apicv_post_state_restore
void vmx_do_interrupt_nmi_irqoff(unsigned long entry);
-static void handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info) +static void handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, + unsigned long entry) { - unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK; - gate_desc *desc = (gate_desc *)host_idt_base + vector; - kvm_before_interrupt(vcpu); - vmx_do_interrupt_nmi_irqoff(gate_offset(desc)); + vmx_do_interrupt_nmi_irqoff(entry); kvm_after_interrupt(vcpu); }
static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx) { + const unsigned long nmi_entry = (unsigned long)asm_exc_nmi_noist; u32 intr_info = vmx_get_intr_info(&vmx->vcpu);
/* if exit due to PF check for async PF */ @@ -6416,18 +6416,20 @@ static void handle_exception_nmi_irqoff( kvm_machine_check(); /* We need to handle NMIs before interrupts are enabled */ else if (is_nmi(intr_info)) - handle_interrupt_nmi_irqoff(&vmx->vcpu, intr_info); + handle_interrupt_nmi_irqoff(&vmx->vcpu, nmi_entry); }
static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu) { u32 intr_info = vmx_get_intr_info(vcpu); + unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK; + gate_desc *desc = (gate_desc *)host_idt_base + vector;
if (WARN_ONCE(!is_external_intr(intr_info), "KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info)) return;
- handle_interrupt_nmi_irqoff(vcpu, intr_info); + handle_interrupt_nmi_irqoff(vcpu, gate_offset(desc)); }
static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
From: Sumeet Pawnikar sumeet.r.pawnikar@intel.com
commit 2404b8747019184002823dba7d2f0ecf89d802b7 upstream.
Add a new unique fan ACPI device ID for Alder Lake to support it in acpi_dev_pm_attach() function.
Fixes: 38748bcb940e ("ACPI: DPTF: Support Alder Lake") Signed-off-by: Sumeet Pawnikar sumeet.r.pawnikar@intel.com Acked-by: Zhang Rui rui.zhang@intel.com Cc: 5.10+ stable@vger.kernel.org # 5.10+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/device_pm.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1310,6 +1310,7 @@ int acpi_dev_pm_attach(struct device *de {"PNP0C0B", }, /* Generic ACPI fan */ {"INT3404", }, /* Fan */ {"INTC1044", }, /* Fan for Tiger Lake generation */ + {"INTC1048", }, /* Fan for Alder Lake generation */ {} }; struct acpi_device *adev = ACPI_COMPANION(dev);
From: Tony Lindgren tony@atomide.com
commit c745253e2a691a40c66790defe85c104a887e14a upstream.
As pm_runtime_need_not_resume() relies also on usage_count, it can return a different value in pm_runtime_force_suspend() compared to when called in pm_runtime_force_resume(). Different return values can happen if anything calls PM runtime functions in between, and causes the parent child_count to increase on every resume.
So far I've seen the issue only for omapdrm that does complicated things with PM runtime calls during system suspend for legacy reasons:
omap_atomic_commit_tail() for omapdrm.0 dispc_runtime_get() wakes up 58000000.dss as it's the dispc parent dispc_runtime_resume() rpm_resume() increases parent child_count dispc_runtime_put() won't idle, PM runtime suspend blocked pm_runtime_force_suspend() for 58000000.dss, !pm_runtime_need_not_resume() __update_runtime_status() system suspended pm_runtime_force_resume() for 58000000.dss, pm_runtime_need_not_resume() pm_runtime_enable() only called because of pm_runtime_need_not_resume() omap_atomic_commit_tail() for omapdrm.0 dispc_runtime_get() wakes up 58000000.dss as it's the dispc parent dispc_runtime_resume() rpm_resume() increases parent child_count dispc_runtime_put() won't idle, PM runtime suspend blocked ... rpm_suspend for 58000000.dss but parent child_count is now unbalanced
Let's fix the issue by adding a flag for needs_force_resume and use it in pm_runtime_force_resume() instead of pm_runtime_need_not_resume().
Additionally omapdrm system suspend could be simplified later on to avoid lots of unnecessary PM runtime calls and the complexity it adds. The driver can just use internal functions that are shared between the PM runtime and system suspend related functions.
Fixes: 4918e1f87c5f ("PM / runtime: Rework pm_runtime_force_suspend/resume()") Signed-off-by: Tony Lindgren tony@atomide.com Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Tested-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Cc: 4.16+ stable@vger.kernel.org # 4.16+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/base/power/runtime.c | 10 +++++++--- include/linux/pm.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-)
--- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1637,6 +1637,7 @@ void pm_runtime_init(struct device *dev) dev->power.request_pending = false; dev->power.request = RPM_REQ_NONE; dev->power.deferred_resume = false; + dev->power.needs_force_resume = 0; INIT_WORK(&dev->power.work, pm_runtime_work);
dev->power.timer_expires = 0; @@ -1804,10 +1805,12 @@ int pm_runtime_force_suspend(struct devi * its parent, but set its status to RPM_SUSPENDED anyway in case this * function will be called again for it in the meantime. */ - if (pm_runtime_need_not_resume(dev)) + if (pm_runtime_need_not_resume(dev)) { pm_runtime_set_suspended(dev); - else + } else { __update_runtime_status(dev, RPM_SUSPENDED); + dev->power.needs_force_resume = 1; + }
return 0;
@@ -1834,7 +1837,7 @@ int pm_runtime_force_resume(struct devic int (*callback)(struct device *); int ret = 0;
- if (!pm_runtime_status_suspended(dev) || pm_runtime_need_not_resume(dev)) + if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume) goto out;
/* @@ -1853,6 +1856,7 @@ int pm_runtime_force_resume(struct devic
pm_runtime_mark_last_busy(dev); out: + dev->power.needs_force_resume = 0; pm_runtime_enable(dev); return ret; } --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -602,6 +602,7 @@ struct dev_pm_info { unsigned int idle_notification:1; unsigned int request_pending:1; unsigned int deferred_resume:1; + unsigned int needs_force_resume:1; unsigned int runtime_auto:1; bool ignore_children:1; unsigned int no_callbacks:1;
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit e5af36b2adb858e982d78d41d7363d05d951a19a upstream.
It turns out that there are systems where HWP is enabled during initialization by the platform firmware (BIOS), but HWP EPP support is not advertised.
After commit 7aa1031223bc ("cpufreq: intel_pstate: Avoid enabling HWP if EPP is not supported") intel_pstate refuses to use HWP on those systems, but the fallback PERF_CTL interface does not work on them either because of enabled HWP, and once enabled, HWP cannot be disabled. Consequently, the users of those systems cannot control CPU performance scaling.
Address this issue by making intel_pstate use HWP unconditionally if it is enabled already when the driver starts.
Fixes: 7aa1031223bc ("cpufreq: intel_pstate: Avoid enabling HWP if EPP is not supported") Reported-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Tested-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Cc: 5.9+ stable@vger.kernel.org # 5.9+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/intel_pstate.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
--- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -3054,6 +3054,14 @@ static const struct x86_cpu_id hwp_suppo {} };
+static bool intel_pstate_hwp_is_enabled(void) +{ + u64 value; + + rdmsrl(MSR_PM_ENABLE, value); + return !!(value & 0x1); +} + static int __init intel_pstate_init(void) { const struct x86_cpu_id *id; @@ -3072,8 +3080,12 @@ static int __init intel_pstate_init(void * Avoid enabling HWP for processors without EPP support, * because that means incomplete HWP implementation which is a * corner case and supporting it is generally problematic. + * + * If HWP is enabled already, though, there is no choice but to + * deal with it. */ - if (!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) { + if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || + intel_pstate_hwp_is_enabled()) { hwp_active++; hwp_mode_bdw = id->driver_data; intel_pstate.attr = hwp_cpufreq_attrs;
From: David Matlack dmatlack@google.com
commit 258785ef08b323bddd844b4926a32c2b2045a1b0 upstream.
When growing halt-polling, there is no check that the poll time exceeds the per-VM limit. It's possible for vcpu->halt_poll_ns to grow past kvm->max_halt_poll_ns and stay there until a halt which takes longer than kvm->halt_poll_ns.
Signed-off-by: David Matlack dmatlack@google.com Signed-off-by: Venkatesh Srinivas venkateshs@chromium.org Message-Id: 20210506152442.4010298-1-venkateshs@chromium.org Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- virt/kvm/kvm_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2758,8 +2758,8 @@ static void grow_halt_poll_ns(struct kvm if (val < grow_start) val = grow_start;
- if (val > halt_poll_ns) - val = halt_poll_ns; + if (val > vcpu->kvm->max_halt_poll_ns) + val = vcpu->kvm->max_halt_poll_ns;
vcpu->halt_poll_ns = val; out:
From: Pradeep Kumar Chitrapu pradeepc@codeaurora.org
[ Upstream commit e3de5bb7ac1a4cb262f8768924fd3ef6182b10bb ]
Fix dangling pointer in thermal temperature event which causes incorrect temperature read.
Tested-on: IPQ8074 AHB WLAN.HK.2.4.0.1-00041-QCAHKSWPL_SILICONZ-1
Signed-off-by: Pradeep Kumar Chitrapu pradeepc@codeaurora.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210218182708.8844-1-pradeepc@codeaurora.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath11k/wmi.c | 53 +++++++++++---------------- 1 file changed, 21 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index cccfd3bd4d27..ca5cda890d58 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -5417,31 +5417,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, return 0; }
-static int -ath11k_pull_pdev_temp_ev(struct ath11k_base *ab, u8 *evt_buf, - u32 len, const struct wmi_pdev_temperature_event *ev) -{ - const void **tb; - int ret; - - tb = ath11k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC); - if (IS_ERR(tb)) { - ret = PTR_ERR(tb); - ath11k_warn(ab, "failed to parse tlv: %d\n", ret); - return ret; - } - - ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT]; - if (!ev) { - ath11k_warn(ab, "failed to fetch pdev temp ev"); - kfree(tb); - return -EPROTO; - } - - kfree(tb); - return 0; -} - size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head) { struct ath11k_fw_stats_vdev *i; @@ -6849,23 +6824,37 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, struct sk_buff *skb) { struct ath11k *ar; - struct wmi_pdev_temperature_event ev = {0}; + const void **tb; + const struct wmi_pdev_temperature_event *ev; + int ret; + + tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath11k_warn(ab, "failed to parse tlv: %d\n", ret); + return; + }
- if (ath11k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) { - ath11k_warn(ab, "failed to extract pdev temperature event"); + ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT]; + if (!ev) { + ath11k_warn(ab, "failed to fetch pdev temp ev"); + kfree(tb); return; }
ath11k_dbg(ab, ATH11K_DBG_WMI, - "pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id); + "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id);
- ar = ath11k_mac_get_ar_by_pdev_id(ab, ev.pdev_id); + ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); if (!ar) { - ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id); + ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id); + kfree(tb); return; }
- ath11k_thermal_event_temperature(ar, ev.temp); + ath11k_thermal_event_temperature(ar, ev->temp); + + kfree(tb); }
static void ath11k_fils_discovery_event(struct ath11k_base *ab,
From: Nicolas MURE nicolas.mure2019@gmail.com
[ Upstream commit a3c30b0cb6d05f5bf66d1a5d42e876f31753a447 ]
Declare the Pioneer DJM-850 interfaces for capture and playback.
See https://github.com/nm2107/Pioneer-DJM-850-driver-reverse-engineering/blob/17... for the complete device spec.
Signed-off-by: Nicolas MURE nicolas.mure2019@gmail.com Link: https://lore.kernel.org/r/20210301152729.18094-2-nicolas.mure2019@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/quirks-table.h | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 48facd262658..8a8fe2b980a1 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3827,6 +3827,69 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * Pioneer DJ DJM-850 + * 8 channels playback and 8 channels capture @ 44.1/48/96kHz S24LE + * Playback on EP 0x05 + * Capture on EP 0x86 + */ + USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x05, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_DATA, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x86, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_DATA, + .rates = SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000| + SNDRV_PCM_RATE_96000, + .rate_min = 44100, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } + } + }, + { + .ifnum = -1 + } + } + } +}, { /* * Pioneer DJ DJM-450
From: Alexander Aring aahringo@redhat.com
[ Upstream commit 92c48950b43f4a767388cf87709d8687151a641f ]
This patch fixes the following message which randomly pops up during glocktop call:
seq_file: buggy .next function table_seq_next did not update position index
The issue is that seq_read_iter() in fs/seq_file.c also needs an increment of the index in an non next record case as well which this patch fixes otherwise seq_read_iter() will print out the above message.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/debug_fs.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index d6bbccb0ed15..d5bd990bcab8 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -542,6 +542,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
if (bucket >= ls->ls_rsbtbl_size) { kfree(ri); + ++*pos; return NULL; } tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
From: Alexander Aring aahringo@redhat.com
[ Upstream commit e125fbeb538e5e35a00c6c8150a5361bef34814c ]
This patch fixes an deadlock issue when dlm_lowcomms_close() is called. When dlm_lowcomms_close() is called the clusters_root.subsys.su_mutex is held to remove configfs items. At this time we flushing (e.g. cancel_work_sync()) the workers of send and recv workqueue. Due the fact that we accessing configfs items (mark values), these workers will lock clusters_root.subsys.su_mutex as well which are already hold by dlm_lowcomms_close() and ends in a deadlock situation.
[67170.703046] ====================================================== [67170.703965] WARNING: possible circular locking dependency detected [67170.704758] 5.11.0-rc4+ #22 Tainted: G W [67170.705433] ------------------------------------------------------ [67170.706228] dlm_controld/280 is trying to acquire lock: [67170.706915] ffff9f2f475a6948 ((wq_completion)dlm_recv){+.+.}-{0:0}, at: __flush_work+0x203/0x4c0 [67170.708026] but task is already holding lock: [67170.708758] ffffffffa132f878 (&clusters_root.subsys.su_mutex){+.+.}-{3:3}, at: configfs_rmdir+0x29b/0x310 [67170.710016] which lock already depends on the new lock.
The new behaviour adds the mark value to the node address configuration which doesn't require to held the clusters_root.subsys.su_mutex by accessing mark values in a separate datastructure. However the mark values can be set now only after a node address was set which is the case when the user is using dlm_controld.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/config.c | 29 ++++++++++------------------ fs/dlm/config.h | 1 - fs/dlm/lowcomms.c | 49 ++++++++++++++++++++++++++++++++--------------- fs/dlm/lowcomms.h | 1 + 4 files changed, 45 insertions(+), 35 deletions(-)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 49c5f9407098..582bffa09a66 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -688,6 +688,7 @@ static ssize_t comm_mark_show(struct config_item *item, char *buf) static ssize_t comm_mark_store(struct config_item *item, const char *buf, size_t len) { + struct dlm_comm *comm; unsigned int mark; int rc;
@@ -695,7 +696,15 @@ static ssize_t comm_mark_store(struct config_item *item, const char *buf, if (rc) return rc;
- config_item_to_comm(item)->mark = mark; + if (mark == 0) + mark = dlm_config.ci_mark; + + comm = config_item_to_comm(item); + rc = dlm_lowcomms_nodes_set_mark(comm->nodeid, mark); + if (rc) + return rc; + + comm->mark = mark; return len; }
@@ -870,24 +879,6 @@ int dlm_comm_seq(int nodeid, uint32_t *seq) return 0; }
-void dlm_comm_mark(int nodeid, unsigned int *mark) -{ - struct dlm_comm *cm; - - cm = get_comm(nodeid); - if (!cm) { - *mark = dlm_config.ci_mark; - return; - } - - if (cm->mark) - *mark = cm->mark; - else - *mark = dlm_config.ci_mark; - - put_comm(cm); -} - int dlm_our_nodeid(void) { return local_comm ? local_comm->nodeid : 0; diff --git a/fs/dlm/config.h b/fs/dlm/config.h index c210250a2581..d2cd4bd20313 100644 --- a/fs/dlm/config.h +++ b/fs/dlm/config.h @@ -48,7 +48,6 @@ void dlm_config_exit(void); int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out, int *count_out); int dlm_comm_seq(int nodeid, uint32_t *seq); -void dlm_comm_mark(int nodeid, unsigned int *mark); int dlm_our_nodeid(void); int dlm_our_addr(struct sockaddr_storage *addr, int num);
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index f7d2c52791f8..a4fabcced0f2 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -116,6 +116,7 @@ struct writequeue_entry { struct dlm_node_addr { struct list_head list; int nodeid; + int mark; int addr_count; int curr_addr_index; struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; @@ -303,7 +304,8 @@ static int addr_compare(const struct sockaddr_storage *x, }
static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, - struct sockaddr *sa_out, bool try_new_addr) + struct sockaddr *sa_out, bool try_new_addr, + unsigned int *mark) { struct sockaddr_storage sas; struct dlm_node_addr *na; @@ -331,6 +333,8 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, if (!na->addr_count) return -ENOENT;
+ *mark = na->mark; + if (sas_out) memcpy(sas_out, &sas, sizeof(struct sockaddr_storage));
@@ -350,7 +354,8 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out, return 0; }
-static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) +static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid, + unsigned int *mark) { struct dlm_node_addr *na; int rv = -EEXIST; @@ -364,6 +369,7 @@ static int addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) for (addr_i = 0; addr_i < na->addr_count; addr_i++) { if (addr_compare(na->addr[addr_i], addr)) { *nodeid = na->nodeid; + *mark = na->mark; rv = 0; goto unlock; } @@ -412,6 +418,7 @@ int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len) new_node->nodeid = nodeid; new_node->addr[0] = new_addr; new_node->addr_count = 1; + new_node->mark = dlm_config.ci_mark; list_add(&new_node->list, &dlm_node_addrs); spin_unlock(&dlm_node_addrs_spin); return 0; @@ -519,6 +526,23 @@ int dlm_lowcomms_connect_node(int nodeid) return 0; }
+int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark) +{ + struct dlm_node_addr *na; + + spin_lock(&dlm_node_addrs_spin); + na = find_node_addr(nodeid); + if (!na) { + spin_unlock(&dlm_node_addrs_spin); + return -ENOENT; + } + + na->mark = mark; + spin_unlock(&dlm_node_addrs_spin); + + return 0; +} + static void lowcomms_error_report(struct sock *sk) { struct connection *con; @@ -867,7 +891,7 @@ static int accept_from_sock(struct listen_connection *con)
/* Get the new node's NODEID */ make_sockaddr(&peeraddr, 0, &len); - if (addr_to_nodeid(&peeraddr, &nodeid)) { + if (addr_to_nodeid(&peeraddr, &nodeid, &mark)) { unsigned char *b=(unsigned char *)&peeraddr; log_print("connect from non cluster node"); print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, @@ -876,9 +900,6 @@ static int accept_from_sock(struct listen_connection *con) return -1; }
- dlm_comm_mark(nodeid, &mark); - sock_set_mark(newsock->sk, mark); - log_print("got connection from %d", nodeid);
/* Check to see if we already have a connection to this node. This @@ -892,6 +913,8 @@ static int accept_from_sock(struct listen_connection *con) goto accept_err; }
+ sock_set_mark(newsock->sk, mark); + mutex_lock(&newcon->sock_mutex); if (newcon->sock) { struct connection *othercon = newcon->othercon; @@ -1016,8 +1039,6 @@ static void sctp_connect_to_sock(struct connection *con) struct socket *sock; unsigned int mark;
- dlm_comm_mark(con->nodeid, &mark); - mutex_lock(&con->sock_mutex);
/* Some odd races can cause double-connects, ignore them */ @@ -1030,7 +1051,7 @@ static void sctp_connect_to_sock(struct connection *con) }
memset(&daddr, 0, sizeof(daddr)); - result = nodeid_to_addr(con->nodeid, &daddr, NULL, true); + result = nodeid_to_addr(con->nodeid, &daddr, NULL, true, &mark); if (result < 0) { log_print("no address for nodeid %d", con->nodeid); goto out; @@ -1105,13 +1126,11 @@ out: static void tcp_connect_to_sock(struct connection *con) { struct sockaddr_storage saddr, src_addr; + unsigned int mark; int addr_len; struct socket *sock = NULL; - unsigned int mark; int result;
- dlm_comm_mark(con->nodeid, &mark); - mutex_lock(&con->sock_mutex); if (con->retries++ > MAX_CONNECT_RETRIES) goto out; @@ -1126,15 +1145,15 @@ static void tcp_connect_to_sock(struct connection *con) if (result < 0) goto out_err;
- sock_set_mark(sock->sk, mark); - memset(&saddr, 0, sizeof(saddr)); - result = nodeid_to_addr(con->nodeid, &saddr, NULL, false); + result = nodeid_to_addr(con->nodeid, &saddr, NULL, false, &mark); if (result < 0) { log_print("no address for nodeid %d", con->nodeid); goto out_err; }
+ sock_set_mark(sock->sk, mark); + add_sock(sock, con);
/* Bind to our cluster-known address connecting to avoid diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h index 0918f9376489..790d6703b17e 100644 --- a/fs/dlm/lowcomms.h +++ b/fs/dlm/lowcomms.h @@ -21,6 +21,7 @@ int dlm_lowcomms_close(int nodeid); void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc); void dlm_lowcomms_commit_buffer(void *mh); int dlm_lowcomms_connect_node(int nodeid); +int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark); int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len);
#endif /* __LOWCOMMS_DOT_H__ */
From: Alexander Aring aahringo@redhat.com
[ Upstream commit 8aa9540b49e0833feba75dbf4f45babadd0ed215 ]
This allows to return individual errno values for the config attribute check callback instead of returning invalid argument only.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/config.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 582bffa09a66..8439610c266a 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -125,7 +125,7 @@ static ssize_t cluster_cluster_name_store(struct config_item *item, CONFIGFS_ATTR(cluster_, cluster_name);
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, - int *info_field, bool (*check_cb)(unsigned int x), + int *info_field, int (*check_cb)(unsigned int x), const char *buf, size_t len) { unsigned int x; @@ -137,8 +137,11 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, if (rc) return rc;
- if (check_cb && check_cb(x)) - return -EINVAL; + if (check_cb) { + rc = check_cb(x); + if (rc) + return rc; + }
*cl_field = x; *info_field = x; @@ -161,14 +164,20 @@ static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \ } \ CONFIGFS_ATTR(cluster_, name);
-static bool dlm_check_zero(unsigned int x) +static int dlm_check_zero(unsigned int x) { - return !x; + if (!x) + return -EINVAL; + + return 0; }
-static bool dlm_check_buffer_size(unsigned int x) +static int dlm_check_buffer_size(unsigned int x) { - return (x < DEFAULT_BUFFER_SIZE); + if (x < DEFAULT_BUFFER_SIZE) + return -EINVAL; + + return 0; }
CLUSTER_ATTR(tcp_port, dlm_check_zero);
From: Alexander Aring aahringo@redhat.com
[ Upstream commit 517461630d1c25ee4dfc1dee80973a64189d6ccf ]
This patch adds checks for dlm config attributes regarding to protocol parameters as it makes only sense to change them when dlm is not running. It also adds a check for valid protocol specifiers and return invalid argument if they are not supported.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/config.c | 34 ++++++++++++++++++++++++++++++++-- fs/dlm/lowcomms.c | 2 +- fs/dlm/lowcomms.h | 3 +++ 3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 8439610c266a..88d95d96e36c 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -164,6 +164,36 @@ static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \ } \ CONFIGFS_ATTR(cluster_, name);
+static int dlm_check_protocol_and_dlm_running(unsigned int x) +{ + switch (x) { + case 0: + /* TCP */ + break; + case 1: + /* SCTP */ + break; + default: + return -EINVAL; + } + + if (dlm_allow_conn) + return -EBUSY; + + return 0; +} + +static int dlm_check_zero_and_dlm_running(unsigned int x) +{ + if (!x) + return -EINVAL; + + if (dlm_allow_conn) + return -EBUSY; + + return 0; +} + static int dlm_check_zero(unsigned int x) { if (!x) @@ -180,7 +210,7 @@ static int dlm_check_buffer_size(unsigned int x) return 0; }
-CLUSTER_ATTR(tcp_port, dlm_check_zero); +CLUSTER_ATTR(tcp_port, dlm_check_zero_and_dlm_running); CLUSTER_ATTR(buffer_size, dlm_check_buffer_size); CLUSTER_ATTR(rsbtbl_size, dlm_check_zero); CLUSTER_ATTR(recover_timer, dlm_check_zero); @@ -188,7 +218,7 @@ CLUSTER_ATTR(toss_secs, dlm_check_zero); CLUSTER_ATTR(scan_secs, dlm_check_zero); CLUSTER_ATTR(log_debug, NULL); CLUSTER_ATTR(log_info, NULL); -CLUSTER_ATTR(protocol, NULL); +CLUSTER_ATTR(protocol, dlm_check_protocol_and_dlm_running); CLUSTER_ATTR(mark, NULL); CLUSTER_ATTR(timewarn_cs, dlm_check_zero); CLUSTER_ATTR(waitwarn_us, NULL); diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index a4fabcced0f2..0f7fa23cccf0 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -135,7 +135,7 @@ static DEFINE_SPINLOCK(dlm_node_addrs_spin); static struct listen_connection listen_con; static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT]; static int dlm_local_count; -static int dlm_allow_conn; +int dlm_allow_conn;
/* Work queues */ static struct workqueue_struct *recv_workqueue; diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h index 790d6703b17e..bcd4dbd1dc98 100644 --- a/fs/dlm/lowcomms.h +++ b/fs/dlm/lowcomms.h @@ -14,6 +14,9 @@
#define LOWCOMMS_MAX_TX_BUFFER_LEN 4096
+/* switch to check if dlm is running */ +extern int dlm_allow_conn; + int dlm_lowcomms_start(void); void dlm_lowcomms_stop(void); void dlm_lowcomms_exit(void);
From: Alexander Aring aahringo@redhat.com
[ Upstream commit c45674fbdda138814ca21138475219c96fa5aa1f ]
While running tcpkill I experienced invalid header length values while receiving to check that a node doesn't try to send a invalid dlm message we also check on applications minimum allocation limit. Also use DEFAULT_BUFFER_SIZE as maximum allocation limit. The define LOWCOMMS_MAX_TX_BUFFER_LEN is to calculate maximum buffer limits on application layer, future midcomms layer will subtract their needs from this define.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/lowcomms.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 0f7fa23cccf0..f827d0b3962a 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1375,9 +1375,11 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc) struct writequeue_entry *e; int offset = 0;
- if (len > LOWCOMMS_MAX_TX_BUFFER_LEN) { - BUILD_BUG_ON(PAGE_SIZE < LOWCOMMS_MAX_TX_BUFFER_LEN); + if (len > DEFAULT_BUFFER_SIZE || + len < sizeof(struct dlm_header)) { + BUILD_BUG_ON(PAGE_SIZE < DEFAULT_BUFFER_SIZE); log_print("failed to allocate a buffer of size %d", len); + WARN_ON(1); return NULL; }
From: Alexander Aring aahringo@redhat.com
[ Upstream commit 710176e8363f269c6ecd73d203973b31ace119d3 ]
This patch adds an additional check for minimum dlm header size which is an invalid dlm message and signals a broken stream. A msglen field cannot be less than the dlm header size because the field is inclusive header lengths.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/midcomms.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index fde3a6afe4be..0bedfa8606a2 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c @@ -49,9 +49,10 @@ int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len) * cannot deliver this message to upper layers */ msglen = get_unaligned_le16(&hd->h_length); - if (msglen > DEFAULT_BUFFER_SIZE) { - log_print("received invalid length header: %u, will abort message parsing", - msglen); + if (msglen > DEFAULT_BUFFER_SIZE || + msglen < sizeof(struct dlm_header)) { + log_print("received invalid length header: %u from node %d, will abort message parsing", + msglen, nodeid); return -EBADMSG; }
From: Alexander Aring aahringo@redhat.com
[ Upstream commit eec054b5a7cfe6d1f1598a323b05771ee99857b5 ]
This patch fixes the flushing of send work before shutdown. The function cancel_work_sync() is not the right workqueue functionality to use here as it would cancel the work if the work queues itself. In cases of EAGAIN in send() for dlm message we need to be sure that everything is send out before. The function flush_work() will ensure that every send work is be done inclusive in EAGAIN cases.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/lowcomms.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index f827d0b3962a..5fe571e44b1a 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -709,10 +709,7 @@ static void shutdown_connection(struct connection *con) { int ret;
- if (cancel_work_sync(&con->swork)) { - log_print("canceled swork for node %d", con->nodeid); - clear_bit(CF_WRITE_PENDING, &con->flags); - } + flush_work(&con->swork);
mutex_lock(&con->sock_mutex); /* nothing to shutdown */
From: Alexander Aring aahringo@redhat.com
[ Upstream commit 9d232469bcd772dbedb9e75a165c681b920524ee ]
This patch fixes issues which occurs when dlm lowcomms synchronize their workqueues but dlm application layer already released the lockspace. In such cases messages like:
dlm: gfs2: release_lockspace final free dlm: invalid lockspace 3841231384 from 1 cmd 1 type 11
are printed on the kernel log. This patch is solving this issue by introducing a new "shutdown" hook before calling "stop" hook when the lockspace is going to be released finally. This should pretend any dlm messages sitting in the workqueues during or after lockspace removal.
It's necessary to call dlm_scand_stop() as I instrumented dlm_lowcomms_get_buffer() code to report a warning after it's called after dlm_midcomms_shutdown() functionality, see below:
WARNING: CPU: 1 PID: 3794 at fs/dlm/midcomms.c:1003 dlm_midcomms_get_buffer+0x167/0x180 Modules linked in: joydev iTCO_wdt intel_pmc_bxt iTCO_vendor_support drm_ttm_helper ttm pcspkr serio_raw i2c_i801 i2c_smbus drm_kms_helper virtio_scsi lpc_ich virtio_balloon virtio_console xhci_pci xhci_pci_renesas cec qemu_fw_cfg drm [last unloaded: qxl] CPU: 1 PID: 3794 Comm: dlm_scand Tainted: G W 5.11.0+ #26 Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.13.0-2.module+el8.3.0+7353+9de0a3cc 04/01/2014 RIP: 0010:dlm_midcomms_get_buffer+0x167/0x180 Code: 5d 41 5c 41 5d 41 5e 41 5f c3 0f 0b 45 31 e4 5b 5d 4c 89 e0 41 5c 41 5d 41 5e 41 5f c3 4c 89 e7 45 31 e4 e8 3b f1 ec ff eb 86 <0f> 0b 4c 89 e7 45 31 e4 e8 2c f1 ec ff e9 74 ff ff ff 0f 1f 80 00 RSP: 0018:ffffa81503f8fe60 EFLAGS: 00010202 RAX: 0000000000000008 RBX: ffff8f969827f200 RCX: 0000000000000001 RDX: 0000000000000000 RSI: ffffffffad1e89a0 RDI: ffff8f96a5294160 RBP: 0000000000000001 R08: 0000000000000000 R09: ffff8f96a250bc60 R10: 00000000000045d3 R11: 0000000000000000 R12: ffff8f96a250bc60 R13: ffffa81503f8fec8 R14: 0000000000000070 R15: 0000000000000c40 FS: 0000000000000000(0000) GS:ffff8f96fbc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055aa3351c000 CR3: 000000010bf22000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: dlm_scan_rsbs+0x420/0x670 ? dlm_uevent+0x20/0x20 dlm_scand+0xbf/0xe0 kthread+0x13a/0x150 ? __kthread_bind_mask+0x60/0x60 ret_from_fork+0x22/0x30
To synchronize all dlm scand messages we stop it right before shutdown hook.
Signed-off-by: Alexander Aring aahringo@redhat.com Signed-off-by: David Teigland teigland@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dlm/lockspace.c | 20 +++++++++++--------- fs/dlm/lowcomms.c | 42 +++++++++++++++++++++++------------------- fs/dlm/lowcomms.h | 1 + 3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 561dcad08ad6..c14cf2b7faab 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -404,12 +404,6 @@ static int threads_start(void) return error; }
-static void threads_stop(void) -{ - dlm_scand_stop(); - dlm_lowcomms_stop(); -} - static int new_lockspace(const char *name, const char *cluster, uint32_t flags, int lvblen, const struct dlm_lockspace_ops *ops, void *ops_arg, @@ -702,8 +696,11 @@ int dlm_new_lockspace(const char *name, const char *cluster, ls_count++; if (error > 0) error = 0; - if (!ls_count) - threads_stop(); + if (!ls_count) { + dlm_scand_stop(); + dlm_lowcomms_shutdown(); + dlm_lowcomms_stop(); + } out: mutex_unlock(&ls_lock); return error; @@ -788,6 +785,11 @@ static int release_lockspace(struct dlm_ls *ls, int force)
dlm_recoverd_stop(ls);
+ if (ls_count == 1) { + dlm_scand_stop(); + dlm_lowcomms_shutdown(); + } + dlm_callback_stop(ls);
remove_lockspace(ls); @@ -880,7 +882,7 @@ int dlm_release_lockspace(void *lockspace, int force) if (!error) ls_count--; if (!ls_count) - threads_stop(); + dlm_lowcomms_stop(); mutex_unlock(&ls_lock);
return error; diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 5fe571e44b1a..45c2fdaf34c4 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1608,6 +1608,29 @@ static int work_start(void) return 0; }
+static void shutdown_conn(struct connection *con) +{ + if (con->shutdown_action) + con->shutdown_action(con); +} + +void dlm_lowcomms_shutdown(void) +{ + /* Set all the flags to prevent any + * socket activity. + */ + dlm_allow_conn = 0; + + if (recv_workqueue) + flush_workqueue(recv_workqueue); + if (send_workqueue) + flush_workqueue(send_workqueue); + + dlm_close_sock(&listen_con.sock); + + foreach_conn(shutdown_conn); +} + static void _stop_conn(struct connection *con, bool and_other) { mutex_lock(&con->sock_mutex); @@ -1629,12 +1652,6 @@ static void stop_conn(struct connection *con) _stop_conn(con, true); }
-static void shutdown_conn(struct connection *con) -{ - if (con->shutdown_action) - con->shutdown_action(con); -} - static void connection_release(struct rcu_head *rcu) { struct connection *con = container_of(rcu, struct connection, rcu); @@ -1691,19 +1708,6 @@ static void work_flush(void)
void dlm_lowcomms_stop(void) { - /* Set all the flags to prevent any - socket activity. - */ - dlm_allow_conn = 0; - - if (recv_workqueue) - flush_workqueue(recv_workqueue); - if (send_workqueue) - flush_workqueue(send_workqueue); - - dlm_close_sock(&listen_con.sock); - - foreach_conn(shutdown_conn); work_flush(); foreach_conn(free_conn); work_stop(); diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h index bcd4dbd1dc98..48bbc4e18761 100644 --- a/fs/dlm/lowcomms.h +++ b/fs/dlm/lowcomms.h @@ -18,6 +18,7 @@ extern int dlm_allow_conn;
int dlm_lowcomms_start(void); +void dlm_lowcomms_shutdown(void); void dlm_lowcomms_stop(void); void dlm_lowcomms_exit(void); int dlm_lowcomms_close(int nodeid);
From: Hoang Le hoang.h.le@dektech.com.au
[ Upstream commit 1980d37565061ab44bdc2f9e4da477d3b9752e81 ]
(struct tipc_link_info)->dest is in network order (__be32), so we must convert the value to network order before assigning. The problem detected by sparse:
net/tipc/netlink_compat.c:699:24: warning: incorrect type in assignment (different base types) net/tipc/netlink_compat.c:699:24: expected restricted __be32 [usertype] dest net/tipc/netlink_compat.c:699:24: got int
Acked-by: Jon Maloy jmaloy@redhat.com Signed-off-by: Hoang Le hoang.h.le@dektech.com.au Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/tipc/netlink_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 5a1ce64039f7..0749df80454d 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -696,7 +696,7 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg, if (err) return err;
- link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]); + link_info.dest = htonl(nla_get_flag(link[TIPC_NLA_LINK_DEST])); link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP])); nla_strscpy(link_info.str, link[TIPC_NLA_LINK_NAME], TIPC_MAX_LINK_NAME);
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit b7c7203a1f751348f35fc4bcb157572d303f7573 ]
The Asus T100TAF uses the same jack-detect settings as the T100TA, this has been confirmed on actual hardware.
Add these settings to the T100TAF quirks to enable jack-detect support on the T100TAF.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20210312114850.13832-1-hdegoede@redhat.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/bytcr_rt5640.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5d48cc359c3d..19faababb78d 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -482,6 +482,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), }, .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | BYT_RT5640_MONO_SPEAKER | BYT_RT5640_DIFF_MIC | BYT_RT5640_SSP0_AIF2 |
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit 991b2654605b455a94dac73e14b23480e7e20991 ]
Commit e20f0dbf204f ("net/mlx5e: RX, Add a prefetch command for small L1_CACHE_BYTES") switched to using net_prefetchw at all places in mlx5e. In the same time frame, commit 5af75c747e2a ("net/mlx5e: Enhanced TX MPWQE for SKBs") added one more usage of prefetchw. When these two changes were merged, this new occurrence of prefetchw wasn't replaced with net_prefetchw.
This commit fixes this last occurrence of prefetchw in mlx5e_tx_mpwqe_session_start, making the same change that was done in mlx5e_xdp_mpwqe_session_start.
Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Saeed Mahameed saeedm@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index bdbffe484fce..d2efe2455955 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -576,7 +576,7 @@ static void mlx5e_tx_mpwqe_session_start(struct mlx5e_txqsq *sq,
pi = mlx5e_txqsq_get_next_pi(sq, MLX5E_TX_MPW_MAX_WQEBBS); wqe = MLX5E_TX_FETCH_WQE(sq, pi); - prefetchw(wqe->data); + net_prefetchw(wqe->data);
*session = (struct mlx5e_tx_mpwqe) { .wqe = wqe,
From: Jonathan McDowell noodles@earth.li
[ Upstream commit e127906b68b49ddb3ecba39ffa36a329c48197d3 ]
Commit eaf4fac47807 ("net: stmmac: Do not accept invalid MTU values") started using the TX FIFO size to verify what counts as a valid MTU request for the stmmac driver. This is unset for the ipq806x variant. Looking at older patches for this it seems the RX + TXs buffers can be up to 8k, so set appropriately.
(I sent this as an RFC patch in June last year, but received no replies. I've been running with this on my hardware (a MikroTik RB3011) since then with larger MTUs to support both the internal qca8k switch and VLANs with no problems. Without the patch it's impossible to set the larger MTU required to support this.)
Signed-off-by: Jonathan McDowell noodles@earth.li Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index bf3250e0e59c..749585fe6fc9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -352,6 +352,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) plat_dat->bsp_priv = gmac; plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; plat_dat->multicast_filter_bins = 0; + plat_dat->tx_fifo_size = 8192; + plat_dat->rx_fifo_size = 8192;
err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (err)
From: Mikhail Durnev mikhail_durnev@mentor.com
[ Upstream commit 19c6a63ced5e07e40f3a5255cb1f0fe0d3be7b14 ]
snd_pcm_hw_params_set_rate_near can return incorrect sample rate in some cases, e.g. when the backend output rate is set to some value higher than 48000 Hz and the input rate is 8000 Hz. So passing the value returned by snd_pcm_hw_params_set_rate_near to snd_pcm_hw_params will result in "FSO/FSI ratio error" and playing no audio at all while the userland is not properly notified about the issue.
If SRC is unable to convert the requested sample rate to the sample rate the backend is using, then the requested sample rate should be adjusted in rsnd_hw_params. The userland will be notified about that change in the returned hw_params structure.
Signed-off-by: Mikhail Durnev mikhail_durnev@mentor.com Link: https://lore.kernel.org/r/1615870055-13954-1-git-send-email-mikhail_durnev@m... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sh/rcar/core.c | 69 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1029d8d9d800..d2b4632d9c2a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1428,8 +1428,75 @@ static int rsnd_hw_params(struct snd_soc_component *component, } if (io->converted_chan) dev_dbg(dev, "convert channels = %d\n", io->converted_chan); - if (io->converted_rate) + if (io->converted_rate) { + /* + * SRC supports convert rates from params_rate(hw_params)/k_down + * to params_rate(hw_params)*k_up, where k_up is always 6, and + * k_down depends on number of channels and SRC unit. + * So all SRC units can upsample audio up to 6 times regardless + * its number of channels. And all SRC units can downsample + * 2 channel audio up to 6 times too. + */ + int k_up = 6; + int k_down = 6; + int channel; + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + dev_dbg(dev, "convert rate = %d\n", io->converted_rate); + + channel = io->converted_chan ? io->converted_chan : + params_channels(hw_params); + + switch (rsnd_mod_id(src_mod)) { + /* + * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 4 channel audio + * up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio + * no more than twice. + */ + case 1: + case 3: + case 4: + if (channel > 4) { + k_down = 2; + break; + } + fallthrough; + case 0: + if (channel > 2) + k_down = 4; + break; + + /* Other SRC units do not support more than 2 channels */ + default: + if (channel > 2) + return -EINVAL; + } + + if (params_rate(hw_params) > io->converted_rate * k_down) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + io->converted_rate * k_down; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + io->converted_rate * k_down; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } else if (params_rate(hw_params) * k_up < io->converted_rate) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + (io->converted_rate + k_up - 1) / k_up; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + (io->converted_rate + k_up - 1) / k_up; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } + + /* + * TBD: Max SRC input and output rates also depend on number + * of channels and SRC unit: + * SRC1, SRC3 and SRC4 do not support more than 128kHz + * for 6 channel and 96kHz for 8 channel audio. + * Perhaps this function should return EINVAL if the input or + * the output rate exceeds the limitation. + */ + } }
return rsnd_dai_call(hw_params, io, substream, hw_params);
From: Ayush Garg ayush.garg@samsung.com
[ Upstream commit 87df8bcccd2cede62dfb97dc3d4ca1fe66cb4f83 ]
Skip updation of tx and rx PHYs values, when PHY Update event's status is not successful.
Signed-off-by: Ayush Garg ayush.garg@samsung.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7a3e42e75235..82f4973a011d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -5912,7 +5912,7 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
- if (!ev->status) + if (ev->status) return;
hci_dev_lock(hdev);
From: Wolfram Sang wsa+renesas@sang-engineering.com
[ Upstream commit 71581562ee36032d2d574a9b23ad4af6d6a64cf7 ]
The buggy parameters currently get caught later, but emit a noisy WARN. Userspace should not be able to trigger this, so add similar checks much earlier. Also avoids some unneeded code paths, of course. Apply kernel coding stlye to a comment while here.
Reported-by: syzbot+ffb0b3ffa6cfbc7d7b3f@syzkaller.appspotmail.com Tested-by: syzbot+ffb0b3ffa6cfbc7d7b3f@syzkaller.appspotmail.com Signed-off-by: Wolfram Sang wsa+renesas@sang-engineering.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/i2c-dev.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 6ceb11cc4be1..6ef38a8ee95c 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -440,8 +440,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) sizeof(rdwr_arg))) return -EFAULT;
- /* Put an arbitrary limit on the number of messages that can - * be sent at once */ + if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0) + return -EINVAL; + + /* + * Put an arbitrary limit on the number of messages that can + * be sent at once + */ if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) return -EINVAL;
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit 507cdb9adba006a7798c358456426e1aea3d9c4f ]
hdsp wants to disable a not enabled pci device, which makes kernel throw a warning. Make sure the device is enabled before calling disable.
[ 1.758292] snd_hdsp 0000:00:03.0: disabling already-disabled device [ 1.758327] WARNING: CPU: 0 PID: 180 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 [ 1.766985] Call Trace: [ 1.767121] snd_hdsp_card_free+0x94/0xf0 [snd_hdsp] [ 1.767388] release_card_device+0x4b/0x80 [snd] [ 1.767639] device_release+0x3b/0xa0 [ 1.767838] kobject_put+0x94/0x1b0 [ 1.768027] put_device+0x13/0x20 [ 1.768207] snd_card_free+0x61/0x90 [snd] [ 1.768430] snd_hdsp_probe+0x524/0x5e0 [snd_hdsp]
Suggested-by: Takashi Iwai tiwai@suse.de Signed-off-by: Tong Zhang ztong0001@gmail.com Link: https://lore.kernel.org/r/20210321153840.378226-2-ztong0001@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/rme9652/hdsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 4cf879c42dc4..720297cbdf87 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -5390,7 +5390,8 @@ static int snd_hdsp_free(struct hdsp *hdsp) if (hdsp->port) pci_release_regions(hdsp->pci);
- pci_disable_device(hdsp->pci); + if (pci_is_enabled(hdsp->pci)) + pci_disable_device(hdsp->pci); return 0; }
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit 790f5719b85e12e10c41753b864e74249585ed08 ]
hdspm wants to disable a not enabled pci device, which makes kernel throw a warning. Make sure the device is enabled before calling disable.
[ 1.786391] snd_hdspm 0000:00:03.0: disabling already-disabled device [ 1.786400] WARNING: CPU: 0 PID: 182 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 [ 1.795181] Call Trace: [ 1.795320] snd_hdspm_card_free+0x58/0xa0 [snd_hdspm] [ 1.795595] release_card_device+0x4b/0x80 [snd] [ 1.795860] device_release+0x3b/0xa0 [ 1.796072] kobject_put+0x94/0x1b0 [ 1.796260] put_device+0x13/0x20 [ 1.796438] snd_card_free+0x61/0x90 [snd] [ 1.796659] snd_hdspm_probe+0x97b/0x1440 [snd_hdspm]
Suggested-by: Takashi Iwai tiwai@suse.de Signed-off-by: Tong Zhang ztong0001@gmail.com Link: https://lore.kernel.org/r/20210321153840.378226-3-ztong0001@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/rme9652/hdspm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 8d900c132f0f..97a0bff96b28 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6883,7 +6883,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) if (hdspm->port) pci_release_regions(hdspm->pci);
- pci_disable_device(hdspm->pci); + if (pci_is_enabled(hdspm->pci)) + pci_disable_device(hdspm->pci); return 0; }
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit f57a741874bb6995089020e97a1dcdf9b165dcbe ]
rme9652 wants to disable a not enabled pci device, which makes kernel throw a warning. Make sure the device is enabled before calling disable.
[ 1.751595] snd_rme9652 0000:00:03.0: disabling already-disabled device [ 1.751605] WARNING: CPU: 0 PID: 174 at drivers/pci/pci.c:2146 pci_disable_device+0x91/0xb0 [ 1.759968] Call Trace: [ 1.760145] snd_rme9652_card_free+0x76/0xa0 [snd_rme9652] [ 1.760434] release_card_device+0x4b/0x80 [snd] [ 1.760679] device_release+0x3b/0xa0 [ 1.760874] kobject_put+0x94/0x1b0 [ 1.761059] put_device+0x13/0x20 [ 1.761235] snd_card_free+0x61/0x90 [snd] [ 1.761454] snd_rme9652_probe+0x3be/0x700 [snd_rme9652]
Suggested-by: Takashi Iwai tiwai@suse.de Signed-off-by: Tong Zhang ztong0001@gmail.com Link: https://lore.kernel.org/r/20210321153840.378226-4-ztong0001@gmail.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/rme9652/rme9652.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 4df992e846f2..7a4d395abcee 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1731,7 +1731,8 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652) if (rme9652->port) pci_release_regions(rme9652->pci);
- pci_disable_device(rme9652->pci); + if (pci_is_enabled(rme9652->pci)) + pci_disable_device(rme9652->pci); return 0; }
From: Takashi Sakamoto o-takashi@sakamocchi.jp
[ Upstream commit d2b6f15bc18ac8fbce25398290774c21f5b2cd44 ]
Current implementation of bebob driver doesn't correctly handle the case that the device has multiple MIDI ports. The cause is the number of MIDI conformant data channels is passed to AM824 data block processing layer.
This commit fixes the bug.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp Link: https://lore.kernel.org/r/20210321032831.340278-4-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/firewire/bebob/bebob_stream.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index bbae04793c50..c18017e0a3d9 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -517,20 +517,22 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, unsigned int rate, unsigned int index) { - struct snd_bebob_stream_formation *formation; + unsigned int pcm_channels; + unsigned int midi_ports; struct cmp_connection *conn; int err;
if (stream == &bebob->tx_stream) { - formation = bebob->tx_stream_formations + index; + pcm_channels = bebob->tx_stream_formations[index].pcm; + midi_ports = bebob->midi_input_ports; conn = &bebob->out_conn; } else { - formation = bebob->rx_stream_formations + index; + pcm_channels = bebob->rx_stream_formations[index].pcm; + midi_ports = bebob->midi_output_ports; conn = &bebob->in_conn; }
- err = amdtp_am824_set_parameters(stream, rate, formation->pcm, - formation->midi, false); + err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false); if (err < 0) return err;
From: Archie Pusaka apusaka@chromium.org
[ Upstream commit 3a9d54b1947ecea8eea9a902c0b7eb58a98add8a ]
Currently l2cap_chan_set_defaults() reset chan->conf_state to zero. However, there is a flag CONF_NOT_COMPLETE which is set when creating the l2cap_chan. It is suggested that the flag should be cleared when l2cap_chan is ready, but when l2cap_chan_set_defaults() is called, l2cap_chan is not yet ready. Therefore, we must set this flag as the default.
Example crash call trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xc4/0x118 lib/dump_stack.c:56 panic+0x1c6/0x38b kernel/panic.c:117 __warn+0x170/0x1b9 kernel/panic.c:471 warn_slowpath_fmt+0xc7/0xf8 kernel/panic.c:494 debug_print_object+0x175/0x193 lib/debugobjects.c:260 debug_object_assert_init+0x171/0x1bf lib/debugobjects.c:614 debug_timer_assert_init kernel/time/timer.c:629 [inline] debug_assert_init kernel/time/timer.c:677 [inline] del_timer+0x7c/0x179 kernel/time/timer.c:1034 try_to_grab_pending+0x81/0x2e5 kernel/workqueue.c:1230 cancel_delayed_work+0x7c/0x1c4 kernel/workqueue.c:2929 l2cap_clear_timer+0x1e/0x41 include/net/bluetooth/l2cap.h:834 l2cap_chan_del+0x2d8/0x37e net/bluetooth/l2cap_core.c:640 l2cap_chan_close+0x532/0x5d8 net/bluetooth/l2cap_core.c:756 l2cap_sock_shutdown+0x806/0x969 net/bluetooth/l2cap_sock.c:1174 l2cap_sock_release+0x64/0x14d net/bluetooth/l2cap_sock.c:1217 __sock_release+0xda/0x217 net/socket.c:580 sock_close+0x1b/0x1f net/socket.c:1039 __fput+0x322/0x55c fs/file_table.c:208 ____fput+0x17/0x19 fs/file_table.c:244 task_work_run+0x19b/0x1d3 kernel/task_work.c:115 exit_task_work include/linux/task_work.h:21 [inline] do_exit+0xe4c/0x204a kernel/exit.c:766 do_group_exit+0x291/0x291 kernel/exit.c:891 get_signal+0x749/0x1093 kernel/signal.c:2396 do_signal+0xa5/0xcdb arch/x86/kernel/signal.c:737 exit_to_usermode_loop arch/x86/entry/common.c:243 [inline] prepare_exit_to_usermode+0xed/0x235 arch/x86/entry/common.c:277 syscall_return_slowpath+0x3a7/0x3b3 arch/x86/entry/common.c:348 int_ret_from_sys_call+0x25/0xa3
Signed-off-by: Archie Pusaka apusaka@chromium.org Reported-by: syzbot+338f014a98367a08a114@syzkaller.appspotmail.com Reviewed-by: Alain Michaud alainm@chromium.org Reviewed-by: Abhishek Pandit-Subedi abhishekpandit@chromium.org Reviewed-by: Guenter Roeck groeck@chromium.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 72c2f5226d67..db6a4b2d0d77 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -516,7 +516,9 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO; chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO; + chan->conf_state = 0; + set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
set_bit(FLAG_FORCE_ACTIVE, &chan->flags); }
From: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp
[ Upstream commit be8597239379f0f53c9710dd6ab551bbf535bec6 ]
syzbot is hitting "INFO: trying to register non-static key." message [1], for "struct l2cap_chan"->tx_q.lock spinlock is not yet initialized when l2cap_chan_del() is called due to e.g. timeout.
Since "struct l2cap_chan"->lock mutex is initialized at l2cap_chan_create() immediately after "struct l2cap_chan" is allocated using kzalloc(), let's as well initialize "struct l2cap_chan"->{tx_q,srej_q}.lock spinlocks there.
[1] https://syzkaller.appspot.com/bug?extid=fadfba6a911f6bf71842
Reported-and-tested-by: syzbot syzbot+fadfba6a911f6bf71842@syzkaller.appspotmail.com Signed-off-by: Tetsuo Handa penguin-kernel@I-love.SAKURA.ne.jp Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index db6a4b2d0d77..53ddbee459b9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -451,6 +451,8 @@ struct l2cap_chan *l2cap_chan_create(void) if (!chan) return NULL;
+ skb_queue_head_init(&chan->tx_q); + skb_queue_head_init(&chan->srej_q); mutex_init(&chan->lock);
/* Set default lock nesting level */
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 6215afcb9a7e35cef334dc0ae7f998cc72c8465f ]
A make W=1 build complains that:
net/sched/cls_flower.c:214:20: warning: cast from restricted __be16 net/sched/cls_flower.c:214:20: warning: incorrect type in argument 1 (different base types) net/sched/cls_flower.c:214:20: expected unsigned short [usertype] val net/sched/cls_flower.c:214:20: got restricted __be16 [usertype] dst
This is because we use htons on struct flow_dissector_key_ports members src and dst, which are defined as __be16, so they are already in network byte order, not host. The byte swap function for the other direction should have been used.
Because htons and ntohs do the same thing (either both swap, or none does), this change has no functional effect except to silence the warnings.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/cls_flower.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index c69a4ba9c33f..3035f96c6e6c 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -209,16 +209,16 @@ static bool fl_range_port_dst_cmp(struct cls_fl_filter *filter, struct fl_flow_key *key, struct fl_flow_key *mkey) { - __be16 min_mask, max_mask, min_val, max_val; + u16 min_mask, max_mask, min_val, max_val;
- min_mask = htons(filter->mask->key.tp_range.tp_min.dst); - max_mask = htons(filter->mask->key.tp_range.tp_max.dst); - min_val = htons(filter->key.tp_range.tp_min.dst); - max_val = htons(filter->key.tp_range.tp_max.dst); + min_mask = ntohs(filter->mask->key.tp_range.tp_min.dst); + max_mask = ntohs(filter->mask->key.tp_range.tp_max.dst); + min_val = ntohs(filter->key.tp_range.tp_min.dst); + max_val = ntohs(filter->key.tp_range.tp_max.dst);
if (min_mask && max_mask) { - if (htons(key->tp_range.tp.dst) < min_val || - htons(key->tp_range.tp.dst) > max_val) + if (ntohs(key->tp_range.tp.dst) < min_val || + ntohs(key->tp_range.tp.dst) > max_val) return false;
/* skb does not have min and max values */ @@ -232,16 +232,16 @@ static bool fl_range_port_src_cmp(struct cls_fl_filter *filter, struct fl_flow_key *key, struct fl_flow_key *mkey) { - __be16 min_mask, max_mask, min_val, max_val; + u16 min_mask, max_mask, min_val, max_val;
- min_mask = htons(filter->mask->key.tp_range.tp_min.src); - max_mask = htons(filter->mask->key.tp_range.tp_max.src); - min_val = htons(filter->key.tp_range.tp_min.src); - max_val = htons(filter->key.tp_range.tp_max.src); + min_mask = ntohs(filter->mask->key.tp_range.tp_min.src); + max_mask = ntohs(filter->mask->key.tp_range.tp_max.src); + min_val = ntohs(filter->key.tp_range.tp_min.src); + max_val = ntohs(filter->key.tp_range.tp_max.src);
if (min_mask && max_mask) { - if (htons(key->tp_range.tp.src) < min_val || - htons(key->tp_range.tp.src) > max_val) + if (ntohs(key->tp_range.tp.src) < min_val || + ntohs(key->tp_range.tp.src) > max_val) return false;
/* skb does not have min and max values */ @@ -783,16 +783,16 @@ static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key, TCA_FLOWER_UNSPEC, sizeof(key->tp_range.tp_max.src));
if (mask->tp_range.tp_min.dst && mask->tp_range.tp_max.dst && - htons(key->tp_range.tp_max.dst) <= - htons(key->tp_range.tp_min.dst)) { + ntohs(key->tp_range.tp_max.dst) <= + ntohs(key->tp_range.tp_min.dst)) { NL_SET_ERR_MSG_ATTR(extack, tb[TCA_FLOWER_KEY_PORT_DST_MIN], "Invalid destination port range (min must be strictly smaller than max)"); return -EINVAL; } if (mask->tp_range.tp_min.src && mask->tp_range.tp_max.src && - htons(key->tp_range.tp_max.src) <= - htons(key->tp_range.tp_min.src)) { + ntohs(key->tp_range.tp_max.src) <= + ntohs(key->tp_range.tp_min.src)) { NL_SET_ERR_MSG_ATTR(extack, tb[TCA_FLOWER_KEY_PORT_SRC_MIN], "Invalid source port range (min must be strictly smaller than max)");
From: Nikolay Aleksandrov nikolay@nvidia.com
[ Upstream commit 0353b4a96b7a9f60fe20d1b3ebd4931a4085f91c ]
Recently we had an interop issue where RARP packets got suppressed with bridge neigh suppression enabled, but the check in the code was meant to suppress GARP. Exclude RARP packets from it which would allow some VMWare setups to work, to quote the report: "Those RARP packets usually get generated by vMware to notify physical switches when vMotion occurs. vMware may use random sip/tip or just use sip=tip=0. So the RARP packet sometimes get properly flooded by the vtep and other times get dropped by the logic"
Reported-by: Amer Abdalamer amer@nvidia.com Signed-off-by: Nikolay Aleksandrov nikolay@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/bridge/br_arp_nd_proxy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c index dfec65eca8a6..3db1def4437b 100644 --- a/net/bridge/br_arp_nd_proxy.c +++ b/net/bridge/br_arp_nd_proxy.c @@ -160,7 +160,9 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { if (p && (p->flags & BR_NEIGH_SUPPRESS)) return; - if (ipv4_is_zeronet(sip) || sip == tip) { + if (parp->ar_op != htons(ARPOP_RREQUEST) && + parp->ar_op != htons(ARPOP_RREPLY) && + (ipv4_is_zeronet(sip) || sip == tip)) { /* prevent flooding to neigh suppress ports */ BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; return;
From: Archie Pusaka apusaka@chromium.org
[ Upstream commit 3af70b39fa2d415dc86c370e5b24ddb9fdacbd6f ]
There is a possibility of receiving a zapped sock on l2cap_sock_connect(). This could lead to interesting crashes, one such case is tearing down an already tore l2cap_sock as is happened with this call trace:
__dump_stack lib/dump_stack.c:15 [inline] dump_stack+0xc4/0x118 lib/dump_stack.c:56 register_lock_class kernel/locking/lockdep.c:792 [inline] register_lock_class+0x239/0x6f6 kernel/locking/lockdep.c:742 __lock_acquire+0x209/0x1e27 kernel/locking/lockdep.c:3105 lock_acquire+0x29c/0x2fb kernel/locking/lockdep.c:3599 __raw_spin_lock_bh include/linux/spinlock_api_smp.h:137 [inline] _raw_spin_lock_bh+0x38/0x47 kernel/locking/spinlock.c:175 spin_lock_bh include/linux/spinlock.h:307 [inline] lock_sock_nested+0x44/0xfa net/core/sock.c:2518 l2cap_sock_teardown_cb+0x88/0x2fb net/bluetooth/l2cap_sock.c:1345 l2cap_chan_del+0xa3/0x383 net/bluetooth/l2cap_core.c:598 l2cap_chan_close+0x537/0x5dd net/bluetooth/l2cap_core.c:756 l2cap_chan_timeout+0x104/0x17e net/bluetooth/l2cap_core.c:429 process_one_work+0x7e3/0xcb0 kernel/workqueue.c:2064 worker_thread+0x5a5/0x773 kernel/workqueue.c:2196 kthread+0x291/0x2a6 kernel/kthread.c:211 ret_from_fork+0x4e/0x80 arch/x86/entry/entry_64.S:604
Signed-off-by: Archie Pusaka apusaka@chromium.org Reported-by: syzbot+abfc0f5e668d4099af73@syzkaller.appspotmail.com Reviewed-by: Alain Michaud alainm@chromium.org Reviewed-by: Abhishek Pandit-Subedi abhishekpandit@chromium.org Reviewed-by: Guenter Roeck groeck@chromium.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_sock.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f1b1edd0b697..c99d65ef13b1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -179,9 +179,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct sockaddr_l2 la; int len, err = 0; + bool zapped;
BT_DBG("sk %p", sk);
+ lock_sock(sk); + zapped = sock_flag(sk, SOCK_ZAPPED); + release_sock(sk); + + if (zapped) + return -EINVAL; + if (!addr || alen < offsetofend(struct sockaddr, sa_family) || addr->sa_family != AF_BLUETOOTH) return -EINVAL;
From: Russell Currey ruscur@russell.cc
[ Upstream commit 3a72c94ebfb1f171eba0715998010678a09ec796 ]
The rfi_flush and entry_flush selftests work by using the PM_LD_MISS_L1 perf event to count L1D misses. The value of this event has changed over time:
- Power7 uses 0x400f0 - Power8 and Power9 use both 0x400f0 and 0x3e054 - Power10 uses only 0x3e054
Rather than relying on raw values, configure perf to count L1D read misses in the most explicit way available.
This fixes the selftests to work on systems without 0x400f0 as PM_LD_MISS_L1, and should change no behaviour for systems that the tests already worked on.
The only potential downside is that referring to a specific perf event requires PMU support implemented in the kernel for that platform.
Signed-off-by: Russell Currey ruscur@russell.cc Acked-by: Daniel Axtens dja@axtens.net Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210223070227.2916871-1-ruscur@russell.cc Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/powerpc/security/entry_flush.c | 2 +- tools/testing/selftests/powerpc/security/flush_utils.h | 4 ++++ tools/testing/selftests/powerpc/security/rfi_flush.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/powerpc/security/entry_flush.c b/tools/testing/selftests/powerpc/security/entry_flush.c index 78cf914fa321..68ce377b205e 100644 --- a/tools/testing/selftests/powerpc/security/entry_flush.c +++ b/tools/testing/selftests/powerpc/security/entry_flush.c @@ -53,7 +53,7 @@ int entry_flush_test(void)
entry_flush = entry_flush_orig;
- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1); + fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1); FAIL_IF(fd < 0);
p = (char *)memalign(zero_size, CACHELINE_SIZE); diff --git a/tools/testing/selftests/powerpc/security/flush_utils.h b/tools/testing/selftests/powerpc/security/flush_utils.h index 07a5eb301466..7a3d60292916 100644 --- a/tools/testing/selftests/powerpc/security/flush_utils.h +++ b/tools/testing/selftests/powerpc/security/flush_utils.h @@ -9,6 +9,10 @@
#define CACHELINE_SIZE 128
+#define PERF_L1D_READ_MISS_CONFIG ((PERF_COUNT_HW_CACHE_L1D) | \ + (PERF_COUNT_HW_CACHE_OP_READ << 8) | \ + (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)) + void syscall_loop(char *p, unsigned long iterations, unsigned long zero_size);
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c index 7565fd786640..f73484a6470f 100644 --- a/tools/testing/selftests/powerpc/security/rfi_flush.c +++ b/tools/testing/selftests/powerpc/security/rfi_flush.c @@ -54,7 +54,7 @@ int rfi_flush_test(void)
rfi_flush = rfi_flush_orig;
- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1); + fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1); FAIL_IF(fd < 0);
p = (char *)memalign(zero_size, CACHELINE_SIZE);
From: Kai Vehmanen kai.vehmanen@linux.intel.com
[ Upstream commit e839fbed26e8b8713803b8ac73da92fd2b0c7594 ]
Increase the device select range to 4 on platforms supporting 4 concurrent displays.
This fixes a problem in scenario where total of 4 displays are active, and 3 of these are audio capable DP receivers and connected to a DP-MST hub. Due to incorrect range for device select, audio could not be played to the 3rd monitor in DP-MST hub.
BugLink: https://github.com/thesofproject/linux/issues/2798 Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Link: https://lore.kernel.org/r/20210324172337.51730-1-kai.vehmanen@linux.intel.co... Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/patch_hdmi.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 45ae845e82df..5de3666a7101 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1848,16 +1848,12 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) */ if (spec->intel_hsw_fixup) { /* - * On Intel platforms, device entries number is - * changed dynamically. If there is a DP MST - * hub connected, the device entries number is 3. - * Otherwise, it is 1. - * Here we manually set dev_num to 3, so that - * we can initialize all the device entries when - * bootup statically. + * On Intel platforms, device entries count returned + * by AC_PAR_DEVLIST_LEN is dynamic, and depends on + * the type of receiver that is connected. Allocate pin + * structures based on worst case. */ - dev_num = 3; - spec->dev_num = 3; + dev_num = spec->dev_num; } else if (spec->dyn_pcm_assign && codec->dp_mst) { dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1; /* @@ -2942,7 +2938,7 @@ static int parse_intel_hdmi(struct hda_codec *codec)
/* Intel Haswell and onwards; audio component with eld notifier */ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, - const int *port_map, int port_num) + const int *port_map, int port_num, int dev_num) { struct hdmi_spec *spec; int err; @@ -2957,6 +2953,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, spec->port_map = port_map; spec->port_num = port_num; spec->intel_hsw_fixup = true; + spec->dev_num = dev_num;
intel_haswell_enable_all_pins(codec, true); intel_haswell_fixup_enable_dp12(codec); @@ -2982,12 +2979,12 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
static int patch_i915_hsw_hdmi(struct hda_codec *codec) { - return intel_hsw_common_init(codec, 0x08, NULL, 0); + return intel_hsw_common_init(codec, 0x08, NULL, 0, 3); }
static int patch_i915_glk_hdmi(struct hda_codec *codec) { - return intel_hsw_common_init(codec, 0x0b, NULL, 0); + return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3); }
static int patch_i915_icl_hdmi(struct hda_codec *codec) @@ -2998,7 +2995,7 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec) */ static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb};
- return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); + return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3); }
static int patch_i915_tgl_hdmi(struct hda_codec *codec) @@ -3010,7 +3007,7 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; int ret;
- ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); + ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4); if (!ret) { struct hdmi_spec *spec = codec->spec;
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit a4719f5bb6d7dc220bffdc1b9f5ce5eaa5543581 ]
The check of the emergency context initialisation in vmap_stack_overflow is buggy for the SMP case, as it compares r1 with 0 while in the SMP case r1 is offseted by the CPU id.
Instead of fixing it, just perform static initialisation of the first emergency context.
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/4a67ba422be75713286dca0c86ee0d3df2eb6dfa.161555286... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/head_32.h | 6 +----- arch/powerpc/kernel/setup_32.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h index 5d4706c14572..cf8ca08295bf 100644 --- a/arch/powerpc/kernel/head_32.h +++ b/arch/powerpc/kernel/head_32.h @@ -261,11 +261,7 @@ label: lis r1, emergency_ctx@ha #endif lwz r1, emergency_ctx@l(r1) - cmpwi cr1, r1, 0 - bne cr1, 1f - lis r1, init_thread_union@ha - addi r1, r1, init_thread_union@l -1: addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE + addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE EXCEPTION_PROLOG_2 SAVE_NVGPRS(r11) addi r3, r1, STACK_FRAME_OVERHEAD diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 8ba49a6bf515..d7c1f92152af 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -164,7 +164,7 @@ void __init irqstack_early_init(void) }
#ifdef CONFIG_VMAP_STACK -void *emergency_ctx[NR_CPUS] __ro_after_init; +void *emergency_ctx[NR_CPUS] __ro_after_init = {[0] = &init_stack};
void __init emergency_stack_init(void) {
From: Guangbin Huang huangguangbin2@huawei.com
[ Upstream commit a2ee6fd28a190588e142ad8ea9d40069cd3c9f98 ]
The array size of bd_num_list is a fixed value, it may have potential overflow risk when array size of hclge_dfx_bd_offset_list is greater than that fixed value. So modify bd_num_list as a pointer and allocate memory for it according to array size of hclge_dfx_bd_offset_list.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../hisilicon/hns3/hns3pf/hclge_main.c | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b0dbe6dcaa7b..7a560d0e19b9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11379,7 +11379,6 @@ static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, #define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) #define REG_SEPARATOR_LINE 1 #define REG_NUM_REMAIN_MASK 3 -#define BD_LIST_MAX_NUM 30
int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) { @@ -11473,15 +11472,19 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) { u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); int data_len_per_desc, bd_num, i; - int bd_num_list[BD_LIST_MAX_NUM]; + int *bd_num_list; u32 data_len; int ret;
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); if (ret) { dev_err(&hdev->pdev->dev, "Get dfx reg bd num fail, status is %d.\n", ret); - return ret; + goto out; }
data_len_per_desc = sizeof_field(struct hclge_desc, data); @@ -11492,6 +11495,8 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; }
+out: + kfree(bd_num_list); return ret; }
@@ -11499,16 +11504,20 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) { u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); int bd_num, bd_num_max, buf_len, i; - int bd_num_list[BD_LIST_MAX_NUM]; struct hclge_desc *desc_src; + int *bd_num_list; u32 *reg = data; int ret;
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); if (ret) { dev_err(&hdev->pdev->dev, "Get dfx reg bd num fail, status is %d.\n", ret); - return ret; + goto out; }
bd_num_max = bd_num_list[0]; @@ -11517,8 +11526,10 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
buf_len = sizeof(*desc_src) * bd_num_max; desc_src = kzalloc(buf_len, GFP_KERNEL); - if (!desc_src) - return -ENOMEM; + if (!desc_src) { + ret = -ENOMEM; + goto out; + }
for (i = 0; i < dfx_reg_type_num; i++) { bd_num = bd_num_list[i]; @@ -11534,6 +11545,8 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) }
kfree(desc_src); +out: + kfree(bd_num_list); return ret; }
From: Yunsheng Lin linyunsheng@huawei.com
[ Upstream commit d5d5e0193ee8f88efbbc7f1471087255657bc19a ]
Currently hns3 driver only handle the xmit skb with one level of fraglist skb, add handling for multi level by calling hns3_tx_bd_num() recursively when calculating bd num and calling hns3_fill_skb_to_desc() recursively when filling tx desc.
When the skb has a fraglist level of 24, the skb is simply dropped and stats.max_recursion_level is added to record the error. Move the stat handling from hns3_nic_net_xmit() to hns3_nic_maybe_stop_tx() in order to handle different error stat and add the 'max_recursion_level' and 'hw_limitation' stat.
Note that the max recursive level as 24 is chose according to below: commit 48a1df65334b ("skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow").
And that we are not able to find a testcase to verify the recursive fraglist case, so Fixes tag is not provided.
Reported-by: Barry Song song.bao.hua@hisilicon.com Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 115 +++++++++++------- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 2 + .../ethernet/hisilicon/hns3/hns3_ethtool.c | 2 + 3 files changed, 78 insertions(+), 41 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 65752f363f43..b19df09ffb76 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1277,23 +1277,21 @@ static unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size, }
static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size, - u8 max_non_tso_bd_num) + u8 max_non_tso_bd_num, unsigned int bd_num, + unsigned int recursion_level) { +#define HNS3_MAX_RECURSION_LEVEL 24 + struct sk_buff *frag_skb; - unsigned int bd_num = 0;
/* If the total len is within the max bd limit */ - if (likely(skb->len <= HNS3_MAX_BD_SIZE && !skb_has_frag_list(skb) && + if (likely(skb->len <= HNS3_MAX_BD_SIZE && !recursion_level && + !skb_has_frag_list(skb) && skb_shinfo(skb)->nr_frags < max_non_tso_bd_num)) return skb_shinfo(skb)->nr_frags + 1U;
- /* The below case will always be linearized, return - * HNS3_MAX_BD_NUM_TSO + 1U to make sure it is linearized. - */ - if (unlikely(skb->len > HNS3_MAX_TSO_SIZE || - (!skb_is_gso(skb) && skb->len > - HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num)))) - return HNS3_MAX_TSO_BD_NUM + 1U; + if (unlikely(recursion_level >= HNS3_MAX_RECURSION_LEVEL)) + return UINT_MAX;
bd_num = hns3_skb_bd_num(skb, bd_size, bd_num);
@@ -1301,7 +1299,8 @@ static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size, return bd_num;
skb_walk_frags(skb, frag_skb) { - bd_num = hns3_skb_bd_num(frag_skb, bd_size, bd_num); + bd_num = hns3_tx_bd_num(frag_skb, bd_size, max_non_tso_bd_num, + bd_num, recursion_level + 1); if (bd_num > HNS3_MAX_TSO_BD_NUM) return bd_num; } @@ -1361,6 +1360,43 @@ void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size) size[i] = skb_frag_size(&shinfo->frags[i]); }
+static int hns3_skb_linearize(struct hns3_enet_ring *ring, + struct sk_buff *skb, + u8 max_non_tso_bd_num, + unsigned int bd_num) +{ + /* 'bd_num == UINT_MAX' means the skb' fraglist has a + * recursion level of over HNS3_MAX_RECURSION_LEVEL. + */ + if (bd_num == UINT_MAX) { + u64_stats_update_begin(&ring->syncp); + ring->stats.over_max_recursion++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + /* The skb->len has exceeded the hw limitation, linearization + * will not help. + */ + if (skb->len > HNS3_MAX_TSO_SIZE || + (!skb_is_gso(skb) && skb->len > + HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num))) { + u64_stats_update_begin(&ring->syncp); + ring->stats.hw_limitation++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + if (__skb_linearize(skb)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.sw_err_cnt++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + return 0; +} + static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, struct net_device *netdev, struct sk_buff *skb) @@ -1370,7 +1406,7 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U]; unsigned int bd_num;
- bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num); + bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num, 0, 0); if (unlikely(bd_num > max_non_tso_bd_num)) { if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) && !hns3_skb_need_linearized(skb, bd_size, bd_num, @@ -1379,16 +1415,11 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring, goto out; }
- if (__skb_linearize(skb)) + if (hns3_skb_linearize(ring, skb, max_non_tso_bd_num, + bd_num)) return -ENOMEM;
bd_num = hns3_tx_bd_count(skb->len); - if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) || - (!skb_is_gso(skb) && - bd_num > max_non_tso_bd_num)) { - trace_hns3_over_max_bd(skb); - return -ENOMEM; - }
u64_stats_update_begin(&ring->syncp); ring->stats.tx_copy++; @@ -1412,6 +1443,10 @@ out: return bd_num; }
+ u64_stats_update_begin(&ring->syncp); + ring->stats.tx_busy++; + u64_stats_update_end(&ring->syncp); + return -EBUSY; }
@@ -1459,6 +1494,7 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, struct sk_buff *skb, enum hns_desc_type type) { unsigned int size = skb_headlen(skb); + struct sk_buff *frag_skb; int i, ret, bd_num = 0;
if (size) { @@ -1483,6 +1519,15 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, bd_num += ret; }
+ skb_walk_frags(skb, frag_skb) { + ret = hns3_fill_skb_to_desc(ring, frag_skb, + DESC_TYPE_FRAGLIST_SKB); + if (unlikely(ret < 0)) + return ret; + + bd_num += ret; + } + return bd_num; }
@@ -1513,8 +1558,6 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping]; struct netdev_queue *dev_queue; int pre_ntu, next_to_use_head; - struct sk_buff *frag_skb; - int bd_num = 0; bool doorbell; int ret;
@@ -1530,15 +1573,8 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ret = hns3_nic_maybe_stop_tx(ring, netdev, skb); if (unlikely(ret <= 0)) { if (ret == -EBUSY) { - u64_stats_update_begin(&ring->syncp); - ring->stats.tx_busy++; - u64_stats_update_end(&ring->syncp); hns3_tx_doorbell(ring, 0, true); return NETDEV_TX_BUSY; - } else if (ret == -ENOMEM) { - u64_stats_update_begin(&ring->syncp); - ring->stats.sw_err_cnt++; - u64_stats_update_end(&ring->syncp); }
hns3_rl_err(netdev, "xmit error: %d!\n", ret); @@ -1551,21 +1587,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) if (unlikely(ret < 0)) goto fill_err;
+ /* 'ret < 0' means filling error, 'ret == 0' means skb->len is + * zero, which is unlikely, and 'ret > 0' means how many tx desc + * need to be notified to the hw. + */ ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB); - if (unlikely(ret < 0)) + if (unlikely(ret <= 0)) goto fill_err;
- bd_num += ret; - - skb_walk_frags(skb, frag_skb) { - ret = hns3_fill_skb_to_desc(ring, frag_skb, - DESC_TYPE_FRAGLIST_SKB); - if (unlikely(ret < 0)) - goto fill_err; - - bd_num += ret; - } - pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) : (ring->desc_num - 1); ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |= @@ -1576,7 +1605,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); doorbell = __netdev_tx_sent_queue(dev_queue, skb->len, netdev_xmit_more()); - hns3_tx_doorbell(ring, bd_num, doorbell); + hns3_tx_doorbell(ring, ret, doorbell);
return NETDEV_TX_OK;
@@ -1748,11 +1777,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_drop += ring->stats.tx_l4_proto_err; tx_drop += ring->stats.tx_l2l3l4_err; tx_drop += ring->stats.tx_tso_err; + tx_drop += ring->stats.over_max_recursion; + tx_drop += ring->stats.hw_limitation; tx_errors += ring->stats.sw_err_cnt; tx_errors += ring->stats.tx_vlan_err; tx_errors += ring->stats.tx_l4_proto_err; tx_errors += ring->stats.tx_l2l3l4_err; tx_errors += ring->stats.tx_tso_err; + tx_errors += ring->stats.over_max_recursion; + tx_errors += ring->stats.hw_limitation; } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
/* fetch the rx stats */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index d069b04ee587..e44224e23315 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -376,6 +376,8 @@ struct ring_stats { u64 tx_l4_proto_err; u64 tx_l2l3l4_err; u64 tx_tso_err; + u64 over_max_recursion; + u64 hw_limitation; }; struct { u64 rx_pkts; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index adcec4ea7cb9..d20f2e246017 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -44,6 +44,8 @@ static const struct hns3_stats hns3_txq_stats[] = { HNS3_TQP_STAT("l4_proto_err", tx_l4_proto_err), HNS3_TQP_STAT("l2l3l4_err", tx_l2l3l4_err), HNS3_TQP_STAT("tso_err", tx_tso_err), + HNS3_TQP_STAT("over_max_recursion", over_max_recursion), + HNS3_TQP_STAT("hw_limitation", hw_limitation), };
#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
From: Eric Dumazet edumazet@google.com
[ Upstream commit 40cb881b5aaa0b69a7d93dec8440d5c62dae299f ]
After adopting CONFIG_PCPU_DEV_REFCNT=n option, syzbot was able to trigger a warning [1]
Issue here is that:
- all dev_put() should be paired with a corresponding prior dev_hold().
- A driver doing a dev_put() in its ndo_uninit() MUST also do a dev_hold() in its ndo_init(), only when ndo_init() is returning 0.
Otherwise, register_netdevice() would call ndo_uninit() in its error path and release a refcount too soon.
Therefore, we need to move dev_hold() call from vti6_tnl_create2() to vti6_dev_init_gen()
[1] WARNING: CPU: 0 PID: 15951 at lib/refcount.c:31 refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 Modules linked in: CPU: 0 PID: 15951 Comm: syz-executor.3 Not tainted 5.12.0-rc4-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:refcount_warn_saturate+0xbf/0x1e0 lib/refcount.c:31 Code: 1d 6a 5a e8 09 31 ff 89 de e8 8d 1a ab fd 84 db 75 e0 e8 d4 13 ab fd 48 c7 c7 a0 e1 c1 89 c6 05 4a 5a e8 09 01 e8 2e 36 fb 04 <0f> 0b eb c4 e8 b8 13 ab fd 0f b6 1d 39 5a e8 09 31 ff 89 de e8 58 RSP: 0018:ffffc90001eaef28 EFLAGS: 00010282 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000040000 RSI: ffffffff815c51f5 RDI: fffff520003d5dd7 RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 R10: ffffffff815bdf8e R11: 0000000000000000 R12: ffff88801bb1c568 R13: ffff88801f69e800 R14: 00000000ffffffff R15: ffff888050889d40 FS: 00007fc79314e700(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f1c1ff47108 CR3: 0000000020fd5000 CR4: 00000000001506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __refcount_dec include/linux/refcount.h:344 [inline] refcount_dec include/linux/refcount.h:359 [inline] dev_put include/linux/netdevice.h:4135 [inline] vti6_dev_uninit+0x31a/0x360 net/ipv6/ip6_vti.c:297 register_netdevice+0xadf/0x1500 net/core/dev.c:10308 vti6_tnl_create2+0x1b5/0x400 net/ipv6/ip6_vti.c:190 vti6_newlink+0x9d/0xd0 net/ipv6/ip6_vti.c:1020 __rtnl_newlink+0x1062/0x1710 net/core/rtnetlink.c:3443 rtnl_newlink+0x64/0xa0 net/core/rtnetlink.c:3491 rtnetlink_rcv_msg+0x44e/0xad0 net/core/rtnetlink.c:5553 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x331/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmmsg+0x195/0x470 net/socket.c:2490 __do_sys_sendmmsg net/socket.c:2519 [inline] __se_sys_sendmmsg net/socket.c:2516 [inline] __x64_sys_sendmmsg+0x99/0x100 net/socket.c:2516
Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/ip6_vti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index e0cc32e45880..932b15b13053 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -193,7 +193,6 @@ static int vti6_tnl_create2(struct net_device *dev)
strcpy(t->parms.name, dev->name);
- dev_hold(dev); vti6_tnl_link(ip6n, t);
return 0; @@ -934,6 +933,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev) dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + dev_hold(dev); return 0; }
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 4168d079aa41498639b2c64b4583375bcdf360d9 ]
A out of bounds access to "struct can_priv::echo_skb" leads to a kernel crash. Better print a sensible warning message instead and try to recover.
This patch is similar to:
| e7a6994d043a ("can: dev: __can_get_echo_skb(): Don't crash the kernel | if can_priv::echo_skb is accessed out of bounds")
Link: https://lore.kernel.org/r/20210319142700.305648-2-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/dev/skb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c index 6a64fe410987..c3508109263e 100644 --- a/drivers/net/can/dev/skb.c +++ b/drivers/net/can/dev/skb.c @@ -151,7 +151,11 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx) { struct can_priv *priv = netdev_priv(dev);
- BUG_ON(idx >= priv->echo_skb_max); + if (idx >= priv->echo_skb_max) { + netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", + __func__, idx, priv->echo_skb_max); + return; + }
if (priv->echo_skb[idx]) { dev_kfree_skb_any(priv->echo_skb[idx]);
From: Xiang Chen chenxiang66@hisilicon.com
[ Upstream commit 6cc7e5a9c6b02507b9be5a99b51e970afa91c85f ]
It may send a invalid tlb sync for smmuv3 if iotlb_gather is not valid (iotlb_gather->pgsize = 0). So add a check to avoid invalid iotlb sync for it.
Signed-off-by: Xiang Chen chenxiang66@hisilicon.com Link: https://lore.kernel.org/r/1617109106-121844-1-git-send-email-chenxiang66@his... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 8594b4a83043..941ba5484731 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2305,6 +2305,9 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain, { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ if (!gather->pgsize) + return; + arm_smmu_tlb_inv_range_domain(gather->start, gather->end - gather->start + 1, gather->pgsize, true, smmu_domain);
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit 875c40eadf6ac6644c0f71842a4f30dd9968d281 ]
The Chuwi Hi8 tablet is using an analog mic on IN1 and has its jack-detect connected to JD2_IN4N, instead of using the default IN3 for its internal mic and JD1_IN4P for jack-detect.
It also only has 1 speaker.
Add a quirk applying the correct settings for this configuration.
Signed-off-by: Hans de Goede hdegoede@redhat.com Link: https://lore.kernel.org/r/20210325221054.22714-1-hdegoede@redhat.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/bytcr_rt5640.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 19faababb78d..22912cab5e63 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -518,6 +518,23 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { + /* Chuwi Hi8 (CWI509) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), + DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"), + DMI_MATCH(DMI_SYS_VENDOR, "ilife"), + DMI_MATCH(DMI_PRODUCT_NAME, "S806"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
From: Paul M Stillwell Jr paul.m.stillwell.jr@intel.com
[ Upstream commit 2ec5638559c13b923250eccf495d2a033fccb3e7 ]
There is an issue when the Tx or Rx ring size increases using 'ethtool -L ...' where the new rings don't get the correct ITR values because when we rebuild the VSI we don't know that some of the rings may be new.
Fix this by looking at the original number of rings and determining if the rings in ice_vsi_rebuild_set_coalesce() were not present in the original rings received in ice_vsi_rebuild_get_coalesce().
Also change the code to return an error if we can't allocate memory for the coalesce data in ice_vsi_rebuild().
Signed-off-by: Paul M Stillwell Jr paul.m.stillwell.jr@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_lib.c | 123 ++++++++++++++++------ drivers/net/ethernet/intel/ice/ice_txrx.h | 2 + 2 files changed, 92 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index d13c7fc8fb0a..195d122c9cb2 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2818,38 +2818,46 @@ int ice_vsi_release(struct ice_vsi *vsi) }
/** - * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector + * ice_vsi_rebuild_update_coalesce_intrl - set interrupt rate limit for a q_vector * @q_vector: pointer to q_vector which is being updated - * @coalesce: pointer to array of struct with stored coalesce + * @stored_intrl_setting: original INTRL setting * * Set coalesce param in q_vector and update these parameters in HW. */ static void -ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector, - struct ice_coalesce_stored *coalesce) +ice_vsi_rebuild_update_coalesce_intrl(struct ice_q_vector *q_vector, + u16 stored_intrl_setting) { - struct ice_ring_container *rx_rc = &q_vector->rx; - struct ice_ring_container *tx_rc = &q_vector->tx; struct ice_hw *hw = &q_vector->vsi->back->hw;
- tx_rc->itr_setting = coalesce->itr_tx; - rx_rc->itr_setting = coalesce->itr_rx; - - /* dynamic ITR values will be updated during Tx/Rx */ - if (!ITR_IS_DYNAMIC(tx_rc->itr_setting)) - wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx), - ITR_REG_ALIGN(tx_rc->itr_setting) >> - ICE_ITR_GRAN_S); - if (!ITR_IS_DYNAMIC(rx_rc->itr_setting)) - wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx), - ITR_REG_ALIGN(rx_rc->itr_setting) >> - ICE_ITR_GRAN_S); - - q_vector->intrl = coalesce->intrl; + q_vector->intrl = stored_intrl_setting; wr32(hw, GLINT_RATE(q_vector->reg_idx), ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); }
+/** + * ice_vsi_rebuild_update_coalesce_itr - set coalesce for a q_vector + * @q_vector: pointer to q_vector which is being updated + * @rc: pointer to ring container + * @stored_itr_setting: original ITR setting + * + * Set coalesce param in q_vector and update these parameters in HW. + */ +static void +ice_vsi_rebuild_update_coalesce_itr(struct ice_q_vector *q_vector, + struct ice_ring_container *rc, + u16 stored_itr_setting) +{ + struct ice_hw *hw = &q_vector->vsi->back->hw; + + rc->itr_setting = stored_itr_setting; + + /* dynamic ITR values will be updated during Tx/Rx */ + if (!ITR_IS_DYNAMIC(rc->itr_setting)) + wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), + ITR_REG_ALIGN(rc->itr_setting) >> ICE_ITR_GRAN_S); +} + /** * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors * @vsi: VSI connected with q_vectors @@ -2869,6 +2877,11 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, coalesce[i].itr_tx = q_vector->tx.itr_setting; coalesce[i].itr_rx = q_vector->rx.itr_setting; coalesce[i].intrl = q_vector->intrl; + + if (i < vsi->num_txq) + coalesce[i].tx_valid = true; + if (i < vsi->num_rxq) + coalesce[i].rx_valid = true; }
return vsi->num_q_vectors; @@ -2893,17 +2906,59 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, if ((size && !coalesce) || !vsi) return;
- for (i = 0; i < size && i < vsi->num_q_vectors; i++) - ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], - &coalesce[i]); - - /* number of q_vectors increased, so assume coalesce settings were - * changed globally (i.e. ethtool -C eth0 instead of per-queue) and use - * the previous settings from q_vector 0 for all of the new q_vectors + /* There are a couple of cases that have to be handled here: + * 1. The case where the number of queue vectors stays the same, but + * the number of Tx or Rx rings changes (the first for loop) + * 2. The case where the number of queue vectors increased (the + * second for loop) */ - for (; i < vsi->num_q_vectors; i++) - ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], - &coalesce[0]); + for (i = 0; i < size && i < vsi->num_q_vectors; i++) { + /* There are 2 cases to handle here and they are the same for + * both Tx and Rx: + * if the entry was valid previously (coalesce[i].[tr]x_valid + * and the loop variable is less than the number of rings + * allocated, then write the previous values + * + * if the entry was not valid previously, but the number of + * rings is less than are allocated (this means the number of + * rings increased from previously), then write out the + * values in the first element + */ + if (i < vsi->alloc_rxq && coalesce[i].rx_valid) + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->rx, + coalesce[i].itr_rx); + else if (i < vsi->alloc_rxq) + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->rx, + coalesce[0].itr_rx); + + if (i < vsi->alloc_txq && coalesce[i].tx_valid) + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->tx, + coalesce[i].itr_tx); + else if (i < vsi->alloc_txq) + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->tx, + coalesce[0].itr_tx); + + ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i], + coalesce[i].intrl); + } + + /* the number of queue vectors increased so write whatever is in + * the first element + */ + for (; i < vsi->num_q_vectors; i++) { + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->tx, + coalesce[0].itr_tx); + ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i], + &vsi->q_vectors[i]->rx, + coalesce[0].itr_rx); + ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i], + coalesce[0].intrl); + } }
/** @@ -2932,9 +2987,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
coalesce = kcalloc(vsi->num_q_vectors, sizeof(struct ice_coalesce_stored), GFP_KERNEL); - if (coalesce) - prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, - coalesce); + if (!coalesce) + return -ENOMEM; + + prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce); + ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); ice_vsi_free_q_vectors(vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index 5dab77504fa5..672a7ff0ee36 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -351,6 +351,8 @@ struct ice_coalesce_stored { u16 itr_tx; u16 itr_rx; u8 intrl; + u8 tx_valid; + u8 rx_valid; };
/* iterator for handling rings in ring container */
From: mark-yw.chen mark-yw.chen@mediatek.com
[ Upstream commit 27e554a4fcd84e499bf0a82122b8c4c3f1de38b6 ]
Adding support LE scatternet and WBS for Mediatek Chip
Signed-off-by: mark-yw.chen mark-yw.chen@mediatek.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5cbfbd948f67..4a901508e48e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -399,7 +399,9 @@ static const struct usb_device_id blacklist_table[] = {
/* MediaTek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01), - .driver_info = BTUSB_MEDIATEK }, + .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES },
/* Additional MediaTek MT7615E Bluetooth devices */ { USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit 84cb0d5581b6a7bd5d96013f67e9f2eb0c7b4378 ]
Add a quirk with the jack-detect and dmic settings necessary to make jack-detect and the builtin mic work on Dell Venue 10 Pro 5055 tablets.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20210402140747.174716-5-hdegoede@redhat.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/rt5670.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 4063aac2a443..dd69d874bad2 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2980,6 +2980,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, + { + .callback = rt5670_quirk_cb, + .ident = "Dell Venue 10 Pro 5055", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"), + }, + .driver_data = (unsigned long *)(RT5670_DMIC_EN | + RT5670_DMIC2_INR | + RT5670_GPIO1_IS_IRQ | + RT5670_JD_MODE1), + }, { .callback = rt5670_quirk_cb, .ident = "Aegex 10 tablet (RU2)",
From: Matthieu Baerts matthieu.baerts@tessares.net
[ Upstream commit 5888a61cb4e00695075bbacfd86f3fa73af00413 ]
'mptcp_connect' already has a timeout for poll() but in some cases, it is not enough.
With "timeout" tool, we will force the command to fail if it doesn't finish on time. Thanks to that, the script will continue and display details about the current state before marking the test as failed. Displaying this state is very important to be able to understand the issue. Best to have our CI reporting the issue than just "the test hanged".
Note that in mptcp_connect.sh, we were using a long timeout to validate the fact we cannot create a socket if a sysctl is set. We don't need this timeout.
In diag.sh, we want to send signals to mptcp_connect instances that have been started in the netns. But we cannot send this signal to 'timeout' otherwise that will stop the timeout and messages telling us SIGUSR1 has been received will be printed. Instead of trying to find the right PID and storing them in an array, we can simply use the output of 'ip netns pids' which is all the PIDs we want to send signal to.
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/160 Signed-off-by: Matthieu Baerts matthieu.baerts@tessares.net Signed-off-by: Mat Martineau mathew.j.martineau@linux.intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/net/mptcp/diag.sh | 55 ++++++++++++------- .../selftests/net/mptcp/mptcp_connect.sh | 15 +++-- .../testing/selftests/net/mptcp/mptcp_join.sh | 22 ++++++-- .../selftests/net/mptcp/simult_flows.sh | 13 ++++- 4 files changed, 72 insertions(+), 33 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh index 39edce4f541c..2674ba20d524 100755 --- a/tools/testing/selftests/net/mptcp/diag.sh +++ b/tools/testing/selftests/net/mptcp/diag.sh @@ -5,8 +5,9 @@ rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) ns="ns1-$rndh" ksft_skip=4 test_cnt=1 +timeout_poll=100 +timeout_test=$((timeout_poll * 2 + 1)) ret=0 -pids=()
flush_pids() { @@ -14,18 +15,14 @@ flush_pids() # give it some time sleep 1.1
- for pid in ${pids[@]}; do - [ -d /proc/$pid ] && kill -SIGUSR1 $pid >/dev/null 2>&1 - done - pids=() + ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGUSR1 &>/dev/null }
cleanup() { + ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGKILL &>/dev/null + ip netns del $ns - for pid in ${pids[@]}; do - [ -d /proc/$pid ] && kill -9 $pid >/dev/null 2>&1 - done }
ip -Version > /dev/null 2>&1 @@ -79,39 +76,57 @@ trap cleanup EXIT ip netns add $ns ip -n $ns link set dev lo up
-echo "a" | ip netns exec $ns ./mptcp_connect -p 10000 -l 0.0.0.0 -t 100 >/dev/null & +echo "a" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p 10000 -l -t ${timeout_poll} \ + 0.0.0.0 >/dev/null & sleep 0.1 -pids[0]=$! chk_msk_nr 0 "no msk on netns creation"
-echo "b" | ip netns exec $ns ./mptcp_connect -p 10000 127.0.0.1 -j -t 100 >/dev/null & +echo "b" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p 10000 -j -t ${timeout_poll} \ + 127.0.0.1 >/dev/null & sleep 0.1 -pids[1]=$! chk_msk_nr 2 "after MPC handshake " chk_msk_remote_key_nr 2 "....chk remote_key" chk_msk_fallback_nr 0 "....chk no fallback" flush_pids
-echo "a" | ip netns exec $ns ./mptcp_connect -p 10001 -s TCP -l 0.0.0.0 -t 100 >/dev/null & -pids[0]=$! +echo "a" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \ + 0.0.0.0 >/dev/null & sleep 0.1 -echo "b" | ip netns exec $ns ./mptcp_connect -p 10001 127.0.0.1 -j -t 100 >/dev/null & -pids[1]=$! +echo "b" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p 10001 -j -t ${timeout_poll} \ + 127.0.0.1 >/dev/null & sleep 0.1 chk_msk_fallback_nr 1 "check fallback" flush_pids
NR_CLIENTS=100 for I in `seq 1 $NR_CLIENTS`; do - echo "a" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) -l 0.0.0.0 -t 100 -w 10 >/dev/null & - pids[$((I*2))]=$! + echo "a" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p $((I+10001)) -l -w 10 \ + -t ${timeout_poll} 0.0.0.0 >/dev/null & done sleep 0.1
for I in `seq 1 $NR_CLIENTS`; do - echo "b" | ip netns exec $ns ./mptcp_connect -p $((I+10001)) 127.0.0.1 -t 100 -w 10 >/dev/null & - pids[$((I*2 + 1))]=$! + echo "b" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ + ./mptcp_connect -p $((I+10001)) -w 10 \ + -t ${timeout_poll} 127.0.0.1 >/dev/null & done sleep 1.5
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh index 10a030b53b23..65b3b983efc2 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh @@ -11,7 +11,8 @@ cin="" cout="" ksft_skip=4 capture=false -timeout=30 +timeout_poll=30 +timeout_test=$((timeout_poll * 2 + 1)) ipv6=true ethtool_random_on=true tc_delay="$((RANDOM%50))" @@ -273,7 +274,7 @@ check_mptcp_disabled() ip netns exec ${disabled_ns} sysctl -q net.mptcp.enabled=0
local err=0 - LANG=C ip netns exec ${disabled_ns} ./mptcp_connect -t $timeout -p 10000 -s MPTCP 127.0.0.1 < "$cin" 2>&1 | \ + LANG=C ip netns exec ${disabled_ns} ./mptcp_connect -p 10000 -s MPTCP 127.0.0.1 < "$cin" 2>&1 | \ grep -q "^socket: Protocol not available$" && err=1 ip netns delete ${disabled_ns}
@@ -430,14 +431,20 @@ do_transfer() local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv")
- ip netns exec ${listener_ns} ./mptcp_connect -t $timeout -l -p $port -s ${srv_proto} $extra_args $local_addr < "$sin" > "$sout" & + timeout ${timeout_test} \ + ip netns exec ${listener_ns} \ + ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ + $extra_args $local_addr < "$sin" > "$sout" & local spid=$!
wait_local_port_listen "${listener_ns}" "${port}"
local start start=$(date +%s%3N) - ip netns exec ${connector_ns} ./mptcp_connect -t $timeout -p $port -s ${cl_proto} $extra_args $connect_addr < "$cin" > "$cout" & + timeout ${timeout_test} \ + ip netns exec ${connector_ns} \ + ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $extra_args $connect_addr < "$cin" > "$cout" & local cpid=$!
wait $cpid diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index ad32240fbfda..43ed99de7734 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -8,7 +8,8 @@ cin="" cinsent="" cout="" ksft_skip=4 -timeout=30 +timeout_poll=30 +timeout_test=$((timeout_poll * 2 + 1)) mptcp_connect="" capture=0 do_all_tests=1 @@ -245,17 +246,26 @@ do_transfer() local_addr="0.0.0.0" fi
- ip netns exec ${listener_ns} $mptcp_connect -t $timeout -l -p $port \ - -s ${srv_proto} ${local_addr} < "$sin" > "$sout" & + timeout ${timeout_test} \ + ip netns exec ${listener_ns} \ + $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ + ${local_addr} < "$sin" > "$sout" & spid=$!
sleep 1
if [ "$test_link_fail" -eq 0 ];then - ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr < "$cin" > "$cout" & + timeout ${timeout_test} \ + ip netns exec ${connector_ns} \ + $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $connect_addr < "$cin" > "$cout" & else - ( cat "$cin" ; sleep 2; link_failure $listener_ns ; cat "$cin" ) | tee "$cinsent" | \ - ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr > "$cout" & + ( cat "$cin" ; sleep 2; link_failure $listener_ns ; cat "$cin" ) | \ + tee "$cinsent" | \ + timeout ${timeout_test} \ + ip netns exec ${connector_ns} \ + $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $connect_addr > "$cout" & fi cpid=$!
diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh index f039ee57eb3c..3aeef3bcb101 100755 --- a/tools/testing/selftests/net/mptcp/simult_flows.sh +++ b/tools/testing/selftests/net/mptcp/simult_flows.sh @@ -7,7 +7,8 @@ ns2="ns2-$rndh" ns3="ns3-$rndh" capture=false ksft_skip=4 -timeout=30 +timeout_poll=30 +timeout_test=$((timeout_poll * 2 + 1)) test_cnt=1 ret=0 bail=0 @@ -157,14 +158,20 @@ do_transfer() sleep 1 fi
- ip netns exec ${ns3} ./mptcp_connect -jt $timeout -l -p $port 0.0.0.0 < "$sin" > "$sout" & + timeout ${timeout_test} \ + ip netns exec ${ns3} \ + ./mptcp_connect -jt ${timeout_poll} -l -p $port \ + 0.0.0.0 < "$sin" > "$sout" & local spid=$!
wait_local_port_listen "${ns3}" "${port}"
local start start=$(date +%s%3N) - ip netns exec ${ns1} ./mptcp_connect -jt $timeout -p $port 10.0.3.3 < "$cin" > "$cout" & + timeout ${timeout_test} \ + ip netns exec ${ns1} \ + ./mptcp_connect -jt ${timeout_poll} -p $port \ + 10.0.3.3 < "$cin" > "$cout" & local cpid=$!
wait $cpid
From: Bence Csókás bence98@sch.bme.hu
[ Upstream commit aca01415e076aa96cca0f801f4420ee5c10c660d ]
This quirk signifies that the adapter cannot do a repeated START, it always issues a STOP condition after transfers.
Suggested-by: Wolfram Sang wsa@kernel.org Signed-off-by: Bence Csókás bence98@sch.bme.hu Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/i2c.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 56622658b215..a670ae129f4b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -687,6 +687,8 @@ struct i2c_adapter_quirks { #define I2C_AQ_NO_ZERO_LEN_READ BIT(5) #define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6) #define I2C_AQ_NO_ZERO_LEN (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE) +/* adapter cannot do repeated START */ +#define I2C_AQ_NO_REP_START BIT(7)
/* * i2c_adapter is the structure used to identify a physical i2c bus along
From: Daniel Winkler danielwinkler@google.com
[ Upstream commit b6f1b79deabd32f89adbf24ef7b30f82d029808a ]
We set hdev->cur_adv_instance in the adv param MGMT request to allow the callback to the hci param request to set the tx power to the correct instance. Now that the callbacks use the advertising handle from the hci request (as they should), this workaround is no longer necessary.
Furthermore, this change resolves a race condition that is more prevalent when using the extended advertising MGMT calls - if hdev->cur_adv_instance is set in the params request, then when the data request is called, we believe our new instance is already active. This treats it as an update and immediately schedules the instance with the controller, which has a potential race with the software rotation adv update. By not setting hdev->cur_adv_instance too early, the new instance is queued as it should be, to be used when the rotation comes around again.
This change is tested on harrison peak to confirm that it resolves the race condition on registration, and that there is no regression in single- and multi-advertising automated tests.
Reviewed-by: Miao-chen Chou mcchou@chromium.org Signed-off-by: Daniel Winkler danielwinkler@google.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/mgmt.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 74971b4bd457..939c6f77fecc 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7976,7 +7976,6 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, goto unlock; }
- hdev->cur_adv_instance = cp->instance; /* Submit request for advertising params if ext adv available */ if (ext_adv_capable(hdev)) { hci_req_init(&req, hdev);
From: Tiezhu Yang yangtiezhu@loongson.cn
[ Upstream commit 5e65c52ec716af6e8f51dacdaeb4a4d872249af1 ]
Loongson64 processors have a writecombine issue that maybe failed to write back framebuffer used with ATI Radeon or AMD GPU at times, after commit 8a08e50cee66 ("drm: Permit video-buffers writecombine mapping for MIPS"), there exists some errors such as blurred screen and lockup, and so on.
[ 60.958721] radeon 0000:03:00.0: ring 0 stalled for more than 10079msec [ 60.965315] radeon 0000:03:00.0: GPU lockup (current fence id 0x0000000000000112 last fence id 0x000000000000011d on ring 0) [ 60.976525] radeon 0000:03:00.0: ring 3 stalled for more than 10086msec [ 60.983156] radeon 0000:03:00.0: GPU lockup (current fence id 0x0000000000000374 last fence id 0x00000000000003a8 on ring 3)
As discussed earlier [1], it might be better to disable writecombine on the CPU detection side because the root cause is unknown now.
Actually, this patch is a temporary solution to just make it work well, it is not a proper and final solution, I hope someone will have a better solution to fix this issue in the future.
[1] https://lore.kernel.org/patchwork/patch/1285542/
Signed-off-by: Tiezhu Yang yangtiezhu@loongson.cn Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/kernel/cpu-probe.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b71892064f27..0ef240adefb5 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1752,7 +1752,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) set_isa(c, MIPS_CPU_ISA_M64R2); break; } - c->writecombine = _CACHE_UNCACHED_ACCELERATED; c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2); break; @@ -1782,7 +1781,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) * register, we correct it here. */ c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; - c->writecombine = _CACHE_UNCACHED_ACCELERATED; c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM | MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2); c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ @@ -1793,7 +1791,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) set_elf_platform(cpu, "loongson3a"); set_isa(c, MIPS_CPU_ISA_M64R2); decode_cpucfg(c); - c->writecombine = _CACHE_UNCACHED_ACCELERATED; break; default: panic("Unknown Loongson Processor ID!");
From: Suzuki K Poulose suzuki.poulose@arm.com
[ Upstream commit 2b921b671a8d29c2adb255a86409aad1e3267309 ]
If a graph node is not found for a given node, of_get_next_endpoint() will emit the following error message :
OF: graph: no port node found in /<node_name>
If the given component doesn't have any explicit connections (e.g, ETE) we could simply ignore the graph parsing. As for any legacy component where this is mandatory, the device will not be usable as before this patch. Updating the DT bindings to Yaml and enabling the schema checks can detect such issues with the DT.
Cc: Mike Leach mike.leach@linaro.org Cc: Leo Yan leo.yan@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Link: https://lore.kernel.org/r/20210405164307.1720226-11-suzuki.poulose@arm.com Signed-off-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hwtracing/coresight/coresight-platform.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 3629b7885aca..c594f45319fc 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -90,6 +90,12 @@ static void of_coresight_get_ports_legacy(const struct device_node *node, struct of_endpoint endpoint; int in = 0, out = 0;
+ /* + * Avoid warnings in of_graph_get_next_endpoint() + * if the device doesn't have any graph connections + */ + if (!of_graph_is_present(node)) + return; do { ep = of_graph_get_next_endpoint(node, ep); if (!ep)
From: Mike Marciniszyn mike.marciniszyn@cornelisnetworks.com
[ Upstream commit b536d4b2a279733f440c911dc831764690b90050 ]
The completion ring for tx is using the wrong size to size the ring, oversizing the ring by two orders of magniture.
Correct the allocation size and use kcalloc_node() to allocate the ring. Fix mistaken GFP defines in similar allocations.
Link: https://lore.kernel.org/r/1617026056-50483-4-git-send-email-dennis.dalessand... Reviewed-by: Kaike Wan kaike.wan@intel.com Signed-off-by: Mike Marciniszyn mike.marciniszyn@cornelisnetworks.com Signed-off-by: Dennis Dalessandro dennis.dalessandro@cornelisnetworks.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hfi1/ipoib.h | 3 ++- drivers/infiniband/hw/hfi1/ipoib_tx.c | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/hw/hfi1/ipoib.h b/drivers/infiniband/hw/hfi1/ipoib.h index f650cac9d424..d30c23b6527a 100644 --- a/drivers/infiniband/hw/hfi1/ipoib.h +++ b/drivers/infiniband/hw/hfi1/ipoib.h @@ -52,8 +52,9 @@ union hfi1_ipoib_flow { * @producer_lock: producer sync lock * @consumer_lock: consumer sync lock */ +struct ipoib_txreq; struct hfi1_ipoib_circ_buf { - void **items; + struct ipoib_txreq **items; unsigned long head; unsigned long tail; unsigned long max_items; diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c index edd4eeac8dd1..cdc26ee3cf52 100644 --- a/drivers/infiniband/hw/hfi1/ipoib_tx.c +++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c @@ -702,14 +702,14 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv)
priv->tx_napis = kcalloc_node(dev->num_tx_queues, sizeof(struct napi_struct), - GFP_ATOMIC, + GFP_KERNEL, priv->dd->node); if (!priv->tx_napis) goto free_txreq_cache;
priv->txqs = kcalloc_node(dev->num_tx_queues, sizeof(struct hfi1_ipoib_txq), - GFP_ATOMIC, + GFP_KERNEL, priv->dd->node); if (!priv->txqs) goto free_tx_napis; @@ -741,9 +741,9 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv) priv->dd->node);
txq->tx_ring.items = - vzalloc_node(array_size(tx_ring_size, - sizeof(struct ipoib_txreq)), - priv->dd->node); + kcalloc_node(tx_ring_size, + sizeof(struct ipoib_txreq *), + GFP_KERNEL, priv->dd->node); if (!txq->tx_ring.items) goto free_txqs;
@@ -764,7 +764,7 @@ free_txqs: struct hfi1_ipoib_txq *txq = &priv->txqs[i];
netif_napi_del(txq->napi); - vfree(txq->tx_ring.items); + kfree(txq->tx_ring.items); }
kfree(priv->txqs); @@ -817,7 +817,7 @@ void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv) hfi1_ipoib_drain_tx_list(txq); netif_napi_del(txq->napi); (void)hfi1_ipoib_drain_tx_ring(txq, txq->tx_ring.max_items); - vfree(txq->tx_ring.items); + kfree(txq->tx_ring.items); }
kfree(priv->txqs);
From: Johan Almbladh johan.almbladh@anyfinetworks.com
[ Upstream commit 96a7109a16665255b65d021e24141c2edae0e202 ]
Some drivers, for example mt76, use the skb priority field, and expects that to be consistent with the skb queue mapping. On some frame injection code paths that was not true, and it broke frame injection. Now the skb queue mapping is set according to the skb priority value when the frame is injected. The skb priority value is also derived from the frame data for all frame types, as it was done prior to commit dbd50a851c50 (only allocate one queue when using iTXQs). Fixes frame injection with the mt76 driver on MT7610E chipset.
Signed-off-by: Johan Almbladh johan.almbladh@anyfinetworks.com Link: https://lore.kernel.org/r/20210401164455.978245-1-johan.almbladh@anyfinetwor... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/tx.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3b3bcefbf657..28422d687096 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2267,17 +2267,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, payload[7]); }
- /* Initialize skb->priority for QoS frames. If the DONT_REORDER flag - * is set, stick to the default value for skb->priority to assure - * frames injected with this flag are not reordered relative to each - * other. - */ - if (ieee80211_is_data_qos(hdr->frame_control) && - !(info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER)) { - u8 *p = ieee80211_get_qos_ctl(hdr); - skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; - } - rcu_read_lock();
/* @@ -2341,6 +2330,15 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
info->band = chandef->chan->band;
+ /* Initialize skb->priority according to frame type and TID class, + * with respect to the sub interface that the frame will actually + * be transmitted on. If the DONT_REORDER flag is set, the original + * skb-priority is preserved to assure frames injected with this + * flag are not reordered relative to each other. + */ + ieee80211_select_queue_80211(sdata, skb, hdr); + skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority)); + /* remove the injection radiotap header */ skb_pull(skb, len_rthdr);
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit d6843d1ee283137723b4a8c76244607ce6db1951 ]
After channel switch, we should consider any beacon with a CSA IE as a new switch. If the CSA IE is a leftover from before the switch that the AP forgot to remove, we'll get a CSA-to-Self.
This caused issues in iwlwifi where the firmware saw a beacon with a CSA-to-Self with mode = 1 on the new channel after a switch. The firmware considered this a new switch and closed its queues. Since the beacon didn't change between before and after the switch, we wouldn't handle it (the CRC is the same) and we wouldn't let the firmware open its queues again or disconnect if the CSA IE stays for too long.
Clear the CRC valid state after we switch to make sure that we handle the beacon and handle the CSA IE as required.
Signed-off-by: Emmanuel Grumbach emmanuel.grumbach@intel.com Link: https://lore.kernel.org/r/20210408143124.b9e68aa98304.I465afb55ca2c7d59f7bf6... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/mlme.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 96f487fc0071..4a8f1b8ce768 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1295,6 +1295,11 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
sdata->vif.csa_active = false; ifmgd->csa_waiting_bcn = false; + /* + * If the CSA IE is still present on the beacon after the switch, + * we need to consider it as a new CSA (possibly to self). + */ + ifmgd->beacon_crc_valid = false;
ret = drv_post_channel_switch(sdata); if (ret) {
From: Gyeongtaek Lee gt82.lee@samsung.com
[ Upstream commit 45475bf60cc1d42da229a0aa757180c88bab8d22 ]
If panic_on_warn=1 is added in bootargs and compress offload playback with DPCM is started, kernel panic would be occurred because rtd->card->pcm_mutex isn't held in soc_compr_open_fe() and soc_compr_free_fe() and it generates lockdep warning in the following code.
void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, int stream, int action) { struct snd_soc_dai *dai; int i;
lockdep_assert_held(&rtd->card->pcm_mutex);
To prevent lockdep warning but minimize side effect by adding mutex, pcm_mutex is held just before snd_soc_runtime_activate() and snd_soc_runtime_deactivate() and is released right after them.
Signed-off-by: Gyeongtaek Lee gt82.lee@samsung.com Link: https://lore.kernel.org/r/1891546521.01617772502282.JavaMail.epsvc@epcpadp3 Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/soc-compress.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 246a5e32e22a..b4810266f5e5 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -153,7 +153,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); snd_soc_runtime_activate(fe, stream); + mutex_unlock(&fe->card->pcm_mutex);
mutex_unlock(&fe->card->mutex);
@@ -181,7 +183,9 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+ mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); snd_soc_runtime_deactivate(fe, stream); + mutex_unlock(&fe->card->pcm_mutex);
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit fba863b816049b03f3fbb07b10ebdcfe5c4141f7 ]
Resume callback of the PHY driver is called after the one for the MAC driver. The PHY driver resume callback calls phy_init_hw(), and this is potentially problematic if the MAC driver calls phy_start() in its resume callback. One issue was reported with the fec driver and a KSZ8081 PHY which seems to become unstable if a soft reset is triggered during aneg.
The new flag allows MAC drivers to indicate that they take care of suspending/resuming the PHY. Then the MAC PM callbacks can handle any dependency between MAC and PHY PM.
Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/phy_device.c | 6 ++++++ include/linux/phy.h | 2 ++ 2 files changed, 8 insertions(+)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index cc38e326405a..af2e1759b523 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -273,6 +273,9 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) { struct phy_device *phydev = to_phy_device(dev);
+ if (phydev->mac_managed_pm) + return 0; + /* We must stop the state machine manually, otherwise it stops out of * control, possibly with the phydev->lock held. Upon resume, netdev * may call phy routines that try to grab the same lock, and that may @@ -294,6 +297,9 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev) struct phy_device *phydev = to_phy_device(dev); int ret;
+ if (phydev->mac_managed_pm) + return 0; + if (!phydev->suspended_by_mdio_bus) goto no_resume;
diff --git a/include/linux/phy.h b/include/linux/phy.h index 1a12e4436b5b..8644b097dea3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -493,6 +493,7 @@ struct macsec_ops; * @loopback_enabled: Set true if this PHY has been loopbacked successfully. * @downshifted_rate: Set true if link speed has been downshifted. * @is_on_sfp_module: Set true if PHY is located on an SFP module. + * @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY * @state: State of the PHY for management purposes * @dev_flags: Device-specific flags used by the PHY driver. * @irq: IRQ number of the PHY's interrupt (-1 if none) @@ -567,6 +568,7 @@ struct phy_device { unsigned loopback_enabled:1; unsigned downshifted_rate:1; unsigned is_on_sfp_module:1; + unsigned mac_managed_pm:1;
unsigned autoneg:1; /* The most recently read link state */
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 557d5dc83f6831b4e54d141e9b121850406f9a60 ]
Use the new mac_managed_pm flag to work around an issue with KSZ8081 PHY that becomes unstable when a soft reset is triggered during aneg.
Reported-by: Joakim Zhang qiangqing.zhang@nxp.com Tested-by: Joakim Zhang qiangqing.zhang@nxp.com Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/fec_main.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3db882322b2b..70aea9c274fe 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2048,6 +2048,8 @@ static int fec_enet_mii_probe(struct net_device *ndev) fep->link = 0; fep->full_duplex = 0;
+ phy_dev->mac_managed_pm = 1; + phy_attached_info(phy_dev);
return 0; @@ -3864,6 +3866,7 @@ static int __maybe_unused fec_resume(struct device *dev) netif_device_attach(ndev); netif_tx_unlock_bh(ndev); napi_enable(&fep->napi); + phy_init_hw(ndev->phydev); phy_start(ndev->phydev); } rtnl_unlock();
From: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com
[ Upstream commit fa0c10a5f3a49130dd11281aa27e7e1c8654abc7 ]
The Special Function Registers on all Exynos SoC, including ARM64, are 32-bit wide, so entire driver uses matching functions like readl() or writel(). On 64-bit ARM using unsigned long for register masks: 1. makes little sense as immediately after bitwise operation it will be cast to 32-bit value when calling writel(), 2. is actually error-prone because it might promote other operands to 64-bit.
Addresses-Coverity: Unintentional integer overflow Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@canonical.com Reviewed-by: Sylwester Nawrocki s.nawrocki@samsung.com Link: https://lore.kernel.org/r/20210408195029.69974-1-krzysztof.kozlowski@canonic... Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pinctrl/samsung/pinctrl-exynos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index 0cd7f33cdf25..2b99f4130e1e 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -55,7 +55,7 @@ static void exynos_irq_mask(struct irq_data *irqd) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; - unsigned long mask; + unsigned int mask; unsigned long flags;
raw_spin_lock_irqsave(&bank->slock, flags); @@ -83,7 +83,7 @@ static void exynos_irq_unmask(struct irq_data *irqd) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; - unsigned long mask; + unsigned int mask; unsigned long flags;
/* @@ -483,7 +483,7 @@ static void exynos_irq_eint0_15(struct irq_desc *desc) chained_irq_exit(chip, desc); }
-static inline void exynos_irq_demux_eint(unsigned long pend, +static inline void exynos_irq_demux_eint(unsigned int pend, struct irq_domain *domain) { unsigned int irq; @@ -500,8 +500,8 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc); - unsigned long pend; - unsigned long mask; + unsigned int pend; + unsigned int mask; int i;
chained_irq_enter(chip, desc);
From: Po-Hao Huang phhuang@realtek.com
[ Upstream commit 7ae7784ec2a812c07d2ca91a6538ef2470154fb6 ]
Fix power tracking issue by replacing unnecessary IQ calibration with LC calibration. When thermal difference exceeds limitation, let RF circuit adjsut its characteristic to fit in current environment.
Signed-off-by: Po-Hao Huang phhuang@realtek.com Signed-off-by: Ping-Ke Shih pkshih@realtek.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210319054218.3319-6-pkshih@realtek.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/realtek/rtw88/main.h | 2 ++ drivers/net/wireless/realtek/rtw88/phy.c | 14 ++++++++++ drivers/net/wireless/realtek/rtw88/phy.h | 1 + drivers/net/wireless/realtek/rtw88/reg.h | 5 ++++ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 27 +++++++++++++++++-- 5 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 35afea91fd29..92b9cf1f9525 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1166,6 +1166,7 @@ struct rtw_chip_info { bool en_dis_dpd; u16 dpd_ratemask; u8 iqk_threshold; + u8 lck_threshold; const struct rtw_pwr_track_tbl *pwr_track_tbl;
u8 bfer_su_max_num; @@ -1534,6 +1535,7 @@ struct rtw_dm_info { u32 rrsr_mask_min; u8 thermal_avg[RTW_RF_PATH_MAX]; u8 thermal_meter_k; + u8 thermal_meter_lck; s8 delta_power_index[RTW_RF_PATH_MAX]; s8 delta_power_index_last[RTW_RF_PATH_MAX]; u8 default_ofdm_index; diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 0b3da5bef703..21e77fcfa4d5 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -2220,6 +2220,20 @@ s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev, } EXPORT_SYMBOL(rtw_phy_pwrtrack_get_pwridx);
+bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 delta_lck; + + delta_lck = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_lck); + if (delta_lck >= rtwdev->chip->lck_threshold) { + dm_info->thermal_meter_lck = dm_info->thermal_avg[0]; + return true; + } + return false; +} +EXPORT_SYMBOL(rtw_phy_pwrtrack_need_lck); + bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev) { struct rtw_dm_info *dm_info = &rtwdev->dm_info; diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index a4fcfb878550..a0742a69446d 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -55,6 +55,7 @@ u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path); s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev, struct rtw_swing_table *swing_table, u8 tbl_path, u8 therm_path, u8 delta); +bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev); bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev); void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, struct rtw_swing_table *swing_table); diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index ea518aa78552..819af34dac34 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -652,8 +652,13 @@ #define RF_TXATANK 0x64 #define RF_TRXIQ 0x66 #define RF_RXIQGEN 0x8d +#define RF_SYN_PFD 0xb0 #define RF_XTALX2 0xb8 +#define RF_SYN_CTRL 0xbb #define RF_MALSEL 0xbe +#define RF_SYN_AAC 0xc9 +#define RF_AAC_CTRL 0xca +#define RF_FAST_LCK 0xcc #define RF_RCKD 0xde #define RF_TXADBG 0xde #define RF_LUTDBG 0xdf diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index dd560c28abb2..448922cb2e63 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1126,6 +1126,7 @@ static void rtw8822c_pwrtrack_init(struct rtw_dev *rtwdev)
dm_info->pwr_trk_triggered = false; dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; + dm_info->thermal_meter_lck = rtwdev->efuse.thermal_meter_k; }
static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev) @@ -2108,6 +2109,26 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev) rtw_write32_set(rtwdev, REG_RX_BREAK, BIT_COM_RX_GCK_EN); }
+static void rtw8822c_do_lck(struct rtw_dev *rtwdev) +{ + u32 val; + + rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_CTRL, RFREG_MASK, 0x80010); + rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0FA); + fsleep(1); + rtw_write_rf(rtwdev, RF_PATH_A, RF_AAC_CTRL, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_AAC, RFREG_MASK, 0x80001); + read_poll_timeout(rtw_read_rf, val, val != 0x1, 1000, 100000, + true, rtwdev, RF_PATH_A, RF_AAC_CTRL, 0x1000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0F8); + rtw_write_rf(rtwdev, RF_PATH_B, RF_SYN_CTRL, RFREG_MASK, 0x80010); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x4f000); + fsleep(1); + rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000); +} + static void rtw8822c_do_iqk(struct rtw_dev *rtwdev) { struct rtw_iqk_para para = {0}; @@ -3538,11 +3559,12 @@ static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev)
rtw_phy_config_swing_table(rtwdev, &swing_table);
+ if (rtw_phy_pwrtrack_need_lck(rtwdev)) + rtw8822c_do_lck(rtwdev); + for (i = 0; i < rtwdev->hal.rf_path_num; i++) rtw8822c_pwr_track_path(rtwdev, &swing_table, i);
- if (rtw_phy_pwrtrack_need_iqk(rtwdev)) - rtw8822c_do_iqk(rtwdev); }
static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) @@ -4351,6 +4373,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .dpd_ratemask = DIS_DPD_RATEALL, .pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl, .iqk_threshold = 8, + .lck_threshold = 8, .bfer_su_max_num = 2, .bfer_mu_max_num = 1, .rx_ldpc = true,
From: Felix Fietkau nbd@nbd.name
[ Upstream commit 730d6d0da8d8f5905faafe645a5b3c08ac3f5a8f ]
There were multiple issues in the current key set/remove code: - deleting a key with the previous key index deletes the current key - BIP key would only be uploaded correctly initially and corrupted on rekey
Rework the code to better keep track of multiple keys and check for the key index before deleting the current key
Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 97 ++++++++++--------- .../net/wireless/mediatek/mt76/mt7615/main.c | 18 ++-- 3 files changed, 65 insertions(+), 51 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8bf45497cfca..36a430f09f64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -222,6 +222,7 @@ struct mt76_wcid {
u16 idx; u8 hw_key_idx; + u8 hw_key_idx2;
u8 sta:1; u8 ext_phy:1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index d73841480544..8dccb589b756 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1037,7 +1037,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; @@ -1054,22 +1054,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, memcpy(data + 16, key->key + 24, 8); memcpy(data + 24, key->key + 16, 8); } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) - memmove(data + 16, data, 16); - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) + if (cipher_mask == BIT(cipher)) memcpy(data, key->key, key->keylen); - else if (cipher == MT_CIPHER_BIP_CMAC_128) + else if (cipher != MT_CIPHER_BIP_CMAC_128) + memcpy(data, key->key, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memcpy(data + 16, key->key, 16); } } else { - if (wcid->cipher & ~BIT(cipher)) { - if (cipher != MT_CIPHER_BIP_CMAC_128) - memmove(data, data + 16, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memset(data + 16, 0, 16); - } else { + else if (cipher_mask) + memset(data, 0, 16); + if (!cipher_mask) memset(data, 0, sizeof(data)); - } } + mt76_wr_copy(dev, addr, data, sizeof(data));
return 0; @@ -1077,7 +1077,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1087,20 +1087,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
w0 = mt76_rr(dev, addr); w1 = mt76_rr(dev, addr + 4); - if (cmd == SET_KEY) { - w0 |= MT_WTBL_W0_RX_KEY_VALID | - FIELD_PREP(MT_WTBL_W0_RX_IK_VALID, - cipher == MT_CIPHER_BIP_CMAC_128); - if (cipher != MT_CIPHER_BIP_CMAC_128 || - !wcid->cipher) - w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); - } else { - if (!(wcid->cipher & ~BIT(cipher))) - w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | - MT_WTBL_W0_KEY_IDX); - if (cipher == MT_CIPHER_BIP_CMAC_128) - w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cipher_mask) + w0 |= MT_WTBL_W0_RX_KEY_VALID; + else + w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX); + if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128)) + w0 |= MT_WTBL_W0_RX_IK_VALID; + else + w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cmd == SET_KEY && + (cipher != MT_CIPHER_BIP_CMAC_128 || + cipher_mask == BIT(cipher))) { + w0 &= ~MT_WTBL_W0_KEY_IDX; + w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); } + mt76_wr(dev, MT_WTBL_RICR0, w0); mt76_wr(dev, MT_WTBL_RICR1, w1);
@@ -1113,24 +1116,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
- if (cmd == SET_KEY) { - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); - } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && - wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128)) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, - MT_CIPHER_BIP_CMAC_128)); - else if (!(wcid->cipher & ~BIT(cipher))) - mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + if (!cipher_mask) { + mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + return; } + + if (cmd != SET_KEY) + return; + + if (cipher == MT_CIPHER_BIP_CMAC_128 && + cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) + return; + + mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, + FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); }
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, @@ -1139,25 +1143,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, enum set_key_cmd cmd) { enum mt7615_cipher_type cipher; + u16 cipher_mask = wcid->cipher; int err;
cipher = mt7615_mac_get_cipher(key->cipher); if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP;
- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); + if (cmd == SET_KEY) + cipher_mask |= BIT(cipher); + else + cipher_mask &= ~BIT(cipher); + + mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); + err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, + cmd); if (err < 0) return err;
- err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, + key->keyidx, cmd); if (err < 0) return err;
- if (cmd == SET_KEY) - wcid->cipher |= BIT(cipher); - else - wcid->cipher &= ~BIT(cipher); + wcid->cipher = cipher_mask;
return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 6107e827b383..d334491667a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -334,7 +334,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx, err; + int idx = key->keyidx, err = 0; + u8 *wcid_keyidx = &wcid->hw_key_idx;
/* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -349,6 +350,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -366,12 +368,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7615_mutex_acquire(dev);
- if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL);
@@ -380,6 +383,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+out: mt7615_mutex_release(dev);
return err;
From: Sander Vanheule sander@svanheule.net
[ Upstream commit 858ebf446bee7d5077bd99488aae617908c3f4fe ]
EEPROM blobs for MT7613BE radios start with (little endian) 0x7663, which is also the PCI device ID for this device. The EEPROM is required for the radio to work at useful power levels, otherwise only the lowest power level is available.
Suggested-by: Georgi Vlaev georgi.vlaev@konsulko.com Tested-by: Stijn Segers foss@volatilesystems.org Signed-off-by: Sander Vanheule sander@svanheule.net Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 2eab23898c77..6dbaaf95ee38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: case 0x7622: + case 0x7663: return 0; default: return -EINVAL;
From: David Bauer mail@david-bauer.net
[ Upstream commit 4b36cc6b390f18dbc59a45fb4141f90d7dfe2b23 ]
When operating two VAP on a MT7610 with encryption (PSK2, SAE, OWE), only the first one to be created will transmit properly encrypteded frames.
All subsequently created VAPs will sent out frames with the payload left unencrypted, breaking multicast traffic (ICMP6 NDP) and potentially disclosing information to a third party.
Disable GTK offloading and encrypt these frames in software to circumvent this issue. THis only seems to be necessary on MT7610 chips, as MT7612 is not affected from our testing.
Signed-off-by: David Bauer mail@david-bauer.net Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index ab671e21f882..02db5d66735d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -447,6 +447,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return -EOPNOTSUPP;
+ /* MT76x0 GTK offloading does not work with more than one VIF */ + if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL; wcid = msta ? &msta->wcid : &mvif->group_wcid;
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit baa3afb39e94965f4ca5b5d3d274379504b8fa24 ]
Even if this is not a real bug since mt76_connac_mcu_alloc_wtbl_req routine can fails just if nskb is NULL , always check return value from mt76_connac_mcu_alloc_wtbl_req in order to avoid possible future mistake.
Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +++ 2 files changed, 6 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 631596fc2f36..4ecbd5406e2a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1040,6 +1040,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev,
wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx, sta_wtbl, wtbl_hdr);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 76a61e8b7fb9..cefd33b74a87 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -833,6 +833,9 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_RESET_AND_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + if (enable) { mt76_connac_mcu_wtbl_generic_tlv(dev, skb, vif, sta, sta_wtbl, wtbl_hdr);
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 45f93e368211fbbd247e1ece254ffb121e20fa10 ]
As done for mt76_connac_mcu_alloc_wtbl_req, even if this is not a real bug since mt7915_mcu_alloc_wtbl_req routine can fails just if nskb is NULL, always check return value from mt7915_mcu_alloc_wtbl_req in order to avoid possible future mistake.
Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 443cb09ae7cb..c747349a4c13 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -1198,6 +1198,9 @@ mt7915_mcu_sta_ba(struct mt7915_dev *dev,
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr);
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, @@ -1714,6 +1717,9 @@ int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev, return -ENOMEM;
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr);
return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD(WTBL_UPDATE), @@ -1738,6 +1744,9 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt7915_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_hdr);
return mt76_mcu_skb_send_msg(&dev->mt76, skb, @@ -2263,6 +2272,9 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_RESET_AND_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + if (enable) { mt7915_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr);
From: Felix Fietkau nbd@nbd.name
[ Upstream commit 1da4fd48d28436f8b690cdc2879603dede6d8355 ]
Deleting a key with the previous key index deletes the current key Rework the code to better keep track of multiple keys and check for the key index before deleting the current key
Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/mediatek/mt76/mt7915/main.c | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 98f4b49642a8..bf032d943f74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -317,7 +317,9 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; + u8 *wcid_keyidx = &wcid->hw_key_idx; int idx = key->keyidx; + int err = 0;
/* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -332,6 +334,7 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -347,16 +350,24 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; }
- if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + mutex_lock(&dev->mt76.mutex); + + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL);
- return mt7915_mcu_add_key(dev, vif, msta, key, cmd); + err = mt7915_mcu_add_key(dev, vif, msta, key, cmd); + +out: + mutex_unlock(&dev->mt76.mutex); + + return err; }
static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
From: Shayne Chen shayne.chen@mediatek.com
[ Upstream commit a226ccd04c479ccd23d6927c64bad1b441707f70 ]
Fix incorrect txpower init value for TSSI off chips which causes too small txpower.
Signed-off-by: Shayne Chen shayne.chen@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../wireless/mediatek/mt76/mt7915/eeprom.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index 660398ac53c2..738ecf8f4fa2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -124,7 +124,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, struct ieee80211_channel *chan, u8 chain_idx) { - int index; + int index, target_power; bool tssi_on;
if (chain_idx > 3) @@ -133,15 +133,22 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, tssi_on = mt7915_tssi_enabled(dev, chan->band);
if (chan->band == NL80211_BAND_2GHZ) { - index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on; + index = MT_EE_TX0_POWER_2G + chain_idx * 3; + target_power = mt7915_eeprom_read(dev, index); + + if (!tssi_on) + target_power += mt7915_eeprom_read(dev, index + 1); } else { - int group = tssi_on ? - mt7915_get_channel_group(chan->hw_value) : 8; + int group = mt7915_get_channel_group(chan->hw_value); + + index = MT_EE_TX0_POWER_5G + chain_idx * 12; + target_power = mt7915_eeprom_read(dev, index + group);
- index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group; + if (!tssi_on) + target_power += mt7915_eeprom_read(dev, index + 8); }
- return mt7915_eeprom_read(dev, index); + return target_power; }
static const u8 sku_cck_delta_map[] = {
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 60468f7fd7072c804b2613f1cadabace8d77d311 ]
Similar to the mt7915 driver, deleting a key with the previous key index deletes the current key. Rework the code to better keep track of multiple keys and check for the key index before deleting the current key
Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/mediatek/mt76/mt7921/main.c | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index cd9fd0e24e3e..ada943c7a950 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -413,7 +413,8 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx; + u8 *wcid_keyidx = &wcid->hw_key_idx; + int idx = key->keyidx, err = 0;
/* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -429,6 +430,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; + wcid_keyidx = &wcid->hw_key_idx2; break; case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: @@ -443,16 +445,23 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; }
- if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + mt7921_mutex_acquire(dev); + + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL);
- return mt7921_mcu_add_key(dev, vif, msta, key, cmd); + err = mt7921_mcu_add_key(dev, vif, msta, key, cmd); +out: + mt7921_mutex_release(dev); + + return err; }
static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
From: Ryder Lee ryder.lee@mediatek.com
[ Upstream commit e07419a7dca97dd9bddfe5d099380857c19535f3 ]
Reset wifi subsystem when MCU is already running. Fixes firmware download failure after soft reboot on systems where the PCIe reset could not be performed properly.
Signed-off-by: Ryder Lee ryder.lee@mediatek.com Co-developed-by: Felix Fietkau nbd@nbd.name Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/mediatek/mt76/mt7915/init.c | 58 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 15 +---- .../net/wireless/mediatek/mt76/mt7915/regs.h | 13 +++++ 3 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 894016fdcf07..c7d4268d860a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -4,6 +4,7 @@ #include <linux/etherdevice.h> #include "mt7915.h" #include "mac.h" +#include "mcu.h" #include "eeprom.h"
#define CCK_RATE(_idx, _rate) { \ @@ -283,9 +284,50 @@ static void mt7915_init_work(struct work_struct *work) mt7915_register_ext_phy(dev); }
+static void mt7915_wfsys_reset(struct mt7915_dev *dev) +{ + u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON; + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); + +#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0) +#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16) + + mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM); + + /* change to software control */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* reset wfsys */ + val &= ~MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* release wfsys then mcu re-excutes romcode */ + val |= MT_TOP_PWR_SW_RST; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* switch to hw control */ + val &= ~MT_TOP_PWR_SW_RST; + val |= MT_TOP_PWR_HW_CTRL; + mt76_wr(dev, MT_TOP_PWR_CTRL, val); + + /* check whether mcu resets to default */ + if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT, + MT_MCU_DUMMY_DEFAULT, 1000)) { + dev_err(dev->mt76.dev, "wifi subsystem reset failure\n"); + return; + } + + /* wfsys reset won't clear host registers */ + mt76_clear(dev, reg, MT_TOP_MISC_FW_STATE); + + msleep(100); +} + static int mt7915_init_hardware(struct mt7915_dev *dev) { int ret, idx; + u32 val;
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
@@ -295,6 +337,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5));
+ val = mt76_rr(dev, mt7915_reg_map_l1(dev, MT_TOP_MISC)); + + /* If MCU was already running, it is likely in a bad state */ + if (FIELD_GET(MT_TOP_MISC_FW_STATE, val) > FW_STATE_FW_DOWNLOAD) + mt7915_wfsys_reset(dev); + ret = mt7915_dma_init(dev); if (ret) return ret; @@ -308,8 +356,14 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7915_mcu_init(dev); - if (ret) - return ret; + if (ret) { + /* Reset and try again */ + mt7915_wfsys_reset(dev); + + ret = mt7915_mcu_init(dev); + if (ret) + return ret; + }
ret = mt7915_eeprom_init(dev); if (ret < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index c747349a4c13..f069a5a03e14 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -2764,21 +2764,8 @@ out:
static int mt7915_load_firmware(struct mt7915_dev *dev) { + u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); int ret; - u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC); - - val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD); - - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) { - /* restart firmware once */ - __mt76_mcu_restart(&dev->mt76); - if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, - val, 1000)) { - dev_err(dev->mt76.dev, - "Firmware is not ready for download\n"); - return -EIO; - } - }
ret = mt7915_load_patch(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index ed0c9a24bb53..dfb8880657bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -4,6 +4,11 @@ #ifndef __MT7915_REGS_H #define __MT7915_REGS_H
+/* MCU WFDMA0 */ +#define MT_MCU_WFDMA0_BASE 0x2000 +#define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs)) +#define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120) + /* MCU WFDMA1 */ #define MT_MCU_WFDMA1_BASE 0x3000 #define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) @@ -396,6 +401,14 @@ #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2)
+#define MT_TOP_RGU_BASE 0xf0000 +#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0)) +#define MT_TOP_PWR_KEY (0x5746 << 16) +#define MT_TOP_PWR_SW_RST BIT(0) +#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2) +#define MT_TOP_PWR_HW_CTRL BIT(4) +#define MT_TOP_PWR_PWR_ON BIT(7) + #define MT_INFRA_CFG_BASE 0xf1000 #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
From: Ye Weihua yeweihua4@huawei.com
[ Upstream commit c4b1fcc310e655fa8414696c38a84d36c00684c8 ]
pm_runtime_get_sync() will increment the PM reference count even on failure. Forgetting to put the reference again will result in a leak.
Replace it with pm_runtime_resume_and_get() to keep the usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Ye Weihua yeweihua4@huawei.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dc9c4b4cc25a..dc5ca71906db 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -801,7 +801,7 @@ static int i2c_imx_reg_slave(struct i2c_client *client) i2c_imx->last_slave_event = I2C_SLAVE_STOP;
/* Resume */ - ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); + ret = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent); if (ret < 0) { dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller"); return ret;
From: Vivek Goyal vgoyal@redhat.com
[ Upstream commit 3466958beb31a8e9d3a1441a34228ed088b84f3e ]
In fuse when a direct/write-through write happens we invalidate attrs because that might have updated mtime/ctime on server and cached mtime/ctime will be stale.
What about page writeback path. Looks like we don't invalidate attrs there. To be consistent, invalidate attrs in writeback path as well. Only exception is when writeback_cache is enabled. In that case we strust local mtime/ctime and there is no need to invalidate attrs.
Recently users started experiencing failure of xfstests generic/080, geneirc/215 and generic/614 on virtiofs. This happened only newer "stat" utility and not older one. This patch fixes the issue.
So what's the root cause of the issue. Here is detailed explanation.
generic/080 test does mmap write to a file, closes the file and then checks if mtime has been updated or not. When file is closed, it leads to flushing of dirty pages (and that should update mtime/ctime on server). But we did not explicitly invalidate attrs after writeback finished. Still generic/080 passed so far and reason being that we invalidated atime in fuse_readpages_end(). This is called in fuse_readahead() path and always seems to trigger before mmaped write.
So after mmaped write when lstat() is called, it sees that atleast one of the fields being asked for is invalid (atime) and that results in generating GETATTR to server and mtime/ctime also get updated and test passes.
But newer /usr/bin/stat seems to have moved to using statx() syscall now (instead of using lstat()). And statx() allows it to query only ctime or mtime (and not rest of the basic stat fields). That means when querying for mtime, fuse_update_get_attr() sees that mtime is not invalid (only atime is invalid). So it does not generate a new GETATTR and fill stat with cached mtime/ctime. And that means updated mtime is not seen by xfstest and tests start failing.
Invalidating attrs after writeback completion should solve this problem in a generic manner.
Signed-off-by: Vivek Goyal vgoyal@redhat.com Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/fuse/file.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index eff4abaa87da..6e6d1e599869 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1776,8 +1776,17 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args, container_of(args, typeof(*wpa), ia.ap.args); struct inode *inode = wpa->inode; struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_conn *fc = get_fuse_conn(inode);
mapping_set_error(inode->i_mapping, error); + /* + * A writeback finished and this might have updated mtime/ctime on + * server making local mtime/ctime stale. Hence invalidate attrs. + * Do this only if writeback_cache is not enabled. If writeback_cache + * is enabled, we trust local ctime/mtime. + */ + if (!fc->writeback_cache) + fuse_invalidate_attr(inode); spin_lock(&fi->lock); rb_erase(&wpa->writepages_entry, &fi->writepages); while (wpa->next) {
From: Miklos Szeredi mszeredi@redhat.com
[ Upstream commit 0a7419c68a45d2d066b996be5087aa2d07ce80eb ]
get_user_ns() is done twice (once in virtio_fs_get_tree() and once in fuse_conn_init()), resulting in a reference leak.
Also looks better to use fsc->user_ns (which *should* be the current_user_ns() at this point).
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/fuse/virtio_fs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 1e5affed158e..005209b1cd50 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -1437,8 +1437,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc) if (!fm) goto out_err;
- fuse_conn_init(fc, fm, get_user_ns(current_user_ns()), - &virtio_fs_fiq_ops, fs); + fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs); fc->release = fuse_free_conn; fc->delete_stale = true; fc->auto_submounts = true;
From: Miklos Szeredi mszeredi@redhat.com
[ Upstream commit 8217673d07256b22881127bf50dce874d0e51653 ]
For cloned connections cuse_channel_release() will be called more than once, resulting in use after free.
Prevent device cloning for CUSE, which does not make sense at this point, and highly unlikely to be used in real life.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/fuse/cuse.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 45082269e698..a37528b51798 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -627,6 +627,8 @@ static int __init cuse_init(void) cuse_channel_fops.owner = THIS_MODULE; cuse_channel_fops.open = cuse_channel_open; cuse_channel_fops.release = cuse_channel_release; + /* CUSE is not prepared for FUSE_DEV_IOC_CLONE */ + cuse_channel_fops.unlocked_ioctl = NULL;
cuse_class = class_create(THIS_MODULE, "cuse"); if (IS_ERR(cuse_class))
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 48a5494d6a4cb5812f0640d9515f1876ffc7a013 ]
If we (for example) have a trans_cfg entry in the PCI IDs table, but then don't find a full cfg entry for it in the info table, we fall through to the code that treats the PCI ID table entry as a full cfg entry. This obviously causes crashes later, e.g. when trying to build the firmware name string.
Avoid such crashes by using the low bit of the pointer as a tag for trans_cfg entries (automatically using a macro that checks the type when assigning) and then checking that before trying to use the data as a full entry - if it's just a partial entry at that point, fail.
Since we're adding some macro magic, also check that the type is in fact either struct iwl_cfg_trans_params or struct iwl_cfg, failing compilation ("initializer element is not constant") if it isn't.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210330162204.6f69fe6e4128.I921d4ae20ef52... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 558a0b2ef0fc..6f4db04ead4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -17,10 +17,20 @@ #include "iwl-prph.h" #include "internal.h"
+#define TRANS_CFG_MARKER BIT(0) +#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \ + struct _struct) +extern int _invalid_type; +#define _TRANS_CFG_MARKER(cfg) \ + (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \ + TRANS_CFG_MARKER, \ + __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type))) +#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg)) + #define IWL_PCI_DEVICE(dev, subdev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ - .driver_data = (kernel_ulong_t)&(cfg) + .driver_data = _ASSIGN_CFG(cfg)
/* Hardware specific file defines the PCI IDs table for that hardware module */ static const struct pci_device_id iwl_hw_card_ids[] = { @@ -1075,19 +1085,22 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct iwl_cfg_trans_params *trans = - (struct iwl_cfg_trans_params *)(ent->driver_data); + const struct iwl_cfg_trans_params *trans; const struct iwl_cfg *cfg_7265d __maybe_unused = NULL; struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; int i, ret; + const struct iwl_cfg *cfg; + + trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER); + /* * This is needed for backwards compatibility with the old * tables, so we don't need to change all the config structs * at the same time. The cfg is used to compare with the old * full cfg structs. */ - const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
/* make sure trans is the first element in iwl_cfg */ BUILD_BUG_ON(offsetof(struct iwl_cfg, trans)); @@ -1202,11 +1215,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif /* - * If we didn't set the cfg yet, assume the trans is actually - * a full cfg from the old tables. + * If we didn't set the cfg yet, the PCI ID table entry should have + * been a full config - if yes, use it, otherwise fail. */ - if (!iwl_trans->cfg) + if (!iwl_trans->cfg) { + if (ent->driver_data & TRANS_CFG_MARKER) { + pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n", + pdev->device, pdev->subsystem_device, + iwl_trans->hw_rev, iwl_trans->hw_rf_id); + ret = -EINVAL; + goto out_free_trans; + } iwl_trans->cfg = cfg; + }
/* if we don't have a name yet, copy name from the old cfg */ if (!iwl_trans->name)
From: Mordechay Goodstein mordechay.goodstein@intel.com
[ Upstream commit 4cf2f5904d971a461f67825434ae3c31900ff84b ]
In case the device is stopped any usage of hw queues needs to be reallocated in fw due to fw reset after device stop, so all driver internal queue should also be freed, and if we don't free the next usage would leak the old memory and get in recover flows "iwlwifi 0000:00:03.0: dma_pool_destroy iwlwifi:bc" warning.
Also warn about trying to reuse an internal allocated queue.
Signed-off-by: Mordechay Goodstein mordechay.goodstein@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210411124417.c72d2f0355c4.Ia3baff633b9b9... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 4 +-- drivers/net/wireless/intel/iwlwifi/queue/tx.c | 30 ++++--------------- drivers/net/wireless/intel/iwlwifi/queue/tx.h | 3 +- 3 files changed, 9 insertions(+), 28 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 94ffc1ae484d..af9412bd697e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include "iwl-trans.h" #include "iwl-prph.h" @@ -143,7 +143,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); - iwl_txq_gen2_tx_stop(trans); + iwl_txq_gen2_tx_free(trans); iwl_pcie_rx_stop(trans); }
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c index 833f43d1ca7a..810dcb3df242 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c @@ -13,30 +13,6 @@ #include "iwl-scd.h" #include <linux/dmapool.h>
-/* - * iwl_txq_gen2_tx_stop - Stop all Tx DMA channels - */ -void iwl_txq_gen2_tx_stop(struct iwl_trans *trans) -{ - int txq_id; - - /* - * This function can be called before the op_mode disabled the - * queues. This happens when we have an rfkill interrupt. - * Since we stop Tx altogether - mark the queues as stopped. - */ - memset(trans->txqs.queue_stopped, 0, - sizeof(trans->txqs.queue_stopped)); - memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used)); - - /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) { - if (!trans->txqs.txq[txq_id]) - continue; - iwl_txq_gen2_unmap(trans, txq_id); - } -} - /* * iwl_txq_update_byte_tbl - Set up entry in Tx byte-count array */ @@ -1189,6 +1165,12 @@ static int iwl_txq_alloc_response(struct iwl_trans *trans, struct iwl_txq *txq, goto error_free_resp; }
+ if (WARN_ONCE(trans->txqs.txq[qid], + "queue %d already allocated\n", qid)) { + ret = -EIO; + goto error_free_resp; + } + txq->id = qid; trans->txqs.txq[qid] = txq; wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1); diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h index af1dbdf5617a..20efc62acf13 100644 --- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation */ #ifndef __iwl_trans_queue_tx_h__ #define __iwl_trans_queue_tx_h__ @@ -123,7 +123,6 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, void iwl_txq_dyn_free(struct iwl_trans *trans, int queue); void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq); void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); -void iwl_txq_gen2_tx_stop(struct iwl_trans *trans); void iwl_txq_gen2_tx_free(struct iwl_trans *trans); int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, bool cmd_queue);
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit d12455fdbfe9430affd88bfbfee51777356667a0 ]
In a few PCIe devices we may have to swap out the configuration after we allocate/initialise some parts of the device because we only know the correct one after reading some registers. This causes some things such as the byte-count table allocations to be incorrect, since the configuration is swapped for one with a bigger queue size.
Fix this by initialising most of the transport much later, only after the configuration has finally been determined.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210411132130.8f5db97db1e4.Ic622da559b586... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/intel/iwlwifi/iwl-trans.c | 91 +++++++++++-------- .../net/wireless/intel/iwlwifi/iwl-trans.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 + 3 files changed, 57 insertions(+), 39 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 60e0db4a5e20..9236f9106826 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation */ #include <linux/kernel.h> #include <linux/bsearch.h> @@ -21,7 +21,6 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, const struct iwl_cfg_trans_params *cfg_trans) { struct iwl_trans *trans; - int txcmd_size, txcmd_align; #ifdef CONFIG_LOCKDEP static struct lock_class_key __key; #endif @@ -31,10 +30,40 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, return NULL;
trans->trans_cfg = cfg_trans; - if (!cfg_trans->gen2) { + +#ifdef CONFIG_LOCKDEP + lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", + &__key, 0); +#endif + + trans->dev = dev; + trans->ops = ops; + trans->num_rx_queues = 1; + + WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); + + if (trans->trans_cfg->use_tfh) { + trans->txqs.tfd.addr_size = 64; + trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; + trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); + } else { + trans->txqs.tfd.addr_size = 36; + trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; + trans->txqs.tfd.size = sizeof(struct iwl_tfd); + } + trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); + + return trans; +} + +int iwl_trans_init(struct iwl_trans *trans) +{ + int txcmd_size, txcmd_align; + + if (!trans->trans_cfg->gen2) { txcmd_size = sizeof(struct iwl_tx_cmd); txcmd_align = sizeof(void *); - } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { + } else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { txcmd_size = sizeof(struct iwl_tx_cmd_gen2); txcmd_align = 64; } else { @@ -46,17 +75,8 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, txcmd_size += 36; /* biggest possible 802.11 header */
/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ - if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) - return ERR_PTR(-EINVAL); - -#ifdef CONFIG_LOCKDEP - lockdep_init_map(&trans->sync_cmd_lockdep_map, "sync_cmd_lockdep_map", - &__key, 0); -#endif - - trans->dev = dev; - trans->ops = ops; - trans->num_rx_queues = 1; + if (WARN_ON(trans->trans_cfg->gen2 && txcmd_size >= txcmd_align)) + return -EINVAL;
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) trans->txqs.bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); @@ -68,23 +88,16 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, * allocate here. */ if (trans->trans_cfg->gen2) { - trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", dev, + trans->txqs.bc_pool = dmam_pool_create("iwlwifi:bc", trans->dev, trans->txqs.bc_tbl_size, 256, 0); if (!trans->txqs.bc_pool) - return NULL; + return -ENOMEM; }
- if (trans->trans_cfg->use_tfh) { - trans->txqs.tfd.addr_size = 64; - trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS; - trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd); - } else { - trans->txqs.tfd.addr_size = 36; - trans->txqs.tfd.max_tbs = IWL_NUM_OF_TBS; - trans->txqs.tfd.size = sizeof(struct iwl_tfd); - } - trans->max_skb_frags = IWL_TRANS_MAX_FRAGS(trans); + /* Some things must not change even if the config does */ + WARN_ON(trans->txqs.tfd.addr_size != + (trans->trans_cfg->use_tfh ? 64 : 36));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); @@ -93,35 +106,35 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, txcmd_size, txcmd_align, SLAB_HWCACHE_ALIGN, NULL); if (!trans->dev_cmd_pool) - return NULL; - - WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty); + return -ENOMEM;
trans->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); if (!trans->txqs.tso_hdr_page) { kmem_cache_destroy(trans->dev_cmd_pool); - return NULL; + return -ENOMEM; }
/* Initialize the wait queue for commands */ init_waitqueue_head(&trans->wait_command_queue);
- return trans; + return 0; }
void iwl_trans_free(struct iwl_trans *trans) { int i;
- for_each_possible_cpu(i) { - struct iwl_tso_hdr_page *p = - per_cpu_ptr(trans->txqs.tso_hdr_page, i); + if (trans->txqs.tso_hdr_page) { + for_each_possible_cpu(i) { + struct iwl_tso_hdr_page *p = + per_cpu_ptr(trans->txqs.tso_hdr_page, i);
- if (p->page) - __free_page(p->page); - } + if (p && p->page) + __free_page(p->page); + }
- free_percpu(trans->txqs.tso_hdr_page); + free_percpu(trans->txqs.tso_hdr_page); + }
kmem_cache_destroy(trans->dev_cmd_pool); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 4a5822c1be13..3e0df6fbb642 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1438,6 +1438,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct device *dev, const struct iwl_trans_ops *ops, const struct iwl_cfg_trans_params *cfg_trans); +int iwl_trans_init(struct iwl_trans *trans); void iwl_trans_free(struct iwl_trans *trans);
/***************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6f4db04ead4a..66faf7914bd8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1243,6 +1243,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans_pcie->num_rx_bufs = RX_QUEUE_SIZE; }
+ ret = iwl_trans_init(iwl_trans); + if (ret) + goto out_free_trans; + pci_set_drvdata(pdev, iwl_trans); iwl_trans->drv = iwl_drv_start(iwl_trans);
From: Vaibhav Jain vaibhav@linux.ibm.com
[ Upstream commit a5d6a3e73acbd619dd5b7b831762b755f9e2db80 ]
While removing large number of mappings from hash page tables for large memory systems as soft-lockup is reported because of the time spent inside htap_remove_mapping() like one below:
watchdog: BUG: soft lockup - CPU#8 stuck for 23s! <snip> NIP plpar_hcall+0x38/0x58 LR pSeries_lpar_hpte_invalidate+0x68/0xb0 Call Trace: 0x1fffffffffff000 (unreliable) pSeries_lpar_hpte_removebolted+0x9c/0x230 hash__remove_section_mapping+0xec/0x1c0 remove_section_mapping+0x28/0x3c arch_remove_memory+0xfc/0x150 devm_memremap_pages_release+0x180/0x2f0 devm_action_release+0x30/0x50 release_nodes+0x28c/0x300 device_release_driver_internal+0x16c/0x280 unbind_store+0x124/0x170 drv_attr_store+0x44/0x60 sysfs_kf_write+0x64/0x90 kernfs_fop_write+0x1b0/0x290 __vfs_write+0x3c/0x70 vfs_write+0xd4/0x270 ksys_write+0xdc/0x130 system_call+0x5c/0x70
Fix this by adding a cond_resched() to the loop in htap_remove_mapping() that issues hcall to remove hpte mapping. The call to cond_resched() is issued every HZ jiffies which should prevent the soft-lockup from being reported.
Suggested-by: Aneesh Kumar K.V aneesh.kumar@linux.ibm.com Signed-off-by: Vaibhav Jain vaibhav@linux.ibm.com Reviewed-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210404163148.321346-1-vaibhav@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/mm/book3s64/hash_utils.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index 7719995323c3..12de1906e97b 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c @@ -338,7 +338,7 @@ repeat: int htab_remove_mapping(unsigned long vstart, unsigned long vend, int psize, int ssize) { - unsigned long vaddr; + unsigned long vaddr, time_limit; unsigned int step, shift; int rc; int ret = 0; @@ -351,8 +351,19 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend,
/* Unmap the full range specificied */ vaddr = ALIGN_DOWN(vstart, step); + time_limit = jiffies + HZ; + for (;vaddr < vend; vaddr += step) { rc = mmu_hash_ops.hpte_removebolted(vaddr, psize, ssize); + + /* + * For large number of mappings introduce a cond_resched() + * to prevent softlockup warnings. + */ + if (time_after(jiffies, time_limit)) { + cond_resched(); + time_limit = jiffies + HZ; + } if (rc == -ENOENT) { ret = -ENOENT; continue;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
[ Upstream commit a122a116fc6d8fcf2f202dcd185173a54268f239 ]
Current rsnd needs to call .prepare (P) for clock settings, .trigger for playback start (S) and stop (E). It should be called as below from SSI point of view.
P -> S -> E -> P -> S -> E -> ...
But, if you used MIXer, below case might happen
(2) 1: P -> S ---> E -> ... 2: P ----> S -> ... (1) (3)
P(1) setups clock, but E(2) resets it. and starts playback (3). In such case, it will reports "SSI parent/child should use same rate".
rsnd_ssi_master_clk_start() which is the main function at (P) was called from rsnd_ssi_init() (= S) before, but was moved by below patch to rsnd_soc_dai_prepare() (= P) to avoid using clk_get_rate() which shouldn't be used under atomic context.
commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set under non-atomic")
Because of above patch, rsnd_ssi_master_clk_start() is now called at (P) which is for non atomic context. But (P) is assuming that spin lock is *not* used. One issue now is rsnd_ssi_master_clk_start() is checking ssi->xxx which should be protected by spin lock.
After above patch, adg.c had below patch for other reasons.
commit 06e8f5c842f2d ("ASoC: rsnd: don't call clk_get_rate() under atomic context")
clk_get_rate() is used at probe() timing by this patch. In other words, rsnd_ssi_master_clk_start() is no longer using clk_get_rate() any more.
This means we can call it from rsnd_ssi_init() (= S) again which is protected by spin lock. This patch re-move it to under spin lock, and solves 1. checking ssi->xxx without spin lock issue. 2. clk setting / device start / device stop race condition.
Reported-by: Linh Phung T. Y. linh.phung.jy@renesas.com Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/875z0x1jt5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sh/rcar/ssi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d0ded427a836..a2f8138d40c7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -507,10 +507,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int ret;
if (!rsnd_ssi_is_run_mods(mod, io)) return 0;
+ ret = rsnd_ssi_master_clk_start(mod, io); + if (ret < 0) + return ret; + ssi->usrcnt++;
rsnd_mod_power_on(mod); @@ -1060,13 +1065,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod, return 0; }
-static int rsnd_ssi_prepare(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) -{ - return rsnd_ssi_master_clk_start(mod, io); -} - static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = SSI_NAME, .probe = rsnd_ssi_common_probe, @@ -1079,7 +1077,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .pointer = rsnd_ssi_pio_pointer, .pcm_new = rsnd_ssi_pcm_new, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, };
@@ -1166,7 +1163,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .pcm_new = rsnd_ssi_pcm_new, .fallback = rsnd_ssi_fallback, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, };
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 229309d7b4ff..72b3193b08ec 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1593,7 +1593,8 @@ out: spin_unlock(&br->multicast_lock); }
-static void br_mc_disabled_update(struct net_device *dev, bool value) +static int br_mc_disabled_update(struct net_device *dev, bool value, + struct netlink_ext_ack *extack) { struct switchdev_attr attr = { .orig_dev = dev, @@ -1602,11 +1603,13 @@ static void br_mc_disabled_update(struct net_device *dev, bool value) .u.mc_disabled = !value, };
- switchdev_port_attr_set(dev, &attr, NULL); + return switchdev_port_attr_set(dev, &attr, extack); }
int br_multicast_add_port(struct net_bridge_port *port) { + int err; + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
@@ -1618,8 +1621,12 @@ int br_multicast_add_port(struct net_bridge_port *port) timer_setup(&port->ip6_own_query.timer, br_ip6_multicast_port_query_expired, 0); #endif - br_mc_disabled_update(port->dev, - br_opt_get(port->br, BROPT_MULTICAST_ENABLED)); + err = br_mc_disabled_update(port->dev, + br_opt_get(port->br, + BROPT_MULTICAST_ENABLED), + NULL); + if (err) + return err;
port->mcast_stats = netdev_alloc_pcpu_stats(struct bridge_mcast_stats); if (!port->mcast_stats) @@ -3543,16 +3550,23 @@ static void br_multicast_start_querier(struct net_bridge *br, rcu_read_unlock(); }
-int br_multicast_toggle(struct net_bridge *br, unsigned long val) +int br_multicast_toggle(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) { struct net_bridge_port *port; bool change_snoopers = false; + int err = 0;
spin_lock_bh(&br->multicast_lock); if (!!br_opt_get(br, BROPT_MULTICAST_ENABLED) == !!val) goto unlock;
- br_mc_disabled_update(br->dev, val); + err = br_mc_disabled_update(br->dev, val, extack); + if (err == -EOPNOTSUPP) + err = 0; + if (err) + goto unlock; + br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val); if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) { change_snoopers = true; @@ -3590,7 +3604,7 @@ unlock: br_multicast_leave_snoopers(br); }
- return 0; + return err; }
bool br_multicast_enabled(const struct net_device *dev) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index f2b1343f8332..0456593aceec 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1293,7 +1293,9 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], if (data[IFLA_BR_MCAST_SNOOPING]) { u8 mcast_snooping = nla_get_u8(data[IFLA_BR_MCAST_SNOOPING]);
- br_multicast_toggle(br, mcast_snooping); + err = br_multicast_toggle(br, mcast_snooping, extack); + if (err) + return err; }
if (data[IFLA_BR_MCAST_QUERY_USE_IFADDR]) { diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d7d167e10b70..af3430c2d6ea 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -810,7 +810,8 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, bool local_rcv, bool local_orig); int br_multicast_set_router(struct net_bridge *br, unsigned long val); int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); -int br_multicast_toggle(struct net_bridge *br, unsigned long val); +int br_multicast_toggle(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack); int br_multicast_set_querier(struct net_bridge *br, unsigned long val); int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val); diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 072e29840082..381467b691d5 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -409,17 +409,11 @@ static ssize_t multicast_snooping_show(struct device *d, return sprintf(buf, "%d\n", br_opt_get(br, BROPT_MULTICAST_ENABLED)); }
-static int toggle_multicast(struct net_bridge *br, unsigned long val, - struct netlink_ext_ack *extack) -{ - return br_multicast_toggle(br, val); -} - static ssize_t multicast_snooping_store(struct device *d, struct device_attribute *attr, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, toggle_multicast); + return store_bridge_parm(d, buf, len, br_multicast_toggle); } static DEVICE_ATTR_RW(multicast_snooping);
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Regards Rudi
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
greg k-h
Greg,
On Tue, May 18, 2021 at 02:39:43PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
Did you backport this patch too? https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?...
On Tue, May 18, 2021 at 01:49:10PM +0000, Vladimir Oltean wrote:
Greg,
On Tue, May 18, 2021 at 02:39:43PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
Did you backport this patch too? https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?...
Ick, I didn't run my "do we need additional fixes" script before this round :(
So no, I didn't. I'll go queue that up now and push out a -rc2.
thanks,
greg k-h
On Tue, May 18, 2021 at 02:39:43PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
greg k-h
Hi Greg,
I can confirm that docker starts correctly with 5.13-rc1
# dmesg | head [ 0.000000] Linux version 5.13.0-rc1 (rudi@0e5f93d4a8a2) (x86_64-libreelec-linux-gnu-gcc-10.3.0 (GCC) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP Tue May 18 14:00:41 UTC 2021 [ 0.000000] Command line: BOOT_IMAGE=/KERNEL boot=LABEL=LIBREELEC disk=LABEL=STORAGE i915.enable_guc=2 quiet ... [ 11.214582] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214589] docker0: port 1(veth2b37ac4) entered disabled state [ 11.214649] device veth2b37ac4 entered promiscuous mode [ 11.214752] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214755] docker0: port 1(veth2b37ac4) entered forwarding state
Regards Rudi
On Tue, May 18, 2021 at 02:12:42PM +0000, Rudi Heitbaum wrote:
On Tue, May 18, 2021 at 02:39:43PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
greg k-h
Hi Greg,
I can confirm that docker starts correctly with 5.13-rc1
# dmesg | head [ 0.000000] Linux version 5.13.0-rc1 (rudi@0e5f93d4a8a2) (x86_64-libreelec-linux-gnu-gcc-10.3.0 (GCC) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP Tue May 18 14:00:41 UTC 2021 [ 0.000000] Command line: BOOT_IMAGE=/KERNEL boot=LABEL=LIBREELEC disk=LABEL=STORAGE i915.enable_guc=2 quiet ... [ 11.214582] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214589] docker0: port 1(veth2b37ac4) entered disabled state [ 11.214649] device veth2b37ac4 entered promiscuous mode [ 11.214752] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214755] docker0: port 1(veth2b37ac4) entered forwarding state
Great, can you try 5.12.5-rc2 now?
thanks,
greg k-h
On Tue, May 18, 2021 at 04:28:30PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 02:12:42PM +0000, Rudi Heitbaum wrote:
On Tue, May 18, 2021 at 02:39:43PM +0200, Greg Kroah-Hartman wrote:
On Tue, May 18, 2021 at 12:24:57PM +0000, Rudi Heitbaum wrote:
On Mon, May 17, 2021 at 03:59:07PM +0200, Greg Kroah-Hartman wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit ae1ea84b33dab45c7b6c1754231ebda5959b504c ]
Some Ethernet switches might only be able to support disabling multicast snooping globally, which is an issue for example when several bridges span the same physical device and request contradictory settings.
Propagate the return value of br_mc_disabled_update() such that this limitation is transmitted correctly to user-space.
Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
net/bridge/br_multicast.c | 28 +++++++++++++++++++++------- net/bridge/br_netlink.c | 4 +++- net/bridge/br_private.h | 3 ++- net/bridge/br_sysfs_br.c | 8 +------- 4 files changed, 27 insertions(+), 16 deletions(-)
This patch results in docker failing to start, and a regression between 5.12.4 and 5.12.5-rc1
A working dmesg output is like:
[ 11.545255] device eth0 entered promiscuous mode [ 11.693848] process 'docker/tmp/qemu-check643160757/check' started with executable stack [ 17.233059] br-92020c7e3aea: port 1(veth17a0552) entered blocking state [ 17.233065] br-92020c7e3aea: port 1(veth17a0552) entered disabled state [ 17.233098] device veth17a0552 entered promiscuous mode [ 17.292839] docker0: port 2(veth9d227f5) entered blocking state [ 17.292848] docker0: port 2(veth9d227f5) entered disabled state [ 17.292946] device veth9d227f5 entered promiscuous mode [ 17.293070] docker0: port 2(veth9d227f5) entered blocking state [ 17.293075] docker0: port 2(veth9d227f5) entered forwarding state
with this patch "device veth17a0552 entered promiscuous mode" never shows up.
the docker error itself is:
docker: Error response from daemon: failed to create endpoint sleepy_dijkstra on network bridge: adding interface veth8cbd8f9 to bridge docker0 failed: operation not supported.
Ick.
Does 5.13-rc1 also show this same problem?
And thanks for testing!
greg k-h
Hi Greg,
I can confirm that docker starts correctly with 5.13-rc1
# dmesg | head [ 0.000000] Linux version 5.13.0-rc1 (rudi@0e5f93d4a8a2) (x86_64-libreelec-linux-gnu-gcc-10.3.0 (GCC) 10.3.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP Tue May 18 14:00:41 UTC 2021 [ 0.000000] Command line: BOOT_IMAGE=/KERNEL boot=LABEL=LIBREELEC disk=LABEL=STORAGE i915.enable_guc=2 quiet ... [ 11.214582] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214589] docker0: port 1(veth2b37ac4) entered disabled state [ 11.214649] device veth2b37ac4 entered promiscuous mode [ 11.214752] docker0: port 1(veth2b37ac4) entered blocking state [ 11.214755] docker0: port 1(veth2b37ac4) entered forwarding state
Great, can you try 5.12.5-rc2 now?
thanks,
greg k-h
confirmed working now.
Thanks Rudi
From: Paul Menzel pmenzel@molgen.mpg.de
[ Upstream commit 715601e4e36903a653cd4294dfd3ed0019101991 ]
This reverts commit 6778ff5b21bd8e78c8bd547fd66437cf2657fd9b.
The original commit tries to address an issue, where PMC power-gating causing the IOMMU PMC pre-init test to fail on certain desktop/mobile platforms where the power-gating is normally enabled.
There have been several reports that the workaround still does not guarantee to work, and can add up to 100 ms (on the worst case) to the boot process on certain platforms such as the MSI B350M MORTAR with AMD Ryzen 3 2200G.
Therefore, revert this commit as a prelude to removing the pre-init test.
Link: https://lore.kernel.org/linux-iommu/alpine.LNX.3.20.13.2006030935570.3181@mo... Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201753 Cc: Tj (Elloe Linux) ml.linux@elloe.vision Cc: Shuah Khan skhan@linuxfoundation.org Cc: Alexander Monakov amonakov@ispras.ru Cc: David Coe david.coe@live.co.uk Signed-off-by: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Suravee Suthikulpanit suravee.suthikulpanit@amd.com Link: https://lore.kernel.org/r/20210409085848.3908-2-suravee.suthikulpanit@amd.co... Signed-off-by: Joerg Roedel jroedel@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/amd/init.c | 45 ++++++++++------------------------------ 1 file changed, 11 insertions(+), 34 deletions(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index f7e31018cd0b..ad53f516e46e 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -12,7 +12,6 @@ #include <linux/acpi.h> #include <linux/list.h> #include <linux/bitmap.h> -#include <linux/delay.h> #include <linux/slab.h> #include <linux/syscore_ops.h> #include <linux/interrupt.h> @@ -257,8 +256,6 @@ static enum iommu_init_state init_state = IOMMU_START_STATE; static int amd_iommu_enable_interrupts(void); static int __init iommu_go_to_state(enum iommu_init_state state); static void init_device_table_dma(void); -static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, - u8 fxn, u64 *value, bool is_write);
static bool amd_iommu_pre_enabled = true;
@@ -1717,11 +1714,13 @@ static int __init init_iommu_all(struct acpi_table_header *table) return 0; }
-static void __init init_iommu_perf_ctr(struct amd_iommu *iommu) +static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, + u8 fxn, u64 *value, bool is_write); + +static void init_iommu_perf_ctr(struct amd_iommu *iommu) { - int retry; struct pci_dev *pdev = iommu->dev; - u64 val = 0xabcd, val2 = 0, save_reg, save_src; + u64 val = 0xabcd, val2 = 0, save_reg = 0;
if (!iommu_feature(iommu, FEATURE_PC)) return; @@ -1729,39 +1728,17 @@ static void __init init_iommu_perf_ctr(struct amd_iommu *iommu) amd_iommu_pc_present = true;
/* save the value to restore, if writable */ - if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false) || - iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, false)) - goto pc_false; - - /* - * Disable power gating by programing the performance counter - * source to 20 (i.e. counts the reads and writes from/to IOMMU - * Reserved Register [MMIO Offset 1FF8h] that are ignored.), - * which never get incremented during this init phase. - * (Note: The event is also deprecated.) - */ - val = 20; - if (iommu_pc_get_set_reg(iommu, 0, 0, 8, &val, true)) + if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false)) goto pc_false;
/* Check if the performance counters can be written to */ - val = 0xabcd; - for (retry = 5; retry; retry--) { - if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true) || - iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false) || - val2) - break; - - /* Wait about 20 msec for power gating to disable and retry. */ - msleep(20); - } - - /* restore */ - if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true) || - iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, true)) + if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || + (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || + (val != val2)) goto pc_false;
- if (val != val2) + /* restore */ + if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true)) goto pc_false;
pci_info(pdev, "IOMMU performance counters supported\n");
From: Suravee Suthikulpanit suravee.suthikulpanit@amd.com
[ Upstream commit 994d6608efe4a4c8834bdc5014c86f4bc6aceea6 ]
In early AMD desktop/mobile platforms (during 2013), when the IOMMU Performance Counter (PMC) support was first introduced in commit 30861ddc9cca ("perf/x86/amd: Add IOMMU Performance Counter resource management"), there was a HW bug where the counters could not be accessed. The result was reading of the counter always return zero.
At the time, the suggested workaround was to add a test logic prior to initializing the PMC feature to check if the counters can be programmed and read back the same value. This has been working fine until the more recent desktop/mobile platforms start enabling power gating for the PMC, which prevents access to the counters. This results in the PMC support being disabled unnecesarily.
Unfortunatly, there is no documentation of since which generation of hardware the original PMC HW bug was fixed. Although, it was fixed soon after the first introduction of the PMC. Base on this, we assume that the buggy platforms are less likely to be in used, and it should be relatively safe to remove this legacy logic.
Link: https://lore.kernel.org/linux-iommu/alpine.LNX.3.20.13.2006030935570.3181@mo... Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201753 Cc: Tj (Elloe Linux) ml.linux@elloe.vision Cc: Shuah Khan skhan@linuxfoundation.org Cc: Alexander Monakov amonakov@ispras.ru Cc: David Coe david.coe@live.co.uk Cc: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Suravee Suthikulpanit suravee.suthikulpanit@amd.com Tested-by: Shuah Khan skhan@linuxfoundation.org Link: https://lore.kernel.org/r/20210409085848.3908-3-suravee.suthikulpanit@amd.co... Signed-off-by: Joerg Roedel jroedel@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/amd/init.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index ad53f516e46e..df7b19ff0a9e 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -1714,33 +1714,16 @@ static int __init init_iommu_all(struct acpi_table_header *table) return 0; }
-static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, - u8 fxn, u64 *value, bool is_write); - static void init_iommu_perf_ctr(struct amd_iommu *iommu) { + u64 val; struct pci_dev *pdev = iommu->dev; - u64 val = 0xabcd, val2 = 0, save_reg = 0;
if (!iommu_feature(iommu, FEATURE_PC)) return;
amd_iommu_pc_present = true;
- /* save the value to restore, if writable */ - if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false)) - goto pc_false; - - /* Check if the performance counters can be written to */ - if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || - (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || - (val != val2)) - goto pc_false; - - /* restore */ - if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true)) - goto pc_false; - pci_info(pdev, "IOMMU performance counters supported\n");
val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET); @@ -1748,11 +1731,6 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) iommu->max_counters = (u8) ((val >> 7) & 0xf);
return; - -pc_false: - pci_err(pdev, "Unable to read/write to IOMMU perf counter.\n"); - amd_iommu_pc_present = false; - return; }
static ssize_t amd_iommu_show_cap(struct device *dev,
From: Anthony Wang anthony1.wang@amd.com
[ Upstream commit 56d63782af9bbd1271bff1422a6a013123eade4d ]
[Why] Underflow observed when disabling PIP overlay in-game when vsync is disabled, due to OTC master lock not working with game pipe which is immediate flip.
[How] When performing a full update, override flip_immediate value to false for all planes, so that flip occurs on vsync.
Signed-off-by: Anthony Wang anthony1.wang@amd.com Acked-by: Bindu Ramamurthy bindur12@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c0b827d16268..4781279024a9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2546,6 +2546,10 @@ static void commit_planes_for_stream(struct dc *dc, plane_state->triplebuffer_flips = true; } } + if (update_type == UPDATE_TYPE_FULL) { + /* force vsync flip when reconfiguring pipes to prevent underflow */ + plane_state->flip_immediate = false; + } } }
From: Yonghong Song yhs@fb.com
[ Upstream commit 26e6dd1072763cd5696b75994c03982dde952ad9 ]
selftests/bpf/Makefile includes lib.mk. With the following command make -j60 LLVM=1 LLVM_IAS=1 <=== compile kernel make -j60 -C tools/testing/selftests/bpf LLVM=1 LLVM_IAS=1 V=1 some files are still compiled with gcc. This patch fixed lib.mk issue which sets CC to gcc in all cases.
Signed-off-by: Yonghong Song yhs@fb.com Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20210413153413.3027426-1-yhs@fb.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/lib.mk | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index be17462fe146..0af84ad48aa7 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -1,6 +1,10 @@ # This mimics the top-level Makefile. We do it explicitly here so that this # Makefile can operate with or without the kbuild infrastructure. +ifneq ($(LLVM),) +CC := clang +else CC := $(CROSS_COMPILE)gcc +endif
ifeq (0,$(MAKELEVEL)) ifeq ($(OUTPUT),)
From: Mihai Moldovan ionic@ionic.de
[ Upstream commit 8c94b430b9f6213dec84e309bb480a71778c4213 ]
If the user selects the very first entry in a page and performs a search-up operation, or selects the very last entry in a page and performs a search-down operation that will not succeed (e.g., via [/]asdfzzz[Up Arrow]), nconf will never terminate searching the page.
The reason is that in this case, the starting point will be set to -1 or n, which is then translated into (n - 1) (i.e., the last entry of the page) or 0 (i.e., the first entry of the page) and finally the search begins. This continues to work fine until the index reaches 0 or (n - 1), at which point it will be decremented to -1 or incremented to n, but not checked against the starting point right away. Instead, it's wrapped around to the bottom or top again, after which the starting point check occurs... and naturally fails.
My original implementation added another check for -1 before wrapping the running index variable around, but Masahiro Yamada pointed out that the actual issue is that the comparison point (starting point) exceeds bounds (i.e., the [0,n-1] interval) in the first place and that, instead, the starting point should be fixed.
This has the welcome side-effect of also fixing the case where the starting point was n while searching down, which also lead to an infinite loop.
OTOH, this code is now essentially all his work.
Amazingly, nobody seems to have been hit by this for 11 years - or at the very least nobody bothered to debug and fix this.
Signed-off-by: Mihai Moldovan ionic@ionic.de Signed-off-by: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- scripts/kconfig/nconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index e0f965529166..af814b39b876 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -504,8 +504,8 @@ static int get_mext_match(const char *match_str, match_f flag) else if (flag == FIND_NEXT_MATCH_UP) --match_start;
+ match_start = (match_start + items_num) % items_num; index = match_start; - index = (index + items_num) % items_num; while (true) { char *str = k_menu_items[index].str; if (strcasestr(str, match_str) != NULL)
From: Takashi Iwai tiwai@suse.de
[ Upstream commit 26928ca1f06aab4361eb5adbe7ef3b5c82f13cf2 ]
Lenovo Ideapad S740 requires quite a few COEF setups to make its speakers working. The verb table was provided from Ryan Prescott as the result of investigation via qemu: https://github.com/ryanprescott/realtek-verb-tools/wiki/How-to-sniff-verbs-f...
BugLink: https://github.com/thesofproject/linux/issues/2748 Tested-by: Ryan Prescott ryan@cousinscomputers.net Link: https://lore.kernel.org/r/20210416081211.20059-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/ideapad_s740_helper.c | 492 ++++++++++++++++++++++++++++ sound/pci/hda/patch_realtek.c | 11 + 2 files changed, 503 insertions(+) create mode 100644 sound/pci/hda/ideapad_s740_helper.c
diff --git a/sound/pci/hda/ideapad_s740_helper.c b/sound/pci/hda/ideapad_s740_helper.c new file mode 100644 index 000000000000..564b9086e52d --- /dev/null +++ b/sound/pci/hda/ideapad_s740_helper.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Fixes for Lenovo Ideapad S740, to be included from codec driver */ + +static const struct hda_verb alc285_ideapad_s740_coefs[] = { +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 }, +{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, +{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, +{} +}; + +static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs); + break; + } +} diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8ec57bd351df..1fe70f2fe4fe 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6282,6 +6282,9 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, /* for alc295_fixup_hp_top_speakers */ #include "hp_x360_helper.c"
+/* for alc285_fixup_ideapad_s740_coef() */ +#include "ideapad_s740_helper.c" + enum { ALC269_FIXUP_GPIO2, ALC269_FIXUP_SONY_VAIO, @@ -6481,6 +6484,7 @@ enum { ALC282_FIXUP_ACER_DISABLE_LINEOUT, ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST, ALC256_FIXUP_ACER_HEADSET_MIC, + ALC285_FIXUP_IDEAPAD_S740_COEF, };
static const struct hda_fixup alc269_fixups[] = { @@ -7973,6 +7977,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC }, + [ALC285_FIXUP_IDEAPAD_S740_COEF] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_ideapad_s740_coef, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI, + }, };
static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -8320,6 +8330,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), + SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
From: Vamshi Krishna Gopal vamshi.krishna.gopal@intel.com
[ Upstream commit d25bbe80485f8bcbbeb91a2a6cd8798c124b27b7 ]
Add quirks for jack detection, rt711 DAI and DMIC
Reviewed-by: Bard Liao bard.liao@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Signed-off-by: Vamshi Krishna Gopal vamshi.krishna.gopal@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20210415175013.192862-6-pierre-louis.bossart@linux... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 8adce6417b02..ecd3f90f4bbe 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -187,6 +187,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, + /* AlderLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), + }, + .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | + SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC), + }, {} };
From: Kai Vehmanen kai.vehmanen@linux.intel.com
[ Upstream commit 0c37e2eb6b83e375e8a654d01598292d5591fc65 ]
When snd-hda-codec-hdmi is used with ASoC HDA controller like SOF (acomp used for ELD notifications), display connection change done during suspend, can be lost due to following sequence of events:
1. system in S3 suspend 2. DP/HDMI receiver connected 3. system resumed 4. HDA controller resumed, but card->deferred_resume_work not complete 5. acomp eld_notify callback 6. eld_notify ignored as power state is not CTL_POWER_D0 7. HDA resume deferred work completed, power state set to CTL_POWER_D0
This results in losing the notification, and the jack state reported to user-space is not correct.
The check on step 6 was added in commit 8ae743e82f0b ("ALSA: hda - Skip ELD notification during system suspend"). It would seem with the deferred resume logic in ASoC core, this check is not safe.
Fix the issue by modifying the check to use "dev.power.power_state.event" instead of ALSA specific card power state variable.
BugLink: https://github.com/thesofproject/linux/issues/2825 Suggested-by: Takashi Iwai tiwai@suse.de Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210416131157.1881366-1-kai.vehmanen@linux.intel.... Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/hda/patch_hdmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5de3666a7101..4b2cc8cb55c4 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2654,7 +2654,7 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) /* skip notification during system suspend (but not in runtime PM); * the state will be updated at resume */ - if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) + if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; /* ditto during suspend/resume process itself */ if (snd_hdac_is_in_pm(&codec->core)) @@ -2840,7 +2840,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) /* skip notification during system suspend (but not in runtime PM); * the state will be updated at resume */ - if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) + if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; /* ditto during suspend/resume process itself */ if (snd_hdac_is_in_pm(&codec->core))
From: Jarkko Nikula jarkko.nikula@linux.intel.com
[ Upstream commit 8f51c1763ae98bb63fc04627ceae383aa0e8ff7b ]
Add PCI ID of SMBus controller on Intel Alder Lake PCH-M.
Signed-off-by: Jarkko Nikula jarkko.nikula@linux.intel.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-i801.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4acee6f9e5a3..99d446763530 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -73,6 +73,7 @@ * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes * Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes * Alder Lake-P (PCH) 0x51a3 32 hard yes yes yes + * Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -230,6 +231,7 @@ #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 @@ -1087,6 +1089,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS) }, { 0, } };
@@ -1771,6 +1774,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_EBG_SMBUS: case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS: case PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS: + case PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS: priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_IRQ;
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit e5272ad4aab347dde5610c0aedb786219e3ff793 ]
Fix the following out-of-bounds warning:
net/sctp/sm_make_chunk.c:3150:4: warning: 'memcpy' offset [17, 28] from the object at 'addr' is out of the bounds of referenced subobject 'v4' with type 'struct sockaddr_in' at offset 0 [-Warray-bounds]
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Reviewed-by: Kees Cook keescook@chromium.org Acked-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sctp/sm_make_chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f77484df097b..da4ce0947c3a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3147,7 +3147,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, * primary. */ if (af->is_any(&addr)) - memcpy(&addr.v4, sctp_source(asconf), sizeof(addr)); + memcpy(&addr, sctp_source(asconf), sizeof(addr));
if (security_sctp_bind_connect(asoc->ep->base.sk, SCTP_PARAM_SET_PRIMARY,
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit 1e3d976dbb23b3fce544752b434bdc32ce64aabc ]
Fix the following out-of-bounds warning:
net/core/flow_dissector.c:835:3: warning: 'memcpy' offset [33, 48] from the object at 'flow_keys' is out of the bounds of referenced subobject 'ipv6_src' with type '__u32[4]' {aka 'unsigned int[4]'} at offset 16 [-Warray-bounds]
The problem is that the original code is trying to copy data into a couple of struct members adjacent to each other in a single call to memcpy(). So, the compiler legitimately complains about it. As these are just a couple of members, fix this by copying each one of them in separate calls to memcpy().
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/flow_dissector.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index a96a4f5de0ce..3f36b04d86a0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -828,8 +828,10 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, key_addrs = skb_flow_dissector_target(flow_dissector, FLOW_DISSECTOR_KEY_IPV6_ADDRS, target_container); - memcpy(&key_addrs->v6addrs, &flow_keys->ipv6_src, - sizeof(key_addrs->v6addrs)); + memcpy(&key_addrs->v6addrs.src, &flow_keys->ipv6_src, + sizeof(key_addrs->v6addrs.src)); + memcpy(&key_addrs->v6addrs.dst, &flow_keys->ipv6_dst, + sizeof(key_addrs->v6addrs.dst)); key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; }
From: Cédric Le Goater clg@kaod.org
[ Upstream commit e9e16917bc388846163b8566a298a291d71e44c9 ]
The 'chip_id' field of the XIVE CPU structure is used to choose a target for a source located on the same chip. For that, the XIVE driver queries the chip identifier from the "ibm,chip-id" property and compares it to a 'src_chip' field identifying the chip of a source. This information is only available on the PowerNV platform, 'src_chip' being assigned to XIVE_INVALID_CHIP_ID under pSeries.
The "ibm,chip-id" property is also not available on all platforms. It was first introduced on PowerNV and later, under QEMU for pSeries/KVM. However, the property is not part of PAPR and does not exist under pSeries/PowerVM.
Assign 'chip_id' to XIVE_INVALID_CHIP_ID by default and let the PowerNV platform override the value with the "ibm,chip-id" property.
Signed-off-by: Cédric Le Goater clg@kaod.org Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210413130352.1183267-1-clg@kaod.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/sysdev/xive/common.c | 9 +++------ arch/powerpc/sysdev/xive/native.c | 6 ++++++ arch/powerpc/sysdev/xive/xive-internal.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index 5cacb632eb37..31b657c37735 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -1341,17 +1341,14 @@ static int xive_prepare_cpu(unsigned int cpu)
xc = per_cpu(xive_cpu, cpu); if (!xc) { - struct device_node *np; - xc = kzalloc_node(sizeof(struct xive_cpu), GFP_KERNEL, cpu_to_node(cpu)); if (!xc) return -ENOMEM; - np = of_get_cpu_node(cpu, NULL); - if (np) - xc->chip_id = of_get_ibm_chip_id(np); - of_node_put(np); xc->hw_ipi = XIVE_BAD_IRQ; + xc->chip_id = XIVE_INVALID_CHIP_ID; + if (xive_ops->prepare_cpu) + xive_ops->prepare_cpu(cpu, xc);
per_cpu(xive_cpu, cpu) = xc; } diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 05a800a3104e..57e3f1540435 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -380,6 +380,11 @@ static void xive_native_update_pending(struct xive_cpu *xc) } }
+static void xive_native_prepare_cpu(unsigned int cpu, struct xive_cpu *xc) +{ + xc->chip_id = cpu_to_chip_id(cpu); +} + static void xive_native_setup_cpu(unsigned int cpu, struct xive_cpu *xc) { s64 rc; @@ -462,6 +467,7 @@ static const struct xive_ops xive_native_ops = { .match = xive_native_match, .shutdown = xive_native_shutdown, .update_pending = xive_native_update_pending, + .prepare_cpu = xive_native_prepare_cpu, .setup_cpu = xive_native_setup_cpu, .teardown_cpu = xive_native_teardown_cpu, .sync_source = xive_native_sync_source, diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h index 9cf57c722faa..6478be19b4d3 100644 --- a/arch/powerpc/sysdev/xive/xive-internal.h +++ b/arch/powerpc/sysdev/xive/xive-internal.h @@ -46,6 +46,7 @@ struct xive_ops { u32 *sw_irq); int (*setup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); void (*cleanup_queue)(unsigned int cpu, struct xive_cpu *xc, u8 prio); + void (*prepare_cpu)(unsigned int cpu, struct xive_cpu *xc); void (*setup_cpu)(unsigned int cpu, struct xive_cpu *xc); void (*teardown_cpu)(unsigned int cpu, struct xive_cpu *xc); bool (*match)(struct device_node *np);
From: Srikar Dronamraju srikar@linux.vnet.ibm.com
[ Upstream commit 6980d13f0dd189846887bbbfa43793d9a41768d3 ]
Geethika reported a trace when doing a dlpar CPU add.
------------[ cut here ]------------ WARNING: CPU: 152 PID: 1134 at kernel/sched/topology.c:2057 CPU: 152 PID: 1134 Comm: kworker/152:1 Not tainted 5.12.0-rc5-master #5 Workqueue: events cpuset_hotplug_workfn NIP: c0000000001cfc14 LR: c0000000001cfc10 CTR: c0000000007e3420 REGS: c0000034a08eb260 TRAP: 0700 Not tainted (5.12.0-rc5-master+) MSR: 8000000000029033 <SF,EE,ME,IR,DR,RI,LE> CR: 28828422 XER: 00000020 CFAR: c0000000001fd888 IRQMASK: 0 #012GPR00: c0000000001cfc10 c0000034a08eb500 c000000001f35400 0000000000000027 #012GPR04: c0000035abaa8010 c0000035abb30a00 0000000000000027 c0000035abaa8018 #012GPR08: 0000000000000023 c0000035abaaef48 00000035aa540000 c0000035a49dffe8 #012GPR12: 0000000028828424 c0000035bf1a1c80 0000000000000497 0000000000000004 #012GPR16: c00000000347a258 0000000000000140 c00000000203d468 c000000001a1a490 #012GPR20: c000000001f9c160 c0000034adf70920 c0000034aec9fd20 0000000100087bd3 #012GPR24: 0000000100087bd3 c0000035b3de09f8 0000000000000030 c0000035b3de09f8 #012GPR28: 0000000000000028 c00000000347a280 c0000034aefe0b00 c0000000010a2a68 NIP [c0000000001cfc14] build_sched_domains+0x6a4/0x1500 LR [c0000000001cfc10] build_sched_domains+0x6a0/0x1500 Call Trace: [c0000034a08eb500] [c0000000001cfc10] build_sched_domains+0x6a0/0x1500 (unreliable) [c0000034a08eb640] [c0000000001d1e6c] partition_sched_domains_locked+0x3ec/0x530 [c0000034a08eb6e0] [c0000000002936d4] rebuild_sched_domains_locked+0x524/0xbf0 [c0000034a08eb7e0] [c000000000296bb0] rebuild_sched_domains+0x40/0x70 [c0000034a08eb810] [c000000000296e74] cpuset_hotplug_workfn+0x294/0xe20 [c0000034a08ebc30] [c000000000178dd0] process_one_work+0x300/0x670 [c0000034a08ebd10] [c0000000001791b8] worker_thread+0x78/0x520 [c0000034a08ebda0] [c000000000185090] kthread+0x1a0/0x1b0 [c0000034a08ebe10] [c00000000000ccec] ret_from_kernel_thread+0x5c/0x70 Instruction dump: 7d2903a6 4e800421 e8410018 7f67db78 7fe6fb78 7f45d378 7f84e378 7c681b78 3c62ff1a 3863c6f8 4802dc35 60000000 <0fe00000> 3920fff4 f9210070 e86100a0 ---[ end trace 532d9066d3d4d7ec ]---
Some of the per-CPU masks use cpu_cpu_mask as a filter to limit the search for related CPUs. On a dlpar add of a CPU, update cpu_cpu_mask before updating the per-CPU masks. This will ensure the cpu_cpu_mask is updated correctly before its used in setting the masks. Setting the numa_node will ensure that when cpu_cpu_mask() gets called, the correct node number is used. This code movement helped fix the above call trace.
Reported-by: Geetika Moolchandani Geetika.Moolchandani1@ibm.com Signed-off-by: Srikar Dronamraju srikar@linux.vnet.ibm.com Reviewed-by: Nathan Lynch nathanl@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210401154200.150077-1-srikar@linux.vnet.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 5c7ce1d50631..c2473e20f5f5 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1546,6 +1546,9 @@ void start_secondary(void *unused)
vdso_getcpu_init(); #endif + set_numa_node(numa_cpu_lookup_table[cpu]); + set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu])); + /* Update topology CPU masks */ add_cpu_to_masks(cpu);
@@ -1564,9 +1567,6 @@ void start_secondary(void *unused) shared_caches = true; }
- set_numa_node(numa_cpu_lookup_table[cpu]); - set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu])); - smp_wmb(); notify_cpu_starting(cpu); set_cpu_online(cpu, true);
From: David Mosberger-Tang davidm@egauge.net
[ Upstream commit a381b78a1598dde34a6e40dae2842024308a6ef2 ]
Linux network drivers normally disallow changing the MAC address when the interface is up. This driver has been different in that it allows to change the MAC address *only* when it's up. This patch brings wilc1000 behavior more in line with other network drivers. We could have replaced wilc_set_mac_addr() with eth_mac_addr() but that would break existing documentation on how to change the MAC address. Likewise, return -EADDRNOTAVAIL (not -EINVAL) when the specified MAC address is invalid or unavailable.
Signed-off-by: David Mosberger-Tang davidm@egauge.net Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210303194846.1823596-1-davidm@egauge.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/microchip/wilc1000/netdev.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 1b205e7d97a8..37f40039e4ca 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -575,7 +575,6 @@ static int wilc_mac_open(struct net_device *ndev) { struct wilc_vif *vif = netdev_priv(ndev); struct wilc *wl = vif->wilc; - unsigned char mac_add[ETH_ALEN] = {0}; int ret = 0; struct mgmt_frame_regs mgmt_regs = {};
@@ -598,9 +597,12 @@ static int wilc_mac_open(struct net_device *ndev)
wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, vif->idx); - wilc_get_mac_address(vif, mac_add); - netdev_dbg(ndev, "Mac address: %pM\n", mac_add); - ether_addr_copy(ndev->dev_addr, mac_add); + + if (is_valid_ether_addr(ndev->dev_addr)) + wilc_set_mac_address(vif, ndev->dev_addr); + else + wilc_get_mac_address(vif, ndev->dev_addr); + netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr);
if (!is_valid_ether_addr(ndev->dev_addr)) { netdev_err(ndev, "Wrong MAC address\n"); @@ -639,7 +641,14 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) int srcu_idx;
if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; + + if (!vif->mac_opened) { + eth_commit_mac_addr_change(dev, p); + return 0; + } + + /* Verify MAC Address is not already in use: */
srcu_idx = srcu_read_lock(&wilc->srcu); list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) { @@ -647,7 +656,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) if (ether_addr_equal(addr->sa_data, mac_addr)) { if (vif != tmp_vif) { srcu_read_unlock(&wilc->srcu, srcu_idx); - return -EINVAL; + return -EADDRNOTAVAIL; } srcu_read_unlock(&wilc->srcu, srcu_idx); return 0; @@ -659,9 +668,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) if (result) return result;
- ether_addr_copy(vif->bssid, addr->sa_data); - ether_addr_copy(vif->ndev->dev_addr, addr->sa_data); - + eth_commit_mac_addr_change(dev, p); return result; }
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit 253907ab8bc0818639af382f6398810fa1f022b3 ]
In case the frequency is invalid, ieee80211_parse_ch_switch_ie will fail and we may not even reach the check in ieee80211_sta_process_chanswitch. Drop the connection in case ieee80211_parse_ch_switch_ie failed, but still take into account the CSA mode to remember not to send a deauth frame in case if it is forbidden to.
Signed-off-by: Emmanuel Grumbach emmanuel.grumbach@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210409123755.34712ef96a0a.I75d7ad7f1d654... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/mlme.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4a8f1b8ce768..0fe91dc9817e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1405,11 +1405,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, ch_switch.delay = csa_ie.max_switch_time; }
- if (res < 0) { - ieee80211_queue_work(&local->hw, - &ifmgd->csa_connection_drop_work); - return; - } + if (res < 0) + goto lock_and_drop_connection;
if (beacon && sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) { if (res)
From: David Ward david.ward@gatech.edu
[ Upstream commit aa2f9c12821e6a4ba1df4fb34a3dbc6a2a1ee7fe ]
The ALC3263 codec on the XPS 13 9343 is also found on the Latitude 13 7350 and Venue 11 Pro 7140. They require the same handling for the combo jack to work with a headset: GPIO pin 6 must be set.
The HDA driver always sets this pin on the ALC3263, which it distinguishes by the codec vendor/device ID 0x10ec0288 and PCI subsystem vendor ID 0x1028 (Dell). The ASoC driver does not use PCI, so adapt this check to use DMI to determine if Dell is the system vendor.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=150601 BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205961 Signed-off-by: David Ward david.ward@gatech.edu Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20210418134658.4333-6-david.ward@gatech.edu Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/rt286.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 8abe232ca4a4..2f18f5114f7e 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1117,12 +1117,11 @@ static const struct dmi_system_id force_combo_jack_table[] = { { } };
-static const struct dmi_system_id dmi_dell_dino[] = { +static const struct dmi_system_id dmi_dell[] = { { - .ident = "Dell Dino", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343") } }, { } @@ -1133,7 +1132,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, { struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt286_priv *rt286; - int i, ret, val; + int i, ret, vendor_id;
rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), GFP_KERNEL); @@ -1149,14 +1148,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c, }
ret = regmap_read(rt286->regmap, - RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val); + RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id); if (ret != 0) { dev_err(&i2c->dev, "I2C error %d\n", ret); return ret; } - if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { + if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) { dev_err(&i2c->dev, - "Device with ID register %#x is not rt286\n", val); + "Device with ID register %#x is not rt286\n", + vendor_id); return -ENODEV; }
@@ -1180,8 +1180,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c, if (pdata) rt286->pdata = *pdata;
- if (dmi_check_system(force_combo_jack_table) || - dmi_check_system(dmi_dell_dino)) + if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) || + dmi_check_system(force_combo_jack_table)) rt286->pdata.cbj_en = true;
regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); @@ -1220,7 +1220,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
- if (dmi_check_system(dmi_dell_dino)) { + if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) { regmap_update_bits(rt286->regmap, RT286_SET_GPIO_MASK, 0x40, 0x40); regmap_update_bits(rt286->regmap,
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit c1d9e34e11281a8ba1a1c54e4db554232a461488 ]
Fix the following out-of-bounds warning:
net/ethtool/ioctl.c:492:2: warning: 'memcpy' offset [49, 84] from the object at 'link_usettings' is out of the bounds of referenced subobject 'base' with type 'struct ethtool_link_settings' at offset 0 [-Warray-bounds]
The problem is that the original code is trying to copy data into a some struct members adjacent to each other in a single call to memcpy(). This causes a legitimate compiler warning because memcpy() overruns the length of &link_usettings.base. Fix this by directly using &link_usettings and _from_ as destination and source addresses, instead.
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ethtool/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 771688e1b0da..2603966da904 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -489,7 +489,7 @@ store_link_ksettings_for_user(void __user *to, { struct ethtool_link_usettings link_usettings;
- memcpy(&link_usettings.base, &from->base, sizeof(link_usettings)); + memcpy(&link_usettings, from, sizeof(link_usettings)); bitmap_to_arr32(link_usettings.link_modes.supported, from->link_modes.supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
From: Du Cheng ducheng2@gmail.com
[ Upstream commit ed8157f1ebf1ae81a8fa2653e3f20d2076fad1c9 ]
There is a reproducible sequence from the userland that will trigger a WARN_ON() condition in taprio_get_start_time, which causes kernel to panic if configured as "panic_on_warn". Catch this condition in parse_taprio_schedule to prevent this condition.
Reported as bug on syzkaller: https://syzkaller.appspot.com/bug?extid=d50710fd0873a9c6b40c
Reported-by: syzbot+d50710fd0873a9c6b40c@syzkaller.appspotmail.com Signed-off-by: Du Cheng ducheng2@gmail.com Acked-by: Cong Wang cong.wang@bytedance.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/sch_taprio.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 8287894541e3..909c798b7403 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -901,6 +901,12 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
list_for_each_entry(entry, &new->entries, list) cycle = ktime_add_ns(cycle, entry->interval); + + if (!cycle) { + NL_SET_ERR_MSG(extack, "'cycle_time' can never be 0"); + return -EINVAL; + } + new->cycle_time = cycle; }
From: Yaqi Chen chendotjs@gmail.com
[ Upstream commit 137733d08f4ab14a354dacaa9a8fc35217747605 ]
From commit c0bbbdc32feb ("__netif_receive_skb_core: pass skb by
reference"), the first argument passed into __netif_receive_skb_core has changed to reference of a skb pointer.
This commit fixes by using bpf_probe_read_kernel.
Signed-off-by: Yaqi Chen chendotjs@gmail.com Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20210416154803.37157-1-chendotjs@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- samples/bpf/tracex1_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c index 3f4599c9a202..ef30d2b353b0 100644 --- a/samples/bpf/tracex1_kern.c +++ b/samples/bpf/tracex1_kern.c @@ -26,7 +26,7 @@ SEC("kprobe/__netif_receive_skb_core") int bpf_prog1(struct pt_regs *ctx) { - /* attaches to kprobe netif_receive_skb, + /* attaches to kprobe __netif_receive_skb_core, * looks for packets on loobpack device and prints them */ char devname[IFNAMSIZ]; @@ -35,7 +35,7 @@ int bpf_prog1(struct pt_regs *ctx) int len;
/* non-portable! works for the given kernel only */ - skb = (struct sk_buff *) PT_REGS_PARM1(ctx); + bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); dev = _(skb->dev); len = _(skb->len);
From: Michael Ellerman mpe@ellerman.id.au
[ Upstream commit ed8029d7b472369a010a1901358567ca3b6dbb0d ]
RCU complains about us calling printk() from an offline CPU:
============================= WARNING: suspicious RCU usage 5.12.0-rc7-02874-g7cf90e481cb8 #1 Not tainted ----------------------------- kernel/locking/lockdep.c:3568 RCU-list traversed in non-reader section!!
other info that might help us debug this:
RCU used illegally from offline CPU! rcu_scheduler_active = 2, debug_locks = 1 no locks held by swapper/0/0.
stack backtrace: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.12.0-rc7-02874-g7cf90e481cb8 #1 Call Trace: dump_stack+0xec/0x144 (unreliable) lockdep_rcu_suspicious+0x124/0x144 __lock_acquire+0x1098/0x28b0 lock_acquire+0x128/0x600 _raw_spin_lock_irqsave+0x6c/0xc0 down_trylock+0x2c/0x70 __down_trylock_console_sem+0x60/0x140 vprintk_emit+0x1a8/0x4b0 vprintk_func+0xcc/0x200 printk+0x40/0x54 pseries_cpu_offline_self+0xc0/0x120 arch_cpu_idle_dead+0x54/0x70 do_idle+0x174/0x4a0 cpu_startup_entry+0x38/0x40 rest_init+0x268/0x388 start_kernel+0x748/0x790 start_here_common+0x1c/0x614
Which happens because by the time we get to rtas_stop_self() we are already offline. In addition the message can be spammy, and is not that helpful for users, so remove it.
Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210418135413.1204031-1-mpe@ellerman.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 12cbffd3c2e3..325f3b220f36 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -47,9 +47,6 @@ static void rtas_stop_self(void)
BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
- printk("cpu %u (hwid %u) Ready to die...\n", - smp_processor_id(), hard_smp_processor_id()); - rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL);
panic("Alas, I survived.\n");
From: Robin Singh robin.singh@amd.com
[ Upstream commit 19cc1f3829567e7dca21c1389ea6407b8f5efab4 ]
[why] During dsc enable, a divide by zero condition triggered the kernel crash.
[how] An IGT test, which enable the DSC, was crashing at the time of restore the default dsc status, becaue of h_totals value becoming 0. So add a check before divide condition. If h_total is zero, gracefully ignore and set the default value.
kernel panic log:
[ 128.758827] divide error: 0000 [#1] PREEMPT SMP NOPTI [ 128.762714] CPU: 5 PID: 4562 Comm: amd_dp_dsc Tainted: G W 5.4.19-android-x86_64 #1 [ 128.769728] Hardware name: ADVANCED MICRO DEVICES, INC. Mauna/Mauna, BIOS WMN0B13N Nov 11 2020 [ 128.777695] RIP: 0010:hubp2_vready_at_or_After_vsync+0x37/0x7a [amdgpu] [ 128.785707] Code: 80 02 00 00 48 89 f3 48 8b 7f 08 b ...... [ 128.805696] RSP: 0018:ffffad8f82d43628 EFLAGS: 00010246 ...... [ 128.857707] CR2: 00007106d8465000 CR3: 0000000426530000 CR4: 0000000000140ee0 [ 128.865695] Call Trace: [ 128.869712] hubp3_setup+0x1f/0x7f [amdgpu] [ 128.873705] dcn20_update_dchubp_dpp+0xc8/0x54a [amdgpu] [ 128.877706] dcn20_program_front_end_for_ctx+0x31d/0x463 [amdgpu] [ 128.885706] dc_commit_state+0x3d2/0x658 [amdgpu] [ 128.889707] amdgpu_dm_atomic_commit_tail+0x4b3/0x1e7c [amdgpu] [ 128.897699] ? dm_read_reg_func+0x41/0xb5 [amdgpu] [ 128.901707] ? dm_read_reg_func+0x41/0xb5 [amdgpu] [ 128.905706] ? __is_insn_slot_addr+0x43/0x48 [ 128.909706] ? fill_plane_buffer_attributes+0x29e/0x3dc [amdgpu] [ 128.917705] ? dm_plane_helper_prepare_fb+0x255/0x284 [amdgpu] [ 128.921700] ? usleep_range+0x7c/0x7c [ 128.925705] ? preempt_count_sub+0xf/0x18 [ 128.929706] ? _raw_spin_unlock_irq+0x13/0x24 [ 128.933732] ? __wait_for_common+0x11e/0x18f [ 128.937705] ? _raw_spin_unlock_irq+0x13/0x24 [ 128.941706] ? __wait_for_common+0x11e/0x18f [ 128.945705] commit_tail+0x8b/0xd2 [drm_kms_helper] [ 128.949707] drm_atomic_helper_commit+0xd8/0xf5 [drm_kms_helper] [ 128.957706] amdgpu_dm_atomic_commit+0x337/0x360 [amdgpu] [ 128.961705] ? drm_atomic_check_only+0x543/0x68d [drm] [ 128.969705] ? drm_atomic_set_property+0x760/0x7af [drm] [ 128.973704] ? drm_mode_atomic_ioctl+0x6f3/0x85a [drm] [ 128.977705] drm_mode_atomic_ioctl+0x6f3/0x85a [drm] [ 128.985705] ? drm_atomic_set_property+0x7af/0x7af [drm] [ 128.989706] drm_ioctl_kernel+0x82/0xda [drm] [ 128.993706] drm_ioctl+0x225/0x319 [drm] [ 128.997707] ? drm_atomic_set_property+0x7af/0x7af [drm] [ 129.001706] ? preempt_count_sub+0xf/0x18 [ 129.005713] amdgpu_drm_ioctl+0x4b/0x76 [amdgpu] [ 129.009705] vfs_ioctl+0x1d/0x2a [ 129.013705] do_vfs_ioctl+0x419/0x43d [ 129.017707] ksys_ioctl+0x52/0x71 [ 129.021707] __x64_sys_ioctl+0x16/0x19 [ 129.025706] do_syscall_64+0x78/0x85 [ 129.029705] entry_SYSCALL_64_after_hwframe+0x44/0xa9
Signed-off-by: Robin Singh robin.singh@amd.com Reviewed-by: Harry Wentland Harry.Wentland@amd.com Reviewed-by: Robin Singh Robin.Singh@amd.com Acked-by: Aurabindo Pillai aurabindo.pillai@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index bec7059f6d5d..a1318c31bcfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-17 Advanced Micro Devices, Inc. + * Copyright 2012-2021 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -181,11 +181,14 @@ void hubp2_vready_at_or_After_vsync(struct hubp *hubp, else Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0 */ - if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width - + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { - value = 1; - } else - value = 0; + if (pipe_dest->htotal != 0) { + if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width + + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { + value = 1; + } else + value = 0; + } + REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value); }
From: Dingchen (David) Zhang dingchen.zhang@amd.com
[ Upstream commit 4ccf9446b2a3615615045346c97f8a1e2a16568a ]
[why] the current implementation of hdcp2 rx id list validation does not have handler/checker for invalid message status, e.g. HMAC, the V parameter calculated from PSP not matching the V prime from Rx.
[how] return a generic FAILURE for any message status not SUCCESS or REVOKED.
Signed-off-by: Dingchen (David) Zhang dingchen.zhang@amd.com Reviewed-by: Bhawanpreet Lakha Bhawanpreet.Lakha@amd.com Acked-by: Aurabindo Pillai aurabindo.pillai@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 904ce9b88088..afbe8856468a 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -791,6 +791,8 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp) TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) { hdcp->connection.is_hdcp2_revoked = 1; status = MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_REVOKED; + } else { + status = MOD_HDCP_STATUS_HDCP2_VALIDATE_RX_ID_LIST_FAILURE; } } mutex_unlock(&psp->hdcp_context.mutex);
From: Jinzhou Su Jinzhou.Su@amd.com
[ Upstream commit 5c88e3b86a88f14efa0a3ddd28641c6ff49fb9c4 ]
The buffer of SA bo will be used by many cases. So it's better to invalidate the cache of indirect buffer allocated by SA before commit the IB.
Signed-off-by: Jinzhou Su Jinzhou.Su@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 7645223ea0ef..97c11aa47ad0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -77,6 +77,8 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, }
ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo); + /* flush the cache before commit the IB */ + ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC;
if (!vm) ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
From: Felix Fietkau nbd@nbd.name
[ Upstream commit 5c7d374444afdeb9dd534a37c4f6c13af032da0c ]
Fixes hardware wakeup issues
Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 4ecbd5406e2a..198e9025b681 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -291,12 +291,20 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) u32 addr; int err;
- addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST; + if (is_mt7663(mdev)) { + /* Clear firmware own via N9 eint */ + mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN); + mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); + + addr = MT_CONN_HIF_ON_LPCTL; + } else { + addr = MT_CFG_LPCR_HOST; + } + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);
mt7622_trigger_hif_int(dev, true);
- addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
mt7622_trigger_hif_int(dev, false);
From: Sean Christopherson seanjc@google.com
[ Upstream commit b61a9071dc72a3c709192c0c00ab87c2b3de1d94 ]
Free the SEV device if later initialization fails. The memory isn't technically leaked as it's tracked in the top-level device's devres list, but unless the top-level device is removed, the memory won't be freed and is effectively leaked.
Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210406224952.4177376-2-seanjc@google.com Reviewed-by: Brijesh Singh brijesh.singh@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/ccp/sev-dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 8fd43c1acac1..3e0d1d6922ba 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -990,7 +990,7 @@ int sev_dev_init(struct psp_device *psp) if (!sev->vdata) { ret = -ENODEV; dev_err(dev, "sev: missing driver data\n"); - goto e_err; + goto e_sev; }
psp_set_sev_irq_handler(psp, sev_irq_handler, sev); @@ -1005,6 +1005,8 @@ int sev_dev_init(struct psp_device *psp)
e_irq: psp_clear_sev_irq_handler(psp); +e_sev: + devm_kfree(dev, sev); e_err: psp->sev_data = NULL;
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit 820aa37638a252b57967bdf4038a514b1ab85d45 ]
Fix the following out-of-bounds warnings by enclosing structure members daddr and saddr into new struct addr, in structures wl3501_md_req and wl3501_md_ind:
arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds] arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [18, 23] from the object at 'sig' is out of the bounds of referenced subobject 'daddr' with type 'u8[6]' {aka 'unsigned char[6]'} at offset 11 [-Warray-bounds]
Refactor the code, accordingly:
$ pahole -C wl3501_md_req drivers/net/wireless/wl3501_cs.o struct wl3501_md_req { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 routing; /* 3 1 */ u16 data; /* 4 2 */ u16 size; /* 6 2 */ u8 pri; /* 8 1 */ u8 service_class; /* 9 1 */ struct { u8 daddr[6]; /* 10 6 */ u8 saddr[6]; /* 16 6 */ } addr; /* 10 12 */
/* size: 22, cachelines: 1, members: 8 */ /* last cacheline: 22 bytes */ };
$ pahole -C wl3501_md_ind drivers/net/wireless/wl3501_cs.o struct wl3501_md_ind { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 routing; /* 3 1 */ u16 data; /* 4 2 */ u16 size; /* 6 2 */ u8 reception; /* 8 1 */ u8 pri; /* 9 1 */ u8 service_class; /* 10 1 */ struct { u8 daddr[6]; /* 11 6 */ u8 saddr[6]; /* 17 6 */ } addr; /* 11 12 */
/* size: 24, cachelines: 1, members: 9 */ /* padding: 1 */ /* last cacheline: 24 bytes */ };
The problem is that the original code is trying to copy data into a couple of arrays adjacent to each other in a single call to memcpy(). Now that a new struct _addr_ enclosing those two adjacent arrays is introduced, memcpy() doesn't overrun the length of &sig.daddr[0] and &sig.daddr, because the address of the new struct object _addr_ is used, instead.
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Reviewed-by: Kees Cook keescook@chromium.org Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/d260fe56aed7112bff2be5b4d152d03ad7b78e78.161844226... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/wl3501.h | 12 ++++++++---- drivers/net/wireless/wl3501_cs.c | 10 ++++++---- 2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index e98e04ee9a2c..aa8222cbea68 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -471,8 +471,10 @@ struct wl3501_md_req { u16 size; u8 pri; u8 service_class; - u8 daddr[ETH_ALEN]; - u8 saddr[ETH_ALEN]; + struct { + u8 daddr[ETH_ALEN]; + u8 saddr[ETH_ALEN]; + } addr; };
struct wl3501_md_ind { @@ -484,8 +486,10 @@ struct wl3501_md_ind { u8 reception; u8 pri; u8 service_class; - u8 daddr[ETH_ALEN]; - u8 saddr[ETH_ALEN]; + struct { + u8 daddr[ETH_ALEN]; + u8 saddr[ETH_ALEN]; + } addr; };
struct wl3501_md_confirm { diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 8ca5789c7b37..70307308635f 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -469,6 +469,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) struct wl3501_md_req sig = { .sig_id = WL3501_SIG_MD_REQ, }; + size_t sig_addr_len = sizeof(sig.addr); u8 *pdata = (char *)data; int rc = -EIO;
@@ -484,9 +485,9 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) goto out; } rc = 0; - memcpy(&sig.daddr[0], pdata, 12); - pktlen = len - 12; - pdata += 12; + memcpy(&sig.addr, pdata, sig_addr_len); + pktlen = len - sig_addr_len; + pdata += sig_addr_len; sig.data = bf; if (((*pdata) * 256 + (*(pdata + 1))) > 1500) { u8 addr4[ETH_ALEN] = { @@ -980,7 +981,8 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, } else { skb->dev = dev; skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ - skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12); + skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr, + sizeof(sig.addr)); wl3501_receive(this, skb->data, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev);
From: Gustavo A. R. Silva gustavoars@kernel.org
[ Upstream commit bb43e5718d8f1b46e7a77e7b39be3c691f293050 ]
Fix the following out-of-bounds warnings by adding a new structure wl3501_req instead of duplicating the same members in structure wl3501_join_req and wl3501_scan_confirm:
arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [39, 108] from the object at 'sig' is out of the bounds of referenced subobject 'beacon_period' with type 'short unsigned int' at offset 36 [-Warray-bounds] arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [25, 95] from the object at 'sig' is out of the bounds of referenced subobject 'beacon_period' with type 'short unsigned int' at offset 22 [-Warray-bounds]
Refactor the code, accordingly:
$ pahole -C wl3501_req drivers/net/wireless/wl3501_cs.o struct wl3501_req { u16 beacon_period; /* 0 2 */ u16 dtim_period; /* 2 2 */ u16 cap_info; /* 4 2 */ u8 bss_type; /* 6 1 */ u8 bssid[6]; /* 7 6 */ struct iw_mgmt_essid_pset ssid; /* 13 34 */ struct iw_mgmt_ds_pset ds_pset; /* 47 3 */ struct iw_mgmt_cf_pset cf_pset; /* 50 8 */ struct iw_mgmt_ibss_pset ibss_pset; /* 58 4 */ struct iw_mgmt_data_rset bss_basic_rset; /* 62 10 */
/* size: 72, cachelines: 2, members: 10 */ /* last cacheline: 8 bytes */ };
$ pahole -C wl3501_join_req drivers/net/wireless/wl3501_cs.o struct wl3501_join_req { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 reserved; /* 3 1 */ struct iw_mgmt_data_rset operational_rset; /* 4 10 */ u16 reserved2; /* 14 2 */ u16 timeout; /* 16 2 */ u16 probe_delay; /* 18 2 */ u8 timestamp[8]; /* 20 8 */ u8 local_time[8]; /* 28 8 */ struct wl3501_req req; /* 36 72 */
/* size: 108, cachelines: 2, members: 10 */ /* last cacheline: 44 bytes */ };
$ pahole -C wl3501_scan_confirm drivers/net/wireless/wl3501_cs.o struct wl3501_scan_confirm { u16 next_blk; /* 0 2 */ u8 sig_id; /* 2 1 */ u8 reserved; /* 3 1 */ u16 status; /* 4 2 */ char timestamp[8]; /* 6 8 */ char localtime[8]; /* 14 8 */ struct wl3501_req req; /* 22 72 */ /* --- cacheline 1 boundary (64 bytes) was 30 bytes ago --- */ u8 rssi; /* 94 1 */
/* size: 96, cachelines: 2, members: 8 */ /* padding: 1 */ /* last cacheline: 32 bytes */ };
The problem is that the original code is trying to copy data into a bunch of struct members adjacent to each other in a single call to memcpy(). Now that a new struct wl3501_req enclosing all those adjacent members is introduced, memcpy() doesn't overrun the length of &sig.beacon_period and &this->bss_set[i].beacon_period, because the address of the new struct object _req_ is used as the destination, instead.
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Reviewed-by: Kees Cook keescook@chromium.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/1fbaf516da763b50edac47d792a9145aa4482e29.161844226... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/wl3501.h | 35 +++++++++++-------------- drivers/net/wireless/wl3501_cs.c | 44 +++++++++++++++++--------------- 2 files changed, 38 insertions(+), 41 deletions(-)
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index aa8222cbea68..59b7b93c5963 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -379,16 +379,7 @@ struct wl3501_get_confirm { u8 mib_value[100]; };
-struct wl3501_join_req { - u16 next_blk; - u8 sig_id; - u8 reserved; - struct iw_mgmt_data_rset operational_rset; - u16 reserved2; - u16 timeout; - u16 probe_delay; - u8 timestamp[8]; - u8 local_time[8]; +struct wl3501_req { u16 beacon_period; u16 dtim_period; u16 cap_info; @@ -401,6 +392,19 @@ struct wl3501_join_req { struct iw_mgmt_data_rset bss_basic_rset; };
+struct wl3501_join_req { + u16 next_blk; + u8 sig_id; + u8 reserved; + struct iw_mgmt_data_rset operational_rset; + u16 reserved2; + u16 timeout; + u16 probe_delay; + u8 timestamp[8]; + u8 local_time[8]; + struct wl3501_req req; +}; + struct wl3501_join_confirm { u16 next_blk; u8 sig_id; @@ -443,16 +447,7 @@ struct wl3501_scan_confirm { u16 status; char timestamp[8]; char localtime[8]; - u16 beacon_period; - u16 dtim_period; - u16 cap_info; - u8 bss_type; - u8 bssid[ETH_ALEN]; - struct iw_mgmt_essid_pset ssid; - struct iw_mgmt_ds_pset ds_pset; - struct iw_mgmt_cf_pset cf_pset; - struct iw_mgmt_ibss_pset ibss_pset; - struct iw_mgmt_data_rset bss_basic_rset; + struct wl3501_req req; u8 rssi; };
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 70307308635f..672f5d5f3f2c 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -590,7 +590,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) struct wl3501_join_req sig = { .sig_id = WL3501_SIG_JOIN_REQ, .timeout = 10, - .ds_pset = { + .req.ds_pset = { .el = { .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, .len = 1, @@ -599,7 +599,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) }, };
- memcpy(&sig.beacon_period, &this->bss_set[stas].beacon_period, 72); + memcpy(&sig.req, &this->bss_set[stas].req, sizeof(sig.req)); return wl3501_esbq_exec(this, &sig, sizeof(sig)); }
@@ -667,35 +667,37 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) if (sig.status == WL3501_STATUS_SUCCESS) { pr_debug("success"); if ((this->net_type == IW_MODE_INFRA && - (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) || + (sig.req.cap_info & WL3501_MGMT_CAPABILITY_ESS)) || (this->net_type == IW_MODE_ADHOC && - (sig.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) || + (sig.req.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) || this->net_type == IW_MODE_AUTO) { if (!this->essid.el.len) matchflag = 1; else if (this->essid.el.len == 3 && !memcmp(this->essid.essid, "ANY", 3)) matchflag = 1; - else if (this->essid.el.len != sig.ssid.el.len) + else if (this->essid.el.len != sig.req.ssid.el.len) matchflag = 0; - else if (memcmp(this->essid.essid, sig.ssid.essid, + else if (memcmp(this->essid.essid, sig.req.ssid.essid, this->essid.el.len)) matchflag = 0; else matchflag = 1; if (matchflag) { for (i = 0; i < this->bss_cnt; i++) { - if (ether_addr_equal_unaligned(this->bss_set[i].bssid, sig.bssid)) { + if (ether_addr_equal_unaligned(this->bss_set[i].req.bssid, + sig.req.bssid)) { matchflag = 0; break; } } } if (matchflag && (i < 20)) { - memcpy(&this->bss_set[i].beacon_period, - &sig.beacon_period, 73); + memcpy(&this->bss_set[i].req, + &sig.req, sizeof(sig.req)); this->bss_cnt++; this->rssi = sig.rssi; + this->bss_set[i].rssi = sig.rssi; } } } else if (sig.status == WL3501_STATUS_TIMEOUT) { @@ -887,19 +889,19 @@ static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr) if (this->join_sta_bss < this->bss_cnt) { const int i = this->join_sta_bss; memcpy(this->bssid, - this->bss_set[i].bssid, ETH_ALEN); - this->chan = this->bss_set[i].ds_pset.chan; + this->bss_set[i].req.bssid, ETH_ALEN); + this->chan = this->bss_set[i].req.ds_pset.chan; iw_copy_mgmt_info_element(&this->keep_essid.el, - &this->bss_set[i].ssid.el); + &this->bss_set[i].req.ssid.el); wl3501_mgmt_auth(this); } } else { const int i = this->join_sta_bss;
- memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN); - this->chan = this->bss_set[i].ds_pset.chan; + memcpy(&this->bssid, &this->bss_set[i].req.bssid, ETH_ALEN); + this->chan = this->bss_set[i].req.ds_pset.chan; iw_copy_mgmt_info_element(&this->keep_essid.el, - &this->bss_set[i].ssid.el); + &this->bss_set[i].req.ssid.el); wl3501_online(dev); } } else { @@ -1573,30 +1575,30 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, for (i = 0; i < this->bss_cnt; ++i) { iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); + memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].req.bssid, ETH_ALEN); current_ev = iwe_stream_add_event(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - iwe.u.data.length = this->bss_set[i].ssid.el.len; + iwe.u.data.length = this->bss_set[i].req.ssid.el.len; current_ev = iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, - this->bss_set[i].ssid.essid); + this->bss_set[i].req.ssid.essid); iwe.cmd = SIOCGIWMODE; - iwe.u.mode = this->bss_set[i].bss_type; + iwe.u.mode = this->bss_set[i].req.bss_type; current_ev = iwe_stream_add_event(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN); iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = this->bss_set[i].ds_pset.chan; + iwe.u.freq.m = this->bss_set[i].req.ds_pset.chan; iwe.u.freq.e = 0; current_ev = iwe_stream_add_event(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN); iwe.cmd = SIOCGIWENCODE; - if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY) + if (this->bss_set[i].req.cap_info & WL3501_MGMT_CAPABILITY_PRIVACY) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED;
From: Lee Gibson leegib@gmail.com
[ Upstream commit 130f634da1af649205f4a3dd86cbe5c126b57914 ]
Function qtnf_event_handle_external_auth calls memcpy without checking the length. A user could control that length and trigger a buffer overflow. Fix by checking the length is within the maximum allowed size.
Signed-off-by: Lee Gibson leegib@gmail.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210419145842.345787-1-leegib@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/quantenna/qtnfmac/event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index c775c177933b..8dc80574d08d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -570,8 +570,10 @@ qtnf_event_handle_external_auth(struct qtnf_vif *vif, return 0;
if (ev->ssid_len) { - memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len); - auth.ssid.ssid_len = ev->ssid_len; + int len = clamp_val(ev->ssid_len, 0, IEEE80211_MAX_SSID_LEN); + + memcpy(auth.ssid.ssid, ev->ssid, len); + auth.ssid.ssid_len = len; }
auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
From: Alexey Kardashevskiy aik@ozlabs.ru
[ Upstream commit cc7130bf119add37f36238343a593b71ef6ecc1e ]
The IOMMU table is divided into pools for concurrent mappings and each pool has a separate spinlock. When taking the ownership of an IOMMU group to pass through a device to a VM, we lock these spinlocks which triggers a false negative warning in lockdep (below).
This fixes it by annotating the large pool's spinlock as a nest lock which makes lockdep not complaining when locking nested locks if the nest lock is locked already.
=== WARNING: possible recursive locking detected 5.11.0-le_syzkaller_a+fstn1 #100 Not tainted -------------------------------------------- qemu-system-ppc/4129 is trying to acquire lock: c0000000119bddb0 (&(p->lock)/1){....}-{2:2}, at: iommu_take_ownership+0xac/0x1e0
but task is already holding lock: c0000000119bdd30 (&(p->lock)/1){....}-{2:2}, at: iommu_take_ownership+0xac/0x1e0
other info that might help us debug this: Possible unsafe locking scenario:
CPU0 ---- lock(&(p->lock)/1); lock(&(p->lock)/1); ===
Signed-off-by: Alexey Kardashevskiy aik@ozlabs.ru Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210301063653.51003-1-aik@ozlabs.ru Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index c00214a4355c..4023f91defa6 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1096,7 +1096,7 @@ int iommu_take_ownership(struct iommu_table *tbl)
spin_lock_irqsave(&tbl->large_pool.lock, flags); for (i = 0; i < tbl->nr_pools; i++) - spin_lock(&tbl->pools[i].lock); + spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
iommu_table_release_pages(tbl);
@@ -1124,7 +1124,7 @@ void iommu_release_ownership(struct iommu_table *tbl)
spin_lock_irqsave(&tbl->large_pool.lock, flags); for (i = 0; i < tbl->nr_pools; i++) - spin_lock(&tbl->pools[i].lock); + spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
memset(tbl->it_map, 0, sz);
From: Stefan Assmann sassmann@kpanic.de
[ Upstream commit 1a0e880b028f97478dc689e2900b312741d0d772 ]
Both iavf_free_all_tx_resources() and iavf_free_all_rx_resources() have already been called in the very same function. Remove the duplicate calls.
Signed-off-by: Stefan Assmann sassmann@kpanic.de Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/iavf/iavf_main.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index dc5b3c06d1e0..ebd08543791b 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -3899,8 +3899,6 @@ static void iavf_remove(struct pci_dev *pdev)
iounmap(hw->hw_addr); pci_release_regions(pdev); - iavf_free_all_tx_resources(adapter); - iavf_free_all_rx_resources(adapter); iavf_free_queues(adapter); kfree(adapter->vf_res); spin_lock_bh(&adapter->mac_vlan_list_lock);
From: Felix Fietkau nbd@nbd.name
[ Upstream commit 3f57d8c40fea9b20543cab4da12f4680d2ef182c ]
The VLAN ID in the rx descriptor is only valid if the RX_DMA_VTAG bit is set. Fixes frames wrongly marked with VLAN tags.
Signed-off-by: Felix Fietkau nbd@nbd.name [Ilya: fix commit message] Signed-off-by: Ilya Lipnitskiy ilya.lipnitskiy@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 01d3ee4b5829..bcd5e7ae8482 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1319,7 +1319,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, skb->protocol = eth_type_trans(skb, netdev);
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX && - RX_DMA_VID(trxd.rxd3)) + (trxd.rxd2 & RX_DMA_VTAG)) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), RX_DMA_VID(trxd.rxd3)); skb_record_rx_queue(skb, 0); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index fd3cec8f06ba..c47272100615 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -296,6 +296,7 @@ #define RX_DMA_LSO BIT(30) #define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) #define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff) +#define RX_DMA_VTAG BIT(15)
/* QDMA descriptor rxd3 */ #define RX_DMA_VID(_x) ((_x) & 0xfff)
From: Petr Machata petrm@nvidia.com
[ Upstream commit dda7f4fa55839baeb72ae040aeaf9ccf89d3e416 ]
The intention behind this test is to make sure that qdisc limit is correctly projected to the HW. However, first, due to rounding in the qdisc, and then in the driver, the number cannot actually be accurate. And second, the approach to testing this is to oversubscribe the port with traffic generated on the same switch. The actual backlog size therefore fluctuates.
In practice, this test proved to be noisier than the rest, and spuriously fails every now and then. Increase the tolerance to 10 % to avoid these issues.
Signed-off-by: Petr Machata petrm@nvidia.com Acked-by: Jiri Pirko jiri@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh index b0cb1aaffdda..33ddd01689be 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh @@ -507,8 +507,8 @@ do_red_test() check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0." local diff=$((limit - backlog)) pct=$((100 * diff / limit)) - ((0 <= pct && pct <= 5)) - check_err $? "backlog $backlog / $limit expected <= 5% distance" + ((0 <= pct && pct <= 10)) + check_err $? "backlog $backlog / $limit expected <= 10% distance" log_test "TC $((vlan - 10)): RED backlog > limit"
stop_traffic
From: Petr Machata petrm@nvidia.com
[ Upstream commit 1233898ab758cbcf5f6fea10b8dd16a0b2c24fab ]
The mirror_gre_scale test creates as many ERSPAN sessions as the underlying chip supports, and tests that they all work. In order to determine that it issues a stream of ICMP packets and checks if they are mirrored as expected.
However, the mausezahn invocation missed the -6 flag to identify the use of IPv6 protocol, and was sending ICMP messages over IPv6, as opposed to ICMP6. It also didn't pass an explicit source IP address, which apparently worked at some point in the past, but does not anymore.
To fix these issues, extend the function mirror_test() in mirror_lib by detecting the IPv6 protocol addresses, and using a different ICMP scheme. Fix __mirror_gre_test() in the selftest itself to pass a source IP address.
Signed-off-by: Petr Machata petrm@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../drivers/net/mlxsw/mirror_gre_scale.sh | 3 ++- .../selftests/net/forwarding/mirror_lib.sh | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh index 6f3a70df63bc..e00435753008 100644 --- a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh @@ -120,12 +120,13 @@ __mirror_gre_test() sleep 5
for ((i = 0; i < count; ++i)); do + local sip=$(mirror_gre_ipv6_addr 1 $i)::1 local dip=$(mirror_gre_ipv6_addr 1 $i)::2 local htun=h3-gt6-$i local message
icmp6_capture_install $htun - mirror_test v$h1 "" $dip $htun 100 10 + mirror_test v$h1 $sip $dip $htun 100 10 icmp6_capture_uninstall $htun done } diff --git a/tools/testing/selftests/net/forwarding/mirror_lib.sh b/tools/testing/selftests/net/forwarding/mirror_lib.sh index 13db1cb50e57..6406cd76a19d 100644 --- a/tools/testing/selftests/net/forwarding/mirror_lib.sh +++ b/tools/testing/selftests/net/forwarding/mirror_lib.sh @@ -20,6 +20,13 @@ mirror_uninstall() tc filter del dev $swp1 $direction pref 1000 }
+is_ipv6() +{ + local addr=$1; shift + + [[ -z ${addr//[0-9a-fA-F:]/} ]] +} + mirror_test() { local vrf_name=$1; shift @@ -29,9 +36,17 @@ mirror_test() local pref=$1; shift local expect=$1; shift
+ if is_ipv6 $dip; then + local proto=-6 + local type="icmp6 type=128" # Echo request. + else + local proto= + local type="icmp echoreq" + fi + local t0=$(tc_rule_stats_get $dev $pref) - $MZ $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \ - -c 10 -d 100msec -t icmp type=8 + $MZ $proto $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \ + -c 10 -d 100msec -t $type sleep 0.5 local t1=$(tc_rule_stats_get $dev $pref) local delta=$((t1 - t0))
From: Masahiro Yamada masahiroy@kernel.org
[ Upstream commit 69bc8d386aebbd91a6bb44b6d33f77c8dfa9ed8c ]
The external module build shows the following warning if Module.symvers is missing in the kernel tree.
WARNING: Symbol version dump "Module.symvers" is missing. Modules may not have dependencies or modversions.
I think this is an important heads-up because the resulting modules may not work as expected. This happens when you did not build the entire kernel tree, for example, you might have prepared the minimal setups for external modules by 'make defconfig && make modules_preapre'.
A problem is that 'make modules' creates Module.symvers even without vmlinux. In this case, that warning is suppressed since Module.symvers already exists in spite of its incomplete content.
The incomplete (i.e. invalid) Module.symvers should not be created.
This commit changes the second pass of modpost to dump symbols into modules-only.symvers. The final Module.symvers is created by concatenating vmlinux.symvers and modules-only.symvers if both exist.
Module.symvers is supposed to collect symbols from both vmlinux and modules. It might be a bit confusing, and I am not quite sure if it is an official interface, but presumably it is difficult to rename it because some tools (e.g. kmod) parse it.
Signed-off-by: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .gitignore | 1 + Documentation/dontdiff | 1 + Makefile | 2 +- scripts/Makefile.modpost | 15 ++++++++++++++- scripts/mod/modpost.c | 15 +-------------- 5 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/.gitignore b/.gitignore index 3af66272d6f1..127012c1f717 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ modules.order /tags /TAGS /linux +/modules-only.symvers /vmlinux /vmlinux.32 /vmlinux.symvers diff --git a/Documentation/dontdiff b/Documentation/dontdiff index e361fc95ca29..82e3eee7363b 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -178,6 +178,7 @@ mktables mktree mkutf8data modpost +modules-only.symvers modules.builtin modules.builtin.modinfo modules.nsdeps diff --git a/Makefile b/Makefile index 0b1852621615..7503ffef6424 100644 --- a/Makefile +++ b/Makefile @@ -1513,7 +1513,7 @@ endif # CONFIG_MODULES # make distclean Remove editor backup files, patch leftover files and the like
# Directories & files removed with 'make clean' -CLEAN_FILES += include/ksym vmlinux.symvers \ +CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \ modules.builtin modules.builtin.modinfo modules.nsdeps \ compile_commands.json .thinlto-cache
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 066beffca09a..4ca5579af4e4 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -68,7 +68,20 @@ else ifeq ($(KBUILD_EXTMOD),)
input-symdump := vmlinux.symvers -output-symdump := Module.symvers +output-symdump := modules-only.symvers + +quiet_cmd_cat = GEN $@ + cmd_cat = cat $(real-prereqs) > $@ + +ifneq ($(wildcard vmlinux.symvers),) + +__modpost: Module.symvers +Module.symvers: vmlinux.symvers modules-only.symvers FORCE + $(call if_changed,cat) + +targets += Module.symvers + +endif
else
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 24725e50c7b4..10c3fba26f03 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2423,19 +2423,6 @@ fail: fatal("parse error in symbol dump file\n"); }
-/* For normal builds always dump all symbols. - * For external modules only dump symbols - * that are not read from kernel Module.symvers. - **/ -static int dump_sym(struct symbol *sym) -{ - if (!external_module) - return 1; - if (sym->module->from_dump) - return 0; - return 1; -} - static void write_dump(const char *fname) { struct buffer buf = { }; @@ -2446,7 +2433,7 @@ static void write_dump(const char *fname) for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n]; while (symbol) { - if (dump_sym(symbol)) { + if (!symbol->module->from_dump) { namespace = symbol->namespace; buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", symbol->crc, symbol->name,
From: Michael Chan michael.chan@broadcom.com
[ Upstream commit 7fbf359bb2c19c824cbb1954020680824f6ee5a5 ]
Support VF device IDs used by the Hyper-V hypervisor.
Reviewed-by: Vasundhara Volam vasundhara-v.volam@broadcom.com Reviewed-by: Andy Gospodarek gospo@broadcom.com Signed-off-by: Edwin Peer edwin.peer@broadcom.com Signed-off-by: Michael Chan michael.chan@broadcom.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 73239d3eaca1..cf4249d59383 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -122,7 +122,10 @@ enum board_idx { NETXTREME_E_VF, NETXTREME_C_VF, NETXTREME_S_VF, + NETXTREME_C_VF_HV, + NETXTREME_E_VF_HV, NETXTREME_E_P5_VF, + NETXTREME_E_P5_VF_HV, };
/* indexed by enum above */ @@ -170,7 +173,10 @@ static const struct { [NETXTREME_E_VF] = { "Broadcom NetXtreme-E Ethernet Virtual Function" }, [NETXTREME_C_VF] = { "Broadcom NetXtreme-C Ethernet Virtual Function" }, [NETXTREME_S_VF] = { "Broadcom NetXtreme-S Ethernet Virtual Function" }, + [NETXTREME_C_VF_HV] = { "Broadcom NetXtreme-C Virtual Function for Hyper-V" }, + [NETXTREME_E_VF_HV] = { "Broadcom NetXtreme-E Virtual Function for Hyper-V" }, [NETXTREME_E_P5_VF] = { "Broadcom BCM5750X NetXtreme-E Ethernet Virtual Function" }, + [NETXTREME_E_P5_VF_HV] = { "Broadcom BCM5750X NetXtreme-E Virtual Function for Hyper-V" }, };
static const struct pci_device_id bnxt_pci_tbl[] = { @@ -222,15 +228,25 @@ static const struct pci_device_id bnxt_pci_tbl[] = { { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 }, #ifdef CONFIG_BNXT_SRIOV { PCI_VDEVICE(BROADCOM, 0x1606), .driver_data = NETXTREME_E_VF }, + { PCI_VDEVICE(BROADCOM, 0x1607), .driver_data = NETXTREME_E_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x1608), .driver_data = NETXTREME_E_VF_HV }, { PCI_VDEVICE(BROADCOM, 0x1609), .driver_data = NETXTREME_E_VF }, + { PCI_VDEVICE(BROADCOM, 0x16bd), .driver_data = NETXTREME_E_VF_HV }, { PCI_VDEVICE(BROADCOM, 0x16c1), .driver_data = NETXTREME_E_VF }, + { PCI_VDEVICE(BROADCOM, 0x16c2), .driver_data = NETXTREME_C_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x16c3), .driver_data = NETXTREME_C_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x16c4), .driver_data = NETXTREME_E_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x16c5), .driver_data = NETXTREME_E_VF_HV }, { PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = NETXTREME_C_VF }, { PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = NETXTREME_E_VF }, { PCI_VDEVICE(BROADCOM, 0x16dc), .driver_data = NETXTREME_E_VF }, { PCI_VDEVICE(BROADCOM, 0x16e1), .driver_data = NETXTREME_C_VF }, { PCI_VDEVICE(BROADCOM, 0x16e5), .driver_data = NETXTREME_C_VF }, + { PCI_VDEVICE(BROADCOM, 0x16e6), .driver_data = NETXTREME_C_VF_HV }, { PCI_VDEVICE(BROADCOM, 0x1806), .driver_data = NETXTREME_E_P5_VF }, { PCI_VDEVICE(BROADCOM, 0x1807), .driver_data = NETXTREME_E_P5_VF }, + { PCI_VDEVICE(BROADCOM, 0x1808), .driver_data = NETXTREME_E_P5_VF_HV }, + { PCI_VDEVICE(BROADCOM, 0x1809), .driver_data = NETXTREME_E_P5_VF_HV }, { PCI_VDEVICE(BROADCOM, 0xd800), .driver_data = NETXTREME_S_VF }, #endif { 0 } @@ -265,7 +281,8 @@ static struct workqueue_struct *bnxt_pf_wq; static bool bnxt_vf_pciid(enum board_idx idx) { return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF || - idx == NETXTREME_S_VF || idx == NETXTREME_E_P5_VF); + idx == NETXTREME_S_VF || idx == NETXTREME_C_VF_HV || + idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF); }
#define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID)
From: Sergei Trofimovich slyfox@gentoo.org
[ Upstream commit 99e729bd40fb3272fa4b0140839d5e957b58588a ]
Noticed failure as a crash on ia64 when tried to symbolize all backtraces collected by page_owner=on:
$ cat /sys/kernel/debug/page_owner <oops>
CPU: 1 PID: 2074 Comm: cat Not tainted 5.12.0-rc4 #226 Hardware name: hp server rx3600, BIOS 04.03 04/08/2008 ip is at dereference_module_function_descriptor+0x41/0x100
Crash happens at dereference_module_function_descriptor() due to use-after-free when dereferencing ".opd" section header.
All section headers are already freed after module is laoded successfully.
To keep symbolizer working the change stores ".opd" address and size after module is relocated to a new place and before section headers are discarded.
To make similar errors less obscure module_finalize() now zeroes out all variables relevant to module loading only.
Link: https://lkml.kernel.org/r/20210403074803.3309096-1-slyfox@gentoo.org Signed-off-by: Sergei Trofimovich slyfox@gentoo.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/ia64/include/asm/module.h | 6 +++++- arch/ia64/kernel/module.c | 29 +++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h index 5a29652e6def..7271b9c5fc76 100644 --- a/arch/ia64/include/asm/module.h +++ b/arch/ia64/include/asm/module.h @@ -14,16 +14,20 @@ struct elf64_shdr; /* forward declration */
struct mod_arch_specific { + /* Used only at module load time. */ struct elf64_shdr *core_plt; /* core PLT section */ struct elf64_shdr *init_plt; /* init PLT section */ struct elf64_shdr *got; /* global offset table */ struct elf64_shdr *opd; /* official procedure descriptors */ struct elf64_shdr *unwind; /* unwind-table section */ unsigned long gp; /* global-pointer for module */ + unsigned int next_got_entry; /* index of next available got entry */
+ /* Used at module run and cleanup time. */ void *core_unw_table; /* core unwind-table cookie returned by unwinder */ void *init_unw_table; /* init unwind-table cookie returned by unwinder */ - unsigned int next_got_entry; /* index of next available got entry */ + void *opd_addr; /* symbolize uses .opd to get to actual function */ + unsigned long opd_size; };
#define ARCH_SHF_SMALL SHF_IA_64_SHORT diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 00a496cb346f..2cba53c1da82 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -905,9 +905,31 @@ register_unwind_table (struct module *mod) int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { + struct mod_arch_specific *mas = &mod->arch; + DEBUGP("%s: init: entry=%p\n", __func__, mod->init); - if (mod->arch.unwind) + if (mas->unwind) register_unwind_table(mod); + + /* + * ".opd" was already relocated to the final destination. Store + * it's address for use in symbolizer. + */ + mas->opd_addr = (void *)mas->opd->sh_addr; + mas->opd_size = mas->opd->sh_size; + + /* + * Module relocation was already done at this point. Section + * headers are about to be deleted. Wipe out load-time context. + */ + mas->core_plt = NULL; + mas->init_plt = NULL; + mas->got = NULL; + mas->opd = NULL; + mas->unwind = NULL; + mas->gp = 0; + mas->next_got_entry = 0; + return 0; }
@@ -926,10 +948,9 @@ module_arch_cleanup (struct module *mod)
void *dereference_module_function_descriptor(struct module *mod, void *ptr) { - Elf64_Shdr *opd = mod->arch.opd; + struct mod_arch_specific *mas = &mod->arch;
- if (ptr < (void *)opd->sh_addr || - ptr >= (void *)(opd->sh_addr + opd->sh_size)) + if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size) return ptr;
return dereference_function_descriptor(ptr);
From: Petr Mladek pmladek@suse.com
[ Upstream commit 7c0012f522c802d25be102bafe54f333168e6119 ]
Patch series "watchdog/softlockup: Report overall time and some cleanup", v2.
I dug deep into the softlockup watchdog history when time permitted this year. And reworked the patchset that fixed timestamps and cleaned up the code[2].
I split it into very small steps and did even more code clean up. The result looks quite strightforward and I am pretty confident with the changes.
[1] v2: https://lore.kernel.org/r/20201210160038.31441-1-pmladek@suse.com [2] v1: https://lore.kernel.org/r/20191024114928.15377-1-pmladek@suse.com
This patch (of 6):
There are many touch_*watchdog() functions. They are called in situations where the watchdog could report false positives or create unnecessary noise. For example, when CPU is entering idle mode, a virtual machine is stopped, or a lot of messages are printed in the atomic context.
These functions set SOFTLOCKUP_RESET instead of a real timestamp. It allows to call them even in a context where jiffies might be outdated. For example, in an atomic context.
The real timestamp is set by __touch_watchdog() that is called from the watchdog timer callback.
Rename this callback to update_touch_ts(). It better describes the effect and clearly distinguish is from the other touch_*watchdog() functions.
Another motivation is that two timestamps are going to be used. One will be used for the total softlockup time. The other will be used to measure time since the last report. The new function name will help to distinguish which timestamp is being updated.
Link: https://lkml.kernel.org/r/20210311122130.6788-1-pmladek@suse.com Link: https://lkml.kernel.org/r/20210311122130.6788-2-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Ingo Molnar mingo@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Laurence Oberman loberman@redhat.com Cc: Vincent Whitchurch vincent.whitchurch@axis.com Cc: Michal Hocko mhocko@suse.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 107bc38b1945..8440e62bfec4 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -236,7 +236,7 @@ static void set_sample_period(void) }
/* Commands for resetting the watchdog */ -static void __touch_watchdog(void) +static void update_touch_ts(void) { __this_cpu_write(watchdog_touch_ts, get_timestamp()); } @@ -332,7 +332,7 @@ static DEFINE_PER_CPU(struct cpu_stop_work, softlockup_stop_work); */ static int softlockup_fn(void *data) { - __touch_watchdog(); + update_touch_ts(); complete(this_cpu_ptr(&softlockup_completion));
return 0; @@ -375,7 +375,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
/* Clear the guest paused flag on watchdog reset */ kvm_check_and_clear_guest_paused(); - __touch_watchdog(); + update_touch_ts(); return HRTIMER_RESTART; }
@@ -461,7 +461,7 @@ static void watchdog_enable(unsigned int cpu) HRTIMER_MODE_REL_PINNED_HARD);
/* Initialize timestamp */ - __touch_watchdog(); + update_touch_ts(); /* Enable the perf event */ if (watchdog_enabled & NMI_WATCHDOG_ENABLED) watchdog_nmi_enable(cpu);
From: Petr Mladek pmladek@suse.com
[ Upstream commit c9ad17c991492f4390f42598f6ab0531f87eed07 ]
The softlockup situation might stay for a long time or even forever. When it happens, the softlockup debug messages are printed in regular intervals defined by get_softlockup_thresh().
There is a mystery. The repeated message is printed after the full interval that is defined by get_softlockup_thresh(). But the timer callback is called more often as defined by sample_period. The code looks like the soflockup should get reported in every sample_period when it was once behind the thresh.
It works only by chance. The watchdog is touched when printing the stall report, for example, in printk_stack_address().
Make the behavior clear and predictable by explicitly updating the timestamp in watchdog_timer_fn() when the report gets printed.
Link: https://lkml.kernel.org/r/20210311122130.6788-3-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Cc: Ingo Molnar mingo@kernel.org Cc: Laurence Oberman loberman@redhat.com Cc: Michal Hocko mhocko@suse.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Vincent Whitchurch vincent.whitchurch@axis.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 8440e62bfec4..8efd2a8d9f10 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -410,6 +410,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) } }
+ /* Start period for the next softlockup warning. */ + update_touch_ts(); + pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(), duration, current->comm, task_pid_nr(current));
From: Petr Mladek pmladek@suse.com
[ Upstream commit fef06efc2ebaa94c8aee299b863e870467dbab8d ]
The softlockup detector currently shows the time spent since the last report. As a result it is not clear whether a CPU is infinitely hogged by a single task or if it is a repeated event.
The situation can be simulated with a simply busy loop:
while (true) cpu_relax();
The softlockup detector produces:
[ 168.277520] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] [ 196.277604] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] [ 236.277522] watchdog: BUG: soft lockup - CPU#1 stuck for 23s! [cat:4865]
But it should be, something like:
[ 480.372418] watchdog: BUG: soft lockup - CPU#2 stuck for 26s! [cat:4943] [ 508.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 52s! [cat:4943] [ 548.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 89s! [cat:4943] [ 576.372351] watchdog: BUG: soft lockup - CPU#2 stuck for 115s! [cat:4943]
For the better output, add an additional timestamp of the last report. Only this timestamp is reset when the watchdog is intentionally touched from slow code paths or when printing the report.
Link: https://lkml.kernel.org/r/20210311122130.6788-4-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Cc: Ingo Molnar mingo@kernel.org Cc: Laurence Oberman loberman@redhat.com Cc: Michal Hocko mhocko@suse.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Vincent Whitchurch vincent.whitchurch@axis.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 8efd2a8d9f10..6bc5113d3d74 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -154,7 +154,11 @@ static void lockup_detector_update_enable(void)
#ifdef CONFIG_SOFTLOCKUP_DETECTOR
-#define SOFTLOCKUP_RESET ULONG_MAX +/* + * Delay the soflockup report when running a known slow code. + * It does _not_ affect the timestamp of the last successdul reschedule. + */ +#define SOFTLOCKUP_DELAY_REPORT ULONG_MAX
#ifdef CONFIG_SMP int __read_mostly sysctl_softlockup_all_cpu_backtrace; @@ -169,7 +173,10 @@ unsigned int __read_mostly softlockup_panic = static bool softlockup_initialized __read_mostly; static u64 __read_mostly sample_period;
+/* Timestamp taken after the last successful reschedule. */ static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); +/* Timestamp of the last softlockup report. */ +static DEFINE_PER_CPU(unsigned long, watchdog_report_ts); static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); static DEFINE_PER_CPU(bool, softlockup_touch_sync); static DEFINE_PER_CPU(bool, soft_watchdog_warn); @@ -235,10 +242,16 @@ static void set_sample_period(void) watchdog_update_hrtimer_threshold(sample_period); }
+static void update_report_ts(void) +{ + __this_cpu_write(watchdog_report_ts, get_timestamp()); +} + /* Commands for resetting the watchdog */ static void update_touch_ts(void) { __this_cpu_write(watchdog_touch_ts, get_timestamp()); + update_report_ts(); }
/** @@ -252,10 +265,10 @@ static void update_touch_ts(void) notrace void touch_softlockup_watchdog_sched(void) { /* - * Preemption can be enabled. It doesn't matter which CPU's timestamp - * gets zeroed here, so use the raw_ operation. + * Preemption can be enabled. It doesn't matter which CPU's watchdog + * report period gets restarted here, so use the raw_ operation. */ - raw_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET); + raw_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT); }
notrace void touch_softlockup_watchdog(void) @@ -279,7 +292,7 @@ void touch_all_softlockup_watchdogs(void) * the softlockup check. */ for_each_cpu(cpu, &watchdog_allowed_mask) { - per_cpu(watchdog_touch_ts, cpu) = SOFTLOCKUP_RESET; + per_cpu(watchdog_report_ts, cpu) = SOFTLOCKUP_DELAY_REPORT; wq_watchdog_touch(cpu); } } @@ -287,16 +300,16 @@ void touch_all_softlockup_watchdogs(void) void touch_softlockup_watchdog_sync(void) { __this_cpu_write(softlockup_touch_sync, true); - __this_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET); + __this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT); }
-static int is_softlockup(unsigned long touch_ts) +static int is_softlockup(unsigned long touch_ts, unsigned long period_ts) { unsigned long now = get_timestamp();
if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){ /* Warn about unreasonable delays. */ - if (time_after(now, touch_ts + get_softlockup_thresh())) + if (time_after(now, period_ts + get_softlockup_thresh())) return now - touch_ts; } return 0; @@ -342,6 +355,7 @@ static int softlockup_fn(void *data) static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) { unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); + unsigned long period_ts = __this_cpu_read(watchdog_report_ts); struct pt_regs *regs = get_irq_regs(); int duration; int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace; @@ -363,7 +377,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) /* .. and repeat */ hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
- if (touch_ts == SOFTLOCKUP_RESET) { + /* Reset the interval when touched externally by a known slow code. */ + if (period_ts == SOFTLOCKUP_DELAY_REPORT) { if (unlikely(__this_cpu_read(softlockup_touch_sync))) { /* * If the time stamp was touched atomically @@ -375,7 +390,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
/* Clear the guest paused flag on watchdog reset */ kvm_check_and_clear_guest_paused(); - update_touch_ts(); + update_report_ts(); + return HRTIMER_RESTART; }
@@ -385,7 +401,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) * indicate it is getting cpu time. If it hasn't then * this is a good indication some task is hogging the cpu */ - duration = is_softlockup(touch_ts); + duration = is_softlockup(touch_ts, period_ts); if (unlikely(duration)) { /* * If a virtual machine is stopped by the host it can look to @@ -411,7 +427,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) }
/* Start period for the next softlockup warning. */ - update_touch_ts(); + update_report_ts();
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(), duration,
From: Petr Mladek pmladek@suse.com
[ Upstream commit 1bc503cb4a2638fb1c57801a7796aca57845ce63 ]
The softlockup detector does some gymnastic with the variable soft_watchdog_warn. It was added by the commit 58687acba59266735ad ("lockup_detector: Combine nmi_watchdog and softlockup detector").
The purpose is not completely clear. There are the following clues. They describe the situation how it looked after the above mentioned commit:
1. The variable was checked with a comment "only warn once".
2. The variable was set when softlockup was reported. It was cleared only when the CPU was not longer in the softlockup state.
3. watchdog_touch_ts was not explicitly updated when the softlockup was reported. Without this variable, the report would normally be printed again during every following watchdog_timer_fn() invocation.
The logic has got even more tangled up by the commit ed235875e2ca98 ("kernel/watchdog.c: print traces for all cpus on lockup detection"). After this commit, soft_watchdog_warn is set only when softlockup_all_cpu_backtrace is enabled. But multiple reports from all CPUs are prevented by a new variable soft_lockup_nmi_warn.
Conclusion:
The variable probably never worked as intended. In each case, it has not worked last many years because the softlockup was reported repeatedly after the full period defined by watchdog_thresh.
The reason is that watchdog gets touched in many known slow paths, for example, in printk_stack_address(). This code is called also when printing the softlockup report. It means that the watchdog timestamp gets updated after each report.
Solution:
Simply remove the logic. People want the periodic report anyway.
Link: https://lkml.kernel.org/r/20210311122130.6788-5-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Cc: Ingo Molnar mingo@kernel.org Cc: Laurence Oberman loberman@redhat.com Cc: Michal Hocko mhocko@suse.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Vincent Whitchurch vincent.whitchurch@axis.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 6bc5113d3d74..b8d4182d14cc 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -179,7 +179,6 @@ static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); static DEFINE_PER_CPU(unsigned long, watchdog_report_ts); static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); static DEFINE_PER_CPU(bool, softlockup_touch_sync); -static DEFINE_PER_CPU(bool, soft_watchdog_warn); static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts); static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); static unsigned long soft_lockup_nmi_warn; @@ -411,19 +410,12 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) if (kvm_check_and_clear_guest_paused()) return HRTIMER_RESTART;
- /* only warn once */ - if (__this_cpu_read(soft_watchdog_warn) == true) - return HRTIMER_RESTART; - if (softlockup_all_cpu_backtrace) { /* Prevent multiple soft-lockup reports if one cpu is already * engaged in dumping cpu back traces */ - if (test_and_set_bit(0, &soft_lockup_nmi_warn)) { - /* Someone else will report us. Let's give up */ - __this_cpu_write(soft_watchdog_warn, true); + if (test_and_set_bit(0, &soft_lockup_nmi_warn)) return HRTIMER_RESTART; - } }
/* Start period for the next softlockup warning. */ @@ -453,9 +445,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); if (softlockup_panic) panic("softlockup: hung tasks"); - __this_cpu_write(soft_watchdog_warn, true); - } else - __this_cpu_write(soft_watchdog_warn, false); + }
return HRTIMER_RESTART; }
From: Petr Mladek pmladek@suse.com
[ Upstream commit 9f113bf760ca90d709f8f89a733d10abb1f04a83 ]
Any parallel softlockup reports are skipped when one CPU is already printing backtraces from all CPUs.
The exclusive rights are synchronized using one bit in soft_lockup_nmi_warn. There is also one memory barrier that does not make much sense.
Use two barriers on the right location to prevent mixing two reports.
[pmladek@suse.com: use bit lock operations to prevent multiple soft-lockup reports] Link: https://lkml.kernel.org/r/YFSVsLGVWMXTvlbk@alley
Link: https://lkml.kernel.org/r/20210311122130.6788-6-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Acked-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: Ingo Molnar mingo@kernel.org Cc: Laurence Oberman loberman@redhat.com Cc: Michal Hocko mhocko@suse.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Vincent Whitchurch vincent.whitchurch@axis.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index b8d4182d14cc..8cf0678378d2 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -410,11 +410,12 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) if (kvm_check_and_clear_guest_paused()) return HRTIMER_RESTART;
+ /* + * Prevent multiple soft-lockup reports if one cpu is already + * engaged in dumping all cpu back traces. + */ if (softlockup_all_cpu_backtrace) { - /* Prevent multiple soft-lockup reports if one cpu is already - * engaged in dumping cpu back traces - */ - if (test_and_set_bit(0, &soft_lockup_nmi_warn)) + if (test_and_set_bit_lock(0, &soft_lockup_nmi_warn)) return HRTIMER_RESTART; }
@@ -432,14 +433,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) dump_stack();
if (softlockup_all_cpu_backtrace) { - /* Avoid generating two back traces for current - * given that one is already made above - */ trigger_allbutself_cpu_backtrace(); - - clear_bit(0, &soft_lockup_nmi_warn); - /* Barrier to sync with other cpus */ - smp_mb__after_atomic(); + clear_bit_unlock(0, &soft_lockup_nmi_warn); }
add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
From: Petr Mladek pmladek@suse.com
[ Upstream commit 9bf3bc949f8aeefeacea4b1198db833b722a8e27 ]
Commit d6ad3e286d2c ("softlockup: Add sched_clock_tick() to avoid kernel warning on kgdb resume") introduced touch_softlockup_watchdog_sync().
It solved a problem when the watchdog was touched in an atomic context, the timer callback was proceed right after releasing interrupts, and the local clock has not been updated yet. In this case, sched_clock_tick() was called in watchdog_timer_fn() before updating the timer.
So far so good.
Later commit 5d1c0f4a80a6 ("watchdog: add check for suspended vm in softlockup detector") added two kvm_check_and_clear_guest_paused() calls. They touch the watchdog when the guest has been sleeping.
The code makes my head spin around.
Scenario 1:
+ guest did sleep: + PVCLOCK_GUEST_STOPPED is set
+ 1st watchdog_timer_fn() invocation: + the watchdog is not touched yet + is_softlockup() returns too big delay + kvm_check_and_clear_guest_paused(): + clear PVCLOCK_GUEST_STOPPED + call touch_softlockup_watchdog_sync() + set SOFTLOCKUP_DELAY_REPORT + set softlockup_touch_sync + return from the timer callback
+ 2nd watchdog_timer_fn() invocation:
+ call sched_clock_tick() even though it is not needed. The timer callback was invoked again only because the clock has already been updated in the meantime.
+ call kvm_check_and_clear_guest_paused() that does nothing because PVCLOCK_GUEST_STOPPED has been cleared already.
+ call update_report_ts() and return. This is fine. Except that sched_clock_tick() might allow to set it already during the 1st invocation.
Scenario 2:
+ guest did sleep
+ 1st watchdog_timer_fn() invocation + same as in 1st scenario
+ guest did sleep again: + set PVCLOCK_GUEST_STOPPED again
+ 2nd watchdog_timer_fn() invocation + SOFTLOCKUP_DELAY_REPORT is set from 1st invocation + call sched_clock_tick() + call kvm_check_and_clear_guest_paused() + clear PVCLOCK_GUEST_STOPPED + call touch_softlockup_watchdog_sync() + set SOFTLOCKUP_DELAY_REPORT + set softlockup_touch_sync + call update_report_ts() (set real timestamp immediately) + return from the timer callback
+ 3rd watchdog_timer_fn() invocation + timestamp is set from 2nd invocation + softlockup_touch_sync is set but not checked because the real timestamp is already set
Make the code more straightforward:
1. Always call kvm_check_and_clear_guest_paused() at the very beginning to handle PVCLOCK_GUEST_STOPPED. It touches the watchdog when the quest did sleep.
2. Handle the situation when the watchdog has been touched (SOFTLOCKUP_DELAY_REPORT is set).
Call sched_clock_tick() when touch_*sync() variant was used. It makes sure that the timestamp will be up to date even when it has been touched in atomic context or quest did sleep.
As a result, kvm_check_and_clear_guest_paused() is called on a single location. And the right timestamp is always set when returning from the timer callback.
Link: https://lkml.kernel.org/r/20210311122130.6788-7-pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Cc: Ingo Molnar mingo@kernel.org Cc: Laurence Oberman loberman@redhat.com Cc: Michal Hocko mhocko@suse.com Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: Vincent Whitchurch vincent.whitchurch@axis.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/watchdog.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 8cf0678378d2..7c397907d0e9 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -376,7 +376,14 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) /* .. and repeat */ hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
- /* Reset the interval when touched externally by a known slow code. */ + /* + * If a virtual machine is stopped by the host it can look to + * the watchdog like a soft lockup. Check to see if the host + * stopped the vm before we process the timestamps. + */ + kvm_check_and_clear_guest_paused(); + + /* Reset the interval when touched by known problematic code. */ if (period_ts == SOFTLOCKUP_DELAY_REPORT) { if (unlikely(__this_cpu_read(softlockup_touch_sync))) { /* @@ -387,10 +394,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) sched_clock_tick(); }
- /* Clear the guest paused flag on watchdog reset */ - kvm_check_and_clear_guest_paused(); update_report_ts(); - return HRTIMER_RESTART; }
@@ -402,14 +406,6 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) */ duration = is_softlockup(touch_ts, period_ts); if (unlikely(duration)) { - /* - * If a virtual machine is stopped by the host it can look to - * the watchdog like a soft lockup, check to see if the host - * stopped the vm before we issue the warning - */ - if (kvm_check_and_clear_guest_paused()) - return HRTIMER_RESTART; - /* * Prevent multiple soft-lockup reports if one cpu is already * engaged in dumping all cpu back traces.
On Mon 2021-05-17 15:59:49, Greg Kroah-Hartman wrote:
From: Petr Mladek pmladek@suse.com
[ Upstream commit 9bf3bc949f8aeefeacea4b1198db833b722a8e27 ]
Commit d6ad3e286d2c ("softlockup: Add sched_clock_tick() to avoid kernel warning on kgdb resume") introduced touch_softlockup_watchdog_sync().
[...]
Make the code more straightforward:
Always call kvm_check_and_clear_guest_paused() at the very beginning to handle PVCLOCK_GUEST_STOPPED. It touches the watchdog when the quest did sleep.
Handle the situation when the watchdog has been touched (SOFTLOCKUP_DELAY_REPORT is set).
Call sched_clock_tick() when touch_*sync() variant was used. It makes sure that the timestamp will be up to date even when it has been touched in atomic context or quest did sleep.
As a result, kvm_check_and_clear_guest_paused() is called on a single location. And the right timestamp is always set when returning from the timer callback.
Link: https://lkml.kernel.org/r/20210311122130.6788-7-pmladek@suse.com
Please, remove this patch from the stable backport. It might cause false softlockup reports, see https://lore.kernel.org/r/20210517140612.222750-1-senozhatsky@chromium.org
Best Regards, Petr
On Mon, May 17, 2021 at 04:30:56PM +0200, Petr Mladek wrote:
On Mon 2021-05-17 15:59:49, Greg Kroah-Hartman wrote:
From: Petr Mladek pmladek@suse.com
[ Upstream commit 9bf3bc949f8aeefeacea4b1198db833b722a8e27 ]
Commit d6ad3e286d2c ("softlockup: Add sched_clock_tick() to avoid kernel warning on kgdb resume") introduced touch_softlockup_watchdog_sync().
[...]
Make the code more straightforward:
Always call kvm_check_and_clear_guest_paused() at the very beginning to handle PVCLOCK_GUEST_STOPPED. It touches the watchdog when the quest did sleep.
Handle the situation when the watchdog has been touched (SOFTLOCKUP_DELAY_REPORT is set).
Call sched_clock_tick() when touch_*sync() variant was used. It makes sure that the timestamp will be up to date even when it has been touched in atomic context or quest did sleep.
As a result, kvm_check_and_clear_guest_paused() is called on a single location. And the right timestamp is always set when returning from the timer callback.
Link: https://lkml.kernel.org/r/20210311122130.6788-7-pmladek@suse.com
Please, remove this patch from the stable backport. It might cause false softlockup reports, see https://lore.kernel.org/r/20210517140612.222750-1-senozhatsky@chromium.org
Now dropped, thanks.
greg k-h
On (21/05/17 16:30), Petr Mladek wrote:
On Mon 2021-05-17 15:59:49, Greg Kroah-Hartman wrote:
From: Petr Mladek pmladek@suse.com
[ Upstream commit 9bf3bc949f8aeefeacea4b1198db833b722a8e27 ]
Commit d6ad3e286d2c ("softlockup: Add sched_clock_tick() to avoid kernel warning on kgdb resume") introduced touch_softlockup_watchdog_sync().
[...]
Make the code more straightforward:
Always call kvm_check_and_clear_guest_paused() at the very beginning to handle PVCLOCK_GUEST_STOPPED. It touches the watchdog when the quest did sleep.
Handle the situation when the watchdog has been touched (SOFTLOCKUP_DELAY_REPORT is set).
Call sched_clock_tick() when touch_*sync() variant was used. It makes sure that the timestamp will be up to date even when it has been touched in atomic context or quest did sleep.
As a result, kvm_check_and_clear_guest_paused() is called on a single location. And the right timestamp is always set when returning from the timer callback.
Link: https://lkml.kernel.org/r/20210311122130.6788-7-pmladek@suse.com
Please, remove this patch from the stable backport. It might cause false softlockup reports, see
Oh, I didn't know about the stable backport. Thank you for taking care of it.
From: David Ward david.ward@gatech.edu
[ Upstream commit cd8499d5c03ba260e3191e90236d0e5f6b147563 ]
The GPIO configuration cannot be applied if the registers are inaccessible. This prevented the headset mic from working on the Dell XPS 13 9343.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=114171 Signed-off-by: David Ward david.ward@gatech.edu Link: https://lore.kernel.org/r/20210418134658.4333-5-david.ward@gatech.edu Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/rt286.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 2f18f5114f7e..ff23a7d4d2ac 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg) case RT286_PROC_COEF: case RT286_SET_AMP_GAIN_ADC_IN1: case RT286_SET_AMP_GAIN_ADC_IN2: + case RT286_SET_GPIO_MASK: + case RT286_SET_GPIO_DIRECTION: + case RT286_SET_GPIO_DATA: case RT286_SET_POWER(RT286_DAC_OUT1): case RT286_SET_POWER(RT286_DAC_OUT2): case RT286_SET_POWER(RT286_ADC_IN1):
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 34731ed13e8a8ca95fa0dca466537396b5f2d1af ]
Without gpiolib, the driver fails to build:
drivers/leds/blink/leds-lgm-sso.c:123:19: error: field has incomplete type 'struct gpio_chip' struct gpio_chip chip; ^ include/linux/gpio.h:107:8: note: forward declaration of 'struct gpio_chip' struct gpio_chip; ^ drivers/leds/blink/leds-lgm-sso.c:263:3: error: implicit declaration of function 'gpiod_set_value' [-Werror,-Wimplicit-function-declaration] gpiod_set_value(led->gpiod, val); ^ drivers/leds/blink/leds-lgm-sso.c:263:3: note: did you mean 'gpio_set_value'? include/linux/gpio.h:168:20: note: 'gpio_set_value' declared here static inline void gpio_set_value(unsigned gpio, int value) ^ drivers/leds/blink/leds-lgm-sso.c:345:3: error: implicit declaration of function 'gpiod_set_value' [-Werror,-Wimplicit-function-declaration] gpiod_set_value(led->gpiod, 1); ^
Add the dependency in Kconfig.
Fixes: c3987cd2bca3 ("leds: lgm: Add LED controller driver for LGM SoC") Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Pavel Machek pavel@ucw.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/leds/blink/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/leds/blink/Kconfig b/drivers/leds/blink/Kconfig index 265b53476a80..6dedc58c47b3 100644 --- a/drivers/leds/blink/Kconfig +++ b/drivers/leds/blink/Kconfig @@ -9,6 +9,7 @@ if LEDS_BLINK
config LEDS_BLINK_LGM tristate "LED support for Intel LGM SoC series" + depends on GPIOLIB depends on LEDS_CLASS depends on MFD_SYSCON depends on OF
From: Jia-Ju Bai baijiaju1990@gmail.com
[ Upstream commit 45c7eaeb29d67224db4ba935deb575586a1fda09 ]
When kcalloc() returns NULL to __tcbp or of_count_phandle_with_args() returns zero or -ENOENT to count, no error return code of thermal_of_populate_bind_params() is assigned. To fix these bugs, ret is assigned with -ENOMEM and -ENOENT in these cases, respectively.
Fixes: a92bab8919e3 ("of: thermal: Allow multiple devices to share cooling map") Reported-by: TOTE Robot oslab@tsinghua.edu.cn Signed-off-by: Jia-Ju Bai baijiaju1990@gmail.com Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210310122423.3266-1-baijiaju1990@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/thermal/thermal_of.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 69ef12f852b7..5b76f9a1280d 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -704,14 +704,17 @@ static int thermal_of_populate_bind_params(struct device_node *np,
count = of_count_phandle_with_args(np, "cooling-device", "#cooling-cells"); - if (!count) { + if (count <= 0) { pr_err("Add a cooling_device property with at least one device\n"); + ret = -ENOENT; goto end; }
__tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL); - if (!__tcbp) + if (!__tcbp) { + ret = -ENOMEM; goto end; + }
for (i = 0; i < count; i++) { ret = of_parse_phandle_with_args(np, "cooling-device",
From: Qiuxu Zhuo qiuxu.zhuo@intel.com
[ Upstream commit d9b7eae8e3424c3480fe9f40ebafbb0c96426e4c ]
rcec_assoc_rciep() used "rciep->devfn" (a single byte encoding both the device and function number) as the device number to check whether the corresponding bit was set in the RCEC's Association Bitmap for RCiEPs.
But per PCIe r5.0, sec 7.9.10.2, "Association Bitmap for RCiEPs", the 32-bit bitmap contains one bit per device. That bit applies to all functions of the device.
Fix rcec_assoc_rciep() to convert the value of "rciep->devfn" to a device number to ensure that RCiEP devices are correctly associated with the RCEC.
Reported-and-tested-by: Wen Jin wen.jin@intel.com Fixes: 507b460f8144 ("PCI/ERR: Add pcie_link_rcec() to associate RCiEPs") Link: https://lore.kernel.org/r/20210222011717.43266-1-qiuxu.zhuo@intel.com Signed-off-by: Qiuxu Zhuo qiuxu.zhuo@intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Sean V Kelley sean.v.kelley@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/pcie/rcec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c index 2c5c552994e4..d0bcd141ac9c 100644 --- a/drivers/pci/pcie/rcec.c +++ b/drivers/pci/pcie/rcec.c @@ -32,7 +32,7 @@ static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep)
/* Same bus, so check bitmap */ for_each_set_bit(devn, &bitmap, 32) - if (devn == rciep->devfn) + if (devn == PCI_SLOT(rciep->devfn)) return true;
return false;
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 7dede88659df38f96128ab3922c50dde2d29c574 ]
F2FS_IOC_FLUSH_DEVICE/F2FS_IOC_RESIZE_FS needs to migrate all blocks of target segment to other place, no matter the segment has partially or fully valid blocks.
However, after commit 803e74be04b3 ("f2fs: stop GC when the victim becomes fully valid"), we may skip migration due to target segment is fully valid, result in failing the ioctl interface, fix this.
Fixes: 803e74be04b3 ("f2fs: stop GC when the victim becomes fully valid") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 9 +++++---- fs/f2fs/gc.c | 21 ++++++++++++--------- fs/f2fs/segment.c | 2 +- fs/f2fs/super.c | 2 +- 5 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e2d302ae3a46..cccdfb1a40ab 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3547,7 +3547,7 @@ void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi); int f2fs_start_gc_thread(struct f2fs_sb_info *sbi); void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi); block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode); -int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, +int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, bool force, unsigned int segno); void f2fs_build_gc_manager(struct f2fs_sb_info *sbi); int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index d26ff2ae3f5e..1863944f4073 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1658,7 +1658,7 @@ next_alloc: if (has_not_enough_free_secs(sbi, 0, GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { down_write(&sbi->gc_lock); - err = f2fs_gc(sbi, true, false, NULL_SEGNO); + err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); if (err && err != -ENODATA && err != -EAGAIN) goto out_err; } @@ -2489,7 +2489,7 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg) down_write(&sbi->gc_lock); }
- ret = f2fs_gc(sbi, sync, true, NULL_SEGNO); + ret = f2fs_gc(sbi, sync, true, false, NULL_SEGNO); out: mnt_drop_write_file(filp); return ret; @@ -2525,7 +2525,8 @@ do_more: down_write(&sbi->gc_lock); }
- ret = f2fs_gc(sbi, range->sync, true, GET_SEGNO(sbi, range->start)); + ret = f2fs_gc(sbi, range->sync, true, false, + GET_SEGNO(sbi, range->start)); if (ret) { if (ret == -EBUSY) ret = -EAGAIN; @@ -2978,7 +2979,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg) sm->last_victim[GC_CB] = end_segno + 1; sm->last_victim[GC_GREEDY] = end_segno + 1; sm->last_victim[ALLOC_NEXT] = end_segno + 1; - ret = f2fs_gc(sbi, true, true, start_segno); + ret = f2fs_gc(sbi, true, true, true, start_segno); if (ret == -EAGAIN) ret = 0; else if (ret < 0) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 39330ad3c44e..b3af76340026 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -112,7 +112,7 @@ do_gc: sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC;
/* if return value is not zero, no victim was selected */ - if (f2fs_gc(sbi, sync_mode, true, NULL_SEGNO)) + if (f2fs_gc(sbi, sync_mode, true, false, NULL_SEGNO)) wait_ms = gc_th->no_gc_sleep_time;
trace_f2fs_background_gc(sbi->sb, wait_ms, @@ -1354,7 +1354,8 @@ out: * the victim data block is ignored. */ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, - struct gc_inode_list *gc_list, unsigned int segno, int gc_type) + struct gc_inode_list *gc_list, unsigned int segno, int gc_type, + bool force_migrate) { struct super_block *sb = sbi->sb; struct f2fs_summary *entry; @@ -1383,8 +1384,8 @@ next_step: * race condition along with SSR block allocation. */ if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) || - get_valid_blocks(sbi, segno, true) == - BLKS_PER_SEC(sbi)) + (!force_migrate && get_valid_blocks(sbi, segno, true) == + BLKS_PER_SEC(sbi))) return submitted;
if (check_valid_map(sbi, segno, off) == 0) @@ -1519,7 +1520,8 @@ static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int start_segno, - struct gc_inode_list *gc_list, int gc_type) + struct gc_inode_list *gc_list, int gc_type, + bool force_migrate) { struct page *sum_page; struct f2fs_summary_block *sum; @@ -1606,7 +1608,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, gc_type); else submitted += gc_data_segment(sbi, sum->entries, gc_list, - segno, gc_type); + segno, gc_type, + force_migrate);
stat_inc_seg_count(sbi, type, gc_type); migrated++; @@ -1634,7 +1637,7 @@ skip: }
int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, - bool background, unsigned int segno) + bool background, bool force, unsigned int segno) { int gc_type = sync ? FG_GC : BG_GC; int sec_freed = 0, seg_freed = 0, total_freed = 0; @@ -1696,7 +1699,7 @@ gc_more: if (ret) goto stop;
- seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type); + seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force); if (gc_type == FG_GC && seg_freed == f2fs_usable_segs_in_sec(sbi, segno)) sec_freed++; @@ -1835,7 +1838,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi, .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), };
- do_garbage_collect(sbi, segno, &gc_list, FG_GC); + do_garbage_collect(sbi, segno, &gc_list, FG_GC, true); put_gc_inode(&gc_list);
if (!gc_only && get_valid_blocks(sbi, segno, true)) { diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index c2866561263e..dcba4ac3dd2b 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -504,7 +504,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) */ if (has_not_enough_free_secs(sbi, 0, 0)) { down_write(&sbi->gc_lock); - f2fs_gc(sbi, false, false, NULL_SEGNO); + f2fs_gc(sbi, false, false, false, NULL_SEGNO); } }
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 82592b19b4e0..1d010a3a144f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1865,7 +1865,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
while (!f2fs_time_over(sbi, DISABLE_TIME)) { down_write(&sbi->gc_lock); - err = f2fs_gc(sbi, true, false, NULL_SEGNO); + err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); if (err == -ENODATA) { err = 0; break;
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 3ab0598e6d860ef49d029943ba80f627c15c15d6 ]
f2fs_resize_fs() hangs in below callstack with testcase: - mkfs 16GB image & mount image - dd 8GB fileA - dd 8GB fileB - sync - rm fileA - sync - resize filesystem to 8GB
kernel BUG at segment.c:2484! Call Trace: allocate_segment_by_default+0x92/0xf0 [f2fs] f2fs_allocate_data_block+0x44b/0x7e0 [f2fs] do_write_page+0x5a/0x110 [f2fs] f2fs_outplace_write_data+0x55/0x100 [f2fs] f2fs_do_write_data_page+0x392/0x850 [f2fs] move_data_page+0x233/0x320 [f2fs] do_garbage_collect+0x14d9/0x1660 [f2fs] free_segment_range+0x1f7/0x310 [f2fs] f2fs_resize_fs+0x118/0x330 [f2fs] __f2fs_ioctl+0x487/0x3680 [f2fs] __x64_sys_ioctl+0x8e/0xd0 do_syscall_64+0x33/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9
The root cause is we forgot to check that whether we have enough space in resized filesystem to store all valid blocks in before-resizing filesystem, then allocator will run out-of-space during block migration in free_segment_range().
Fixes: b4b10061ef98 ("f2fs: refactor resize_fs to avoid meta updates in progress") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/gc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b3af76340026..86ba8ed0b8a7 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1977,7 +1977,20 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)
/* stop CP to protect MAIN_SEC in free_segment_range */ f2fs_lock_op(sbi); + + spin_lock(&sbi->stat_lock); + if (shrunk_blocks + valid_user_blocks(sbi) + + sbi->current_reserved_blocks + sbi->unusable_block_count + + F2FS_OPTION(sbi).root_reserved_blocks > sbi->user_block_count) + err = -ENOSPC; + spin_unlock(&sbi->stat_lock); + + if (err) + goto out_unlock; + err = free_segment_range(sbi, secs, true); + +out_unlock: f2fs_unlock_op(sbi); up_write(&sbi->gc_lock); if (err)
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 28e18ee636ba28532dbe425540af06245a0bbecb ]
The uninitialized variable dn.node_changed does not get set when a call to f2fs_get_node_page fails. This uninitialized value gets used in the call to f2fs_balance_fs() that may or not may not balances dirty node and dentry pages depending on the uninitialized state of the variable. Fix this by only calling f2fs_balance_fs if err is not set.
Thanks to Jaegeuk Kim for suggesting an appropriate fix.
Addresses-Coverity: ("Uninitialized scalar variable") Fixes: 2a3407607028 ("f2fs: call f2fs_balance_fs only when node was changed") Signed-off-by: Colin Ian King colin.king@canonical.com Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/inline.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 993caefcd2bb..92652ca7a7c8 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -219,7 +219,8 @@ out:
f2fs_put_page(page, 1);
- f2fs_balance_fs(sbi, dn.node_changed); + if (!err) + f2fs_balance_fs(sbi, dn.node_changed);
return err; }
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 936d3685e62436a378f02b8b74759b054d4aeca1 ]
The added device_property_present() call causes a build failure in some configurations because of the missing header:
drivers/rtc/rtc-tps65910.c:422:7: error: implicit declaration of function 'device_property_present' [-Werror,-Wimplicit-function-declaration]
Fixes: 454ba154a62c ("rtc: tps65910: Support wakeup-source property") Signed-off-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210225134215.2263694-1-arnd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/rtc-tps65910.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 288abb1abdb8..bc89c62ccb9b 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -18,6 +18,7 @@ #include <linux/rtc.h> #include <linux/bcd.h> #include <linux/math64.h> +#include <linux/property.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/mfd/tps65910.h>
From: Bjorn Andersson bjorn.andersson@linaro.org
[ Upstream commit 3d2ee78906af5f08d499d6aa3aa504406fa38106 ]
Analog to the issue in the common mdt_loader code the MSS ELF loader does not validate that p_filesz bytes will fit in the memory region and that the loaded segments are not truncated. Fix this in the same way as proposed for the mdt_loader.
Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Fixes: 135b9e8d1cd8 ("remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before load") Link: https://lore.kernel.org/r/20210312232002.3466791-1-bjorn.andersson@linaro.or... Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/remoteproc/qcom_q6v5_mss.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 66106ba25ba3..14e0ce5f18f5 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -1210,6 +1210,14 @@ static int q6v5_mpss_load(struct q6v5 *qproc) goto release_firmware; }
+ if (phdr->p_filesz > phdr->p_memsz) { + dev_err(qproc->dev, + "refusing to load segment %d with p_filesz > p_memsz\n", + i); + ret = -EINVAL; + goto release_firmware; + } + ptr = memremap(qproc->mpss_phys + offset, phdr->p_memsz, MEMREMAP_WC); if (!ptr) { dev_err(qproc->dev, @@ -1241,6 +1249,16 @@ static int q6v5_mpss_load(struct q6v5 *qproc) goto release_firmware; }
+ if (seg_fw->size != phdr->p_filesz) { + dev_err(qproc->dev, + "failed to load segment %d from truncated file %s\n", + i, fw_name); + ret = -EINVAL; + release_firmware(seg_fw); + memunmap(ptr); + goto release_firmware; + } + release_firmware(seg_fw); }
From: Pali Rohár pali@kernel.org
[ Upstream commit 1e83130f01b04c16579ed5a5e03d729bcffc4c5d ]
IRQ domain alloc function should return zero on success. Non-zero value indicates failure.
Link: https://lore.kernel.org/r/20210303142202.25780-1-pali@kernel.org Fixes: fc54bae28818 ("PCI: iproc: Allow allocation of multiple MSIs") Signed-off-by: Pali Rohár pali@kernel.org Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Reviewed-by: Krzysztof Wilczyński kw@linux.com Acked-by: Ray Jui ray.jui@broadcom.com Acked-by: Marc Zyngier maz@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-iproc-msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c index 908475d27e0e..eede4e8f3f75 100644 --- a/drivers/pci/controller/pcie-iproc-msi.c +++ b/drivers/pci/controller/pcie-iproc-msi.c @@ -271,7 +271,7 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, NULL, NULL); }
- return hwirq; + return 0; }
static void iproc_msi_irq_domain_free(struct irq_domain *domain,
From: Wei Yongjun weiyongjun1@huawei.com
[ Upstream commit b5d9209d50838474fc1b2901d0e11bba59906428 ]
Fix to return negative error code -ENODEV from the unsupported revision error handling case instead of 0, as done elsewhere in this function.
Link: https://lore.kernel.org/r/20210308135619.19133-1-weiyongjun1@huawei.com Fixes: 0cdfaceb9889 ("PCI: brcmstb: support BCM4908 with external PERST# signal controller") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Wei Yongjun weiyongjun1@huawei.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Reviewed-by: Krzysztof Wilczyński kw@linux.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-brcmstb.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index e330e6811f0b..69c999222cc8 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1296,6 +1296,7 @@ static int brcm_pcie_probe(struct platform_device *pdev) pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION); if (pcie->type == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) { dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n"); + ret = -ENODEV; goto fail; }
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
[ Upstream commit c99e755a4a4c165cad6effb39faffd0f3377c02d ]
In pci_scan_device(), if pci_setup_device() fails for any reason, the code will not release device's of_node by calling pci_release_of_node(). Fix that by calling the release function.
Fixes: 98d9f30c820d ("pci/of: Match PCI devices to OF nodes dynamically") Link: https://lore.kernel.org/r/20210124232826.1879-1-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/probe.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 953f15abc850..be51670572fa 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2353,6 +2353,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) pci_set_of_node(dev);
if (pci_setup_device(dev)) { + pci_release_of_node(dev); pci_bus_put(dev->bus); kfree(dev); return NULL;
From: Zhen Lei thunder.leizhen@huawei.com
[ Upstream commit a506bd5756290821a4314f502b4bafc2afcf5260 ]
The commit 1879445dfa7b ("perf/core: Set event's default ::overflow_handler()") set a default event->overflow_handler in perf_event_alloc(), and replace the check event->overflow_handler with is_default_overflow_handler(), but one is missing.
Currently, the bp->overflow_handler can not be NULL. As a result, enable_single_step() is always not invoked.
Comments from Zhen Lei:
https://patchwork.kernel.org/project/linux-arm-kernel/patch/20210207105934.2...
Fixes: 1879445dfa7b ("perf/core: Set event's default ::overflow_handler()") Signed-off-by: Zhen Lei thunder.leizhen@huawei.com Cc: Wang Nan wangnan0@huawei.com Acked-by: Will Deacon will@kernel.org Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/kernel/hw_breakpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 08660ae9dcbc..b1423fb130ea 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -886,7 +886,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) info->trigger = addr; pr_debug("breakpoint fired: address = 0x%x\n", addr); perf_bp_event(bp, regs); - if (!bp->overflow_handler) + if (is_default_overflow_handler(bp)) enable_single_step(bp, addr); goto unlock; }
From: Chao Yu yuchao0@huawei.com
[ Upstream commit e1175f02291141bbd924fc578299305fcde35855 ]
Now, fallocate() on a pinned file only allocates blocks which aligns to segment rather than section, so GC may try to migrate pinned file's block, and after several times of failure, pinned file's block could be migrated to other place, however user won't be aware of such condition, and then old obsolete block address may be readed/written incorrectly.
To avoid such condition, let's try to allocate pinned file's blocks with section alignment.
Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 19 +++++++++---------- fs/f2fs/segment.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index cccdfb1a40ab..45a83f8c9e87 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3383,7 +3383,7 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi, unsigned int *newseg, bool new_sec, int dir); void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type, unsigned int start, unsigned int end); -void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type); +void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type); void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi); int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range); bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 1863944f4073..bd5a77091d23 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1646,27 +1646,26 @@ static int expand_inode_data(struct inode *inode, loff_t offset, return 0;
if (f2fs_is_pinned_file(inode)) { - block_t len = (map.m_len >> sbi->log_blocks_per_seg) << - sbi->log_blocks_per_seg; + block_t sec_blks = BLKS_PER_SEC(sbi); + block_t sec_len = roundup(map.m_len, sec_blks); block_t done = 0;
- if (map.m_len % sbi->blocks_per_seg) - len += sbi->blocks_per_seg; - - map.m_len = sbi->blocks_per_seg; + map.m_len = sec_blks; next_alloc: if (has_not_enough_free_secs(sbi, 0, GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { down_write(&sbi->gc_lock); err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); - if (err && err != -ENODATA && err != -EAGAIN) + if (err && err != -ENODATA && err != -EAGAIN) { + map.m_len = done; goto out_err; + } }
down_write(&sbi->pin_sem);
f2fs_lock_op(sbi); - f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED); + f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED); f2fs_unlock_op(sbi);
map.m_seg_type = CURSEG_COLD_DATA_PINNED; @@ -1675,9 +1674,9 @@ next_alloc: up_write(&sbi->pin_sem);
done += map.m_len; - len -= map.m_len; + sec_len -= map.m_len; map.m_lblk += map.m_len; - if (!err && len) + if (!err && sec_len) goto next_alloc;
map.m_len = done; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index dcba4ac3dd2b..91708460f584 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2893,7 +2893,8 @@ unlock: up_read(&SM_I(sbi)->curseg_lock); }
-static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type) +static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type, + bool new_sec) { struct curseg_info *curseg = CURSEG_I(sbi, type); unsigned int old_segno; @@ -2901,10 +2902,22 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type) if (!curseg->inited) goto alloc;
- if (!curseg->next_blkoff && - !get_valid_blocks(sbi, curseg->segno, false) && - !get_ckpt_valid_blocks(sbi, curseg->segno)) - return; + if (curseg->next_blkoff || + get_valid_blocks(sbi, curseg->segno, new_sec)) + goto alloc; + + if (new_sec) { + unsigned int segno = START_SEGNO(curseg->segno); + int i; + + for (i = 0; i < sbi->segs_per_sec; i++, segno++) { + if (get_ckpt_valid_blocks(sbi, segno)) + goto alloc; + } + } else { + if (!get_ckpt_valid_blocks(sbi, curseg->segno)) + return; + }
alloc: old_segno = curseg->segno; @@ -2912,10 +2925,15 @@ alloc: locate_dirty_segment(sbi, old_segno); }
-void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type) +static void __allocate_new_section(struct f2fs_sb_info *sbi, int type) +{ + __allocate_new_segment(sbi, type, true); +} + +void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type) { down_write(&SIT_I(sbi)->sentry_lock); - __allocate_new_segment(sbi, type); + __allocate_new_section(sbi, type); up_write(&SIT_I(sbi)->sentry_lock); }
@@ -2925,7 +2943,7 @@ void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
down_write(&SIT_I(sbi)->sentry_lock); for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) - __allocate_new_segment(sbi, i); + __allocate_new_segment(sbi, i, false); up_write(&SIT_I(sbi)->sentry_lock); }
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 88f2cfc5fa90326edb569b4a81bb38ed4dcd3108 ]
In the case of expanding pinned file, map.m_lblk and map.m_len will update in each round of section allocation, so in error path, last i_size will be calculated with wrong m_lblk and m_len, fix it.
Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/file.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index bd5a77091d23..dc79694e512c 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1619,9 +1619,10 @@ static int expand_inode_data(struct inode *inode, loff_t offset, struct f2fs_map_blocks map = { .m_next_pgofs = NULL, .m_next_extent = NULL, .m_seg_type = NO_CHECK_TYPE, .m_may_create = true }; - pgoff_t pg_end; + pgoff_t pg_start, pg_end; loff_t new_size = i_size_read(inode); loff_t off_end; + block_t expanded = 0; int err;
err = inode_newsize_ok(inode, (len + offset)); @@ -1634,11 +1635,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
f2fs_balance_fs(sbi, true);
+ pg_start = ((unsigned long long)offset) >> PAGE_SHIFT; pg_end = ((unsigned long long)offset + len) >> PAGE_SHIFT; off_end = (offset + len) & (PAGE_SIZE - 1);
- map.m_lblk = ((unsigned long long)offset) >> PAGE_SHIFT; - map.m_len = pg_end - map.m_lblk; + map.m_lblk = pg_start; + map.m_len = pg_end - pg_start; if (off_end) map.m_len++;
@@ -1648,7 +1650,6 @@ static int expand_inode_data(struct inode *inode, loff_t offset, if (f2fs_is_pinned_file(inode)) { block_t sec_blks = BLKS_PER_SEC(sbi); block_t sec_len = roundup(map.m_len, sec_blks); - block_t done = 0;
map.m_len = sec_blks; next_alloc: @@ -1656,10 +1657,8 @@ next_alloc: GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) { down_write(&sbi->gc_lock); err = f2fs_gc(sbi, true, false, false, NULL_SEGNO); - if (err && err != -ENODATA && err != -EAGAIN) { - map.m_len = done; + if (err && err != -ENODATA && err != -EAGAIN) goto out_err; - } }
down_write(&sbi->pin_sem); @@ -1673,24 +1672,25 @@ next_alloc:
up_write(&sbi->pin_sem);
- done += map.m_len; + expanded += map.m_len; sec_len -= map.m_len; map.m_lblk += map.m_len; if (!err && sec_len) goto next_alloc;
- map.m_len = done; + map.m_len = expanded; } else { err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO); + expanded = map.m_len; } out_err: if (err) { pgoff_t last_off;
- if (!map.m_len) + if (!expanded) return err;
- last_off = map.m_lblk + map.m_len - 1; + last_off = pg_start + expanded - 1;
/* update new size to the failed position */ new_size = (last_off == pg_end) ? offset + len :
From: Shradha Todi shradha.t@samsung.com
[ Upstream commit 6613bc2301ba291a1c5a90e1dc24cf3edf223c03 ]
get_features ops of pci_epc_ops may return NULL, causing NULL pointer dereference in pci_epf_test_alloc_space function. Let us add a check for pci_epc_feature pointer in pci_epf_test_bind before we access it to avoid any such NULL pointer dereference and return -ENOTSUPP in case pci_epc_feature is not found.
When the patch is not applied and EPC features is not implemented in the platform driver, we see the following dump due to kernel NULL pointer dereference.
Call trace: pci_epf_test_bind+0xf4/0x388 pci_epf_bind+0x3c/0x80 pci_epc_epf_link+0xa8/0xcc configfs_symlink+0x1a4/0x48c vfs_symlink+0x104/0x184 do_symlinkat+0x80/0xd4 __arm64_sys_symlinkat+0x1c/0x24 el0_svc_common.constprop.3+0xb8/0x170 el0_svc_handler+0x70/0x88 el0_svc+0x8/0x640 Code: d2800581 b9403ab9 f9404ebb 8b394f60 (f9400400) ---[ end trace a438e3c5a24f9df0 ]---
Link: https://lore.kernel.org/r/20210324101609.79278-1-shradha.t@samsung.com Fixes: 2c04c5b8eef79 ("PCI: pci-epf-test: Use pci_epc_get_features() to get EPC features") Signed-off-by: Sriram Dash dash.sriram@gmail.com Signed-off-by: Shradha Todi shradha.t@samsung.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Reviewed-by: Pankaj Dubey pankaj.dubey@samsung.com Reviewed-by: Kishon Vijay Abraham I kishon@ti.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/endpoint/functions/pci-epf-test.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index c0ac4e9cbe72..bc35b3566be6 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -833,15 +833,18 @@ static int pci_epf_test_bind(struct pci_epf *epf) return -EINVAL;
epc_features = pci_epc_get_features(epc, epf->func_no); - if (epc_features) { - linkup_notifier = epc_features->linkup_notifier; - core_init_notifier = epc_features->core_init_notifier; - test_reg_bar = pci_epc_get_first_free_bar(epc_features); - if (test_reg_bar < 0) - return -EINVAL; - pci_epf_configure_bar(epf, epc_features); + if (!epc_features) { + dev_err(&epf->dev, "epc_features not implemented\n"); + return -EOPNOTSUPP; }
+ linkup_notifier = epc_features->linkup_notifier; + core_init_notifier = epc_features->core_init_notifier; + test_reg_bar = pci_epc_get_first_free_bar(epc_features); + if (test_reg_bar < 0) + return -EINVAL; + pci_epf_configure_bar(epf, epc_features); + epf_test->test_reg_bar = test_reg_bar; epf_test->epc_features = epc_features;
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 61461fc921b756ae16e64243f72af2bfc2e620db ]
In CP disabling mode, there are two issues when using LFS or SSR | AT_SSR mode to select victim:
1. LFS is set to find source section during GC, the victim should have no checkpointed data, since after GC, section could not be set free for reuse.
Previously, we only check valid chpt blocks in current segment rather than section, fix it.
2. SSR | AT_SSR are set to find target segment for writes which can be fully filled by checkpointed and newly written blocks, we should never select such segment, otherwise it can cause panic or data corruption during allocation, potential case is described as below:
a) target segment has 'n' (n < 512) ckpt valid blocks b) GC migrates 'n' valid blocks to other segment (segment is still in dirty list) c) GC migrates '512 - n' blocks to target segment (segment has 'n' cp_vblocks and '512 - n' vblocks) d) If GC selects target segment via {AT,}SSR allocator, however there is no free space in targe segment.
Fixes: 4354994f097d ("f2fs: checkpoint disabling") Fixes: 093749e296e2 ("f2fs: support age threshold based garbage collection") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/f2fs.h | 1 + fs/f2fs/gc.c | 28 ++++++++++++++++++++-------- fs/f2fs/segment.c | 36 +++++++++++++++++++++--------------- fs/f2fs/segment.h | 14 +++++++++++++- 4 files changed, 55 insertions(+), 24 deletions(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 45a83f8c9e87..eaf6f62206de 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3376,6 +3376,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi); int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable); void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi); int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); +bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno); void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi); void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi); void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 86ba8ed0b8a7..a8567cb47621 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, if (p->gc_mode == GC_AT && get_valid_blocks(sbi, segno, true) == 0) return; - - if (p->alloc_mode == AT_SSR && - get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0) - return; }
for (i = 0; i < sbi->segs_per_sec; i++) @@ -728,11 +724,27 @@ retry:
if (sec_usage_check(sbi, secno)) goto next; + /* Don't touch checkpointed data */ - if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && - get_ckpt_valid_blocks(sbi, segno) && - p.alloc_mode == LFS)) - goto next; + if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { + if (p.alloc_mode == LFS) { + /* + * LFS is set to find source section during GC. + * The victim should have no checkpointed data. + */ + if (get_ckpt_valid_blocks(sbi, segno, true)) + goto next; + } else { + /* + * SSR | AT_SSR are set to find target segment + * for writes which can be full by checkpointed + * and newly written blocks. + */ + if (!f2fs_segment_has_free_slot(sbi, segno)) + goto next; + } + } + if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) goto next;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 91708460f584..0fbb0e07ca53 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -861,7 +861,7 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) mutex_lock(&dirty_i->seglist_lock);
valid_blocks = get_valid_blocks(sbi, segno, false); - ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno); + ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno, false);
if (valid_blocks == 0 && (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) || ckpt_valid_blocks == usable_blocks)) { @@ -946,7 +946,7 @@ static unsigned int get_free_segment(struct f2fs_sb_info *sbi) for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) { if (get_valid_blocks(sbi, segno, false)) continue; - if (get_ckpt_valid_blocks(sbi, segno)) + if (get_ckpt_valid_blocks(sbi, segno, false)) continue; mutex_unlock(&dirty_i->seglist_lock); return segno; @@ -2636,6 +2636,23 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, seg->next_blkoff++; }
+bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno) +{ + struct seg_entry *se = get_seg_entry(sbi, segno); + int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); + unsigned long *target_map = SIT_I(sbi)->tmp_map; + unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; + unsigned long *cur_map = (unsigned long *)se->cur_valid_map; + int i, pos; + + for (i = 0; i < entries; i++) + target_map[i] = ckpt_map[i] | cur_map[i]; + + pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0); + + return pos < sbi->blocks_per_seg; +} + /* * This function always allocates a used segment(from dirty seglist) by SSR * manner, so it should recover the existing segment information of valid blocks @@ -2906,19 +2923,8 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type, get_valid_blocks(sbi, curseg->segno, new_sec)) goto alloc;
- if (new_sec) { - unsigned int segno = START_SEGNO(curseg->segno); - int i; - - for (i = 0; i < sbi->segs_per_sec; i++, segno++) { - if (get_ckpt_valid_blocks(sbi, segno)) - goto alloc; - } - } else { - if (!get_ckpt_valid_blocks(sbi, curseg->segno)) - return; - } - + if (!get_ckpt_valid_blocks(sbi, curseg->segno, new_sec)) + return; alloc: old_segno = curseg->segno; SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index e9a7a637d688..afb175739de5 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -361,8 +361,20 @@ static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, }
static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi, - unsigned int segno) + unsigned int segno, bool use_section) { + if (use_section && __is_large_section(sbi)) { + unsigned int start_segno = START_SEGNO(segno); + unsigned int blocks = 0; + int i; + + for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) { + struct seg_entry *se = get_seg_entry(sbi, start_segno); + + blocks += se->ckpt_valid_blocks; + } + return blocks; + } return get_seg_entry(sbi, segno)->ckpt_valid_blocks; }
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 823d13e12b6cbaef2f6e5d63c648643e7bc094dd ]
In order to avoid race with f2fs_do_replace_block().
Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/segment.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 0fbb0e07ca53..4fba82294a73 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2938,19 +2938,23 @@ static void __allocate_new_section(struct f2fs_sb_info *sbi, int type)
void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type) { + down_read(&SM_I(sbi)->curseg_lock); down_write(&SIT_I(sbi)->sentry_lock); __allocate_new_section(sbi, type); up_write(&SIT_I(sbi)->sentry_lock); + up_read(&SM_I(sbi)->curseg_lock); }
void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi) { int i;
+ down_read(&SM_I(sbi)->curseg_lock); down_write(&SIT_I(sbi)->sentry_lock); for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) __allocate_new_segment(sbi, i, false); up_write(&SIT_I(sbi)->sentry_lock); + up_read(&SM_I(sbi)->curseg_lock); }
static const struct segment_allocation default_salloc_ops = {
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit f8b139e2f24112f4e21f1eb02c7fc7600fea4b8d ]
IS_ERR() and PTR_ERR() use wrong pointer, it should be writeback_fid, fix it.
Link: http://lkml.kernel.org/r/20210330130632.1054357-1-yangyingliang@huawei.com Fixes: 5bfe97d7382b ("9p: Fix writeback fid incorrectly being attached to dentry") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com [Dominique: adjusted commit summary] Signed-off-by: Dominique Martinet asmadeus@codewreck.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/9p/vfs_file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 649f04f112dc..59c32c9b799f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -86,8 +86,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) * to work. */ writeback_fid = v9fs_writeback_fid(file_dentry(file)); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); + if (IS_ERR(writeback_fid)) { + err = PTR_ERR(writeback_fid); mutex_unlock(&v9inode->v_mutex); goto out_error; }
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 23738e74472f9c5f3a05a68724a2ccfba97d283d ]
When we mount an unclean f2fs image in a readonly block device, let's make mount() succeed only when there is no recoverable data in that image, otherwise after mount(), file fsyned won't be recovered as user expected.
Fixes: 938a184265d7 ("f2fs: give a warning only for readonly partition") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/super.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1d010a3a144f..d852d96773a3 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3929,10 +3929,18 @@ try_onemore: * previous checkpoint was not done by clean system shutdown. */ if (f2fs_hw_is_readonly(sbi)) { - if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) - f2fs_err(sbi, "Need to recover fsync data, but write access unavailable"); - else - f2fs_info(sbi, "write access unavailable, skipping recovery"); + if (!is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) { + err = f2fs_recover_fsync_data(sbi, true); + if (err > 0) { + err = -EROFS; + f2fs_err(sbi, "Need to recover fsync data, but " + "write access unavailable, please try " + "mount w/ disable_roll_forward or norecovery"); + } + if (err < 0) + goto free_meta; + } + f2fs_info(sbi, "write access unavailable, skipping recovery"); goto reset_checkpoint; }
From: Yi Zhuang zhuangyi1@huawei.com
[ Upstream commit be1ee45d51384161681ecf21085a42d316ae25f7 ]
In the cache writing process, if it is an atomic file, increase the page count of F2FS_WB_CP_DATA, otherwise increase the page count of F2FS_WB_DATA.
When you step into the hook branch due to insufficient memory in f2fs_write_begin, f2fs_drop_inmem_pages_all will be called to traverse all atomic inodes and clear the FI_ATOMIC_FILE mark of all atomic files.
In f2fs_drop_inmem_pages,first acquire the inmem_lock , revoke all the inmem_pages, and then clear the FI_ATOMIC_FILE mark. Before this mark is cleared, other threads may hold inmem_lock to add inmem_pages to the inode that has just been emptied inmem_pages, and increase the page count of F2FS_WB_CP_DATA.
When the IO returns, it is found that the FI_ATOMIC_FILE flag is cleared by f2fs_drop_inmem_pages_all, and f2fs_is_atomic_file returns false,which causes the page count of F2FS_WB_DATA to be decremented. The page count of F2FS_WB_CP_DATA cannot be cleared. Finally, hungtask is triggered in f2fs_wait_on_all_pages because get_pages will never return zero.
process A: process B: f2fs_drop_inmem_pages_all ->f2fs_drop_inmem_pages of inode#1 ->mutex_lock(&fi->inmem_lock) ->__revoke_inmem_pages of inode#1 f2fs_ioc_commit_atomic_write ->mutex_unlock(&fi->inmem_lock) ->f2fs_commit_inmem_pages of inode#1 ->mutex_lock(&fi->inmem_lock) ->__f2fs_commit_inmem_pages ->f2fs_do_write_data_page ->f2fs_outplace_write_data ->do_write_page ->f2fs_submit_page_write ->inc_page_count(sbi, F2FS_WB_CP_DATA ) ->mutex_unlock(&fi->inmem_lock) ->spin_lock(&sbi->inode_lock[ATOMIC_FILE]); ->clear_inode_flag(inode, FI_ATOMIC_FILE) ->spin_unlock(&sbi->inode_lock[ATOMIC_FILE]) f2fs_write_end_io ->dec_page_count(sbi, F2FS_WB_DATA );
We can fix the problem by putting the action of clearing the FI_ATOMIC_FILE mark into the inmem_lock lock. This operation can ensure that no one will submit the inmem pages before the FI_ATOMIC_FILE mark is cleared, so that there will be no atomic writes waiting for writeback.
Fixes: 57864ae5ce3a ("f2fs: limit # of inmemory pages") Signed-off-by: Yi Zhuang zhuangyi1@huawei.com Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/segment.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 4fba82294a73..d83cb1359e53 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -324,23 +324,27 @@ void f2fs_drop_inmem_pages(struct inode *inode) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode);
- while (!list_empty(&fi->inmem_pages)) { + do { mutex_lock(&fi->inmem_lock); + if (list_empty(&fi->inmem_pages)) { + fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0; + + spin_lock(&sbi->inode_lock[ATOMIC_FILE]); + if (!list_empty(&fi->inmem_ilist)) + list_del_init(&fi->inmem_ilist); + if (f2fs_is_atomic_file(inode)) { + clear_inode_flag(inode, FI_ATOMIC_FILE); + sbi->atomic_files--; + } + spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); + + mutex_unlock(&fi->inmem_lock); + break; + } __revoke_inmem_pages(inode, &fi->inmem_pages, true, false, true); mutex_unlock(&fi->inmem_lock); - } - - fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0; - - spin_lock(&sbi->inode_lock[ATOMIC_FILE]); - if (!list_empty(&fi->inmem_ilist)) - list_del_init(&fi->inmem_ilist); - if (f2fs_is_atomic_file(inode)) { - clear_inode_flag(inode, FI_ATOMIC_FILE); - sbi->atomic_files--; - } - spin_unlock(&sbi->inode_lock[ATOMIC_FILE]); + } while (1); }
void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
From: Nagendra S Tomar natomar@microsoft.com
[ Upstream commit ee3707ae2c1f1327ad5188836b7ab62ed2c93b28 ]
If the loop in nfs_readdir_xdr_to_array() runs more than once, subsequent READDIR RPCs may wrongly carry a zero cookie verifier and non-zero cookie. Make sure subsequent calls to READDIR carry the cookie verifier returned by the first call.
Signed-off-by: Nagendra S Tomar natomar@microsoft.com Fixes: b593c09f83a2 ("NFS: Improve handling of directory verifiers") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/dir.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index fc4f490f2d78..08a1e2e31d0b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -866,6 +866,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc, break; }
+ verf_arg = verf_res; + status = nfs_readdir_page_filler(desc, entry, pages, pglen, arrays, narrays); } while (!status && nfs_readdir_page_needs_filling(page));
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 13884ff2bef01df37c450c6dd09122f92333dccc ]
If we're doing uncached readdir(), then the readdir cookie could be different from the one cached in the nfs_inode. We should therefore ensure that we save that one in the struct nfs_open_dir_context.
Fixes: 35df59d3ef69 ("NFS: Reduce number of RPC calls when doing uncached readdir") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/dir.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 08a1e2e31d0b..2cf2a7d92faf 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -976,10 +976,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) /* * Once we've found the start of the dirent within a page: fill 'er up... */ -static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) +static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, + const __be32 *verf) { struct file *file = desc->file; - struct nfs_inode *nfsi = NFS_I(file_inode(file)); struct nfs_cache_array *array; unsigned int i = 0;
@@ -993,7 +993,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) desc->eof = true; break; } - memcpy(desc->verf, nfsi->cookieverf, sizeof(desc->verf)); + memcpy(desc->verf, verf, sizeof(desc->verf)); if (i < (array->size-1)) desc->dir_cookie = array->array[i+1].cookie; else @@ -1050,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) { desc->page = arrays[i]; - nfs_do_filldir(desc); + nfs_do_filldir(desc, verf); } desc->page = NULL;
@@ -1071,6 +1071,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) { struct dentry *dentry = file_dentry(file); struct inode *inode = d_inode(dentry); + struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_dir_context *dir_ctx = file->private_data; struct nfs_readdir_descriptor *desc; int res; @@ -1124,7 +1125,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) break; } if (res == -ETOOSMALL && desc->plus) { - clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); + clear_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags); nfs_zap_caches(inode); desc->page_index = 0; desc->plus = false; @@ -1134,7 +1135,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) if (res < 0) break;
- nfs_do_filldir(desc); + nfs_do_filldir(desc, nfsi->cookieverf); nfs_readdir_page_unlock_and_put_cached(desc); } while (!desc->eof);
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit f892c41c14e0fa3d78ce37de1d5c8161ed13bf08 ]
The cached NFSv3/v4 readdir cookies are associated with a verifier, which is checked by the server on subsequent calls to readdir, and is only expected to change when the cookies (and hence also the page cache contents) are considered invalid. We therefore do have to store the verifier, but only when the page cache is empty.
Fixes: b593c09f83a2 ("NFS: Improve handling of directory verifiers") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/dir.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2cf2a7d92faf..0cd7c59a6601 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -929,7 +929,12 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc) } return res; } - memcpy(nfsi->cookieverf, verf, sizeof(nfsi->cookieverf)); + /* + * Set the cookie verifier if the page cache was empty + */ + if (desc->page_index == 0) + memcpy(nfsi->cookieverf, verf, + sizeof(nfsi->cookieverf)); } res = nfs_readdir_search_array(desc); if (res == 0) {
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 25ae837e61dee712b4b1df36602ebfe724b2a0b6 ]
Callers may pass fio parameter with NULL value to f2fs_allocate_data_block(), so we should make sure accessing fio's field after fio's validation check.
Fixes: f608c38c59c6 ("f2fs: clean up parameter of f2fs_allocate_data_block()") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/segment.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d83cb1359e53..77456d228f2a 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3397,12 +3397,12 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, f2fs_inode_chksum_set(sbi, page); }
- if (F2FS_IO_ALIGNED(sbi)) - fio->retry = false; - if (fio) { struct f2fs_bio_info *io;
+ if (F2FS_IO_ALIGNED(sbi)) + fio->retry = false; + INIT_LIST_HEAD(&fio->list); fio->in_list = true; io = sbi->write_io[fio->type] + fio->temp;
From: Jia-Ju Bai baijiaju1990@gmail.com
[ Upstream commit 26594c6bbb60c6bc87e3762a86ceece57d164c66 ]
When idr_find() returns NULL to intent, no error return code of qcom_glink_rx_data() is assigned. To fix this bug, ret is assigned with -ENOENT in this case.
Fixes: 64f95f87920d ("rpmsg: glink: Use the local intents when receiving data") Reported-by: TOTE Robot oslab@tsinghua.edu.cn Signed-off-by: Jia-Ju Bai baijiaju1990@gmail.com Link: https://lore.kernel.org/r/20210306133624.17237-1-baijiaju1990@gmail.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 27a05167c18c..4840886532ff 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -857,6 +857,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) dev_err(glink->dev, "no intent found for channel %s intent %d", channel->name, liid); + ret = -ENOENT; goto advance_rx; } }
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 332d1a0373be32a3a3c152756bca45ff4f4e11b5 ]
As currently set, the calls to nfs4_bitmask_adjust() will end up overwriting the contents of the nfs_server cache_consistency_bitmask field. The intention here should be to modify a private copy of that mask in the close/delegreturn/write arguments.
Fixes: 76bd5c016ef4 ("NFSv4: make cache consistency bitmask dynamic") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs4proc.c | 56 +++++++++++++++++++++++++---------------- include/linux/nfs_xdr.h | 11 +++++--- 2 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c65c4b41e2c1..820abae88cf0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -108,9 +108,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *, const struct cred *, bool); #endif -static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, - struct nfs_server *server, - struct nfs4_label *label); +static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], + const __u32 *src, struct inode *inode, + struct nfs_server *server, + struct nfs4_label *label);
#ifdef CONFIG_NFS_V4_SECURITY_LABEL static inline struct nfs4_label * @@ -3591,6 +3592,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) struct nfs4_closedata *calldata = data; struct nfs4_state *state = calldata->state; struct inode *inode = calldata->inode; + struct nfs_server *server = NFS_SERVER(inode); struct pnfs_layout_hdr *lo; bool is_rdonly, is_wronly, is_rdwr; int call_close = 0; @@ -3647,8 +3649,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) { /* Close-to-open cache consistency revalidation */ if (!nfs4_have_delegation(inode, FMODE_READ)) { - calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; - nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL); + nfs4_bitmask_set(calldata->arg.bitmask_store, + server->cache_consistency_bitmask, + inode, server, NULL); + calldata->arg.bitmask = calldata->arg.bitmask_store; } else calldata->arg.bitmask = NULL; } @@ -5416,19 +5420,17 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr) return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; }
-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, - struct nfs_server *server, - struct nfs4_label *label) +static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src, + struct inode *inode, struct nfs_server *server, + struct nfs4_label *label) { - unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); + unsigned int i;
- if ((cache_validity & NFS_INO_INVALID_DATA) || - (cache_validity & NFS_INO_REVAL_PAGECACHE) || - (cache_validity & NFS_INO_REVAL_FORCED) || - (cache_validity & NFS_INO_INVALID_OTHER)) - nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode); + memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ);
+ if (cache_validity & (NFS_INO_INVALID_CHANGE | NFS_INO_REVAL_PAGECACHE)) + bitmask[0] |= FATTR4_WORD0_CHANGE; if (cache_validity & NFS_INO_INVALID_ATIME) bitmask[1] |= FATTR4_WORD1_TIME_ACCESS; if (cache_validity & NFS_INO_INVALID_OTHER) @@ -5437,16 +5439,22 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode, FATTR4_WORD1_NUMLINKS; if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL) bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL; - if (cache_validity & NFS_INO_INVALID_CHANGE) - bitmask[0] |= FATTR4_WORD0_CHANGE; if (cache_validity & NFS_INO_INVALID_CTIME) bitmask[1] |= FATTR4_WORD1_TIME_METADATA; if (cache_validity & NFS_INO_INVALID_MTIME) bitmask[1] |= FATTR4_WORD1_TIME_MODIFY; - if (cache_validity & NFS_INO_INVALID_SIZE) - bitmask[0] |= FATTR4_WORD0_SIZE; if (cache_validity & NFS_INO_INVALID_BLOCKS) bitmask[1] |= FATTR4_WORD1_SPACE_USED; + + if (nfs4_have_delegation(inode, FMODE_READ) && + !(cache_validity & NFS_INO_REVAL_FORCED)) + bitmask[0] &= ~FATTR4_WORD0_SIZE; + else if (cache_validity & + (NFS_INO_INVALID_SIZE | NFS_INO_REVAL_PAGECACHE)) + bitmask[0] |= FATTR4_WORD0_SIZE; + + for (i = 0; i < NFS4_BITMASK_SZ; i++) + bitmask[i] &= server->attr_bitmask[i]; }
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, @@ -5459,8 +5467,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr, hdr->args.bitmask = NULL; hdr->res.fattr = NULL; } else { - hdr->args.bitmask = server->cache_consistency_bitmask; - nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL); + nfs4_bitmask_set(hdr->args.bitmask_store, + server->cache_consistency_bitmask, + hdr->inode, server, NULL); + hdr->args.bitmask = hdr->args.bitmask_store; }
if (!hdr->pgio_done_cb) @@ -6502,8 +6512,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
data->args.fhandle = &data->fh; data->args.stateid = &data->stateid; - data->args.bitmask = server->cache_consistency_bitmask; - nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL); + nfs4_bitmask_set(data->args.bitmask_store, + server->cache_consistency_bitmask, inode, server, + NULL); + data->args.bitmask = data->args.bitmask_store; nfs_copy_fh(&data->fh, NFS_FH(inode)); nfs4_stateid_copy(&data->stateid, stateid); data->res.fattr = &data->fattr; diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 3327239fa2f9..cc29dee508f7 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -15,6 +15,8 @@ #define NFS_DEF_FILE_IO_SIZE (4096U) #define NFS_MIN_FILE_IO_SIZE (1024U)
+#define NFS_BITMASK_SZ 3 + struct nfs4_string { unsigned int len; char *data; @@ -525,7 +527,8 @@ struct nfs_closeargs { struct nfs_seqid * seqid; fmode_t fmode; u32 share_access; - u32 * bitmask; + const u32 * bitmask; + u32 bitmask_store[NFS_BITMASK_SZ]; struct nfs4_layoutreturn_args *lr_args; };
@@ -608,7 +611,8 @@ struct nfs4_delegreturnargs { struct nfs4_sequence_args seq_args; const struct nfs_fh *fhandle; const nfs4_stateid *stateid; - u32 * bitmask; + const u32 *bitmask; + u32 bitmask_store[NFS_BITMASK_SZ]; struct nfs4_layoutreturn_args *lr_args; };
@@ -648,7 +652,8 @@ struct nfs_pgio_args { union { unsigned int replen; /* used by read */ struct { - u32 * bitmask; /* used by write */ + const u32 * bitmask; /* used by write */ + u32 bitmask_store[NFS_BITMASK_SZ]; /* used by write */ enum nfs3_stable_how stable; /* used by write */ }; };
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit e99812e1382f0bfb6149393262bc70645c9f537a ]
We can't use nfs4_fattr_bitmap as a bitmask, because it hasn't been filtered to represent the attributes supported by the server. Instead, let's revert to using server->cache_consistency_bitmask after adding in the missing SPACE_USED attribute.
Fixes: 913eca1aea87 ("NFS: Fallocate should use the nfs4_fattr_bitmap") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs42proc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 094024b0aca1..597005bc8a05 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -46,11 +46,12 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, { struct inode *inode = file_inode(filep); struct nfs_server *server = NFS_SERVER(inode); + u32 bitmask[3]; struct nfs42_falloc_args args = { .falloc_fh = NFS_FH(inode), .falloc_offset = offset, .falloc_length = len, - .falloc_bitmask = nfs4_fattr_bitmap, + .falloc_bitmask = bitmask, }; struct nfs42_falloc_res res = { .falloc_server = server, @@ -68,6 +69,10 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, return status; }
+ memcpy(bitmask, server->cache_consistency_bitmask, sizeof(bitmask)); + if (server->attr_bitmask[1] & FATTR4_WORD1_SPACE_USED) + bitmask[1] |= FATTR4_WORD1_SPACE_USED; + res.falloc_fattr = nfs_alloc_fattr(); if (!res.falloc_fattr) return -ENOMEM; @@ -75,7 +80,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, status = nfs4_call_sync(server->client, server, msg, &args.seq_args, &res.seq_res, 0); if (status == 0) - status = nfs_post_op_update_inode(inode, res.falloc_fattr); + status = nfs_post_op_update_inode_force_wcc(inode, + res.falloc_fattr);
kfree(res.falloc_fattr); return status;
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 99f23783224355e7022ceea9b8d9f62c0fd01bd8 ]
Whether we're allocating or delallocating space, we should flush out the pending writes in order to avoid races with attribute updates.
Fixes: 1e564d3dbd68 ("NFSv4.2: Fix a race in nfs42_proc_deallocate()") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs42proc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 597005bc8a05..704a5246ccb5 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -90,7 +90,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, loff_t offset, loff_t len) { - struct nfs_server *server = NFS_SERVER(file_inode(filep)); + struct inode *inode = file_inode(filep); + struct nfs_server *server = NFS_SERVER(inode); struct nfs4_exception exception = { }; struct nfs_lock_context *lock; int err; @@ -99,9 +100,13 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, if (IS_ERR(lock)) return PTR_ERR(lock);
- exception.inode = file_inode(filep); + exception.inode = inode; exception.state = lock->open_context->state;
+ err = nfs_sync_inode(inode); + if (err) + goto out; + do { err = _nfs42_proc_fallocate(msg, filep, lock, offset, len); if (err == -ENOTSUPP) { @@ -110,7 +115,7 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, } err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); - +out: nfs_put_lock_context(lock); return err; } @@ -148,16 +153,13 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len) return -EOPNOTSUPP;
inode_lock(inode); - err = nfs_sync_inode(inode); - if (err) - goto out_unlock;
err = nfs42_proc_fallocate(&msg, filep, offset, len); if (err == 0) truncate_pagecache_range(inode, offset, (offset + len) -1); if (err == -EOPNOTSUPP) NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; -out_unlock: + inode_unlock(inode); return err; }
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 9fdbfad1777cb4638f489eeb62d85432010c0031 ]
We need to use unsigned long subtraction and then convert to signed in order to deal correcly with C overflow rules.
Fixes: f5062003465c ("NFS: Set an attribute barrier on all updates") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index a7fb076a5f44..7cfeee3eeef7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1662,10 +1662,10 @@ EXPORT_SYMBOL_GPL(_nfs_display_fhandle); */ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr) { - const struct nfs_inode *nfsi = NFS_I(inode); + unsigned long attr_gencount = NFS_I(inode)->attr_gencount;
- return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || - ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); + return (long)(fattr->gencount - attr_gencount) > 0 || + (long)(attr_gencount - nfs_read_attr_generation_counter()) > 0; }
static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) @@ -2094,7 +2094,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) nfsi->attrtimeo_timestamp = now; } /* Set the barrier to be more recent than this fattr */ - if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) + if ((long)(fattr->gencount - nfsi->attr_gencount) > 0) nfsi->attr_gencount = fattr->gencount; }
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit acaef7981a218813e3617edb9c01837808de063c ]
Add the missing destroy_workqueue() before return from pci_epf_test_init() in the error handling case and add destroy_workqueue() in pci_epf_test_exit().
Link: https://lore.kernel.org/r/20210331084012.2091010-1-yangyingliang@huawei.com Fixes: 349e7a85b25fa ("PCI: endpoint: functions: Add an EP function to test PCI") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/endpoint/functions/pci-epf-test.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index bc35b3566be6..f9760e73d568 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -925,6 +925,7 @@ static int __init pci_epf_test_init(void)
ret = pci_epf_register_driver(&test_driver); if (ret) { + destroy_workqueue(kpcitest_workqueue); pr_err("Failed to register pci epf test driver --> %d\n", ret); return ret; } @@ -935,6 +936,8 @@ module_init(pci_epf_test_init);
static void __exit pci_epf_test_exit(void) { + if (kpcitest_workqueue) + destroy_workqueue(kpcitest_workqueue); pci_epf_unregister_driver(&test_driver); } module_exit(pci_epf_test_exit);
From: Suman Anna s-anna@ti.com
[ Upstream commit 6d1f2803cb6b414c2e45fa64d1fdad6b581e1e88 ]
The PRU firmware interrupt mapping logic in pru_handle_intrmap() uses of_irq_find_parent() with PRU device node to get a handle to the PRUSS Interrupt Controller at present. This logic however requires that the PRU nodes always define a interrupt-parent property. This property is neither a required/defined property as per the PRU remoteproc binding, nor is relevant from a DT node point of view without any associated interrupts. The current logic finds a wrong interrupt controller and fails to perform proper mapping without any interrupt-parent property in the PRU nodes.
Fix this logic to always find and use the sibling interrupt controller. Also, while at this, fix the acquired interrupt controller device node reference properly.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") Signed-off-by: Suman Anna s-anna@ti.com Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Link: https://lore.kernel.org/r/20210407155641.5501-2-s-anna@ti.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/remoteproc/pru_rproc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index dcb380e868df..9226b8f3fe14 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -284,7 +284,7 @@ static int pru_handle_intrmap(struct rproc *rproc) struct pru_rproc *pru = rproc->priv; struct pru_irq_rsc *rsc = pru->pru_interrupt_map; struct irq_fwspec fwspec; - struct device_node *irq_parent; + struct device_node *parent, *irq_parent; int i, ret = 0;
/* not having pru_interrupt_map is not an error */ @@ -312,9 +312,16 @@ static int pru_handle_intrmap(struct rproc *rproc)
/* * parse and fill in system event to interrupt channel and - * channel-to-host mapping + * channel-to-host mapping. The interrupt controller to be used + * for these mappings for a given PRU remoteproc is always its + * corresponding sibling PRUSS INTC node. */ - irq_parent = of_irq_find_parent(pru->dev->of_node); + parent = of_get_parent(dev_of_node(pru->dev)); + if (!parent) + return -ENODEV; + + irq_parent = of_get_child_by_name(parent, "interrupt-controller"); + of_node_put(parent); if (!irq_parent) { kfree(pru->mapped_irq); return -ENODEV; @@ -337,11 +344,13 @@ static int pru_handle_intrmap(struct rproc *rproc) goto map_fail; } } + of_node_put(irq_parent);
return ret;
map_fail: pru_dispose_irq_mapping(pru); + of_node_put(irq_parent);
return ret; }
From: Suman Anna s-anna@ti.com
[ Upstream commit 1fe72bcfac087dba5ab52778e0646ed9e145cd32 ]
The irq_create_fwspec_mapping() returns a proper virq value on success and 0 upon any failure. The pru_handle_intrmap() treats this as an error and disposes all firmware event mappings correctly, but is returning this incorrect value as is, letting the pru_rproc_start() interpret it as a success and boot the PRU.
Fix this by returning an error value back upon any such failure. While at this, revise the error trace to print some meaningful info about the failed event.
Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") Signed-off-by: Suman Anna s-anna@ti.com Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Link: https://lore.kernel.org/r/20210407155641.5501-3-s-anna@ti.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/remoteproc/pru_rproc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 9226b8f3fe14..dcd5ea0d1f37 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -339,8 +339,10 @@ static int pru_handle_intrmap(struct rproc *rproc)
pru->mapped_irq[i] = irq_create_fwspec_mapping(&fwspec); if (!pru->mapped_irq[i]) { - dev_err(dev, "failed to get virq\n"); - ret = pru->mapped_irq[i]; + dev_err(dev, "failed to get virq for fw mapping %d: event %d chnl %d host %d\n", + i, fwspec.param[0], fwspec.param[1], + fwspec.param[2]); + ret = -EINVAL; goto map_fail; } }
From: Suman Anna s-anna@ti.com
[ Upstream commit 880a66e026fbe6a17cd59fe0ee942bbad62a6c26 ]
The PRU firmware interrupt mappings are configured and unconfigured in .start() and .stop() callbacks respectively using the variables 'evt_count' and a 'mapped_irq' pointer. These variables are modified only during these callbacks but are not re-initialized/reset properly during unwind or failure paths. These stale values caused a kernel crash while stopping a PRU remoteproc running a different firmware with no events on a subsequent run after a previous run that was running a firmware with events.
Fix this crash by ensuring that the evt_count is 0 and the mapped_irq pointer is set to NULL in pru_dispose_irq_mapping(). Also, reset these variables properly during any failures in the .start() callback. While at this, the pru_dispose_irq_mapping() callsites are all made to look the same, moving any conditional logic to inside the function.
Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Fixes: c75c9fdac66e ("remoteproc: pru: Add support for PRU specific interrupt configuration") Reported-by: Vignesh Raghavendra vigneshr@ti.com Signed-off-by: Suman Anna s-anna@ti.com Link: https://lore.kernel.org/r/20210407155641.5501-4-s-anna@ti.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/remoteproc/pru_rproc.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index dcd5ea0d1f37..549ed3fed625 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -266,12 +266,17 @@ static void pru_rproc_create_debug_entries(struct rproc *rproc)
static void pru_dispose_irq_mapping(struct pru_rproc *pru) { - while (pru->evt_count--) { + if (!pru->mapped_irq) + return; + + while (pru->evt_count) { + pru->evt_count--; if (pru->mapped_irq[pru->evt_count] > 0) irq_dispose_mapping(pru->mapped_irq[pru->evt_count]); }
kfree(pru->mapped_irq); + pru->mapped_irq = NULL; }
/* @@ -307,8 +312,10 @@ static int pru_handle_intrmap(struct rproc *rproc) pru->evt_count = rsc->num_evts; pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int), GFP_KERNEL); - if (!pru->mapped_irq) + if (!pru->mapped_irq) { + pru->evt_count = 0; return -ENOMEM; + }
/* * parse and fill in system event to interrupt channel and @@ -317,13 +324,19 @@ static int pru_handle_intrmap(struct rproc *rproc) * corresponding sibling PRUSS INTC node. */ parent = of_get_parent(dev_of_node(pru->dev)); - if (!parent) + if (!parent) { + kfree(pru->mapped_irq); + pru->mapped_irq = NULL; + pru->evt_count = 0; return -ENODEV; + }
irq_parent = of_get_child_by_name(parent, "interrupt-controller"); of_node_put(parent); if (!irq_parent) { kfree(pru->mapped_irq); + pru->mapped_irq = NULL; + pru->evt_count = 0; return -ENODEV; }
@@ -398,8 +411,7 @@ static int pru_rproc_stop(struct rproc *rproc) pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
/* dispose irq mapping - new firmware can provide new mapping */ - if (pru->mapped_irq) - pru_dispose_irq_mapping(pru); + pru_dispose_irq_mapping(pru);
return 0; }
From: Nikola Livic nlivic@gmail.com
[ Upstream commit ed34695e15aba74f45247f1ee2cf7e09d449f925 ]
We (adam zabrocki, alexander matrosov, alexander tereshkin, maksym bazalii) observed the check:
if (fh->size > sizeof(struct nfs_fh))
should not use the size of the nfs_fh struct which includes an extra two bytes from the size field.
struct nfs_fh { unsigned short size; unsigned char data[NFS_MAXFHSIZE]; }
but should determine the size from data[NFS_MAXFHSIZE] so the memcpy will not write 2 bytes beyond destination. The proposed fix is to compare against the NFS_MAXFHSIZE directly, as is done elsewhere in fs code base.
Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") Signed-off-by: Nikola Livic nlivic@gmail.com Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/flexfilelayout/flexfilelayout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 872112bffcab..d383de00d486 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -106,7 +106,7 @@ static int decode_nfs_fh(struct xdr_stream *xdr, struct nfs_fh *fh) if (unlikely(!p)) return -ENOBUFS; fh->size = be32_to_cpup(p++); - if (fh->size > sizeof(struct nfs_fh)) { + if (fh->size > NFS_MAXFHSIZE) { printk(KERN_ERR "NFS flexfiles: Too big fh received %d\n", fh->size); return -EOVERFLOW;
From: Olga Kornievskaia kolga@netapp.com
[ Upstream commit 73f5c88f521a630ea1628beb9c2d48a2e777a419 ]
Currently the client ignores the value of the sr_eof of the SEEK operation. According to the spec, if the server didn't find the requested extent and reached the end of the file, the server would return sr_eof=true. In case the request for DATA and no data was found (ie in the middle of the hole), then the lseek expects that ENXIO would be returned.
Fixes: 1c6dcbe5ceff8 ("NFS: Implement SEEK") Signed-off-by: Olga Kornievskaia kolga@netapp.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs42proc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 704a5246ccb5..8d64eb953347 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -667,7 +667,10 @@ static loff_t _nfs42_proc_llseek(struct file *filep, if (status) return status;
- return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); + if (whence == SEEK_DATA && res.sr_eof) + return -NFS4ERR_NXIO; + else + return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); }
loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 7638e0bfaed1b653d3ca663e560e9ffb44bb1030 ]
I've hit some crashes that occur in the xprt_rdma_inject_disconnect path. It appears that, for some provides, rdma_disconnect() can take so long that the transport can disconnect and release its hardware resources while rdma_disconnect() is still running, resulting in a UAF in the provider.
The transport's fault injection method may depend on the stability of transport data structures. That means it needs to be invoked only from contexts that hold the transport write lock.
Fixes: 4a0682583988 ("SUNRPC: Transport fault injection") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/clnt.c | 1 - net/sunrpc/xprt.c | 6 ++++-- net/sunrpc/xprtrdma/transport.c | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 612f0a641f4c..c2a01125be1a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1799,7 +1799,6 @@ call_allocate(struct rpc_task *task)
status = xprt->ops->buf_alloc(task); trace_rpc_buf_alloc(task, status); - xprt_inject_disconnect(xprt); if (status == 0) return; if (status != -ENOMEM) { diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 691ccf8049a4..d616b93751d8 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1483,7 +1483,10 @@ bool xprt_prepare_transmit(struct rpc_task *task)
void xprt_end_transmit(struct rpc_task *task) { - xprt_release_write(task->tk_rqstp->rq_xprt, task); + struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; + + xprt_inject_disconnect(xprt); + xprt_release_write(xprt, task); }
/** @@ -1885,7 +1888,6 @@ void xprt_release(struct rpc_task *task) spin_unlock(&xprt->transport_lock); if (req->rq_buffer) xprt->ops->buf_free(task); - xprt_inject_disconnect(xprt); xdr_free_bvec(&req->rq_rcv_buf); xdr_free_bvec(&req->rq_snd_buf); if (req->rq_cred != NULL) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 78d29d1bcc20..09953597d055 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -262,8 +262,10 @@ xprt_rdma_connect_worker(struct work_struct *work) * xprt_rdma_inject_disconnect - inject a connection fault * @xprt: transport context * - * If @xprt is connected, disconnect it to simulate spurious connection - * loss. + * If @xprt is connected, disconnect it to simulate spurious + * connection loss. Caller must hold @xprt's send lock to + * ensure that data structures and hardware resources are + * stable during the rdma_disconnect() call. */ static void xprt_rdma_inject_disconnect(struct rpc_xprt *xprt)
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 6cf23783f750634e10daeede48b0f5f5d64ebf3a ]
This tracepoint can crash when dereferencing snd_task because when some transports connect, they put a cookie in that field instead of a pointer to an rpc_task.
BUG: KASAN: use-after-free in trace_event_raw_event_xprt_writelock_event+0x141/0x18e [sunrpc] Read of size 2 at addr ffff8881a83bd3a0 by task git/331872
CPU: 11 PID: 331872 Comm: git Tainted: G S 5.12.0-rc2-00007-g3ab6e585a7f9 #1453 Hardware name: Supermicro SYS-6028R-T/X10DRi, BIOS 1.1a 10/16/2015 Call Trace: dump_stack+0x9c/0xcf print_address_description.constprop.0+0x18/0x239 kasan_report+0x174/0x1b0 trace_event_raw_event_xprt_writelock_event+0x141/0x18e [sunrpc] xprt_prepare_transmit+0x8e/0xc1 [sunrpc] call_transmit+0x4d/0xc6 [sunrpc]
Fixes: 9ce07ae5eb1d ("SUNRPC: Replace dprintk() call site in xprt_prepare_transmit") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/trace/events/sunrpc.h | 1 - net/sunrpc/xprt.c | 2 -- 2 files changed, 3 deletions(-)
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 036eb1f5c133..2f01314de73a 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -1141,7 +1141,6 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
DEFINE_WRITELOCK_EVENT(reserve_xprt); DEFINE_WRITELOCK_EVENT(release_xprt); -DEFINE_WRITELOCK_EVENT(transmit_queued);
DECLARE_EVENT_CLASS(xprt_cong_event, TP_PROTO( diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index d616b93751d8..11ebe8a127b8 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1469,8 +1469,6 @@ bool xprt_prepare_transmit(struct rpc_task *task) struct rpc_xprt *xprt = req->rq_xprt;
if (!xprt_lock_write(xprt, task)) { - trace_xprt_transmit_queued(xprt, task); - /* Race breaker: someone may have transmitted us */ if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) rpc_wake_up_queued_task_set_status(&xprt->sending,
From: Chris Dion Christopher.Dion@dell.com
[ Upstream commit 09252177d5f924f404551b4b4eded5daa7f04a3a ]
Currently if a major timeout value is reached, but the minor value has not been reached, an ETIMEOUT will not be sent back to the caller. This can occur if the v4 server is not responding to requests and retrans is configured larger than the default of two.
For example, A TCP mount with a configured timeout value of 50 and a retransmission count of 3 to a v4 server which is not responding:
1. Initial value and increment set to 5s, maxval set to 20s, retries at 3 2. Major timeout is set to 20s, minor timeout set to 5s initially 3. xport_adjust_timeout() is called after 5s, retry with 10s timeout, minor timeout is bumped to 10s 4. And again after another 10s, 15s total time with minor timeout set to 15s 5. After 20s total time xport_adjust_timeout is called as major timeout is reached, but skipped because the minor timeout is not reached - After this time the cpu spins continually calling xport_adjust_timeout() and returning 0 for 10 seconds. As seen on perf sched: 39243.913182 [0005] mount.nfs[3794] 4607.938 0.017 9746.863 6. This continues until the 15s minor timeout condition is reached (in this case for 10 seconds). After which the ETIMEOUT is processed back to the caller, the cpu spinning stops, and normal operations continue
Fixes: 7de62bc09fe6 ("SUNRPC dont update timeout value on connection reset") Signed-off-by: Chris Dion Christopher.Dion@dell.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/xprt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 11ebe8a127b8..20fe31b1b776 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -698,9 +698,9 @@ int xprt_adjust_timeout(struct rpc_rqst *req) const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; int status = 0;
- if (time_before(jiffies, req->rq_minortimeo)) - return status; if (time_before(jiffies, req->rq_majortimeo)) { + if (time_before(jiffies, req->rq_minortimeo)) + return status; if (to->to_exponential) req->rq_timeout <<= 1; else
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 94d202d5ca39d0eb757d16ef2624b013fb64f64d ]
If the result of a copy offload or clone operation is to grow the destination file size, then we should update it. The reason is that when a client holds a delegation, it is authoritative for the file size.
Fixes: 16abd2a0c124 ("NFSv4.2: fix client's attribute cache management for copy_file_range") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs42proc.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 8d64eb953347..3875120ef3ef 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -269,6 +269,33 @@ out: return status; }
+/** + * nfs42_copy_dest_done - perform inode cache updates after clone/copy offload + * @inode: pointer to destination inode + * @pos: destination offset + * @len: copy length + * + * Punch a hole in the inode page cache, so that the NFS client will + * know to retrieve new data. + * Update the file size if necessary, and then mark the inode as having + * invalid cached values for change attribute, ctime, mtime and space used. + */ +static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len) +{ + loff_t newsize = pos + len; + loff_t end = newsize - 1; + + truncate_pagecache_range(inode, pos, end); + spin_lock(&inode->i_lock); + if (newsize > i_size_read(inode)) + i_size_write(inode, newsize); + nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE | + NFS_INO_INVALID_CTIME | + NFS_INO_INVALID_MTIME | + NFS_INO_INVALID_BLOCKS); + spin_unlock(&inode->i_lock); +} + static ssize_t _nfs42_proc_copy(struct file *src, struct nfs_lock_context *src_lock, struct file *dst, @@ -362,14 +389,8 @@ static ssize_t _nfs42_proc_copy(struct file *src, goto out; }
- truncate_pagecache_range(dst_inode, pos_dst, - pos_dst + res->write_res.count); - spin_lock(&dst_inode->i_lock); - nfs_set_cache_invalid( - dst_inode, NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED | - NFS_INO_INVALID_SIZE | NFS_INO_INVALID_ATTR | - NFS_INO_INVALID_DATA); - spin_unlock(&dst_inode->i_lock); + nfs42_copy_dest_done(dst_inode, pos_dst, res->write_res.count); + spin_lock(&src_inode->i_lock); nfs_set_cache_invalid(src_inode, NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED | @@ -1055,8 +1076,10 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
status = nfs4_call_sync(server->client, server, msg, &args.seq_args, &res.seq_res, 0); - if (status == 0) + if (status == 0) { + nfs42_copy_dest_done(dst_inode, dst_offset, count); status = nfs_post_op_update_inode(dst_inode, res.dst_fattr); + }
kfree(res.dst_fattr); return status;
From: Guangqing Zhu zhuguangqing83@gmail.com
[ Upstream commit f4136863e8899fa0554343201b78b9e197c78a78 ]
Fixes coccicheck error:
drivers/thermal/qcom/tsens.c:759:4-10: ERROR: missing put_device; call of_find_device_by_node on line 715, but without a corresponding object release within this function.
Fixes: a7ff82976122 ("drivers: thermal: tsens: Merge tsens-common.c into tsens.c") Signed-off-by: Guangqing Zhu zhuguangqing83@gmail.com Reviewed-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210404125431.12208-1-zhuguangqing83@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/thermal/qcom/tsens.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index d8ce3a687b80..3c4c0516e58a 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -755,8 +755,10 @@ int __init init_common(struct tsens_priv *priv) for (i = VER_MAJOR; i <= VER_STEP; i++) { priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[i]); - if (IS_ERR(priv->rf[i])) - return PTR_ERR(priv->rf[i]); + if (IS_ERR(priv->rf[i])) { + ret = PTR_ERR(priv->rf[i]); + goto err_put_device; + } } ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor); if (ret)
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 8926cc8302819be9e67f70409ed001ecb2c924a9 ]
If the NFS super block is being unmounted, then we currently may end up telling the server that we've forgotten the layout while it is actually still in use by the client. In that case, just assume that the client will soon return the layout anyway, and so return NFS4ERR_DELAY in response to the layout recall.
Fixes: 58ac3e59235f ("NFSv4/pnfs: Clean up nfs_layout_find_inode()") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/callback_proc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index f7786e00a6a7..ed9d580826f5 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -137,12 +137,12 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp, list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { if (!pnfs_layout_is_valid(lo)) continue; - if (stateid != NULL && - !nfs4_stateid_match_other(stateid, &lo->plh_stateid)) + if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid)) continue; - if (!nfs_sb_active(server->super)) - continue; - inode = igrab(lo->plh_inode); + if (nfs_sb_active(server->super)) + inode = igrab(lo->plh_inode); + else + inode = ERR_PTR(-EAGAIN); rcu_read_unlock(); if (inode) return inode; @@ -176,9 +176,10 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp, continue; if (nfsi->layout != lo) continue; - if (!nfs_sb_active(server->super)) - continue; - inode = igrab(lo->plh_inode); + if (nfs_sb_active(server->super)) + inode = igrab(lo->plh_inode); + else + inode = ERR_PTR(-EAGAIN); rcu_read_unlock(); if (inode) return inode;
From: J. Bruce Fields bfields@redhat.com
[ Upstream commit 217fd6f625af591e2866bebb8cda778cf85bea2e ]
If nfsd already has an open file that it plans to use for IO from another, it may not need to do another vfs open, but it still may need to break any delegations in case the existing opens are for another client.
Symptoms are that we may incorrectly fail to break a delegation on a write open from a different client, when the delegation-holding client already has a write open.
Fixes: 28df3d1539de ("nfsd: clients don't need to break their own delegations") Signed-off-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfsd/nfs4state.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 97447a64bad0..886e50ed07c2 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4869,6 +4869,11 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, if (nf) nfsd_file_put(nf);
+ status = nfserrno(nfsd_open_break_lease(cur_fh->fh_dentry->d_inode, + access)); + if (status) + goto out_put_access; + status = nfsd4_truncate(rqstp, cur_fh, open); if (status) goto out_put_access; @@ -6849,11 +6854,20 @@ out: static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) { struct nfsd_file *nf; - __be32 err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf); - if (!err) { - err = nfserrno(vfs_test_lock(nf->nf_file, lock)); - nfsd_file_put(nf); - } + __be32 err; + + err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf); + if (err) + return err; + fh_lock(fhp); /* to block new leases till after test_lock: */ + err = nfserrno(nfsd_open_break_lease(fhp->fh_dentry->d_inode, + NFSD_MAY_READ)); + if (err) + goto out; + err = nfserrno(vfs_test_lock(nf->nf_file, lock)); +out: + fh_unlock(fhp); + nfsd_file_put(nf); return err; }
From: Michael Walle michael@walle.cc
[ Upstream commit 7fcb86185978661c9188397d474f90364745b8d9 ]
The module doesn't load automatically. Fix it by adding the missing MODULE_TABLE().
Fixes: 7b0b551dbc1e ("rtc: fsl-ftm-alarm: add FTM alarm driver") Signed-off-by: Michael Walle michael@walle.cc Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210414084006.17933-1-michael@walle.cc Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/rtc-fsl-ftm-alarm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index 57cc09d0a806..c0df49fb978c 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -310,6 +310,7 @@ static const struct of_device_id ftm_rtc_match[] = { { .compatible = "fsl,lx2160a-ftm-alarm", }, { }, }; +MODULE_DEVICE_TABLE(of, ftm_rtc_match);
static const struct acpi_device_id ftm_imx_acpi_ids[] = { {"NXP0014",},
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 28ac8e03c43dfc6a703aa420d18222540b801120 ]
There are calls to idxd_cmd_exec that pass a null status pointer however a recent commit has added an assignment to *status that can end up with a null pointer dereference. The function expects a null status pointer sometimes as there is a later assignment to *status where status is first null checked. Fix the issue by null checking status before making the assignment.
Addresses-Coverity: ("Explicit null dereferenced") Fixes: 89e3becd8f82 ("dmaengine: idxd: check device state before issue command") Signed-off-by: Colin Ian King colin.king@canonical.com Acked-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/20210415110654.1941580-1-colin.king@canonical.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 31c819544a22..78d2dc5e9bd8 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -451,7 +451,8 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
if (idxd_device_is_halted(idxd)) { dev_warn(&idxd->pdev->dev, "Device is HALTED!\n"); - *status = IDXD_CMDSTS_HW_ERR; + if (status) + *status = IDXD_CMDSTS_HW_ERR; return; }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 397862855619271296e46d10f7dfa7bafe71eb81 ]
The devm managed lifetime is incompatible with 'struct device' objects that resides in idxd context. This is one of the series that clean up the idxd driver 'struct device' lifetime. Remove embedding of dma_device and dma_chan in idxd since it's not the only interface that idxd will use. The freeing of the dma_device will be managed by the ->release() function.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Link: https://lore.kernel.org/r/161852983001.2203940.14817017492384561719.stgit@dj... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 2 - drivers/dma/idxd/dma.c | 77 ++++++++++++++++++++++++++++++++------- drivers/dma/idxd/idxd.h | 18 +++++++-- 3 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 78d2dc5e9bd8..d255bb016c4d 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -186,8 +186,6 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq) desc->id = i; desc->wq = wq; desc->cpu = -1; - dma_async_tx_descriptor_init(&desc->txd, &wq->dma_chan); - desc->txd.tx_submit = idxd_dma_tx_submit; }
return 0; diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c index a15e50126434..77439b645044 100644 --- a/drivers/dma/idxd/dma.c +++ b/drivers/dma/idxd/dma.c @@ -14,7 +14,10 @@
static inline struct idxd_wq *to_idxd_wq(struct dma_chan *c) { - return container_of(c, struct idxd_wq, dma_chan); + struct idxd_dma_chan *idxd_chan; + + idxd_chan = container_of(c, struct idxd_dma_chan, chan); + return idxd_chan->wq; }
void idxd_dma_complete_txd(struct idxd_desc *desc, @@ -135,7 +138,7 @@ static void idxd_dma_issue_pending(struct dma_chan *dma_chan) { }
-dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx) +static dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx) { struct dma_chan *c = tx->chan; struct idxd_wq *wq = to_idxd_wq(c); @@ -156,14 +159,25 @@ dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx)
static void idxd_dma_release(struct dma_device *device) { + struct idxd_dma_dev *idxd_dma = container_of(device, struct idxd_dma_dev, dma); + + kfree(idxd_dma); }
int idxd_register_dma_device(struct idxd_device *idxd) { - struct dma_device *dma = &idxd->dma_dev; + struct idxd_dma_dev *idxd_dma; + struct dma_device *dma; + struct device *dev = &idxd->pdev->dev; + int rc;
+ idxd_dma = kzalloc_node(sizeof(*idxd_dma), GFP_KERNEL, dev_to_node(dev)); + if (!idxd_dma) + return -ENOMEM; + + dma = &idxd_dma->dma; INIT_LIST_HEAD(&dma->channels); - dma->dev = &idxd->pdev->dev; + dma->dev = dev;
dma_cap_set(DMA_PRIVATE, dma->cap_mask); dma_cap_set(DMA_COMPLETION_NO_ORDER, dma->cap_mask); @@ -179,35 +193,72 @@ int idxd_register_dma_device(struct idxd_device *idxd) dma->device_alloc_chan_resources = idxd_dma_alloc_chan_resources; dma->device_free_chan_resources = idxd_dma_free_chan_resources;
- return dma_async_device_register(&idxd->dma_dev); + rc = dma_async_device_register(dma); + if (rc < 0) { + kfree(idxd_dma); + return rc; + } + + idxd_dma->idxd = idxd; + /* + * This pointer is protected by the refs taken by the dma_chan. It will remain valid + * as long as there are outstanding channels. + */ + idxd->idxd_dma = idxd_dma; + return 0; }
void idxd_unregister_dma_device(struct idxd_device *idxd) { - dma_async_device_unregister(&idxd->dma_dev); + dma_async_device_unregister(&idxd->idxd_dma->dma); }
int idxd_register_dma_channel(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; - struct dma_device *dma = &idxd->dma_dev; - struct dma_chan *chan = &wq->dma_chan; - int rc; + struct dma_device *dma = &idxd->idxd_dma->dma; + struct device *dev = &idxd->pdev->dev; + struct idxd_dma_chan *idxd_chan; + struct dma_chan *chan; + int rc, i; + + idxd_chan = kzalloc_node(sizeof(*idxd_chan), GFP_KERNEL, dev_to_node(dev)); + if (!idxd_chan) + return -ENOMEM;
- memset(&wq->dma_chan, 0, sizeof(struct dma_chan)); + chan = &idxd_chan->chan; chan->device = dma; list_add_tail(&chan->device_node, &dma->channels); + + for (i = 0; i < wq->num_descs; i++) { + struct idxd_desc *desc = wq->descs[i]; + + dma_async_tx_descriptor_init(&desc->txd, chan); + desc->txd.tx_submit = idxd_dma_tx_submit; + } + rc = dma_async_device_channel_register(dma, chan); - if (rc < 0) + if (rc < 0) { + kfree(idxd_chan); return rc; + } + + wq->idxd_chan = idxd_chan; + idxd_chan->wq = wq; + get_device(&wq->conf_dev);
return 0; }
void idxd_unregister_dma_channel(struct idxd_wq *wq) { - struct dma_chan *chan = &wq->dma_chan; + struct idxd_dma_chan *idxd_chan = wq->idxd_chan; + struct dma_chan *chan = &idxd_chan->chan; + struct idxd_dma_dev *idxd_dma = wq->idxd->idxd_dma;
- dma_async_device_channel_unregister(&wq->idxd->dma_dev, chan); + dma_async_device_channel_unregister(&idxd_dma->dma, chan); list_del(&chan->device_node); + kfree(wq->idxd_chan); + wq->idxd_chan = NULL; + put_device(&wq->conf_dev); } diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 76014c14f473..80e534680c9a 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -14,6 +14,9 @@
extern struct kmem_cache *idxd_desc_pool;
+struct idxd_device; +struct idxd_wq; + #define IDXD_REG_TIMEOUT 50 #define IDXD_DRAIN_TIMEOUT 5000
@@ -96,6 +99,11 @@ enum idxd_complete_type { IDXD_COMPLETE_DEV_FAIL, };
+struct idxd_dma_chan { + struct dma_chan chan; + struct idxd_wq *wq; +}; + struct idxd_wq { void __iomem *portal; struct device conf_dev; @@ -125,7 +133,7 @@ struct idxd_wq { int compls_size; struct idxd_desc **descs; struct sbitmap_queue sbq; - struct dma_chan dma_chan; + struct idxd_dma_chan *idxd_chan; char name[WQ_NAME_SIZE + 1]; u64 max_xfer_bytes; u32 max_batch_size; @@ -162,6 +170,11 @@ enum idxd_device_flag { IDXD_FLAG_PASID_ENABLED, };
+struct idxd_dma_dev { + struct idxd_device *idxd; + struct dma_device dma; +}; + struct idxd_device { enum idxd_type type; struct device conf_dev; @@ -210,7 +223,7 @@ struct idxd_device { int num_wq_irqs; struct idxd_irq_entry *irq_entries;
- struct dma_device dma_dev; + struct idxd_dma_dev *idxd_dma; struct workqueue_struct *wq; struct work_struct work; }; @@ -363,7 +376,6 @@ void idxd_unregister_dma_channel(struct idxd_wq *wq); void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res); void idxd_dma_complete_txd(struct idxd_desc *desc, enum idxd_complete_type comp_type); -dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx);
/* cdev */ int idxd_cdev_register(void);
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 5fc8e85ff12ce0530ac658686902a0ee64600f56 ]
The devm managed lifetime is incompatible with 'struct device' objects that resides in idxd context. This is one of the series that clean up the idxd driver 'struct device' lifetime. Remove devm managed pci interrupt vectors and replace with unmanged allocators.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Link: https://lore.kernel.org/r/161852983563.2203940.8116028229124776669.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 4 +-- drivers/dma/idxd/idxd.h | 2 +- drivers/dma/idxd/init.c | 64 +++++++++++++++++---------------------- 3 files changed, 30 insertions(+), 40 deletions(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index d255bb016c4d..3f696abd74ac 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -19,7 +19,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, /* Interrupt control bits */ void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id) { - struct irq_data *data = irq_get_irq_data(idxd->msix_entries[vec_id].vector); + struct irq_data *data = irq_get_irq_data(idxd->irq_entries[vec_id].vector);
pci_msi_mask_irq(data); } @@ -36,7 +36,7 @@ void idxd_mask_msix_vectors(struct idxd_device *idxd)
void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id) { - struct irq_data *data = irq_get_irq_data(idxd->msix_entries[vec_id].vector); + struct irq_data *data = irq_get_irq_data(idxd->irq_entries[vec_id].vector);
pci_msi_unmask_irq(data); } diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 80e534680c9a..401b035e42b1 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -36,6 +36,7 @@ struct idxd_device_driver { struct idxd_irq_entry { struct idxd_device *idxd; int id; + int vector; struct llist_head pending_llist; struct list_head work_list; /* @@ -219,7 +220,6 @@ struct idxd_device {
union sw_err_reg sw_err; wait_queue_head_t cmd_waitq; - struct msix_entry *msix_entries; int num_wq_irqs; struct idxd_irq_entry *irq_entries;
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 6584b0ec07d5..5cf1bf095ae1 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -61,7 +61,6 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) { struct pci_dev *pdev = idxd->pdev; struct device *dev = &pdev->dev; - struct msix_entry *msix; struct idxd_irq_entry *irq_entry; int i, msixcnt; int rc = 0; @@ -69,23 +68,13 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) msixcnt = pci_msix_vec_count(pdev); if (msixcnt < 0) { dev_err(dev, "Not MSI-X interrupt capable.\n"); - goto err_no_irq; + return -ENOSPC; }
- idxd->msix_entries = devm_kzalloc(dev, sizeof(struct msix_entry) * - msixcnt, GFP_KERNEL); - if (!idxd->msix_entries) { - rc = -ENOMEM; - goto err_no_irq; - } - - for (i = 0; i < msixcnt; i++) - idxd->msix_entries[i].entry = i; - - rc = pci_enable_msix_exact(pdev, idxd->msix_entries, msixcnt); - if (rc) { - dev_err(dev, "Failed enabling %d MSIX entries.\n", msixcnt); - goto err_no_irq; + rc = pci_alloc_irq_vectors(pdev, msixcnt, msixcnt, PCI_IRQ_MSIX); + if (rc != msixcnt) { + dev_err(dev, "Failed enabling %d MSIX entries: %d\n", msixcnt, rc); + return -ENOSPC; } dev_dbg(dev, "Enabled %d msix vectors\n", msixcnt);
@@ -98,58 +87,57 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) GFP_KERNEL); if (!idxd->irq_entries) { rc = -ENOMEM; - goto err_no_irq; + goto err_irq_entries; }
for (i = 0; i < msixcnt; i++) { idxd->irq_entries[i].id = i; idxd->irq_entries[i].idxd = idxd; + idxd->irq_entries[i].vector = pci_irq_vector(pdev, i); spin_lock_init(&idxd->irq_entries[i].list_lock); }
- msix = &idxd->msix_entries[0]; irq_entry = &idxd->irq_entries[0]; - rc = devm_request_threaded_irq(dev, msix->vector, idxd_irq_handler, - idxd_misc_thread, 0, "idxd-misc", - irq_entry); + rc = request_threaded_irq(irq_entry->vector, idxd_irq_handler, idxd_misc_thread, + 0, "idxd-misc", irq_entry); if (rc < 0) { dev_err(dev, "Failed to allocate misc interrupt.\n"); - goto err_no_irq; + goto err_misc_irq; }
- dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", - msix->vector); + dev_dbg(dev, "Allocated idxd-misc handler on msix vector %d\n", irq_entry->vector);
/* first MSI-X entry is not for wq interrupts */ idxd->num_wq_irqs = msixcnt - 1;
for (i = 1; i < msixcnt; i++) { - msix = &idxd->msix_entries[i]; irq_entry = &idxd->irq_entries[i];
init_llist_head(&idxd->irq_entries[i].pending_llist); INIT_LIST_HEAD(&idxd->irq_entries[i].work_list); - rc = devm_request_threaded_irq(dev, msix->vector, - idxd_irq_handler, - idxd_wq_thread, 0, - "idxd-portal", irq_entry); + rc = request_threaded_irq(irq_entry->vector, idxd_irq_handler, + idxd_wq_thread, 0, "idxd-portal", irq_entry); if (rc < 0) { - dev_err(dev, "Failed to allocate irq %d.\n", - msix->vector); - goto err_no_irq; + dev_err(dev, "Failed to allocate irq %d.\n", irq_entry->vector); + goto err_wq_irqs; } - dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", - i, msix->vector); + dev_dbg(dev, "Allocated idxd-msix %d for vector %d\n", i, irq_entry->vector); }
idxd_unmask_error_interrupts(idxd); idxd_msix_perm_setup(idxd); return 0;
- err_no_irq: + err_wq_irqs: + while (--i >= 0) { + irq_entry = &idxd->irq_entries[i]; + free_irq(irq_entry->vector, irq_entry); + } + err_misc_irq: /* Disable error interrupt generation */ idxd_mask_error_interrupts(idxd); - pci_disable_msix(pdev); + err_irq_entries: + pci_free_irq_vectors(pdev); dev_err(dev, "No usable interrupts\n"); return rc; } @@ -495,7 +483,8 @@ static void idxd_shutdown(struct pci_dev *pdev)
for (i = 0; i < msixcnt; i++) { irq_entry = &idxd->irq_entries[i]; - synchronize_irq(idxd->msix_entries[i].vector); + synchronize_irq(irq_entry->vector); + free_irq(irq_entry->vector, irq_entry); if (i == 0) continue; idxd_flush_pending_llist(irq_entry); @@ -503,6 +492,7 @@ static void idxd_shutdown(struct pci_dev *pdev) }
idxd_msix_perm_clear(idxd); + pci_free_irq_vectors(pdev); destroy_workqueue(idxd->wq); }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit a39c7cd0438ee2f0b859ee1eb86cdc52217d2223 ]
The devm managed lifetime is incompatible with 'struct device' objects that resides in idxd context. This is one of the series that clean up the idxd driver 'struct device' lifetime. Remove pcim_* management of the PCI device and the ioremap of MMIO BAR and replace with unmanaged versions. This is for consistency of removing all the pcim/devm based calls.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Link: https://lore.kernel.org/r/161852984150.2203940.8043988289748519056.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/init.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 5cf1bf095ae1..11a2e14b5b80 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -384,32 +384,36 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct idxd_device *idxd; int rc;
- rc = pcim_enable_device(pdev); + rc = pci_enable_device(pdev); if (rc) return rc;
dev_dbg(dev, "Alloc IDXD context\n"); idxd = idxd_alloc(pdev); - if (!idxd) - return -ENOMEM; + if (!idxd) { + rc = -ENOMEM; + goto err_idxd_alloc; + }
dev_dbg(dev, "Mapping BARs\n"); - idxd->reg_base = pcim_iomap(pdev, IDXD_MMIO_BAR, 0); - if (!idxd->reg_base) - return -ENOMEM; + idxd->reg_base = pci_iomap(pdev, IDXD_MMIO_BAR, 0); + if (!idxd->reg_base) { + rc = -ENOMEM; + goto err_iomap; + }
dev_dbg(dev, "Set DMA masks\n"); rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (rc) rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc) - return rc; + goto err;
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (rc) rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc) - return rc; + goto err;
idxd_set_type(idxd);
@@ -423,13 +427,13 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = idxd_probe(idxd); if (rc) { dev_err(dev, "Intel(R) IDXD DMA Engine init failed\n"); - return -ENODEV; + goto err; }
rc = idxd_setup_sysfs(idxd); if (rc) { dev_err(dev, "IDXD sysfs setup failed\n"); - return -ENODEV; + goto err; }
idxd->state = IDXD_DEV_CONF_READY; @@ -438,6 +442,13 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) idxd->hw.version);
return 0; + + err: + pci_iounmap(pdev, idxd->reg_base); + err_iomap: + err_idxd_alloc: + pci_disable_device(pdev); + return rc; }
static void idxd_flush_pending_llist(struct idxd_irq_entry *ie) @@ -493,6 +504,8 @@ static void idxd_shutdown(struct pci_dev *pdev)
idxd_msix_perm_clear(idxd); pci_free_irq_vectors(pdev); + pci_iounmap(pdev, idxd->reg_base); + pci_disable_device(pdev); destroy_workqueue(idxd->wq); }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit f7f7739847bd68b3c3103fd1b50d943038bd14c7 ]
The idr is only used for an device id, never to lookup context from that id. Switch to plain ida.
Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Reported-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/161852984730.2203940.15032482460902003819.stgit@dj... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/init.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 11a2e14b5b80..a4f0489515b4 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -34,8 +34,7 @@ MODULE_PARM_DESC(sva, "Toggle SVA support on/off");
bool support_enqcmd;
-static struct idr idxd_idrs[IDXD_TYPE_MAX]; -static DEFINE_MUTEX(idxd_idr_lock); +static struct ida idxd_idas[IDXD_TYPE_MAX];
static struct pci_device_id idxd_pci_tbl[] = { /* DSA ver 1.0 platforms */ @@ -348,12 +347,10 @@ static int idxd_probe(struct idxd_device *idxd)
dev_dbg(dev, "IDXD interrupt setup complete.\n");
- mutex_lock(&idxd_idr_lock); - idxd->id = idr_alloc(&idxd_idrs[idxd->type], idxd, 0, 0, GFP_KERNEL); - mutex_unlock(&idxd_idr_lock); + idxd->id = ida_alloc(&idxd_idas[idxd->type], GFP_KERNEL); if (idxd->id < 0) { rc = -ENOMEM; - goto err_idr_fail; + goto err_ida_fail; }
idxd->major = idxd_cdev_get_major(idxd); @@ -361,7 +358,7 @@ static int idxd_probe(struct idxd_device *idxd) dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); return 0;
- err_idr_fail: + err_ida_fail: idxd_mask_error_interrupts(idxd); idxd_mask_msix_vectors(idxd); err_setup: @@ -518,9 +515,7 @@ static void idxd_remove(struct pci_dev *pdev) idxd_shutdown(pdev); if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); - mutex_lock(&idxd_idr_lock); - idr_remove(&idxd_idrs[idxd->type], idxd->id); - mutex_unlock(&idxd_idr_lock); + ida_free(&idxd_idas[idxd->type], idxd->id); }
static struct pci_driver idxd_pci_driver = { @@ -550,7 +545,7 @@ static int __init idxd_init_module(void) support_enqcmd = true;
for (i = 0; i < IDXD_TYPE_MAX; i++) - idr_init(&idxd_idrs[i]); + ida_init(&idxd_idas[i]);
err = idxd_register_bus_type(); if (err < 0)
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 47c16ac27d4cb664cee53ee0b9b7e2f907923fb3 ]
The devm managed lifetime is incompatible with 'struct device' objects that resides in idxd context. This is one of the series that clean up the idxd driver 'struct device' lifetime. Fix idxd->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory at the appropriate time.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/161852985319.2203940.4650791514462735368.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/idxd.h | 36 ++++++++++------ drivers/dma/idxd/init.c | 56 ++++++++++++++++-------- drivers/dma/idxd/sysfs.c | 92 ++++++++++++++-------------------------- 3 files changed, 94 insertions(+), 90 deletions(-)
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 401b035e42b1..bb3a580732af 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -8,6 +8,7 @@ #include <linux/percpu-rwsem.h> #include <linux/wait.h> #include <linux/cdev.h> +#include <linux/idr.h> #include "registers.h"
#define IDXD_DRIVER_VERSION "1.00" @@ -255,6 +256,23 @@ extern struct bus_type dsa_bus_type; extern struct bus_type iax_bus_type;
extern bool support_enqcmd; +extern struct device_type dsa_device_type; +extern struct device_type iax_device_type; + +static inline bool is_dsa_dev(struct device *dev) +{ + return dev->type == &dsa_device_type; +} + +static inline bool is_iax_dev(struct device *dev) +{ + return dev->type == &iax_device_type; +} + +static inline bool is_idxd_dev(struct device *dev) +{ + return is_dsa_dev(dev) || is_iax_dev(dev); +}
static inline bool wq_dedicated(struct idxd_wq *wq) { @@ -292,18 +310,6 @@ static inline int idxd_get_wq_portal_full_offset(int wq_id, return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot); }
-static inline void idxd_set_type(struct idxd_device *idxd) -{ - struct pci_dev *pdev = idxd->pdev; - - if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0) - idxd->type = IDXD_TYPE_DSA; - else if (pdev->device == PCI_DEVICE_ID_INTEL_IAX_SPR0) - idxd->type = IDXD_TYPE_IAX; - else - idxd->type = IDXD_TYPE_UNKNOWN; -} - static inline void idxd_wq_get(struct idxd_wq *wq) { wq->client_count++; @@ -319,14 +325,16 @@ static inline int idxd_wq_refcount(struct idxd_wq *wq) return wq->client_count; };
+struct ida *idxd_ida(struct idxd_device *idxd); const char *idxd_get_dev_name(struct idxd_device *idxd); int idxd_register_bus_type(void); void idxd_unregister_bus_type(void); -int idxd_setup_sysfs(struct idxd_device *idxd); -void idxd_cleanup_sysfs(struct idxd_device *idxd); +int idxd_register_devices(struct idxd_device *idxd); +void idxd_unregister_devices(struct idxd_device *idxd); int idxd_register_driver(void); void idxd_unregister_driver(void); struct bus_type *idxd_get_bus_type(struct idxd_device *idxd); +struct device_type *idxd_get_device_type(struct idxd_device *idxd);
/* device interrupt control */ void idxd_msix_perm_setup(struct idxd_device *idxd); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index a4f0489515b4..17d3b36610a9 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -51,6 +51,11 @@ static char *idxd_name[] = { "iax" };
+struct ida *idxd_ida(struct idxd_device *idxd) +{ + return &idxd_idas[idxd->type]; +} + const char *idxd_get_dev_name(struct idxd_device *idxd) { return idxd_name[idxd->type]; @@ -81,9 +86,8 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) * We implement 1 completion list per MSI-X entry except for * entry 0, which is for errors and others. */ - idxd->irq_entries = devm_kcalloc(dev, msixcnt, - sizeof(struct idxd_irq_entry), - GFP_KERNEL); + idxd->irq_entries = kcalloc_node(msixcnt, sizeof(struct idxd_irq_entry), + GFP_KERNEL, dev_to_node(dev)); if (!idxd->irq_entries) { rc = -ENOMEM; goto err_irq_entries; @@ -262,16 +266,44 @@ static void idxd_read_caps(struct idxd_device *idxd) } }
+static inline void idxd_set_type(struct idxd_device *idxd) +{ + struct pci_dev *pdev = idxd->pdev; + + if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0) + idxd->type = IDXD_TYPE_DSA; + else if (pdev->device == PCI_DEVICE_ID_INTEL_IAX_SPR0) + idxd->type = IDXD_TYPE_IAX; + else + idxd->type = IDXD_TYPE_UNKNOWN; +} + static struct idxd_device *idxd_alloc(struct pci_dev *pdev) { struct device *dev = &pdev->dev; struct idxd_device *idxd; + int rc;
- idxd = devm_kzalloc(dev, sizeof(struct idxd_device), GFP_KERNEL); + idxd = kzalloc_node(sizeof(*idxd), GFP_KERNEL, dev_to_node(dev)); if (!idxd) return NULL;
idxd->pdev = pdev; + idxd_set_type(idxd); + idxd->id = ida_alloc(idxd_ida(idxd), GFP_KERNEL); + if (idxd->id < 0) + return NULL; + + device_initialize(&idxd->conf_dev); + idxd->conf_dev.parent = dev; + idxd->conf_dev.bus = idxd_get_bus_type(idxd); + idxd->conf_dev.type = idxd_get_device_type(idxd); + rc = dev_set_name(&idxd->conf_dev, "%s%d", idxd_get_dev_name(idxd), idxd->id); + if (rc < 0) { + put_device(&idxd->conf_dev); + return NULL; + } + spin_lock_init(&idxd->dev_lock);
return idxd; @@ -347,20 +379,11 @@ static int idxd_probe(struct idxd_device *idxd)
dev_dbg(dev, "IDXD interrupt setup complete.\n");
- idxd->id = ida_alloc(&idxd_idas[idxd->type], GFP_KERNEL); - if (idxd->id < 0) { - rc = -ENOMEM; - goto err_ida_fail; - } - idxd->major = idxd_cdev_get_major(idxd);
dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); return 0;
- err_ida_fail: - idxd_mask_error_interrupts(idxd); - idxd_mask_msix_vectors(idxd); err_setup: if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); @@ -412,7 +435,6 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) goto err;
- idxd_set_type(idxd);
idxd_type_init(idxd);
@@ -427,7 +449,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; }
- rc = idxd_setup_sysfs(idxd); + rc = idxd_register_devices(idxd); if (rc) { dev_err(dev, "IDXD sysfs setup failed\n"); goto err; @@ -443,6 +465,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) err: pci_iounmap(pdev, idxd->reg_base); err_iomap: + put_device(&idxd->conf_dev); err_idxd_alloc: pci_disable_device(pdev); return rc; @@ -511,11 +534,10 @@ static void idxd_remove(struct pci_dev *pdev) struct idxd_device *idxd = pci_get_drvdata(pdev);
dev_dbg(&pdev->dev, "%s called\n", __func__); - idxd_cleanup_sysfs(idxd); idxd_shutdown(pdev); if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); - ida_free(&idxd_idas[idxd->type], idxd->id); + idxd_unregister_devices(idxd); }
static struct pci_driver idxd_pci_driver = { diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 18bf4d148989..36193e555e36 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -16,51 +16,26 @@ static char *idxd_wq_type_names[] = { [IDXD_WQT_USER] = "user", };
-static void idxd_conf_device_release(struct device *dev) +static void idxd_conf_sub_device_release(struct device *dev) { dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev)); }
static struct device_type idxd_group_device_type = { .name = "group", - .release = idxd_conf_device_release, + .release = idxd_conf_sub_device_release, };
static struct device_type idxd_wq_device_type = { .name = "wq", - .release = idxd_conf_device_release, + .release = idxd_conf_sub_device_release, };
static struct device_type idxd_engine_device_type = { .name = "engine", - .release = idxd_conf_device_release, + .release = idxd_conf_sub_device_release, };
-static struct device_type dsa_device_type = { - .name = "dsa", - .release = idxd_conf_device_release, -}; - -static struct device_type iax_device_type = { - .name = "iax", - .release = idxd_conf_device_release, -}; - -static inline bool is_dsa_dev(struct device *dev) -{ - return dev ? dev->type == &dsa_device_type : false; -} - -static inline bool is_iax_dev(struct device *dev) -{ - return dev ? dev->type == &iax_device_type : false; -} - -static inline bool is_idxd_dev(struct device *dev) -{ - return is_dsa_dev(dev) || is_iax_dev(dev); -} - static inline bool is_idxd_wq_dev(struct device *dev) { return dev ? dev->type == &idxd_wq_device_type : false; @@ -405,7 +380,7 @@ struct bus_type *idxd_get_bus_type(struct idxd_device *idxd) return idxd_bus_types[idxd->type]; }
-static struct device_type *idxd_get_device_type(struct idxd_device *idxd) +struct device_type *idxd_get_device_type(struct idxd_device *idxd) { if (idxd->type == IDXD_TYPE_DSA) return &dsa_device_type; @@ -1644,6 +1619,30 @@ static const struct attribute_group *idxd_attribute_groups[] = { NULL, };
+static void idxd_conf_device_release(struct device *dev) +{ + struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev); + + kfree(idxd->groups); + kfree(idxd->wqs); + kfree(idxd->engines); + kfree(idxd->irq_entries); + ida_free(idxd_ida(idxd), idxd->id); + kfree(idxd); +} + +struct device_type dsa_device_type = { + .name = "dsa", + .release = idxd_conf_device_release, + .groups = idxd_attribute_groups, +}; + +struct device_type iax_device_type = { + .name = "iax", + .release = idxd_conf_device_release, + .groups = idxd_attribute_groups, +}; + static int idxd_setup_engine_sysfs(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; @@ -1745,39 +1744,14 @@ cleanup: return rc; }
-static int idxd_setup_device_sysfs(struct idxd_device *idxd) +int idxd_register_devices(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; int rc; - char devname[IDXD_NAME_SIZE];
- sprintf(devname, "%s%d", idxd_get_dev_name(idxd), idxd->id); - idxd->conf_dev.parent = dev; - dev_set_name(&idxd->conf_dev, "%s", devname); - idxd->conf_dev.bus = idxd_get_bus_type(idxd); - idxd->conf_dev.groups = idxd_attribute_groups; - idxd->conf_dev.type = idxd_get_device_type(idxd); - - dev_dbg(dev, "IDXD device register: %s\n", dev_name(&idxd->conf_dev)); - rc = device_register(&idxd->conf_dev); - if (rc < 0) { - put_device(&idxd->conf_dev); - return rc; - } - - return 0; -} - -int idxd_setup_sysfs(struct idxd_device *idxd) -{ - struct device *dev = &idxd->pdev->dev; - int rc; - - rc = idxd_setup_device_sysfs(idxd); - if (rc < 0) { - dev_dbg(dev, "Device sysfs registering failed: %d\n", rc); + rc = device_add(&idxd->conf_dev); + if (rc < 0) return rc; - }
rc = idxd_setup_wq_sysfs(idxd); if (rc < 0) { @@ -1803,7 +1777,7 @@ int idxd_setup_sysfs(struct idxd_device *idxd) return 0; }
-void idxd_cleanup_sysfs(struct idxd_device *idxd) +void idxd_unregister_devices(struct idxd_device *idxd) { int i;
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 7c5dd23e57c14cf7177b8a5e0fd08916e0c60005 ]
Remove devm_* allocation and fix wq->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory for the wq context at device destruction time.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/161852985907.2203940.6840120734115043753.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 6 +-- drivers/dma/idxd/idxd.h | 20 +++++++- drivers/dma/idxd/init.c | 105 ++++++++++++++++++++++++++++---------- drivers/dma/idxd/irq.c | 6 +-- drivers/dma/idxd/sysfs.c | 100 ++++++++++++++++-------------------- 5 files changed, 146 insertions(+), 91 deletions(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 3f696abd74ac..c4183294a704 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -520,7 +520,7 @@ void idxd_device_wqs_clear_state(struct idxd_device *idxd) lockdep_assert_held(&idxd->dev_lock);
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
if (wq->state == IDXD_WQ_ENABLED) { idxd_wq_disable_cleanup(wq); @@ -738,7 +738,7 @@ static int idxd_wqs_config_write(struct idxd_device *idxd) int i, rc;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
rc = idxd_wq_config_write(wq); if (rc < 0) @@ -816,7 +816,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) }
for (i = 0; i < idxd->max_wqs; i++) { - wq = &idxd->wqs[i]; + wq = idxd->wqs[i]; group = wq->group;
if (!wq->group) diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index bb3a580732af..6cade6a05314 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -194,7 +194,7 @@ struct idxd_device { spinlock_t dev_lock; /* spinlock for device */ struct completion *cmd_done; struct idxd_group *groups; - struct idxd_wq *wqs; + struct idxd_wq **wqs; struct idxd_engine *engines;
struct iommu_sva *sva; @@ -258,6 +258,7 @@ extern struct bus_type iax_bus_type; extern bool support_enqcmd; extern struct device_type dsa_device_type; extern struct device_type iax_device_type; +extern struct device_type idxd_wq_device_type;
static inline bool is_dsa_dev(struct device *dev) { @@ -274,6 +275,23 @@ static inline bool is_idxd_dev(struct device *dev) return is_dsa_dev(dev) || is_iax_dev(dev); }
+static inline bool is_idxd_wq_dev(struct device *dev) +{ + return dev->type == &idxd_wq_device_type; +} + +static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) +{ + if (wq->type == IDXD_WQT_KERNEL && strcmp(wq->name, "dmaengine") == 0) + return true; + return false; +} + +static inline bool is_idxd_wq_cdev(struct idxd_wq *wq) +{ + return wq->type == IDXD_WQT_USER; +} + static inline bool wq_dedicated(struct idxd_wq *wq) { return test_bit(WQ_FLAG_DEDICATED, &wq->flags); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 17d3b36610a9..a2dca27aebc3 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -145,16 +145,74 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) return rc; }
+static int idxd_setup_wqs(struct idxd_device *idxd) +{ + struct device *dev = &idxd->pdev->dev; + struct idxd_wq *wq; + int i, rc; + + idxd->wqs = kcalloc_node(idxd->max_wqs, sizeof(struct idxd_wq *), + GFP_KERNEL, dev_to_node(dev)); + if (!idxd->wqs) + return -ENOMEM; + + for (i = 0; i < idxd->max_wqs; i++) { + wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); + if (!wq) { + rc = -ENOMEM; + goto err; + } + + wq->id = i; + wq->idxd = idxd; + device_initialize(&wq->conf_dev); + wq->conf_dev.parent = &idxd->conf_dev; + wq->conf_dev.bus = idxd_get_bus_type(idxd); + wq->conf_dev.type = &idxd_wq_device_type; + rc = dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id); + if (rc < 0) { + put_device(&wq->conf_dev); + goto err; + } + + mutex_init(&wq->wq_lock); + wq->idxd_cdev.minor = -1; + wq->max_xfer_bytes = idxd->max_xfer_bytes; + wq->max_batch_size = idxd->max_batch_size; + wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); + if (!wq->wqcfg) { + put_device(&wq->conf_dev); + rc = -ENOMEM; + goto err; + } + idxd->wqs[i] = wq; + } + + return 0; + + err: + while (--i >= 0) + put_device(&idxd->wqs[i]->conf_dev); + return rc; +} + static int idxd_setup_internals(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; - int i; + int i, rc;
init_waitqueue_head(&idxd->cmd_waitq); + + rc = idxd_setup_wqs(idxd); + if (rc < 0) + return rc; + idxd->groups = devm_kcalloc(dev, idxd->max_groups, sizeof(struct idxd_group), GFP_KERNEL); - if (!idxd->groups) - return -ENOMEM; + if (!idxd->groups) { + rc = -ENOMEM; + goto err; + }
for (i = 0; i < idxd->max_groups; i++) { idxd->groups[i].idxd = idxd; @@ -163,40 +221,31 @@ static int idxd_setup_internals(struct idxd_device *idxd) idxd->groups[i].tc_b = -1; }
- idxd->wqs = devm_kcalloc(dev, idxd->max_wqs, sizeof(struct idxd_wq), - GFP_KERNEL); - if (!idxd->wqs) - return -ENOMEM; - idxd->engines = devm_kcalloc(dev, idxd->max_engines, sizeof(struct idxd_engine), GFP_KERNEL); - if (!idxd->engines) - return -ENOMEM; - - for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; - - wq->id = i; - wq->idxd = idxd; - mutex_init(&wq->wq_lock); - wq->idxd_cdev.minor = -1; - wq->max_xfer_bytes = idxd->max_xfer_bytes; - wq->max_batch_size = idxd->max_batch_size; - wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL); - if (!wq->wqcfg) - return -ENOMEM; + if (!idxd->engines) { + rc = -ENOMEM; + goto err; }
+ for (i = 0; i < idxd->max_engines; i++) { idxd->engines[i].idxd = idxd; idxd->engines[i].id = i; }
idxd->wq = create_workqueue(dev_name(dev)); - if (!idxd->wq) - return -ENOMEM; + if (!idxd->wq) { + rc = -ENOMEM; + goto err; + }
return 0; + + err: + for (i = 0; i < idxd->max_wqs; i++) + put_device(&idxd->wqs[i]->conf_dev); + return rc; }
static void idxd_read_table_offsets(struct idxd_device *idxd) @@ -371,11 +420,11 @@ static int idxd_probe(struct idxd_device *idxd)
rc = idxd_setup_internals(idxd); if (rc) - goto err_setup; + goto err;
rc = idxd_setup_interrupts(idxd); if (rc) - goto err_setup; + goto err;
dev_dbg(dev, "IDXD interrupt setup complete.\n");
@@ -384,7 +433,7 @@ static int idxd_probe(struct idxd_device *idxd) dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id); return 0;
- err_setup: + err: if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); return rc; diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index f1463fc58112..7b0181532f77 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -45,7 +45,7 @@ static void idxd_device_reinit(struct work_struct *work) goto out;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
if (wq->state == IDXD_WQ_ENABLED) { rc = idxd_wq_enable(wq); @@ -130,7 +130,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
if (idxd->sw_err.valid && idxd->sw_err.wq_idx_valid) { int id = idxd->sw_err.wq_idx; - struct idxd_wq *wq = &idxd->wqs[id]; + struct idxd_wq *wq = idxd->wqs[id];
if (wq->type == IDXD_WQT_USER) wake_up_interruptible(&wq->idxd_cdev.err_queue); @@ -138,7 +138,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) int i;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
if (wq->type == IDXD_WQT_USER) wake_up_interruptible(&wq->idxd_cdev.err_queue); diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 36193e555e36..409b3ce52f07 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -26,34 +26,11 @@ static struct device_type idxd_group_device_type = { .release = idxd_conf_sub_device_release, };
-static struct device_type idxd_wq_device_type = { - .name = "wq", - .release = idxd_conf_sub_device_release, -}; - static struct device_type idxd_engine_device_type = { .name = "engine", .release = idxd_conf_sub_device_release, };
-static inline bool is_idxd_wq_dev(struct device *dev) -{ - return dev ? dev->type == &idxd_wq_device_type : false; -} - -static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) -{ - if (wq->type == IDXD_WQT_KERNEL && - strcmp(wq->name, "dmaengine") == 0) - return true; - return false; -} - -static inline bool is_idxd_wq_cdev(struct idxd_wq *wq) -{ - return wq->type == IDXD_WQT_USER; -} - static int idxd_config_bus_match(struct device *dev, struct device_driver *drv) { @@ -297,7 +274,7 @@ static int idxd_config_bus_remove(struct device *dev) dev_dbg(dev, "%s removing dev %s\n", __func__, dev_name(&idxd->conf_dev)); for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
if (wq->state == IDXD_WQ_DISABLED) continue; @@ -309,7 +286,7 @@ static int idxd_config_bus_remove(struct device *dev) idxd_unregister_dma_device(idxd); rc = idxd_device_disable(idxd); for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
mutex_lock(&wq->wq_lock); idxd_wq_disable_cleanup(wq); @@ -678,7 +655,7 @@ static ssize_t group_work_queues_show(struct device *dev, struct idxd_device *idxd = group->idxd;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
if (!wq->group) continue; @@ -935,7 +912,7 @@ static int total_claimed_wq_size(struct idxd_device *idxd) int wq_size = 0;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
wq_size += wq->size; } @@ -1331,6 +1308,20 @@ static const struct attribute_group *idxd_wq_attribute_groups[] = { NULL, };
+static void idxd_conf_wq_release(struct device *dev) +{ + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + + kfree(wq->wqcfg); + kfree(wq); +} + +struct device_type idxd_wq_device_type = { + .name = "wq", + .release = idxd_conf_wq_release, + .groups = idxd_wq_attribute_groups, +}; + /* IDXD device attribs */ static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1461,7 +1452,7 @@ static ssize_t clients_show(struct device *dev,
spin_lock_irqsave(&idxd->dev_lock, flags); for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
count += wq->client_count; } @@ -1711,70 +1702,67 @@ cleanup: return rc; }
-static int idxd_setup_wq_sysfs(struct idxd_device *idxd) +static int idxd_register_wq_devices(struct idxd_device *idxd) { - struct device *dev = &idxd->pdev->dev; - int i, rc; + int i, rc, j;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; - - wq->conf_dev.parent = &idxd->conf_dev; - dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id); - wq->conf_dev.bus = idxd_get_bus_type(idxd); - wq->conf_dev.groups = idxd_wq_attribute_groups; - wq->conf_dev.type = &idxd_wq_device_type; - dev_dbg(dev, "WQ device register: %s\n", - dev_name(&wq->conf_dev)); - rc = device_register(&wq->conf_dev); - if (rc < 0) { - put_device(&wq->conf_dev); + struct idxd_wq *wq = idxd->wqs[i]; + + rc = device_add(&wq->conf_dev); + if (rc < 0) goto cleanup; - } }
return 0;
cleanup: - while (i--) { - struct idxd_wq *wq = &idxd->wqs[i]; + j = i - 1; + for (; i < idxd->max_wqs; i++) + put_device(&idxd->wqs[i]->conf_dev);
- device_unregister(&wq->conf_dev); - } + while (j--) + device_unregister(&idxd->wqs[j]->conf_dev); return rc; }
int idxd_register_devices(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; - int rc; + int rc, i;
rc = device_add(&idxd->conf_dev); if (rc < 0) return rc;
- rc = idxd_setup_wq_sysfs(idxd); + rc = idxd_register_wq_devices(idxd); if (rc < 0) { - /* unregister conf dev */ - dev_dbg(dev, "Work Queue sysfs registering failed: %d\n", rc); - return rc; + dev_dbg(dev, "WQ devices registering failed: %d\n", rc); + goto err_wq; }
rc = idxd_setup_group_sysfs(idxd); if (rc < 0) { /* unregister conf dev */ dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); - return rc; + goto err; }
rc = idxd_setup_engine_sysfs(idxd); if (rc < 0) { /* unregister conf dev */ dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc); - return rc; + goto err; }
return 0; + + err: + for (i = 0; i < idxd->max_wqs; i++) + device_unregister(&idxd->wqs[i]->conf_dev); + err_wq: + device_del(&idxd->conf_dev); + return rc; }
void idxd_unregister_devices(struct idxd_device *idxd) @@ -1782,7 +1770,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) int i;
for (i = 0; i < idxd->max_wqs; i++) { - struct idxd_wq *wq = &idxd->wqs[i]; + struct idxd_wq *wq = idxd->wqs[i];
device_unregister(&wq->conf_dev); }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 75b911309060f42ba94bbbf46f5f497d35d5cd02 ]
Remove devm_* allocation and fix engine->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory at the engine conf_dev destruction time.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/161852986460.2203940.16603218225412118431.stgit@dj... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 2 +- drivers/dma/idxd/idxd.h | 3 +- drivers/dma/idxd/init.c | 60 +++++++++++++++++++++++++------- drivers/dma/idxd/sysfs.c | 72 +++++++++++++++++++-------------------- 4 files changed, 86 insertions(+), 51 deletions(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index c4183294a704..be1dcddfe3c4 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -786,7 +786,7 @@ static int idxd_engines_setup(struct idxd_device *idxd) }
for (i = 0; i < idxd->max_engines; i++) { - eng = &idxd->engines[i]; + eng = idxd->engines[i]; group = eng->group;
if (!group) diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 6cade6a05314..b9b7e8e8c384 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -195,7 +195,7 @@ struct idxd_device { struct completion *cmd_done; struct idxd_group *groups; struct idxd_wq **wqs; - struct idxd_engine *engines; + struct idxd_engine **engines;
struct iommu_sva *sva; unsigned int pasid; @@ -259,6 +259,7 @@ extern bool support_enqcmd; extern struct device_type dsa_device_type; extern struct device_type iax_device_type; extern struct device_type idxd_wq_device_type; +extern struct device_type idxd_engine_device_type;
static inline bool is_dsa_dev(struct device *dev) { diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index a2dca27aebc3..b90ef2f519eb 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -196,6 +196,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd) return rc; }
+static int idxd_setup_engines(struct idxd_device *idxd) +{ + struct idxd_engine *engine; + struct device *dev = &idxd->pdev->dev; + int i, rc; + + idxd->engines = kcalloc_node(idxd->max_engines, sizeof(struct idxd_engine *), + GFP_KERNEL, dev_to_node(dev)); + if (!idxd->engines) + return -ENOMEM; + + for (i = 0; i < idxd->max_engines; i++) { + engine = kzalloc_node(sizeof(*engine), GFP_KERNEL, dev_to_node(dev)); + if (!engine) { + rc = -ENOMEM; + goto err; + } + + engine->id = i; + engine->idxd = idxd; + device_initialize(&engine->conf_dev); + engine->conf_dev.parent = &idxd->conf_dev; + engine->conf_dev.type = &idxd_engine_device_type; + rc = dev_set_name(&engine->conf_dev, "engine%d.%d", idxd->id, engine->id); + if (rc < 0) { + put_device(&engine->conf_dev); + goto err; + } + + idxd->engines[i] = engine; + } + + return 0; + + err: + while (--i >= 0) + put_device(&idxd->engines[i]->conf_dev); + return rc; +} + static int idxd_setup_internals(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; @@ -207,6 +247,10 @@ static int idxd_setup_internals(struct idxd_device *idxd) if (rc < 0) return rc;
+ rc = idxd_setup_engines(idxd); + if (rc < 0) + goto err_engine; + idxd->groups = devm_kcalloc(dev, idxd->max_groups, sizeof(struct idxd_group), GFP_KERNEL); if (!idxd->groups) { @@ -221,19 +265,6 @@ static int idxd_setup_internals(struct idxd_device *idxd) idxd->groups[i].tc_b = -1; }
- idxd->engines = devm_kcalloc(dev, idxd->max_engines, - sizeof(struct idxd_engine), GFP_KERNEL); - if (!idxd->engines) { - rc = -ENOMEM; - goto err; - } - - - for (i = 0; i < idxd->max_engines; i++) { - idxd->engines[i].idxd = idxd; - idxd->engines[i].id = i; - } - idxd->wq = create_workqueue(dev_name(dev)); if (!idxd->wq) { rc = -ENOMEM; @@ -243,6 +274,9 @@ static int idxd_setup_internals(struct idxd_device *idxd) return 0;
err: + for (i = 0; i < idxd->max_engines; i++) + put_device(&idxd->engines[i]->conf_dev); + err_engine: for (i = 0; i < idxd->max_wqs; i++) put_device(&idxd->wqs[i]->conf_dev); return rc; diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 409b3ce52f07..ab02e3b4d75d 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -26,11 +26,6 @@ static struct device_type idxd_group_device_type = { .release = idxd_conf_sub_device_release, };
-static struct device_type idxd_engine_device_type = { - .name = "engine", - .release = idxd_conf_sub_device_release, -}; - static int idxd_config_bus_match(struct device *dev, struct device_driver *drv) { @@ -464,6 +459,19 @@ static const struct attribute_group *idxd_engine_attribute_groups[] = { NULL, };
+static void idxd_conf_engine_release(struct device *dev) +{ + struct idxd_engine *engine = container_of(dev, struct idxd_engine, conf_dev); + + kfree(engine); +} + +struct device_type idxd_engine_device_type = { + .name = "engine", + .release = idxd_conf_engine_release, + .groups = idxd_engine_attribute_groups, +}; + /* Group attributes */
static void idxd_set_free_tokens(struct idxd_device *idxd) @@ -626,7 +634,7 @@ static ssize_t group_engines_show(struct device *dev, struct idxd_device *idxd = group->idxd;
for (i = 0; i < idxd->max_engines; i++) { - struct idxd_engine *engine = &idxd->engines[i]; + struct idxd_engine *engine = idxd->engines[i];
if (!engine->group) continue; @@ -1634,37 +1642,27 @@ struct device_type iax_device_type = { .groups = idxd_attribute_groups, };
-static int idxd_setup_engine_sysfs(struct idxd_device *idxd) +static int idxd_register_engine_devices(struct idxd_device *idxd) { - struct device *dev = &idxd->pdev->dev; - int i, rc; + int i, j, rc;
for (i = 0; i < idxd->max_engines; i++) { - struct idxd_engine *engine = &idxd->engines[i]; - - engine->conf_dev.parent = &idxd->conf_dev; - dev_set_name(&engine->conf_dev, "engine%d.%d", - idxd->id, engine->id); - engine->conf_dev.bus = idxd_get_bus_type(idxd); - engine->conf_dev.groups = idxd_engine_attribute_groups; - engine->conf_dev.type = &idxd_engine_device_type; - dev_dbg(dev, "Engine device register: %s\n", - dev_name(&engine->conf_dev)); - rc = device_register(&engine->conf_dev); - if (rc < 0) { - put_device(&engine->conf_dev); + struct idxd_engine *engine = idxd->engines[i]; + + rc = device_add(&engine->conf_dev); + if (rc < 0) goto cleanup; - } }
return 0;
cleanup: - while (i--) { - struct idxd_engine *engine = &idxd->engines[i]; + j = i - 1; + for (; i < idxd->max_engines; i++) + put_device(&idxd->engines[i]->conf_dev);
- device_unregister(&engine->conf_dev); - } + while (j--) + device_unregister(&idxd->engines[j]->conf_dev); return rc; }
@@ -1741,23 +1739,25 @@ int idxd_register_devices(struct idxd_device *idxd) goto err_wq; }
- rc = idxd_setup_group_sysfs(idxd); + rc = idxd_register_engine_devices(idxd); if (rc < 0) { - /* unregister conf dev */ - dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); - goto err; + dev_dbg(dev, "Engine devices registering failed: %d\n", rc); + goto err_engine; }
- rc = idxd_setup_engine_sysfs(idxd); + rc = idxd_setup_group_sysfs(idxd); if (rc < 0) { /* unregister conf dev */ - dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc); - goto err; + dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); + goto err_group; }
return 0;
- err: + err_group: + for (i = 0; i < idxd->max_engines; i++) + device_unregister(&idxd->engines[i]->conf_dev); + err_engine: for (i = 0; i < idxd->max_wqs; i++) device_unregister(&idxd->wqs[i]->conf_dev); err_wq: @@ -1776,7 +1776,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) }
for (i = 0; i < idxd->max_engines; i++) { - struct idxd_engine *engine = &idxd->engines[i]; + struct idxd_engine *engine = idxd->engines[i];
device_unregister(&engine->conf_dev); }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit defe49f96012ca91e8e673cb95b5c30b4a3735e8 ]
Remove devm_* allocation and fix group->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory at the group->conf_dev destruction time.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/161852987144.2203940.8830315575880047.stgit@djiang... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/device.c | 8 ++--- drivers/dma/idxd/idxd.h | 3 +- drivers/dma/idxd/init.c | 68 ++++++++++++++++++++++++++++++--------- drivers/dma/idxd/sysfs.c | 68 +++++++++++++++++---------------------- 4 files changed, 88 insertions(+), 59 deletions(-)
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index be1dcddfe3c4..4fef57717049 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -659,7 +659,7 @@ static int idxd_groups_config_write(struct idxd_device *idxd) ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET));
for (i = 0; i < idxd->max_groups; i++) { - struct idxd_group *group = &idxd->groups[i]; + struct idxd_group *group = idxd->groups[i];
idxd_group_config_write(group); } @@ -754,7 +754,7 @@ static void idxd_group_flags_setup(struct idxd_device *idxd)
/* TC-A 0 and TC-B 1 should be defaults */ for (i = 0; i < idxd->max_groups; i++) { - struct idxd_group *group = &idxd->groups[i]; + struct idxd_group *group = idxd->groups[i];
if (group->tc_a == -1) group->tc_a = group->grpcfg.flags.tc_a = 0; @@ -781,7 +781,7 @@ static int idxd_engines_setup(struct idxd_device *idxd) struct idxd_group *group;
for (i = 0; i < idxd->max_groups; i++) { - group = &idxd->groups[i]; + group = idxd->groups[i]; group->grpcfg.engines = 0; }
@@ -810,7 +810,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) struct device *dev = &idxd->pdev->dev;
for (i = 0; i < idxd->max_groups; i++) { - group = &idxd->groups[i]; + group = idxd->groups[i]; for (j = 0; j < 4; j++) group->grpcfg.wqs[j] = 0; } diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index b9b7e8e8c384..3c4ce7997c88 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -193,7 +193,7 @@ struct idxd_device {
spinlock_t dev_lock; /* spinlock for device */ struct completion *cmd_done; - struct idxd_group *groups; + struct idxd_group **groups; struct idxd_wq **wqs; struct idxd_engine **engines;
@@ -260,6 +260,7 @@ extern struct device_type dsa_device_type; extern struct device_type iax_device_type; extern struct device_type idxd_wq_device_type; extern struct device_type idxd_engine_device_type; +extern struct device_type idxd_group_device_type;
static inline bool is_dsa_dev(struct device *dev) { diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index b90ef2f519eb..c20ea6bf09bf 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -236,11 +236,54 @@ static int idxd_setup_engines(struct idxd_device *idxd) return rc; }
-static int idxd_setup_internals(struct idxd_device *idxd) +static int idxd_setup_groups(struct idxd_device *idxd) { struct device *dev = &idxd->pdev->dev; + struct idxd_group *group; int i, rc;
+ idxd->groups = kcalloc_node(idxd->max_groups, sizeof(struct idxd_group *), + GFP_KERNEL, dev_to_node(dev)); + if (!idxd->groups) + return -ENOMEM; + + for (i = 0; i < idxd->max_groups; i++) { + group = kzalloc_node(sizeof(*group), GFP_KERNEL, dev_to_node(dev)); + if (!group) { + rc = -ENOMEM; + goto err; + } + + group->id = i; + group->idxd = idxd; + device_initialize(&group->conf_dev); + group->conf_dev.parent = &idxd->conf_dev; + group->conf_dev.bus = idxd_get_bus_type(idxd); + group->conf_dev.type = &idxd_group_device_type; + rc = dev_set_name(&group->conf_dev, "group%d.%d", idxd->id, group->id); + if (rc < 0) { + put_device(&group->conf_dev); + goto err; + } + + idxd->groups[i] = group; + group->tc_a = -1; + group->tc_b = -1; + } + + return 0; + + err: + while (--i >= 0) + put_device(&idxd->groups[i]->conf_dev); + return rc; +} + +static int idxd_setup_internals(struct idxd_device *idxd) +{ + struct device *dev = &idxd->pdev->dev; + int rc, i; + init_waitqueue_head(&idxd->cmd_waitq);
rc = idxd_setup_wqs(idxd); @@ -251,29 +294,22 @@ static int idxd_setup_internals(struct idxd_device *idxd) if (rc < 0) goto err_engine;
- idxd->groups = devm_kcalloc(dev, idxd->max_groups, - sizeof(struct idxd_group), GFP_KERNEL); - if (!idxd->groups) { - rc = -ENOMEM; - goto err; - } - - for (i = 0; i < idxd->max_groups; i++) { - idxd->groups[i].idxd = idxd; - idxd->groups[i].id = i; - idxd->groups[i].tc_a = -1; - idxd->groups[i].tc_b = -1; - } + rc = idxd_setup_groups(idxd); + if (rc < 0) + goto err_group;
idxd->wq = create_workqueue(dev_name(dev)); if (!idxd->wq) { rc = -ENOMEM; - goto err; + goto err_wkq_create; }
return 0;
- err: + err_wkq_create: + for (i = 0; i < idxd->max_groups; i++) + put_device(&idxd->groups[i]->conf_dev); + err_group: for (i = 0; i < idxd->max_engines; i++) put_device(&idxd->engines[i]->conf_dev); err_engine: diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index ab02e3b4d75d..f793688039c9 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -16,16 +16,6 @@ static char *idxd_wq_type_names[] = { [IDXD_WQT_USER] = "user", };
-static void idxd_conf_sub_device_release(struct device *dev) -{ - dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev)); -} - -static struct device_type idxd_group_device_type = { - .name = "group", - .release = idxd_conf_sub_device_release, -}; - static int idxd_config_bus_match(struct device *dev, struct device_driver *drv) { @@ -435,7 +425,7 @@ static ssize_t engine_group_id_store(struct device *dev,
if (prevg) prevg->num_engines--; - engine->group = &idxd->groups[id]; + engine->group = idxd->groups[id]; engine->group->num_engines++;
return count; @@ -479,7 +469,7 @@ static void idxd_set_free_tokens(struct idxd_device *idxd) int i, tokens;
for (i = 0, tokens = 0; i < idxd->max_groups; i++) { - struct idxd_group *g = &idxd->groups[i]; + struct idxd_group *g = idxd->groups[i];
tokens += g->tokens_reserved; } @@ -784,6 +774,19 @@ static const struct attribute_group *idxd_group_attribute_groups[] = { NULL, };
+static void idxd_conf_group_release(struct device *dev) +{ + struct idxd_group *group = container_of(dev, struct idxd_group, conf_dev); + + kfree(group); +} + +struct device_type idxd_group_device_type = { + .name = "group", + .release = idxd_conf_group_release, + .groups = idxd_group_attribute_groups, +}; + /* IDXD work queue attribs */ static ssize_t wq_clients_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -856,7 +859,7 @@ static ssize_t wq_group_id_store(struct device *dev, return count; }
- group = &idxd->groups[id]; + group = idxd->groups[id]; prevg = wq->group;
if (prevg) @@ -1666,37 +1669,27 @@ cleanup: return rc; }
-static int idxd_setup_group_sysfs(struct idxd_device *idxd) +static int idxd_register_group_devices(struct idxd_device *idxd) { - struct device *dev = &idxd->pdev->dev; - int i, rc; + int i, j, rc;
for (i = 0; i < idxd->max_groups; i++) { - struct idxd_group *group = &idxd->groups[i]; - - group->conf_dev.parent = &idxd->conf_dev; - dev_set_name(&group->conf_dev, "group%d.%d", - idxd->id, group->id); - group->conf_dev.bus = idxd_get_bus_type(idxd); - group->conf_dev.groups = idxd_group_attribute_groups; - group->conf_dev.type = &idxd_group_device_type; - dev_dbg(dev, "Group device register: %s\n", - dev_name(&group->conf_dev)); - rc = device_register(&group->conf_dev); - if (rc < 0) { - put_device(&group->conf_dev); + struct idxd_group *group = idxd->groups[i]; + + rc = device_add(&group->conf_dev); + if (rc < 0) goto cleanup; - } }
return 0;
cleanup: - while (i--) { - struct idxd_group *group = &idxd->groups[i]; + j = i - 1; + for (; i < idxd->max_groups; i++) + put_device(&idxd->groups[i]->conf_dev);
- device_unregister(&group->conf_dev); - } + while (j--) + device_unregister(&idxd->groups[j]->conf_dev); return rc; }
@@ -1745,10 +1738,9 @@ int idxd_register_devices(struct idxd_device *idxd) goto err_engine; }
- rc = idxd_setup_group_sysfs(idxd); + rc = idxd_register_group_devices(idxd); if (rc < 0) { - /* unregister conf dev */ - dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); + dev_dbg(dev, "Group device registering failed: %d\n", rc); goto err_group; }
@@ -1782,7 +1774,7 @@ void idxd_unregister_devices(struct idxd_device *idxd) }
for (i = 0; i < idxd->max_groups; i++) { - struct idxd_group *group = &idxd->groups[i]; + struct idxd_group *group = idxd->groups[i];
device_unregister(&group->conf_dev); }
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit 04922b7445a1950b86f130a1fe8c52cc27b3e30b ]
The char device setup and cleanup has device lifetime issues regarding when parts are initialized and cleaned up. The initialization of struct device is done incorrectly. device_initialize() needs to be called on the 'struct device' and then additional changes can be added. The ->release() function needs to be setup via device_type before dev_set_name() to allow proper cleanup. The change re-parents the cdev under the wq->conf_dev to get natural reference inheritance. No known dependency on the old device path exists.
Reported-by: Jason Gunthorpe jgg@nvidia.com Fixes: 42d279f9137a ("dmaengine: idxd: add char driver to expose submission portal to userland") Signed-off-by: Dave Jiang dave.jiang@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Link: https://lore.kernel.org/r/161852987721.2203940.1478218825576630810.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/cdev.c | 129 ++++++++++++++------------------------- drivers/dma/idxd/idxd.h | 7 ++- drivers/dma/idxd/init.c | 2 +- drivers/dma/idxd/irq.c | 4 +- drivers/dma/idxd/sysfs.c | 10 ++- 5 files changed, 63 insertions(+), 89 deletions(-)
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index 0db9b82ed8cf..1d8a3876b745 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -39,15 +39,15 @@ struct idxd_user_context { struct iommu_sva *sva; };
-enum idxd_cdev_cleanup { - CDEV_NORMAL = 0, - CDEV_FAILED, -}; - static void idxd_cdev_dev_release(struct device *dev) { - dev_dbg(dev, "releasing cdev device\n"); - kfree(dev); + struct idxd_cdev *idxd_cdev = container_of(dev, struct idxd_cdev, dev); + struct idxd_cdev_context *cdev_ctx; + struct idxd_wq *wq = idxd_cdev->wq; + + cdev_ctx = &ictx[wq->idxd->type]; + ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor); + kfree(idxd_cdev); }
static struct device_type idxd_cdev_device_type = { @@ -62,14 +62,11 @@ static inline struct idxd_cdev *inode_idxd_cdev(struct inode *inode) return container_of(cdev, struct idxd_cdev, cdev); }
-static inline struct idxd_wq *idxd_cdev_wq(struct idxd_cdev *idxd_cdev) -{ - return container_of(idxd_cdev, struct idxd_wq, idxd_cdev); -} - static inline struct idxd_wq *inode_wq(struct inode *inode) { - return idxd_cdev_wq(inode_idxd_cdev(inode)); + struct idxd_cdev *idxd_cdev = inode_idxd_cdev(inode); + + return idxd_cdev->wq; }
static int idxd_cdev_open(struct inode *inode, struct file *filp) @@ -220,11 +217,10 @@ static __poll_t idxd_cdev_poll(struct file *filp, struct idxd_user_context *ctx = filp->private_data; struct idxd_wq *wq = ctx->wq; struct idxd_device *idxd = wq->idxd; - struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; unsigned long flags; __poll_t out = 0;
- poll_wait(filp, &idxd_cdev->err_queue, wait); + poll_wait(filp, &wq->err_queue, wait); spin_lock_irqsave(&idxd->dev_lock, flags); if (idxd->sw_err.valid) out = EPOLLIN | EPOLLRDNORM; @@ -246,98 +242,67 @@ int idxd_cdev_get_major(struct idxd_device *idxd) return MAJOR(ictx[idxd->type].devt); }
-static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq) +int idxd_wq_add_cdev(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; - struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; - struct idxd_cdev_context *cdev_ctx; + struct idxd_cdev *idxd_cdev; + struct cdev *cdev; struct device *dev; - int minor, rc; + struct idxd_cdev_context *cdev_ctx; + int rc, minor;
- idxd_cdev->dev = kzalloc(sizeof(*idxd_cdev->dev), GFP_KERNEL); - if (!idxd_cdev->dev) + idxd_cdev = kzalloc(sizeof(*idxd_cdev), GFP_KERNEL); + if (!idxd_cdev) return -ENOMEM;
- dev = idxd_cdev->dev; - dev->parent = &idxd->pdev->dev; - dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd), - idxd->id, wq->id); - dev->bus = idxd_get_bus_type(idxd); - + idxd_cdev->wq = wq; + cdev = &idxd_cdev->cdev; + dev = &idxd_cdev->dev; cdev_ctx = &ictx[wq->idxd->type]; minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL); if (minor < 0) { - rc = minor; - kfree(dev); - goto ida_err; - } - - dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor); - dev->type = &idxd_cdev_device_type; - rc = device_register(dev); - if (rc < 0) { - dev_err(&idxd->pdev->dev, "device register failed\n"); - goto dev_reg_err; + kfree(idxd_cdev); + return minor; } idxd_cdev->minor = minor;
- return 0; - - dev_reg_err: - ida_simple_remove(&cdev_ctx->minor_ida, MINOR(dev->devt)); - put_device(dev); - ida_err: - idxd_cdev->dev = NULL; - return rc; -} - -static void idxd_wq_cdev_cleanup(struct idxd_wq *wq, - enum idxd_cdev_cleanup cdev_state) -{ - struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; - struct idxd_cdev_context *cdev_ctx; - - cdev_ctx = &ictx[wq->idxd->type]; - if (cdev_state == CDEV_NORMAL) - cdev_del(&idxd_cdev->cdev); - device_unregister(idxd_cdev->dev); - /* - * The device_type->release() will be called on the device and free - * the allocated struct device. We can just forget it. - */ - ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor); - idxd_cdev->dev = NULL; - idxd_cdev->minor = -1; -} - -int idxd_wq_add_cdev(struct idxd_wq *wq) -{ - struct idxd_cdev *idxd_cdev = &wq->idxd_cdev; - struct cdev *cdev = &idxd_cdev->cdev; - struct device *dev; - int rc; + device_initialize(dev); + dev->parent = &wq->conf_dev; + dev->bus = idxd_get_bus_type(idxd); + dev->type = &idxd_cdev_device_type; + dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor);
- rc = idxd_wq_cdev_dev_setup(wq); + rc = dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd), + idxd->id, wq->id); if (rc < 0) - return rc; + goto err;
- dev = idxd_cdev->dev; + wq->idxd_cdev = idxd_cdev; cdev_init(cdev, &idxd_cdev_fops); - cdev_set_parent(cdev, &dev->kobj); - rc = cdev_add(cdev, dev->devt, 1); + rc = cdev_device_add(cdev, dev); if (rc) { dev_dbg(&wq->idxd->pdev->dev, "cdev_add failed: %d\n", rc); - idxd_wq_cdev_cleanup(wq, CDEV_FAILED); - return rc; + goto err; }
- init_waitqueue_head(&idxd_cdev->err_queue); return 0; + + err: + put_device(dev); + wq->idxd_cdev = NULL; + return rc; }
void idxd_wq_del_cdev(struct idxd_wq *wq) { - idxd_wq_cdev_cleanup(wq, CDEV_NORMAL); + struct idxd_cdev *idxd_cdev; + struct idxd_cdev_context *cdev_ctx; + + cdev_ctx = &ictx[wq->idxd->type]; + idxd_cdev = wq->idxd_cdev; + wq->idxd_cdev = NULL; + cdev_device_del(&idxd_cdev->cdev, &idxd_cdev->dev); + put_device(&idxd_cdev->dev); }
int idxd_cdev_register(void) diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 3c4ce7997c88..89daf746d121 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -80,10 +80,10 @@ enum idxd_wq_type { };
struct idxd_cdev { + struct idxd_wq *wq; struct cdev cdev; - struct device *dev; + struct device dev; int minor; - struct wait_queue_head err_queue; };
#define IDXD_ALLOCATED_BATCH_SIZE 128U @@ -109,7 +109,8 @@ struct idxd_dma_chan { struct idxd_wq { void __iomem *portal; struct device conf_dev; - struct idxd_cdev idxd_cdev; + struct idxd_cdev *idxd_cdev; + struct wait_queue_head err_queue; struct idxd_device *idxd; int id; enum idxd_wq_type type; diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index c20ea6bf09bf..07cf7977a045 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -176,7 +176,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) }
mutex_init(&wq->wq_lock); - wq->idxd_cdev.minor = -1; + init_waitqueue_head(&wq->err_queue); wq->max_xfer_bytes = idxd->max_xfer_bytes; wq->max_batch_size = idxd->max_batch_size; wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index 7b0181532f77..fc0781e3f36d 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -133,7 +133,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) struct idxd_wq *wq = idxd->wqs[id];
if (wq->type == IDXD_WQT_USER) - wake_up_interruptible(&wq->idxd_cdev.err_queue); + wake_up_interruptible(&wq->err_queue); } else { int i;
@@ -141,7 +141,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) struct idxd_wq *wq = idxd->wqs[i];
if (wq->type == IDXD_WQT_USER) - wake_up_interruptible(&wq->idxd_cdev.err_queue); + wake_up_interruptible(&wq->err_queue); } }
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index f793688039c9..9586b55abce5 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1169,8 +1169,16 @@ static ssize_t wq_cdev_minor_show(struct device *dev, struct device_attribute *attr, char *buf) { struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); + int minor = -1;
- return sprintf(buf, "%d\n", wq->idxd_cdev.minor); + mutex_lock(&wq->wq_lock); + if (wq->idxd_cdev) + minor = wq->idxd_cdev->minor; + mutex_unlock(&wq->wq_lock); + + if (minor == -1) + return -ENXIO; + return sysfs_emit(buf, "%d\n", minor); }
static struct device_attribute dev_attr_wq_cdev_minor =
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit cb579086536f6564f5846f89808ec394ef8b8621 ]
This code is supposed to pass negative "err" values for tracing but it passes positive values instead. The problem is that the trace_svcsock_tcp_send() function takes a long but "err" is an int and "sent" is a u32. The negative is first type promoted to u32 so it becomes a high positive then it is promoted to long and it stays positive.
Fix this by casting "err" directly to long.
Fixes: 998024dee197 ("SUNRPC: Add more svcsock tracepoints") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/svcsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 2e2f007dfc9f..7cde41a936a4 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1171,7 +1171,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp) tcp_sock_set_cork(svsk->sk_sk, true); err = svc_tcp_sendmsg(svsk->sk_sock, xdr, marker, &sent); xdr_free_bvec(xdr); - trace_svcsock_tcp_send(xprt, err < 0 ? err : sent); + trace_svcsock_tcp_send(xprt, err < 0 ? (long)err : sent); if (err < 0 || sent != (xdr->len + sizeof(marker))) goto out_close; if (atomic_dec_and_test(&svsk->sk_sendqlen))
From: Yunjian Wang wangyunjian@huawei.com
[ Upstream commit b9f83ffaa0c096b4c832a43964fe6bff3acffe10 ]
When alloc_pages_node() returns null in svc_rqst_alloc(), the null rq_scratch_page pointer will be dereferenced when calling put_page() in svc_rqst_free(). Fix it by adding a null check.
Addresses-Coverity: ("Dereference after null check") Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side") Signed-off-by: Yunjian Wang wangyunjian@huawei.com Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/svc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index d76dc9d95d16..0de918cb3d90 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -846,7 +846,8 @@ void svc_rqst_free(struct svc_rqst *rqstp) { svc_release_buffer(rqstp); - put_page(rqstp->rq_scratch_page); + if (rqstp->rq_scratch_page) + put_page(rqstp->rq_scratch_page); kfree(rqstp->rq_resp); kfree(rqstp->rq_argp); kfree(rqstp->rq_auth_data);
From: Uwe Kleine-König u.kleine-koenig@pengutronix.de
[ Upstream commit 453e8b3d8e36ddcb283b3d1698864a03ea45599a ]
The CDTY register contains the number of inactive cycles. .apply() does this correctly, however .get_state() got this wrong.
Fixes: 651b510a74d4 ("pwm: atmel: Implement .get_state()") Signed-off-by: Uwe Kleine-König u.kleine-koenig@pengutronix.de Signed-off-by: Thierry Reding thierry.reding@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pwm/pwm-atmel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 5813339b597b..3292158157b6 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -319,7 +319,7 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, atmel_pwm->data->regs.duty); - tmp = (u64)cdty * NSEC_PER_SEC; + tmp = (u64)(cprd - cdty) * NSEC_PER_SEC; tmp <<= pres; state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate);
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 32e6b68167f1d446111c973d57e6f52aee11897a ]
Commit e340c2d6ef2a ("xprtrdma: Reduce the doorbell rate (Receive)") increased the number of Receive WRs that are posted by the client, but did not increase the size of the Receive Queue allocated during transport set-up.
This is usually not an issue because RPCRDMA_BACKWARD_WRS is defined as (32) when SUNRPC_BACKCHANNEL is defined. In cases where it isn't, there is a real risk of Receive Queue wrapping.
Fixes: e340c2d6ef2a ("xprtrdma: Reduce the doorbell rate (Receive)") Signed-off-by: Chuck Lever chuck.lever@oracle.com Reviewed-by: Tom Talpey tom@talpey.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/xprtrdma/frwr_ops.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 766a1048a48a..132df9b59ab4 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c @@ -257,6 +257,7 @@ int frwr_query_device(struct rpcrdma_ep *ep, const struct ib_device *device) ep->re_attr.cap.max_send_wr += 1; /* for ib_drain_sq */ ep->re_attr.cap.max_recv_wr = ep->re_max_requests; ep->re_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS; + ep->re_attr.cap.max_recv_wr += RPCRDMA_MAX_RECV_BATCH; ep->re_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
ep->re_max_rdma_segs =
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 35d8b10a25884050bb3b0149b62c3818ec59f77c ]
After a reconnect, the reply handler is opening the cwnd (and thus enabling more RPC Calls to be sent) /before/ rpcrdma_post_recvs() can post enough Receive WRs to receive their replies. This causes an RNR and the new connection is lost immediately.
The race is most clearly exposed when KASAN and disconnect injection are enabled. This slows down rpcrdma_rep_create() enough to allow the send side to post a bunch of RPC Calls before the Receive completion handler can invoke ib_post_recv().
Fixes: 2ae50ad68cd7 ("xprtrdma: Close window between waking RPC senders and posting Receives") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/xprtrdma/rpc_rdma.c | 3 ++- net/sunrpc/xprtrdma/verbs.c | 10 +++++----- net/sunrpc/xprtrdma/xprt_rdma.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 292f066d006e..21ddd78a8c35 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -1430,9 +1430,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) credits = 1; /* don't deadlock */ else if (credits > r_xprt->rx_ep->re_max_requests) credits = r_xprt->rx_ep->re_max_requests; + rpcrdma_post_recvs(r_xprt, credits + (buf->rb_bc_srv_max_requests << 1), + false); if (buf->rb_credits != credits) rpcrdma_update_cwnd(r_xprt, credits); - rpcrdma_post_recvs(r_xprt, false);
req = rpcr_to_rdmar(rqst); if (unlikely(req->rl_reply)) diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index ec912cf9c618..f3fffc74ab0f 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -535,7 +535,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt) * outstanding Receives. */ rpcrdma_ep_get(ep); - rpcrdma_post_recvs(r_xprt, true); + rpcrdma_post_recvs(r_xprt, 1, true);
rc = rdma_connect(ep->re_id, &ep->re_remote_cma); if (rc) @@ -1364,21 +1364,21 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) /** * rpcrdma_post_recvs - Refill the Receive Queue * @r_xprt: controlling transport instance - * @temp: mark Receive buffers to be deleted after use + * @needed: current credit grant + * @temp: mark Receive buffers to be deleted after one use * */ -void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp) +void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp) { struct rpcrdma_buffer *buf = &r_xprt->rx_buf; struct rpcrdma_ep *ep = r_xprt->rx_ep; struct ib_recv_wr *wr, *bad_wr; struct rpcrdma_rep *rep; - int needed, count, rc; + int count, rc;
rc = 0; count = 0;
- needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1); if (likely(ep->re_receive_count > needed)) goto out; needed -= ep->re_receive_count; diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index fe3be985e239..28af11fbe643 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -461,7 +461,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt); void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt);
int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req); -void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp); +void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp);
/* * Buffer calls - xprtrdma/verbs.c
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 1363e6388c363d0433f9aa4e2f33efe047572687 ]
The rpcrdma_mr_pop() earlier in the function has already cleared out mr_list, so it must not be done again in the error path.
Fixes: 847568942f93 ("xprtrdma: Remove fr_state") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/xprtrdma/frwr_ops.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index 132df9b59ab4..aca2228095db 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c @@ -576,7 +576,6 @@ void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) mr = container_of(frwr, struct rpcrdma_mr, frwr); bad_wr = bad_wr->next;
- list_del_init(&mr->mr_list); frwr_mr_recycle(mr); } }
From: Nathan Chancellor nathan@kernel.org
[ Upstream commit adebc8817b5c975d598ac379bbdf67a7a5186ade ]
clang prior to 13.0.0 does not support -fpatchable-function-entry for RISC-V.
clang: error: unsupported option '-fpatchable-function-entry=8' for target 'riscv64-unknown-linux-gnu'
To avoid this error, only select HAVE_DYNAMIC_FTRACE when this option is not available.
Fixes: afc76b8b8011 ("riscv: Using PATCHABLE_FUNCTION_ENTRY instead of MCOUNT") Link: https://github.com/ClangBuiltLinux/linux/issues/1268 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Nathan Chancellor nathan@kernel.org Reviewed-by: Fangrui Song maskray@google.com Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 4515a10c5d22..d9522fc35ca5 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -227,7 +227,7 @@ config ARCH_RV64I bool "RV64I" select 64BIT select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && GCC_VERSION >= 50000 - select HAVE_DYNAMIC_FTRACE if MMU + select HAVE_DYNAMIC_FTRACE if MMU && $(cc-option,-fpatchable-function-entry=8) select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER
From: Claire Chang tientzu@chromium.org
[ Upstream commit 95b079d8215b83b37fa59341fda92fcb9392f14a ]
Fix the type of index from unsigned int to int since find_slots() might return -1.
Fixes: 26a7e094783d ("swiotlb: refactor swiotlb_tbl_map_single") Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Claire Chang tientzu@chromium.org Signed-off-by: Konrad Rzeszutek Wilk konrad@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/dma/swiotlb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index c10e855a03bc..fe4c01c14ab2 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -608,7 +608,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, enum dma_data_direction dir, unsigned long attrs) { unsigned int offset = swiotlb_align_offset(dev, orig_addr); - unsigned int index, i; + unsigned int i; + int index; phys_addr_t tlb_addr;
if (no_iotlb_memory)
From: Jeff Layton jlayton@kernel.org
[ Upstream commit 1775c7ddacfcea29051c67409087578f8f4d751b ]
Fixes: 878dabb64117 ("ceph: don't return -ESTALE if there's still an open file") Signed-off-by: Jeff Layton jlayton@kernel.org Reviewed-by: Xiubo Li xiubli@redhat.com Signed-off-by: Ilya Dryomov idryomov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ceph/export.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index e088843a7734..baa6368bece5 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -178,8 +178,10 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino) return ERR_CAST(inode); /* We need LINK caps to reliably check i_nlink */ err = ceph_do_getattr(inode, CEPH_CAP_LINK_SHARED, false); - if (err) + if (err) { + iput(inode); return ERR_PTR(err); + } /* -ESTALE if inode as been unlinked and no file is open */ if ((inode->i_nlink == 0) && (atomic_read(&inode->i_count) == 1)) { iput(inode);
From: Anastasia Kovaleva a.kovaleva@yadro.com
[ Upstream commit fcb16d9a8ecf1e9bfced0fc654ea4e2caa7517f4 ]
In a case when the initiator in P2P mode by some circumstances does not send PRLI, the target, in a case when the target port's WWPN is less than initiator's, changes the discovery state in DSC_GNL. When gnl completes it sends PRLI to the initiator.
Usually the initiator in P2P mode always sends PRLI. We caught this issue on Linux stable v5.4.6 https://www.spinics.net/lists/stable/msg458515.html.
Fix this particular corner case in the behaviour of the P2P mod target login state machine.
Link: https://lore.kernel.org/r/20210422153414.4022-1-a.kovaleva@yadro.com Fixes: a9ed06d4e640 ("scsi: qla2xxx: Allow PLOGI in target mode") Reviewed-by: Roman Bolshakov r.bolshakov@yadro.com Reviewed-by: Himanshu Madhani himanshu.madhani@oracle.com Signed-off-by: Anastasia Kovaleva a.kovaleva@yadro.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f01f07116bd3..8cb0574cfa91 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1194,6 +1194,9 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport) { struct qla_work_evt *e;
+ if (vha->host->active_mode == MODE_TARGET) + return QLA_FUNCTION_FAILED; + e = qla2x00_alloc_work(vha, QLA_EVT_PRLI); if (!e) return QLA_FUNCTION_FAILED;
From: Can Guo cang@codeaurora.org
[ Upstream commit 23043dd87b153d02eaf676e752d32429be5e5126 ]
During resume, if link is broken due to AH8 failure, make sure ufshcd_resume() does not put UFS power back into LPM.
Link: https://lore.kernel.org/r/1619408921-30426-2-git-send-email-cang@codeaurora.... Fixes: 4db7a2360597 ("scsi: ufs: Fix concurrency of error handler and other error recovery paths") Reviewed-by: Daejun Park daejun7.park@samsung.com Signed-off-by: Can Guo cang@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d3d05e997c13..fed32517d7d1 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8599,7 +8599,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); vcc_off = true; - if (!ufshcd_is_link_active(hba)) { + if (ufshcd_is_link_hibern8(hba) || ufshcd_is_link_off(hba)) { ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } @@ -8621,7 +8621,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) !hba->dev_info.is_lu_power_on_wp) { ret = ufshcd_setup_vreg(hba, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { - if (!ret && !ufshcd_is_link_active(hba)) { + if (!ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) goto vcc_disable;
From: Can Guo cang@codeaurora.org
[ Upstream commit 637822e63b79ee8a729f7ba2645a26cf5a524ee4 ]
During ufs system suspend, leaving rpm_dev_flush_recheck_work running or pending is risky because concurrency may happen between system suspend/resume and runtime resume routine. Fix this by cancelling rpm_dev_flush_recheck_work synchronously during system suspend.
Link: https://lore.kernel.org/r/1619408921-30426-3-git-send-email-cang@codeaurora.... Fixes: 51dd905bd2f6 ("scsi: ufs: Fix WriteBooster flush during runtime suspend") Reviewed-by: Daejun Park daejun7.park@samsung.com Signed-off-by: Can Guo cang@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index fed32517d7d1..4631a609b0e3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8978,6 +8978,8 @@ int ufshcd_system_suspend(struct ufs_hba *hba) if (!hba->is_powered) return 0;
+ cancel_delayed_work_sync(&hba->rpm_dev_flush_recheck_work); + if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
From: Can Guo cang@codeaurora.org
[ Upstream commit ce4f62f9dd8cf43ac044045ed598a0b80ef33890 ]
If spm_lvl is set to 0 or 1, when system suspend kicks start and HBA is runtime active, system suspend may just bail without doing anything (the fast path), leaving other contexts still running, e.g., clock gating and clock scaling. When system resume kicks start, concurrency can happen between ufshcd_resume() and these contexts, leading to various stability issues.
Add a check against HBA's runtime state and allowing fast path only if HBA is runtime suspended, otherwise let system suspend go ahead call ufshcd_suspend(). This will guarantee that these contexts are stopped by either runtime suspend or system suspend.
Link: https://lore.kernel.org/r/1619408921-30426-4-git-send-email-cang@codeaurora.... Fixes: 0b257734344a ("scsi: ufs: optimize system suspend handling") Reviewed-by: Daejun Park daejun7.park@samsung.com Signed-off-by: Can Guo cang@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4631a609b0e3..0c71a159d08f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8984,6 +8984,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) hba->curr_dev_pwr_mode) && (ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) == hba->uic_link_state) && + pm_runtime_suspended(hba->dev) && !hba->dev_info.b_rpm_dev_flush_capable) goto out;
From: Nobuhiro Iwamatsu nobuhiro1.iwamatsu@toshiba.co.jp
[ Upstream commit 204756f016726a380bafe619438ed979088bd04a ]
rx8130 wday specifies the bit position, not BCD.
Fixes: ee0981be7704 ("rtc: ds1307: Add support for Epson RX8130CE") Signed-off-by: Nobuhiro Iwamatsu nobuhiro1.iwamatsu@toshiba.co.jp Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210420023917.1949066-1-nobuhiro1.iwamatsu@toshib... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/rtc-ds1307.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index cd8e438bc9c4..8752620d8e34 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -296,7 +296,11 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); tmp = regs[DS1307_REG_HOUR] & 0x3f; t->tm_hour = bcd2bin(tmp); - t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; + /* rx8130 is bit position, not BCD */ + if (ds1307->type == rx_8130) + t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f); + else + t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1; t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f); tmp = regs[DS1307_REG_MONTH] & 0x1f; t->tm_mon = bcd2bin(tmp) - 1; @@ -343,7 +347,11 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec); regs[DS1307_REG_MIN] = bin2bcd(t->tm_min); regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour); - regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); + /* rx8130 is bit position, not BCD */ + if (ds1307->type == rx_8130) + regs[DS1307_REG_WDAY] = 1 << t->tm_wday; + else + regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1); regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday); regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
From: Yufeng Mo moyufeng@huawei.com
[ Upstream commit 2867298dd49ee84214b8721521dc7a5a6382520c ]
According to the UM, the type and enable status of igu_egu_hw_err should be configured separately. Currently, the type field is incorrect when disable this error. So fix it by configuring these two fields separately.
Fixes: bf1faf9415dd ("net: hns3: Add enable and process hw errors from IGU, EGU and NCSI") Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 3 ++- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 0ca7f1b984bf..78d3eb142df8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -753,8 +753,9 @@ static int hclge_config_igu_egu_hw_err_int(struct hclge_dev *hdev, bool en)
/* configure IGU,EGU error interrupts */ hclge_cmd_setup_basic_desc(&desc, HCLGE_IGU_COMMON_INT_EN, false); + desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_TYPE); if (en) - desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN); + desc.data[0] |= cpu_to_le32(HCLGE_IGU_ERR_INT_EN);
desc.data[1] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN_MASK);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index 608fe26fc3fe..d647f3c84134 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -32,7 +32,8 @@ #define HCLGE_TQP_ECC_ERR_INT_EN_MASK 0x0FFF #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN_MASK 0x0F000000 #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN 0x0F000000 -#define HCLGE_IGU_ERR_INT_EN 0x0000066F +#define HCLGE_IGU_ERR_INT_EN 0x0000000F +#define HCLGE_IGU_ERR_INT_TYPE 0x00000660 #define HCLGE_IGU_ERR_INT_EN_MASK 0x000F #define HCLGE_IGU_TNL_ERR_INT_EN 0x0002AABF #define HCLGE_IGU_TNL_ERR_INT_EN_MASK 0x003F
From: Yufeng Mo moyufeng@huawei.com
[ Upstream commit 568a54bdf70b143f3e0befa298e22ad469ffc732 ]
The message sent to VF should be initialized, otherwise random value of some contents may cause improper processing by the target. So add a initialization to message in hclge_get_link_mode().
Fixes: 9194d18b0577 ("net: hns3: fix the problem that the supported port is empty") Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 51a36e74f088..c3bb16b1f060 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -535,7 +535,7 @@ static void hclge_get_link_mode(struct hclge_vport *vport, unsigned long advertising; unsigned long supported; unsigned long send_data; - u8 msg_data[10]; + u8 msg_data[10] = {}; u8 dest_vfid;
advertising = hdev->hw.mac.advertising[0];
From: Jian Shen shenjian15@huawei.com
[ Upstream commit b4047aac4ec1066bab6c71950623746d7bcf7154 ]
In some cases, the device is not initialized because reset failed. If another task calls hns3_reset_notify_up_enet() before reset retry, it will cause an error since uninitialized pointer access. So add check for HNS3_NIC_STATE_INITED before calling hns3_nic_net_open() in hns3_reset_notify_up_enet().
Fixes: bb6b94a896d4 ("net: hns3: Add reset interface implementation in client") Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b19df09ffb76..59d4d1e87f65 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4588,6 +4588,11 @@ static int hns3_reset_notify_up_enet(struct hnae3_handle *handle) struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev); int ret = 0;
+ if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) { + netdev_err(kinfo->netdev, "device is not initialized yet\n"); + return -EFAULT; + } + clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
if (netif_running(kinfo->netdev)) {
From: Mark Rutland mark.rutland@arm.com
[ Upstream commit 8533d5bfad41e74b7dd80d292fd484913cdfb374 ]
We removed the terminal frame records in commit:
6106e1112cc69a36 ("arm64: remove EL0 exception frame record")
... on the assumption that as we no longer used them to find the pt_regs at exception boundaries, they were no longer necessary.
However, Leo reports that as an unintended side-effect, this causes traces which cross secondary_start_kernel to terminate one entry too late, with a spurious "0" entry.
There are a few ways we could sovle this, but as we're planning to use terminal records for RELIABLE_STACKTRACE, let's revert the logic change for now, keeping the update comments and accounting for the changes in commit:
3c02600144bdb0a1 ("arm64: stacktrace: Report when we reach the end of the stack")
This is effectively a partial revert of commit:
6106e1112cc69a36 ("arm64: remove EL0 exception frame record")
Signed-off-by: Mark Rutland mark.rutland@arm.com Fixes: 6106e1112cc6 ("arm64: remove EL0 exception frame record") Reported-by: Leo Yan leo.yan@linaro.org Tested-by: Leo Yan leo.yan@linaro.org Cc: Will Deacon will@kernel.org Cc: Mark Brown broonie@kernel.org Cc: "Madhavan T. Venkataraman" madvenka@linux.microsoft.com Link: https://lore.kernel.org/r/20210429104813.GA33550@C02TD0UTHF1T.local Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/kernel/entry.S | 6 +++--- arch/arm64/kernel/stacktrace.c | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 6acfc5e6b5e0..9b205744a233 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -263,16 +263,16 @@ alternative_else_nop_endif stp lr, x21, [sp, #S_LR]
/* - * For exceptions from EL0, terminate the callchain here. + * For exceptions from EL0, create a terminal frame record. * For exceptions from EL1, create a synthetic frame record so the * interrupted code shows up in the backtrace. */ .if \el == 0 - mov x29, xzr + stp xzr, xzr, [sp, #S_STACKFRAME] .else stp x29, x22, [sp, #S_STACKFRAME] - add x29, sp, #S_STACKFRAME .endif + add x29, sp, #S_STACKFRAME
#ifdef CONFIG_ARM64_SW_TTBR0_PAN alternative_if_not ARM64_HAS_PAN diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index d55bdfb7789c..7032a5f9e624 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -44,10 +44,6 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) unsigned long fp = frame->fp; struct stack_info info;
- /* Terminal record; nothing to unwind */ - if (!fp) - return -ENOENT; - if (fp & 0xf) return -EINVAL;
@@ -108,6 +104,12 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
frame->pc = ptrauth_strip_insn_pac(frame->pc);
+ /* + * This is a terminal record, so we have finished unwinding. + */ + if (!frame->fp && !frame->pc) + return -ENOENT; + return 0; } NOKPROBE_SYMBOL(unwind_frame);
From: Hao Chen chenhao288@hisilicon.com
[ Upstream commit 905416f18fe74bdd4de91bf94ef5a790a36e4b99 ]
When skb->ip_summed is CHECKSUM_PARTIAL, for non-tunnel udp packet, which has a dest port as the IANA assigned, the hardware is expected to do the checksum offload, but the hardware whose version is below V3 will not do the checksum offload when udp dest port is 4790.
So fixes it by doing the checksum in software for this case.
Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Hao Chen chenhao288@hisilicon.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 59d4d1e87f65..d24bafb7ce46 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -823,7 +823,7 @@ static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto, * and it is udp packet, which has a dest port as the IANA assigned. * the hardware is expected to do the checksum offload, but the * hardware will not do the checksum offload when udp dest port is - * 4789 or 6081. + * 4789, 4790 or 6081. */ static bool hns3_tunnel_csum_bug(struct sk_buff *skb) { @@ -841,7 +841,8 @@ static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
if (!(!skb->encapsulation && (l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) || - l4.udp->dest == htons(GENEVE_UDP_PORT)))) + l4.udp->dest == htons(GENEVE_UDP_PORT) || + l4.udp->dest == htons(4790)))) return false;
skb_checksum_help(skb);
From: Peng Li lipeng321@huawei.com
[ Upstream commit b416e872be06fdace3c36cf5210130509d0f0e72 ]
Currently, netif_tx_stop_all_queues() is used to ensure that the xmit is not running, but for the concurrent case it will not take effect, since netif_tx_stop_all_queues() just sets a flag without locking to indicate that the xmit queue(s) should not be run.
So use netif_tx_disable() to replace netif_tx_stop_all_queues(), it takes the xmit queue lock while marking the queue stopped.
Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index d24bafb7ce46..0f70158c2551 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -576,8 +576,8 @@ static int hns3_nic_net_stop(struct net_device *netdev) if (h->ae_algo->ops->set_timer_task) h->ae_algo->ops->set_timer_task(priv->ae_handle, false);
- netif_tx_stop_all_queues(netdev); netif_carrier_off(netdev); + netif_tx_disable(netdev);
hns3_nic_net_down(netdev);
From: Yufeng Mo moyufeng@huawei.com
[ Upstream commit 472497d0bdae890a896013332a0b673f9acdf2bf ]
If selftest and reset are performed at the same time, the phy loopback setting may be still in enable state after the reset, and device cannot link up. So fix this issue by disabling phy loopback before phy_start().
Fixes: 256727da7395 ("net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC") Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index e89820702540..c194bba187d6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -255,6 +255,8 @@ void hclge_mac_start_phy(struct hclge_dev *hdev) if (!phydev) return;
+ phy_loopback(phydev, false); + phy_start(phydev); }
From: Xin Long lucien.xin@gmail.com
[ Upstream commit 35b4f24415c854cd718ccdf38dbea6297f010aae ]
There's a panic that occurs in a few of envs, the call trace is as below:
[] general protection fault, ... 0x29acd70f1000a: 0000 [#1] SMP PTI [] RIP: 0010:sctp_ulpevent_notify_peer_addr_change+0x4b/0x1fa [sctp] [] sctp_assoc_control_transport+0x1b9/0x210 [sctp] [] sctp_do_8_2_transport_strike.isra.16+0x15c/0x220 [sctp] [] sctp_cmd_interpreter.isra.21+0x1231/0x1a10 [sctp] [] sctp_do_sm+0xc3/0x2a0 [sctp] [] sctp_generate_timeout_event+0x81/0xf0 [sctp]
This is caused by a transport use-after-free issue. When processing a duplicate COOKIE-ECHO chunk in sctp_sf_do_dupcook_a(), both COOKIE-ACK and SHUTDOWN chunks are allocated with the transort from the new asoc. However, later in the sideeffect machine, the old asoc is used to send them out and old asoc's shutdown_last_sent_to is set to the transport that SHUTDOWN chunk attached to in sctp_cmd_setup_t2(), which actually belongs to the new asoc. After the new_asoc is freed and the old asoc T2 timeout, the old asoc's shutdown_last_sent_to that is already freed would be accessed in sctp_sf_t2_timer_expire().
Thanks Alexander and Jere for helping dig into this issue.
To fix it, this patch is to do the asoc update first, then allocate the COOKIE-ACK and SHUTDOWN chunks with the 'updated' old asoc. This would make more sense, as a chunk from an asoc shouldn't be sent out with another asoc. We had fixed quite a few issues caused by this.
Fixes: 145cb2f7177d ("sctp: Fix bundling of SHUTDOWN with COOKIE-ACK") Reported-by: Alexander Sverdlin alexander.sverdlin@nokia.com Reported-by: syzbot+bbe538efd1046586f587@syzkaller.appspotmail.com Reported-by: Michal Tesar mtesar@redhat.com Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sctp/sm_statefuns.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index af2b7041fa4e..c7138f85f18f 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1852,20 +1852,35 @@ static enum sctp_disposition sctp_sf_do_dupcook_a( SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL());
- repl = sctp_make_cookie_ack(new_asoc, chunk); + /* Update the content of current association. */ + if (sctp_assoc_update((struct sctp_association *)asoc, new_asoc)) { + struct sctp_chunk *abort; + + abort = sctp_make_abort(asoc, NULL, sizeof(struct sctp_errhdr)); + if (abort) { + sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + } + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_PERR(SCTP_ERROR_RSRC_LOW)); + SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); + SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); + goto nomem; + } + + repl = sctp_make_cookie_ack(asoc, chunk); if (!repl) goto nomem;
/* Report association restart to upper layer. */ ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, - new_asoc->c.sinit_num_ostreams, - new_asoc->c.sinit_max_instreams, + asoc->c.sinit_num_ostreams, + asoc->c.sinit_max_instreams, NULL, GFP_ATOMIC); if (!ev) goto nomem_ev;
- /* Update the content of current association. */ - sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); if ((sctp_state(asoc, SHUTDOWN_PENDING) || sctp_state(asoc, SHUTDOWN_SENT)) &&
From: Anup Patel anup.patel@wdc.com
[ Upstream commit 533b4f3a789d49574e7ae0f6ececed153f651f97 ]
We should return a negative error code upon failure in riscv_hartid_to_cpuid() instead of NR_CPUS. This is also aligned with all uses of riscv_hartid_to_cpuid() which expect negative error code upon failure.
Fixes: 6825c7a80f18 ("RISC-V: Add logical CPU indexing for RISC-V") Fixes: f99fb607fb2b ("RISC-V: Use Linux logical CPU number instead of hartid") Signed-off-by: Anup Patel anup.patel@wdc.com Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index ea028d9e0d24..d44567490d91 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -54,7 +54,7 @@ int riscv_hartid_to_cpuid(int hartid) return i;
pr_err("Couldn't find cpu id for hartid [%d]\n", hartid); - return i; + return -ENOENT; }
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
From: Baptiste Lepers baptiste.lepers@gmail.com
[ Upstream commit f8f7e0fb22b2e75be55f2f0c13e229e75b0eac07 ]
Fix a misplaced barrier in call_decode. The struct rpc_rqst is modified as follows by xprt_complete_rqst:
req->rq_private_buf.len = copied; /* Ensure all writes are done before we update */ /* req->rq_reply_bytes_recvd */ smp_wmb(); req->rq_reply_bytes_recvd = copied;
And currently read as follows by call_decode:
smp_rmb(); // misplaced if (!req->rq_reply_bytes_recvd) goto out; req->rq_rcv_buf.len = req->rq_private_buf.len;
This patch places the smp_rmb after the if to ensure that rq_reply_bytes_recvd and rq_private_buf.len are read in order.
Fixes: 9ba828861c56a ("SUNRPC: Don't try to parse incomplete RPC messages") Signed-off-by: Baptiste Lepers baptiste.lepers@gmail.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/clnt.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index c2a01125be1a..f555d335e910 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -2456,12 +2456,6 @@ call_decode(struct rpc_task *task) task->tk_flags &= ~RPC_CALL_MAJORSEEN; }
- /* - * Ensure that we see all writes made by xprt_complete_rqst() - * before it changed req->rq_reply_bytes_recvd. - */ - smp_rmb(); - /* * Did we ever call xprt_complete_rqst()? If not, we should assume * the message is incomplete. @@ -2470,6 +2464,11 @@ call_decode(struct rpc_task *task) if (!req->rq_reply_bytes_recvd) goto out;
+ /* Ensure that we see all writes made by xprt_complete_rqst() + * before it changed req->rq_reply_bytes_recvd. + */ + smp_rmb(); + req->rq_rcv_buf.len = req->rq_private_buf.len; trace_rpc_xdr_recvfrom(task, &req->rq_rcv_buf);
From: Brendan Jackman jackmanb@google.com
[ Upstream commit 2a30f9440640c418bcfbea9b2b344d268b58e0a2 ]
One of our benchmarks running in (Google-internal) CI pushes data through the ringbuf faster htan than userspace is able to consume it. In this case it seems we're actually able to get >INT_MAX entries in a single ring_buffer__consume() call. ASAN detected that cnt overflows in this case.
Fix by using 64-bit counter internally and then capping the result to INT_MAX before converting to the int return type. Do the same for the ring_buffer__poll().
Fixes: bf99c936f947 (libbpf: Add BPF ring buffer support) Signed-off-by: Brendan Jackman jackmanb@google.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20210429130510.1621665-1-jackmanb@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/lib/bpf/ringbuf.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c index e7a8d847161f..1d80ad4e0de8 100644 --- a/tools/lib/bpf/ringbuf.c +++ b/tools/lib/bpf/ringbuf.c @@ -202,9 +202,11 @@ static inline int roundup_len(__u32 len) return (len + 7) / 8 * 8; }
-static int ringbuf_process_ring(struct ring* r) +static int64_t ringbuf_process_ring(struct ring* r) { - int *len_ptr, len, err, cnt = 0; + int *len_ptr, len, err; + /* 64-bit to avoid overflow in case of extreme application behavior */ + int64_t cnt = 0; unsigned long cons_pos, prod_pos; bool got_new_data; void *sample; @@ -244,12 +246,14 @@ done: }
/* Consume available ring buffer(s) data without event polling. - * Returns number of records consumed across all registered ring buffers, or - * negative number if any of the callbacks return error. + * Returns number of records consumed across all registered ring buffers (or + * INT_MAX, whichever is less), or negative number if any of the callbacks + * return error. */ int ring_buffer__consume(struct ring_buffer *rb) { - int i, err, res = 0; + int64_t err, res = 0; + int i;
for (i = 0; i < rb->ring_cnt; i++) { struct ring *ring = &rb->rings[i]; @@ -259,18 +263,24 @@ int ring_buffer__consume(struct ring_buffer *rb) return err; res += err; } + if (res > INT_MAX) + return INT_MAX; return res; }
/* Poll for available data and consume records, if any are available. - * Returns number of records consumed, or negative number, if any of the - * registered callbacks returned error. + * Returns number of records consumed (or INT_MAX, whichever is less), or + * negative number, if any of the registered callbacks returned error. */ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms) { - int i, cnt, err, res = 0; + int i, cnt; + int64_t err, res = 0;
cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms); + if (cnt < 0) + return -errno; + for (i = 0; i < cnt; i++) { __u32 ring_id = rb->events[i].data.fd; struct ring *ring = &rb->rings[ring_id]; @@ -280,7 +290,9 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms) return err; res += err; } - return cnt < 0 ? -errno : res; + if (res > INT_MAX) + return INT_MAX; + return res; }
/* Get an fd that can be used to sleep until data is available in the ring(s) */
From: Md Haris Iqbal haris.iqbal@cloud.ionos.com
[ Upstream commit 80d43cbd46155744ee450d2476ee4fcf2917ae9b ]
The member queue_depth in the structure rnbd_clt_session is read from the rtrs client side using the function rtrs_clt_query, which in turn is read from the rtrs_clt structure. It should really be of type size_t.
Fixes: 90426e89f54db ("block/rnbd: client: private header with client structs and functions") Signed-off-by: Md Haris Iqbal haris.iqbal@ionos.com Reviewed-by: Guoqing Jiang guoqing.jiang@ionos.com Signed-off-by: Gioh Kim gi-oh.kim@ionos.com Link: https://lore.kernel.org/r/20210428061359.206794-2-gi-oh.kim@ionos.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/block/rnbd/rnbd-clt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h index 537d499dad3b..73d980840531 100644 --- a/drivers/block/rnbd/rnbd-clt.h +++ b/drivers/block/rnbd/rnbd-clt.h @@ -87,7 +87,7 @@ struct rnbd_clt_session { DECLARE_BITMAP(cpu_queues_bm, NR_CPUS); int __percpu *cpu_rr; /* per-cpu var for CPU round-robin */ atomic_t busy; - int queue_depth; + size_t queue_depth; u32 max_io_size; struct blk_mq_tag_set tag_set; struct mutex lock; /* protects state and devs_list */
From: Md Haris Iqbal haris.iqbal@cloud.ionos.com
[ Upstream commit 1056ad829ec43f9b705b507c2093b05e2088b0b7 ]
In case none of the paths are in connected state, the function rtrs_clt_query returns an error. In such a case, error out since the values in the rtrs_attrs structure would be garbage.
Fixes: f7a7a5c228d45 ("block/rnbd: client: main functionality") Signed-off-by: Md Haris Iqbal haris.iqbal@ionos.com Reviewed-by: Guoqing Jiang guoqing.jiang@ionos.com Signed-off-by: Jack Wang jinpu.wang@ionos.com Signed-off-by: Gioh Kim gi-oh.kim@ionos.com Link: https://lore.kernel.org/r/20210428061359.206794-4-gi-oh.kim@ionos.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/block/rnbd/rnbd-clt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c index 45a470076652..5ab7319ff2ea 100644 --- a/drivers/block/rnbd/rnbd-clt.c +++ b/drivers/block/rnbd/rnbd-clt.c @@ -693,7 +693,11 @@ static void remap_devs(struct rnbd_clt_session *sess) return; }
- rtrs_clt_query(sess->rtrs, &attrs); + err = rtrs_clt_query(sess->rtrs, &attrs); + if (err) { + pr_err("rtrs_clt_query("%s"): %d\n", sess->sessname, err); + return; + } mutex_lock(&sess->lock); sess->max_io_size = attrs.max_io_size;
@@ -1234,7 +1238,11 @@ find_and_get_or_create_sess(const char *sessname, err = PTR_ERR(sess->rtrs); goto wake_up_and_put; } - rtrs_clt_query(sess->rtrs, &attrs); + + err = rtrs_clt_query(sess->rtrs, &attrs); + if (err) + goto close_rtrs; + sess->max_io_size = attrs.max_io_size; sess->queue_depth = attrs.queue_depth;
From: Jim Quinlan jim2101024@gmail.com
[ Upstream commit e8d6f9e56187c101b325e8d18f1d4032420d08ff ]
This driver may use one of two resets controllers. Keep them in separate variables to keep things simple. The reset controller "rescal" is shared between the AHCI driver and the PCIe driver for the BrcmSTB 7216 chip. Use devm_reset_control_get_optional_shared() to handle this sharing.
[bhelgaas: add Jens' ack from v5 posting] Fixes: 272ecd60a636 ("ata: ahci_brcm: BCM7216 reset is self de-asserting") Fixes: c345ec6a50e9 ("ata: ahci_brcm: Support BCM7216 reset controller name") Link: https://lore.kernel.org/r/20210430152156.21162-3-jim2101024@gmail.com Signed-off-by: Jim Quinlan jim2101024@gmail.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Acked-by: Jens Axboe axboe@kernel.dk Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ata/ahci_brcm.c | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 5b32df5d33ad..6e9c5ade4c2e 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -86,7 +86,8 @@ struct brcm_ahci_priv { u32 port_mask; u32 quirks; enum brcm_ahci_version version; - struct reset_control *rcdev; + struct reset_control *rcdev_rescal; + struct reset_control *rcdev_ahci; };
static inline u32 brcm_sata_readreg(void __iomem *addr) @@ -352,8 +353,8 @@ static int brcm_ahci_suspend(struct device *dev) else ret = 0;
- if (priv->version != BRCM_SATA_BCM7216) - reset_control_assert(priv->rcdev); + reset_control_assert(priv->rcdev_ahci); + reset_control_rearm(priv->rcdev_rescal);
return ret; } @@ -365,10 +366,10 @@ static int __maybe_unused brcm_ahci_resume(struct device *dev) struct brcm_ahci_priv *priv = hpriv->plat_data; int ret = 0;
- if (priv->version == BRCM_SATA_BCM7216) - ret = reset_control_reset(priv->rcdev); - else - ret = reset_control_deassert(priv->rcdev); + ret = reset_control_deassert(priv->rcdev_ahci); + if (ret) + return ret; + ret = reset_control_reset(priv->rcdev_rescal); if (ret) return ret;
@@ -434,7 +435,6 @@ static int brcm_ahci_probe(struct platform_device *pdev) { const struct of_device_id *of_id; struct device *dev = &pdev->dev; - const char *reset_name = NULL; struct brcm_ahci_priv *priv; struct ahci_host_priv *hpriv; struct resource *res; @@ -456,15 +456,15 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (IS_ERR(priv->top_ctrl)) return PTR_ERR(priv->top_ctrl);
- /* Reset is optional depending on platform and named differently */ - if (priv->version == BRCM_SATA_BCM7216) - reset_name = "rescal"; - else - reset_name = "ahci"; - - priv->rcdev = devm_reset_control_get_optional(&pdev->dev, reset_name); - if (IS_ERR(priv->rcdev)) - return PTR_ERR(priv->rcdev); + if (priv->version == BRCM_SATA_BCM7216) { + priv->rcdev_rescal = devm_reset_control_get_optional_shared( + &pdev->dev, "rescal"); + if (IS_ERR(priv->rcdev_rescal)) + return PTR_ERR(priv->rcdev_rescal); + } + priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci"); + if (IS_ERR(priv->rcdev_ahci)) + return PTR_ERR(priv->rcdev_ahci);
hpriv = ahci_platform_get_resources(pdev, 0); if (IS_ERR(hpriv)) @@ -485,10 +485,10 @@ static int brcm_ahci_probe(struct platform_device *pdev) break; }
- if (priv->version == BRCM_SATA_BCM7216) - ret = reset_control_reset(priv->rcdev); - else - ret = reset_control_deassert(priv->rcdev); + ret = reset_control_reset(priv->rcdev_rescal); + if (ret) + return ret; + ret = reset_control_deassert(priv->rcdev_ahci); if (ret) return ret;
@@ -539,8 +539,8 @@ out_disable_regulators: out_disable_clks: ahci_platform_disable_clks(hpriv); out_reset: - if (priv->version != BRCM_SATA_BCM7216) - reset_control_assert(priv->rcdev); + reset_control_assert(priv->rcdev_ahci); + reset_control_rearm(priv->rcdev_rescal); return ret; }
From: Jim Quinlan jim2101024@gmail.com
[ Upstream commit bb610757fcd74558ad94fe19993fd4470208dd02 ]
The Broadcom STB PCIe RC uses a reset control "rescal" for certain chips. The "rescal" implements a "pulse reset" so using assert/deassert is wrong for this device. Instead, we use reset/rearm. We need to use rearm so that we can reset it after a suspend/resume cycle; w/o using "rearm", the "rescal" device will only ever fire once.
Of course for suspend/resume to work we also need to put the reset/rearm calls in the suspend and resume routines.
Fixes: 740d6c3708a9 ("PCI: brcmstb: Add control of rescal reset") Link: https://lore.kernel.org/r/20210430152156.21162-4-jim2101024@gmail.com Signed-off-by: Jim Quinlan jim2101024@gmail.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-brcmstb.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index 69c999222cc8..08bc788d9422 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1148,6 +1148,7 @@ static int brcm_pcie_suspend(struct device *dev)
brcm_pcie_turn_off(pcie); ret = brcm_phy_stop(pcie); + reset_control_rearm(pcie->rescal); clk_disable_unprepare(pcie->clk);
return ret; @@ -1163,9 +1164,13 @@ static int brcm_pcie_resume(struct device *dev) base = pcie->base; clk_prepare_enable(pcie->clk);
+ ret = reset_control_reset(pcie->rescal); + if (ret) + goto err_disable_clk; + ret = brcm_phy_start(pcie); if (ret) - goto err; + goto err_reset;
/* Take bridge out of reset so we can access the SERDES reg */ pcie->bridge_sw_init_set(pcie, 0); @@ -1180,14 +1185,16 @@ static int brcm_pcie_resume(struct device *dev)
ret = brcm_pcie_setup(pcie); if (ret) - goto err; + goto err_reset;
if (pcie->msi) brcm_msi_set_regs(pcie->msi);
return 0;
-err: +err_reset: + reset_control_rearm(pcie->rescal); +err_disable_clk: clk_disable_unprepare(pcie->clk); return ret; } @@ -1197,7 +1204,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie) brcm_msi_remove(pcie); brcm_pcie_turn_off(pcie); brcm_phy_stop(pcie); - reset_control_assert(pcie->rescal); + reset_control_rearm(pcie->rescal); clk_disable_unprepare(pcie->clk); }
@@ -1278,13 +1285,13 @@ static int brcm_pcie_probe(struct platform_device *pdev) return PTR_ERR(pcie->perst_reset); }
- ret = reset_control_deassert(pcie->rescal); + ret = reset_control_reset(pcie->rescal); if (ret) dev_err(&pdev->dev, "failed to deassert 'rescal'\n");
ret = brcm_phy_start(pcie); if (ret) { - reset_control_assert(pcie->rescal); + reset_control_rearm(pcie->rescal); clk_disable_unprepare(pcie->clk); return ret; }
From: Lv Yunlong lyl2019@mail.ustc.edu.cn
[ Upstream commit 643001b47adc844ae33510c4bb93c236667008a3 ]
In enic_hard_start_xmit, it calls enic_queue_wq_skb(). Inside enic_queue_wq_skb, if some error happens, the skb will be freed by dev_kfree_skb(skb). But the freed skb is still used in skb_tx_timestamp(skb).
My patch makes enic_queue_wq_skb() return error and goto spin_unlock() incase of error. The solution is provided by Govind. See https://lkml.org/lkml/2021/4/30/961.
Fixes: fb7516d42478e ("enic: add sw timestamp support") Signed-off-by: Lv Yunlong lyl2019@mail.ustc.edu.cn Acked-by: Govindarajulu Varadarajan gvaradar@cisco.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/cisco/enic/enic_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index f04ec53544ae..b1443ff439de 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -768,7 +768,7 @@ static inline int enic_queue_wq_skb_encap(struct enic *enic, struct vnic_wq *wq, return err; }
-static inline void enic_queue_wq_skb(struct enic *enic, +static inline int enic_queue_wq_skb(struct enic *enic, struct vnic_wq *wq, struct sk_buff *skb) { unsigned int mss = skb_shinfo(skb)->gso_size; @@ -814,6 +814,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, wq->to_use = buf->next; dev_kfree_skb(skb); } + return err; }
/* netif_tx_lock held, process context with BHs disabled, or BH */ @@ -857,7 +858,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; }
- enic_queue_wq_skb(enic, wq, skb); + if (enic_queue_wq_skb(enic, wq, skb)) + goto error;
if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS) netif_tx_stop_queue(txq); @@ -865,6 +867,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, if (!netdev_xmit_more() || netif_xmit_stopped(txq)) vnic_wq_doorbell(wq);
+error: spin_unlock(&enic->wq_lock[txq_map]);
return NETDEV_TX_OK;
From: Xin Long lucien.xin@gmail.com
[ Upstream commit f282df0391267fb2b263da1cc3233aa6fb81defc ]
Normally SCTP_MIB_CURRESTAB is always incremented once asoc enter into ESTABLISHED from the state < ESTABLISHED and decremented when the asoc is being deleted.
However, in sctp_sf_do_dupcook_b(), the asoc's state can be changed to ESTABLISHED from the state >= ESTABLISHED where it shouldn't increment SCTP_MIB_CURRESTAB. Otherwise, one asoc may increment MIB_CURRESTAB multiple times but only decrement once at the end.
I was able to reproduce it by using scapy to do the 4-way shakehands, after that I replayed the COOKIE-ECHO chunk with 'peer_vtag' field changed to different values, and SCTP_MIB_CURRESTAB was incremented multiple times and never went back to 0 even when the asoc was freed.
This patch is to fix it by only incrementing SCTP_MIB_CURRESTAB when the state < ESTABLISHED in sctp_sf_do_dupcook_b().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: Xin Long lucien.xin@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sctp/sm_statefuns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index c7138f85f18f..73bb4c6e9201 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1944,7 +1944,8 @@ static enum sctp_disposition sctp_sf_do_dupcook_b( sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_ESTABLISHED)); - SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); + if (asoc->state < SCTP_STATE_ESTABLISHED) + SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
repl = sctp_make_cookie_ack(new_asoc, chunk);
From: Pablo Neira Ayuso pablo@netfilter.org
[ Upstream commit c7d13358b6a2f49f81a34aa323a2d0878a0532a2 ]
This extension breaks when trying to delete rules, add a new revision to fix this.
Fixes: 5e6874cdb8de ("[SECMARK]: Add xtables SECMARK target") Signed-off-by: Phil Sutter phil@nwl.cc Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/uapi/linux/netfilter/xt_SECMARK.h | 6 ++ net/netfilter/xt_SECMARK.c | 88 ++++++++++++++++++----- 2 files changed, 75 insertions(+), 19 deletions(-)
diff --git a/include/uapi/linux/netfilter/xt_SECMARK.h b/include/uapi/linux/netfilter/xt_SECMARK.h index 1f2a708413f5..beb2cadba8a9 100644 --- a/include/uapi/linux/netfilter/xt_SECMARK.h +++ b/include/uapi/linux/netfilter/xt_SECMARK.h @@ -20,4 +20,10 @@ struct xt_secmark_target_info { char secctx[SECMARK_SECCTX_MAX]; };
+struct xt_secmark_target_info_v1 { + __u8 mode; + char secctx[SECMARK_SECCTX_MAX]; + __u32 secid; +}; + #endif /*_XT_SECMARK_H_target */ diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 75625d13e976..498a0bf6f044 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -24,10 +24,9 @@ MODULE_ALIAS("ip6t_SECMARK"); static u8 mode;
static unsigned int -secmark_tg(struct sk_buff *skb, const struct xt_action_param *par) +secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info) { u32 secmark = 0; - const struct xt_secmark_target_info *info = par->targinfo;
switch (mode) { case SECMARK_MODE_SEL: @@ -41,7 +40,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par) return XT_CONTINUE; }
-static int checkentry_lsm(struct xt_secmark_target_info *info) +static int checkentry_lsm(struct xt_secmark_target_info_v1 *info) { int err;
@@ -73,15 +72,15 @@ static int checkentry_lsm(struct xt_secmark_target_info *info) return 0; }
-static int secmark_tg_check(const struct xt_tgchk_param *par) +static int +secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info) { - struct xt_secmark_target_info *info = par->targinfo; int err;
- if (strcmp(par->table, "mangle") != 0 && - strcmp(par->table, "security") != 0) { + if (strcmp(table, "mangle") != 0 && + strcmp(table, "security") != 0) { pr_info_ratelimited("only valid in 'mangle' or 'security' table, not '%s'\n", - par->table); + table); return -EINVAL; }
@@ -116,25 +115,76 @@ static void secmark_tg_destroy(const struct xt_tgdtor_param *par) } }
-static struct xt_target secmark_tg_reg __read_mostly = { - .name = "SECMARK", - .revision = 0, - .family = NFPROTO_UNSPEC, - .checkentry = secmark_tg_check, - .destroy = secmark_tg_destroy, - .target = secmark_tg, - .targetsize = sizeof(struct xt_secmark_target_info), - .me = THIS_MODULE, +static int secmark_tg_check_v0(const struct xt_tgchk_param *par) +{ + struct xt_secmark_target_info *info = par->targinfo; + struct xt_secmark_target_info_v1 newinfo = { + .mode = info->mode, + }; + int ret; + + memcpy(newinfo.secctx, info->secctx, SECMARK_SECCTX_MAX); + + ret = secmark_tg_check(par->table, &newinfo); + info->secid = newinfo.secid; + + return ret; +} + +static unsigned int +secmark_tg_v0(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct xt_secmark_target_info *info = par->targinfo; + struct xt_secmark_target_info_v1 newinfo = { + .secid = info->secid, + }; + + return secmark_tg(skb, &newinfo); +} + +static int secmark_tg_check_v1(const struct xt_tgchk_param *par) +{ + return secmark_tg_check(par->table, par->targinfo); +} + +static unsigned int +secmark_tg_v1(struct sk_buff *skb, const struct xt_action_param *par) +{ + return secmark_tg(skb, par->targinfo); +} + +static struct xt_target secmark_tg_reg[] __read_mostly = { + { + .name = "SECMARK", + .revision = 0, + .family = NFPROTO_UNSPEC, + .checkentry = secmark_tg_check_v0, + .destroy = secmark_tg_destroy, + .target = secmark_tg_v0, + .targetsize = sizeof(struct xt_secmark_target_info), + .me = THIS_MODULE, + }, + { + .name = "SECMARK", + .revision = 1, + .family = NFPROTO_UNSPEC, + .checkentry = secmark_tg_check_v1, + .destroy = secmark_tg_destroy, + .target = secmark_tg_v1, + .targetsize = sizeof(struct xt_secmark_target_info_v1), + .usersize = offsetof(struct xt_secmark_target_info_v1, secid), + .me = THIS_MODULE, + }, };
static int __init secmark_tg_init(void) { - return xt_register_target(&secmark_tg_reg); + return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg)); }
static void __exit secmark_tg_exit(void) { - xt_unregister_target(&secmark_tg_reg); + xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg)); }
module_init(secmark_tg_init);
From: Xuan Zhuo xuanzhuo@linux.alibaba.com
[ Upstream commit ac31565c21937eee9117e43c9cd34f557f6f1cb8 ]
When desc->len is equal to chunk_size, it is legal. But when the xp_aligned_validate_desc() got chunk_end from desc->addr + desc->len pointing to the next chunk during the check, it caused the check to fail.
This problem was first introduced in bbff2f321a86 ("xsk: new descriptor addressing scheme"). Later in 2b43470add8c ("xsk: Introduce AF_XDP buffer allocation API") this piece of code was moved into the new function called xp_aligned_validate_desc(). This function was then moved into xsk_queue.h via 26062b185eee ("xsk: Explicitly inline functions and move definitions").
Fixes: bbff2f321a86 ("xsk: new descriptor addressing scheme") Signed-off-by: Xuan Zhuo xuanzhuo@linux.alibaba.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Acked-by: Magnus Karlsson magnus.karlsson@intel.com Link: https://lore.kernel.org/bpf/20210428094424.54435-1-xuanzhuo@linux.alibaba.co... Signed-off-by: Sasha Levin sashal@kernel.org --- net/xdp/xsk_queue.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index 2823b7c3302d..40f359bf2044 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h @@ -128,13 +128,12 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr) static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool, struct xdp_desc *desc) { - u64 chunk, chunk_end; + u64 chunk;
- chunk = xp_aligned_extract_addr(pool, desc->addr); - chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len); - if (chunk != chunk_end) + if (desc->len > pool->chunk_size) return false;
+ chunk = xp_aligned_extract_addr(pool, desc->addr); if (chunk >= pool->addrs_cnt) return false;
From: Sandipan Das sandipan@linux.ibm.com
[ Upstream commit b910fcbada9721c21f1d59ab59e07e8e354c23cc ]
Trace memory is cleared and the corresponding dcache lines are flushed after allocation. However, this should not be done using the PFN. This adds the missing conversion to virtual address.
Fixes: 2ac02e5ecec0 ("powerpc/mm: Remove dcache flush from memory remove.") Signed-off-by: Sandipan Das sandipan@linux.ibm.com Reviewed-by: Aneesh Kumar K.V aneesh.kumar@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210501160254.1179831-1-sandipan@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/powernv/memtrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 019669eb21d2..4ab7c3ef5826 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -88,8 +88,8 @@ static void memtrace_clear_range(unsigned long start_pfn, * Before we go ahead and use this range as cache inhibited range * flush the cache. */ - flush_dcache_range_chunked(PFN_PHYS(start_pfn), - PFN_PHYS(start_pfn + nr_pages), + flush_dcache_range_chunked((unsigned long)pfn_to_kaddr(start_pfn), + (unsigned long)pfn_to_kaddr(start_pfn + nr_pages), FLUSH_CHUNK_SIZE); }
From: Ramesh Babu B ramesh.babu.b@intel.com
[ Upstream commit 4c7a94286ef7ac7301d633f17519fb1bb89d7550 ]
In promiscuous mode Receive All bit is set in GMAC packet filter register, but outside promiscuous mode Receive All bit is not cleared, which resulted in all network packets are received when toggle (ON/OFF) the promiscuous mode.
Fixes: e0f9956a3862 ("net: stmmac: Add option for VLAN filter fail queue enable") Signed-off-by: Ramesh Babu B ramesh.babu.b@intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 29f765a246a0..aaf37598cbd3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -638,6 +638,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, value &= ~GMAC_PACKET_FILTER_PCF; value &= ~GMAC_PACKET_FILTER_PM; value &= ~GMAC_PACKET_FILTER_PR; + value &= ~GMAC_PACKET_FILTER_RA; if (dev->flags & IFF_PROMISC) { /* VLAN Tag Filter Fail Packets Queuing */ if (hw->vlan_fail_q_en) {
From: Kees Cook keescook@chromium.org
[ Upstream commit 5bbf219328849e83878bddb7c226d8d42e84affc ]
An out of bounds write happens when setting the default power state. KASAN sees this as:
[drm] radeon: 512M of GTT memory ready. [drm] GART: num cpu pages 131072, num gpu pages 131072 ================================================================== BUG: KASAN: slab-out-of-bounds in radeon_atombios_parse_power_table_1_3+0x1837/0x1998 [radeon] Write of size 4 at addr ffff88810178d858 by task systemd-udevd/157
CPU: 0 PID: 157 Comm: systemd-udevd Not tainted 5.12.0-E620 #50 Hardware name: eMachines eMachines E620 /Nile , BIOS V1.03 09/30/2008 Call Trace: dump_stack+0xa5/0xe6 print_address_description.constprop.0+0x18/0x239 kasan_report+0x170/0x1a8 radeon_atombios_parse_power_table_1_3+0x1837/0x1998 [radeon] radeon_atombios_get_power_modes+0x144/0x1888 [radeon] radeon_pm_init+0x1019/0x1904 [radeon] rs690_init+0x76e/0x84a [radeon] radeon_device_init+0x1c1a/0x21e5 [radeon] radeon_driver_load_kms+0xf5/0x30b [radeon] drm_dev_register+0x255/0x4a0 [drm] radeon_pci_probe+0x246/0x2f6 [radeon] pci_device_probe+0x1aa/0x294 really_probe+0x30e/0x850 driver_probe_device+0xe6/0x135 device_driver_attach+0xc1/0xf8 __driver_attach+0x13f/0x146 bus_for_each_dev+0xfa/0x146 bus_add_driver+0x2b3/0x447 driver_register+0x242/0x2c1 do_one_initcall+0x149/0x2fd do_init_module+0x1ae/0x573 load_module+0x4dee/0x5cca __do_sys_finit_module+0xf1/0x140 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae
Without KASAN, this will manifest later when the kernel attempts to allocate memory that was stomped, since it collides with the inline slab freelist pointer:
invalid opcode: 0000 [#1] SMP NOPTI CPU: 0 PID: 781 Comm: openrc-run.sh Tainted: G W 5.10.12-gentoo-E620 #2 Hardware name: eMachines eMachines E620 /Nile , BIOS V1.03 09/30/2008 RIP: 0010:kfree+0x115/0x230 Code: 89 c5 e8 75 ea ff ff 48 8b 00 0f ba e0 09 72 63 e8 1f f4 ff ff 41 89 c4 48 8b 45 00 0f ba e0 10 72 0a 48 8b 45 08 a8 01 75 02 <0f> 0b 44 89 e1 48 c7 c2 00 f0 ff ff be 06 00 00 00 48 d3 e2 48 c7 RSP: 0018:ffffb42f40267e10 EFLAGS: 00010246 RAX: ffffd61280ee8d88 RBX: 0000000000000004 RCX: 000000008010000d RDX: 4000000000000000 RSI: ffffffffba1360b0 RDI: ffffd61280ee8d80 RBP: ffffd61280ee8d80 R08: ffffffffb91bebdf R09: 0000000000000000 R10: ffff8fe2c1047ac8 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000100 FS: 00007fe80eff6b68(0000) GS:ffff8fe339c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fe80eec7bc0 CR3: 0000000038012000 CR4: 00000000000006f0 Call Trace: __free_fdtable+0x16/0x1f put_files_struct+0x81/0x9b do_exit+0x433/0x94d do_group_exit+0xa6/0xa6 __x64_sys_exit_group+0xf/0xf do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fe80ef64bea Code: Unable to access opcode bytes at RIP 0x7fe80ef64bc0. RSP: 002b:00007ffdb1c47528 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fe80ef64bea RDX: 00007fe80ef64f60 RSI: 0000000000000000 RDI: 0000000000000000 RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 R10: 00007fe80ee2c620 R11: 0000000000000246 R12: 00007fe80eff41e0 R13: 00000000ffffffff R14: 0000000000000024 R15: 00007fe80edf9cd0 Modules linked in: radeon(+) ath5k(+) snd_hda_codec_realtek ...
Use a valid power_state index when initializing the "flags" and "misc" and "misc2" fields.
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211537 Reported-by: Erhard F. erhard_f@mailbox.org Fixes: a48b9b4edb8b ("drm/radeon/kms/pm: add asic specific callbacks for getting power state (v2)") Fixes: 79daedc94281 ("drm/radeon/kms: minor pm cleanups") Signed-off-by: Kees Cook keescook@chromium.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/radeon/radeon_atombios.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 42301b4e56f5..f9f4efa1738c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2250,10 +2250,10 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) rdev->pm.default_power_state_index = state_index - 1; rdev->pm.power_state[state_index - 1].default_clock_mode = &rdev->pm.power_state[state_index - 1].clock_info[0]; - rdev->pm.power_state[state_index].flags &= + rdev->pm.power_state[state_index - 1].flags &= ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - rdev->pm.power_state[state_index].misc = 0; - rdev->pm.power_state[state_index].misc2 = 0; + rdev->pm.power_state[state_index - 1].misc = 0; + rdev->pm.power_state[state_index - 1].misc2 = 0; } return state_index; }
From: Kees Cook keescook@chromium.org
[ Upstream commit c69f27137a38d24301a6b659454a91ad85dff4aa ]
Avoid leaving a hanging pre-allocated clock_info if last mode is invalid, and avoid heap corruption if no valid modes are found.
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211537 Fixes: 6991b8f2a319 ("drm/radeon/kms: fix segfault in pm rework") Signed-off-by: Kees Cook keescook@chromium.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/radeon/radeon_atombios.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f9f4efa1738c..28c4413f4dc8 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2120,11 +2120,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) return state_index; /* last mode is usually default, array is low to high */ for (i = 0; i < num_modes; i++) { - rdev->pm.power_state[state_index].clock_info = - kcalloc(1, sizeof(struct radeon_pm_clock_info), - GFP_KERNEL); + /* avoid memory leaks from invalid modes or unknown frev. */ + if (!rdev->pm.power_state[state_index].clock_info) { + rdev->pm.power_state[state_index].clock_info = + kzalloc(sizeof(struct radeon_pm_clock_info), + GFP_KERNEL); + } if (!rdev->pm.power_state[state_index].clock_info) - return state_index; + goto out; rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; switch (frev) { @@ -2243,8 +2246,15 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) break; } } +out: + /* free any unused clock_info allocation. */ + if (state_index && state_index < num_modes) { + kfree(rdev->pm.power_state[state_index].clock_info); + rdev->pm.power_state[state_index].clock_info = NULL; + } + /* last mode is usually default */ - if (rdev->pm.default_power_state_index == -1) { + if (state_index && rdev->pm.default_power_state_index == -1) { rdev->pm.power_state[state_index - 1].type = POWER_STATE_TYPE_DEFAULT; rdev->pm.default_power_state_index = state_index - 1;
From: Marc Zyngier maz@kernel.org
[ Upstream commit 9eb563cdabe1d583c262042d5d44cc256f644543 ]
In subsequent patches we'll allow an FIQ handler to be registered, and FIQ exceptions will need to be triaged very similarly to IRQ exceptions. So that we can reuse the existing logic, this patch factors the IRQ triage logic out into macros that can be reused for FIQ.
The macros are named to follow the elX_foo_handler scheme used by the C exception handlers. For consistency with other top-level exception handlers, the kernel_entry/kernel_exit logic is not moved into the macros. As FIQ will use a different C handler, this handler name is provided as an argument to the macros.
There should be no functional change as a result of this patch.
Signed-off-by: Marc Zyngier maz@kernel.org [Mark: rework macros, commit message, rebase before DAIF rework] Signed-off-by: Mark Rutland mark.rutland@arm.com Tested-by: Hector Martin marcan@marcan.st Cc: James Morse james.morse@arm.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Will Deacon will@kernel.org Acked-by: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20210315115629.57191-5-mark.rutland@arm.com Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/kernel/entry.S | 80 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 37 deletions(-)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 9b205744a233..feb9e4b9f9f2 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -493,8 +493,8 @@ tsk .req x28 // current thread_info /* * Interrupt handling. */ - .macro irq_handler - ldr_l x1, handle_arch_irq + .macro irq_handler, handler:req + ldr_l x1, \handler mov x0, sp irq_stack_entry blr x1 @@ -533,6 +533,45 @@ alternative_endif #endif .endm
+ .macro el1_interrupt_handler, handler:req + gic_prio_irq_setup pmr=x20, tmp=x1 + enable_da_f + + mov x0, sp + bl enter_el1_irq_or_nmi + + irq_handler \handler + +#ifdef CONFIG_PREEMPTION + ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count +alternative_if ARM64_HAS_IRQ_PRIO_MASKING + /* + * DA_F were cleared at start of handling. If anything is set in DAIF, + * we come back from an NMI, so skip preemption + */ + mrs x0, daif + orr x24, x24, x0 +alternative_else_nop_endif + cbnz x24, 1f // preempt count != 0 || NMI return path + bl arm64_preempt_schedule_irq // irq en/disable is done inside +1: +#endif + + mov x0, sp + bl exit_el1_irq_or_nmi + .endm + + .macro el0_interrupt_handler, handler:req + gic_prio_irq_setup pmr=x20, tmp=x0 + user_exit_irqoff + enable_da_f + + tbz x22, #55, 1f + bl do_el0_irq_bp_hardening +1: + irq_handler \handler + .endm + .text
/* @@ -662,32 +701,7 @@ SYM_CODE_END(el1_sync) .align 6 SYM_CODE_START_LOCAL_NOALIGN(el1_irq) kernel_entry 1 - gic_prio_irq_setup pmr=x20, tmp=x1 - enable_da_f - - mov x0, sp - bl enter_el1_irq_or_nmi - - irq_handler - -#ifdef CONFIG_PREEMPTION - ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count -alternative_if ARM64_HAS_IRQ_PRIO_MASKING - /* - * DA_F were cleared at start of handling. If anything is set in DAIF, - * we come back from an NMI, so skip preemption - */ - mrs x0, daif - orr x24, x24, x0 -alternative_else_nop_endif - cbnz x24, 1f // preempt count != 0 || NMI return path - bl arm64_preempt_schedule_irq // irq en/disable is done inside -1: -#endif - - mov x0, sp - bl exit_el1_irq_or_nmi - + el1_interrupt_handler handle_arch_irq kernel_exit 1 SYM_CODE_END(el1_irq)
@@ -727,15 +741,7 @@ SYM_CODE_END(el0_error_compat) SYM_CODE_START_LOCAL_NOALIGN(el0_irq) kernel_entry 0 el0_irq_naked: - gic_prio_irq_setup pmr=x20, tmp=x0 - user_exit_irqoff - enable_da_f - - tbz x22, #55, 1f - bl do_el0_irq_bp_hardening -1: - irq_handler - + el0_interrupt_handler handle_arch_irq b ret_to_user SYM_CODE_END(el0_irq)
[ Upstream commit 4d6a38da8e79e94cbd1344aa90876f0f805db705 ]
Zenghui reports that booting a kernel with "irqchip.gicv3_pseudo_nmi=1" on the command line hits a warning during kernel entry, due to the way we manipulate the PMR.
Early in the entry sequence, we call lockdep_hardirqs_off() to inform lockdep that interrupts have been masked (as the HW sets DAIF wqhen entering an exception). Architecturally PMR_EL1 is not affected by exception entry, and we don't set GIC_PRIO_PSR_I_SET in the PMR early in the exception entry sequence, so early in exception entry the PMR can indicate that interrupts are unmasked even though they are masked by DAIF.
If DEBUG_LOCKDEP is selected, lockdep_hardirqs_off() will check that interrupts are masked, before we set GIC_PRIO_PSR_I_SET in any of the exception entry paths, and hence lockdep_hardirqs_off() will WARN() that something is amiss.
We can avoid this by consistently setting GIC_PRIO_PSR_I_SET during exception entry so that kernel code sees a consistent environment. We must also update local_daif_inherit() to undo this, as currently only touches DAIF. For other paths, local_daif_restore() will update both DAIF and the PMR. With this done, we can remove the existing special cases which set this later in the entry code.
We always use (GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET) for consistency with local_daif_save(), as this will warn if it ever encounters (GIC_PRIO_IRQOFF | GIC_PRIO_PSR_I_SET), and never sets this itself. This matches the gic_prio_kentry_setup that we have to retain for ret_to_user.
The original splat from Zenghui's report was:
| DEBUG_LOCKS_WARN_ON(!irqs_disabled()) | WARNING: CPU: 3 PID: 125 at kernel/locking/lockdep.c:4258 lockdep_hardirqs_off+0xd4/0xe8 | Modules linked in: | CPU: 3 PID: 125 Comm: modprobe Tainted: G W 5.12.0-rc8+ #463 | Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 | pstate: 604003c5 (nZCv DAIF +PAN -UAO -TCO BTYPE=--) | pc : lockdep_hardirqs_off+0xd4/0xe8 | lr : lockdep_hardirqs_off+0xd4/0xe8 | sp : ffff80002a39bad0 | pmr_save: 000000e0 | x29: ffff80002a39bad0 x28: ffff0000de214bc0 | x27: ffff0000de1c0400 x26: 000000000049b328 | x25: 0000000000406f30 x24: ffff0000de1c00a0 | x23: 0000000020400005 x22: ffff8000105f747c | x21: 0000000096000044 x20: 0000000000498ef9 | x19: ffff80002a39bc88 x18: ffffffffffffffff | x17: 0000000000000000 x16: ffff800011c61eb0 | x15: ffff800011700a88 x14: 0720072007200720 | x13: 0720072007200720 x12: 0720072007200720 | x11: 0720072007200720 x10: 0720072007200720 | x9 : ffff80002a39bad0 x8 : ffff80002a39bad0 | x7 : ffff8000119f0800 x6 : c0000000ffff7fff | x5 : ffff8000119f07a8 x4 : 0000000000000001 | x3 : 9bcdab23f2432800 x2 : ffff800011730538 | x1 : 9bcdab23f2432800 x0 : 0000000000000000 | Call trace: | lockdep_hardirqs_off+0xd4/0xe8 | enter_from_kernel_mode.isra.5+0x7c/0xa8 | el1_abort+0x24/0x100 | el1_sync_handler+0x80/0xd0 | el1_sync+0x6c/0x100 | __arch_clear_user+0xc/0x90 | load_elf_binary+0x9fc/0x1450 | bprm_execve+0x404/0x880 | kernel_execve+0x180/0x188 | call_usermodehelper_exec_async+0xdc/0x158 | ret_from_fork+0x10/0x18
Fixes: 23529049c684 ("arm64: entry: fix non-NMI user<->kernel transitions") Fixes: 7cd1ea1010ac ("arm64: entry: fix non-NMI kernel<->kernel transitions") Fixes: f0cd5ac1e4c5 ("arm64: entry: fix NMI {user, kernel}->kernel transitions") Fixes: 2a9b3e6ac69a ("arm64: entry: fix EL1 debug transitions") Link: https://lore.kernel.org/r/f4012761-026f-4e51-3a0c-7524e434e8b3@huawei.com Signed-off-by: Mark Rutland mark.rutland@arm.com Reported-by: Zenghui Yu yuzenghui@huawei.com Cc: Marc Zyngier maz@kernel.org Cc: Will Deacon will@kernel.org Acked-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210428111555.50880-1-mark.rutland@arm.com Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/include/asm/daifflags.h | 3 +++ arch/arm64/kernel/entry-common.c | 17 ----------------- arch/arm64/kernel/entry.S | 15 ++------------- 3 files changed, 5 insertions(+), 30 deletions(-)
diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h index 1c26d7baa67f..cfdde3a56805 100644 --- a/arch/arm64/include/asm/daifflags.h +++ b/arch/arm64/include/asm/daifflags.h @@ -131,6 +131,9 @@ static inline void local_daif_inherit(struct pt_regs *regs) if (interrupts_enabled(regs)) trace_hardirqs_on();
+ if (system_uses_irq_prio_masking()) + gic_write_pmr(regs->pmr_save); + /* * We can't use local_daif_restore(regs->pstate) here as * system_has_prio_mask_debugging() won't restore the I bit if it can diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 9d3588450473..117412bae915 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -226,14 +226,6 @@ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr) { unsigned long far = read_sysreg(far_el1);
- /* - * The CPU masked interrupts, and we are leaving them masked during - * do_debug_exception(). Update PMR as if we had called - * local_daif_mask(). - */ - if (system_uses_irq_prio_masking()) - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); - arm64_enter_el1_dbg(regs); if (!cortex_a76_erratum_1463225_debug_handler(regs)) do_debug_exception(far, esr, regs); @@ -398,9 +390,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr) /* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */ unsigned long far = read_sysreg(far_el1);
- if (system_uses_irq_prio_masking()) - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); - enter_from_user_mode(); do_debug_exception(far, esr, regs); local_daif_restore(DAIF_PROCCTX_NOIRQ); @@ -408,9 +397,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc(struct pt_regs *regs) { - if (system_uses_irq_prio_masking()) - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); - enter_from_user_mode(); cortex_a76_erratum_1463225_svc_handler(); do_el0_svc(regs); @@ -486,9 +472,6 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
static void noinstr el0_svc_compat(struct pt_regs *regs) { - if (system_uses_irq_prio_masking()) - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); - enter_from_user_mode(); cortex_a76_erratum_1463225_svc_handler(); do_el0_svc_compat(regs); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index feb9e4b9f9f2..e03fba3ae2a0 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -292,6 +292,8 @@ alternative_else_nop_endif alternative_if ARM64_HAS_IRQ_PRIO_MASKING mrs_s x20, SYS_ICC_PMR_EL1 str x20, [sp, #S_PMR_SAVE] + mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET + msr_s SYS_ICC_PMR_EL1, x20 alternative_else_nop_endif
/* Re-enable tag checking (TCO set on exception entry) */ @@ -524,17 +526,7 @@ alternative_endif #endif .endm
- .macro gic_prio_irq_setup, pmr:req, tmp:req -#ifdef CONFIG_ARM64_PSEUDO_NMI - alternative_if ARM64_HAS_IRQ_PRIO_MASKING - orr \tmp, \pmr, #GIC_PRIO_PSR_I_SET - msr_s SYS_ICC_PMR_EL1, \tmp - alternative_else_nop_endif -#endif - .endm - .macro el1_interrupt_handler, handler:req - gic_prio_irq_setup pmr=x20, tmp=x1 enable_da_f
mov x0, sp @@ -562,7 +554,6 @@ alternative_else_nop_endif .endm
.macro el0_interrupt_handler, handler:req - gic_prio_irq_setup pmr=x20, tmp=x0 user_exit_irqoff enable_da_f
@@ -748,7 +739,6 @@ SYM_CODE_END(el0_irq) SYM_CODE_START_LOCAL(el1_error) kernel_entry 1 mrs x1, esr_el1 - gic_prio_kentry_setup tmp=x2 enable_dbg mov x0, sp bl do_serror @@ -759,7 +749,6 @@ SYM_CODE_START_LOCAL(el0_error) kernel_entry 0 el0_error_naked: mrs x25, esr_el1 - gic_prio_kentry_setup tmp=x2 user_exit_irqoff enable_dbg mov x0, sp
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit 74e579bf231a337ab3786d59e64bc94f45ca7b3f ]
In writable and !referenced case, the result value should be SCAN_LACK_REFERENCED_PAGE for trace_mm_collapse_huge_page_isolate() instead of default 0 (SCAN_FAIL) here.
Link: https://lkml.kernel.org/r/20210306032947.35921-5-linmiaohe@huawei.com Fixes: 7d2eba0557c1 ("mm: add tracepoint for scanning pages") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Acked-by: Kirill A. Shutemov kirill.shutemov@linux.intel.com Cc: Dan Carpenter dan.carpenter@oracle.com Cc: Ebru Akagunduz ebru.akagunduz@gmail.com Cc: Mike Kravetz mike.kravetz@oracle.com Cc: Rik van Riel riel@redhat.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/khugepaged.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c index a7d6cb912b05..2680d5ffee7f 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -716,17 +716,17 @@ next: if (pte_write(pteval)) writable = true; } - if (likely(writable)) { - if (likely(referenced)) { - result = SCAN_SUCCEED; - trace_mm_collapse_huge_page_isolate(page, none_or_zero, - referenced, writable, result); - return 1; - } - } else { + + if (unlikely(!writable)) { result = SCAN_PAGE_RO; + } else if (unlikely(!referenced)) { + result = SCAN_LACK_REFERENCED_PAGE; + } else { + result = SCAN_SUCCEED; + trace_mm_collapse_huge_page_isolate(page, none_or_zero, + referenced, writable, result); + return 1; } - out: release_pte_pages(pte, _pte, compound_pagelist); trace_mm_collapse_huge_page_isolate(page, none_or_zero,
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit da56388c4397878a65b74f7fe97760f5aa7d316b ]
A rare out of memory error would prevent removal of the reserve map region for a page. hugetlb_fix_reserve_counts() handles this rare case to avoid dangling with incorrect counts. Unfortunately, hugepage_subpool_get_pages and hugetlb_acct_memory could possibly fail too. We should correctly handle these cases.
Link: https://lkml.kernel.org/r/20210410072348.20437-5-linmiaohe@huawei.com Fixes: b5cec28d36f5 ("hugetlbfs: truncate_hugepages() takes a range of pages") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Cc: Feilong Lin linfeilong@huawei.com Cc: Mike Kravetz mike.kravetz@oracle.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/hugetlb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a86a58ef132d..cb253c8e55cc 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -743,13 +743,20 @@ void hugetlb_fix_reserve_counts(struct inode *inode) { struct hugepage_subpool *spool = subpool_inode(inode); long rsv_adjust; + bool reserved = false;
rsv_adjust = hugepage_subpool_get_pages(spool, 1); - if (rsv_adjust) { + if (rsv_adjust > 0) { struct hstate *h = hstate_inode(inode);
- hugetlb_acct_memory(h, 1); + if (!hugetlb_acct_memory(h, 1)) + reserved = true; + } else if (!rsv_adjust) { + reserved = true; } + + if (!reserved) + pr_warn("hugetlb: Huge Page Reserved count may go negative.\n"); }
/*
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit 34f5e9b9d1990d286199084efa752530ee3d8297 ]
If the zone device page does not belong to un-addressable device memory, the variable entry will be uninitialized and lead to indeterminate pte entry ultimately. Fix this unexpected case and warn about it.
Link: https://lkml.kernel.org/r/20210325131524.48181-4-linmiaohe@huawei.com Fixes: df6ad69838fc ("mm/device-public-memory: device memory cache coherent with CPU") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: David Hildenbrand david@redhat.com Cc: Alistair Popple apopple@nvidia.com Cc: Jerome Glisse jglisse@redhat.com Cc: Rafael Aquini aquini@redhat.com Cc: Yang Shi shy828301@gmail.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/migrate.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/mm/migrate.c b/mm/migrate.c index 62b81d5257aa..773622cffe77 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -2973,6 +2973,13 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
swp_entry = make_device_private_entry(page, vma->vm_flags & VM_WRITE); entry = swp_entry_to_pte(swp_entry); + } else { + /* + * For now we only support migrating to un-addressable + * device memory. + */ + pr_warn_once("Unsupported ZONE_DEVICE page type.\n"); + goto abort; } } else { entry = mk_pte(page, vma->vm_page_prot);
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit c89a384e2551c692a9fe60d093fd7080f50afc51 ]
When removing rmap_item from stable tree, STABLE_FLAG of rmap_item is cleared with head reserved. So the following scenario might happen: For ksm page with rmap_item1:
cmp_and_merge_page stable_node->head = &migrate_nodes; remove_rmap_item_from_tree, but head still equal to stable_node; try_to_merge_with_ksm_page failed; return;
For the same ksm page with rmap_item2, stable node migration succeed this time. The stable_node->head does not equal to migrate_nodes now. For ksm page with rmap_item1 again:
cmp_and_merge_page stable_node->head != &migrate_nodes && rmap_item->head == stable_node return;
We would miss the rmap_item for stable_node and might result in failed rmap_walk_ksm(). Fix this by set rmap_item->head to NULL when rmap_item is removed from stable tree.
Link: https://lkml.kernel.org/r/20210330140228.45635-5-linmiaohe@huawei.com Fixes: 4146d2d673e8 ("ksm: make !merge_across_nodes migration safe") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Cc: Hugh Dickins hughd@google.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/ksm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/mm/ksm.c b/mm/ksm.c index 9694ee2c71de..b32391ccf6d5 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -794,6 +794,7 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) stable_node->rmap_hlist_len--;
put_anon_vma(rmap_item->anon_vma); + rmap_item->head = NULL; rmap_item->address &= PAGE_MASK;
} else if (rmap_item->address & UNSTABLE_FLAG) {
From: Pavel Tatashin pasha.tatashin@soleen.com
[ Upstream commit 83c02c23d0747a7bdcd71f99a538aacec94b146c ]
When pages are isolated in check_and_migrate_movable_pages() we skip compound number of pages at a time. However, as Jason noted, it is not necessary correct that pages[i] corresponds to the pages that we skipped. This is because it is possible that the addresses in this range had split_huge_pmd()/split_huge_pud(), and these functions do not update the compound page metadata.
The problem can be reproduced if something like this occurs:
1. User faulted huge pages. 2. split_huge_pmd() was called for some reason 3. User has unmapped some sub-pages in the range 4. User tries to longterm pin the addresses.
The resulting pages[i] might end-up having pages which are not compound size page aligned.
Link: https://lkml.kernel.org/r/20210215161349.246722-3-pasha.tatashin@soleen.com Fixes: aa712399c1e8 ("mm/gup: speed up check_and_migrate_cma_pages() on huge page") Signed-off-by: Pavel Tatashin pasha.tatashin@soleen.com Reported-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Jason Gunthorpe jgg@nvidia.com Cc: Dan Williams dan.j.williams@intel.com Cc: David Hildenbrand david@redhat.com Cc: David Rientjes rientjes@google.com Cc: Ingo Molnar mingo@redhat.com Cc: Ira Weiny ira.weiny@intel.com Cc: James Morris jmorris@namei.org Cc: Jason Gunthorpe jgg@ziepe.ca Cc: John Hubbard jhubbard@nvidia.com Cc: Joonsoo Kim iamjoonsoo.kim@lge.com Cc: Matthew Wilcox willy@infradead.org Cc: Mel Gorman mgorman@suse.de Cc: Michal Hocko mhocko@kernel.org Cc: Michal Hocko mhocko@suse.com Cc: Mike Kravetz mike.kravetz@oracle.com Cc: Oscar Salvador osalvador@suse.de Cc: Peter Zijlstra peterz@infradead.org Cc: Sasha Levin sashal@kernel.org Cc: Steven Rostedt (VMware) rostedt@goodmis.org Cc: Tyler Hicks tyhicks@linux.microsoft.com Cc: Vlastimil Babka vbabka@suse.cz Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/gup.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c index ef7d2da9f03f..6530672131db 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1552,26 +1552,23 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, unsigned int gup_flags) { unsigned long i; - unsigned long step; bool drain_allow = true; bool migrate_allow = true; LIST_HEAD(cma_page_list); long ret = nr_pages; + struct page *prev_head, *head; struct migration_target_control mtc = { .nid = NUMA_NO_NODE, .gfp_mask = GFP_USER | __GFP_MOVABLE | __GFP_NOWARN, };
check_again: - for (i = 0; i < nr_pages;) { - - struct page *head = compound_head(pages[i]); - - /* - * gup may start from a tail page. Advance step by the left - * part. - */ - step = compound_nr(head) - (pages[i] - head); + prev_head = NULL; + for (i = 0; i < nr_pages; i++) { + head = compound_head(pages[i]); + if (head == prev_head) + continue; + prev_head = head; /* * If we get a page from the CMA zone, since we are going to * be pinning these entries, we might as well move them out @@ -1595,8 +1592,6 @@ check_again: } } } - - i += step; }
if (!list_empty(&cma_page_list)) {
From: Pavel Tatashin pasha.tatashin@soleen.com
[ Upstream commit f0f4463837da17a89d965dcbe4e411629dbcf308 ]
When migration failure occurs, we still pin pages, which means that we may pin CMA movable pages which should never be the case.
Instead return an error without pinning pages when migration failure happens.
No need to retry migrating, because migrate_pages() already retries 10 times.
Link: https://lkml.kernel.org/r/20210215161349.246722-4-pasha.tatashin@soleen.com Signed-off-by: Pavel Tatashin pasha.tatashin@soleen.com Reviewed-by: Jason Gunthorpe jgg@nvidia.com Cc: Dan Williams dan.j.williams@intel.com Cc: David Hildenbrand david@redhat.com Cc: David Rientjes rientjes@google.com Cc: Ingo Molnar mingo@redhat.com Cc: Ira Weiny ira.weiny@intel.com Cc: James Morris jmorris@namei.org Cc: Jason Gunthorpe jgg@ziepe.ca Cc: John Hubbard jhubbard@nvidia.com Cc: Joonsoo Kim iamjoonsoo.kim@lge.com Cc: Matthew Wilcox willy@infradead.org Cc: Mel Gorman mgorman@suse.de Cc: Michal Hocko mhocko@kernel.org Cc: Michal Hocko mhocko@suse.com Cc: Mike Kravetz mike.kravetz@oracle.com Cc: Oscar Salvador osalvador@suse.de Cc: Peter Zijlstra peterz@infradead.org Cc: Sasha Levin sashal@kernel.org Cc: Steven Rostedt (VMware) rostedt@goodmis.org Cc: Tyler Hicks tyhicks@linux.microsoft.com Cc: Vlastimil Babka vbabka@suse.cz Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/gup.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c index 6530672131db..2b48c65e27cc 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1553,7 +1553,6 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, { unsigned long i; bool drain_allow = true; - bool migrate_allow = true; LIST_HEAD(cma_page_list); long ret = nr_pages; struct page *prev_head, *head; @@ -1604,17 +1603,15 @@ check_again: for (i = 0; i < nr_pages; i++) put_page(pages[i]);
- if (migrate_pages(&cma_page_list, alloc_migration_target, NULL, - (unsigned long)&mtc, MIGRATE_SYNC, MR_CONTIG_RANGE)) { - /* - * some of the pages failed migration. Do get_user_pages - * without migration. - */ - migrate_allow = false; - + ret = migrate_pages(&cma_page_list, alloc_migration_target, + NULL, (unsigned long)&mtc, MIGRATE_SYNC, + MR_CONTIG_RANGE); + if (ret) { if (!list_empty(&cma_page_list)) putback_movable_pages(&cma_page_list); + return ret > 0 ? -ENOMEM : ret; } + /* * We did migrate all the pages, Try to get the page references * again migrating any new CMA pages which we failed to isolate @@ -1624,7 +1621,7 @@ check_again: pages, vmas, NULL, gup_flags);
- if ((ret > 0) && migrate_allow) { + if (ret > 0) { nr_pages = ret; drain_allow = true; goto check_again;
From: Pavel Tatashin pasha.tatashin@soleen.com
[ Upstream commit 6e7f34ebb8d25d71ce7f4580ba3cbfc10b895580 ]
It is still possible that we pin movable CMA pages if there are isolation errors and cma_page_list stays empty when we check again.
Check for isolation errors, and return success only when there are no isolation errors, and cma_page_list is empty after checking.
Because isolation errors are transient, we retry indefinitely.
Link: https://lkml.kernel.org/r/20210215161349.246722-5-pasha.tatashin@soleen.com Fixes: 9a4e9f3b2d73 ("mm: update get_user_pages_longterm to migrate pages allocated from CMA region") Signed-off-by: Pavel Tatashin pasha.tatashin@soleen.com Reviewed-by: Jason Gunthorpe jgg@nvidia.com Cc: Dan Williams dan.j.williams@intel.com Cc: David Hildenbrand david@redhat.com Cc: David Rientjes rientjes@google.com Cc: Ingo Molnar mingo@redhat.com Cc: Ira Weiny ira.weiny@intel.com Cc: James Morris jmorris@namei.org Cc: Jason Gunthorpe jgg@ziepe.ca Cc: John Hubbard jhubbard@nvidia.com Cc: Joonsoo Kim iamjoonsoo.kim@lge.com Cc: Matthew Wilcox willy@infradead.org Cc: Mel Gorman mgorman@suse.de Cc: Michal Hocko mhocko@kernel.org Cc: Michal Hocko mhocko@suse.com Cc: Mike Kravetz mike.kravetz@oracle.com Cc: Oscar Salvador osalvador@suse.de Cc: Peter Zijlstra peterz@infradead.org Cc: Sasha Levin sashal@kernel.org Cc: Steven Rostedt (VMware) rostedt@goodmis.org Cc: Tyler Hicks tyhicks@linux.microsoft.com Cc: Vlastimil Babka vbabka@suse.cz Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/gup.c | 60 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 26 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c index 2b48c65e27cc..333f5dfd8942 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1551,8 +1551,8 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm, struct vm_area_struct **vmas, unsigned int gup_flags) { - unsigned long i; - bool drain_allow = true; + unsigned long i, isolation_error_count; + bool drain_allow; LIST_HEAD(cma_page_list); long ret = nr_pages; struct page *prev_head, *head; @@ -1563,6 +1563,8 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm,
check_again: prev_head = NULL; + isolation_error_count = 0; + drain_allow = true; for (i = 0; i < nr_pages; i++) { head = compound_head(pages[i]); if (head == prev_head) @@ -1574,25 +1576,35 @@ check_again: * of the CMA zone if possible. */ if (is_migrate_cma_page(head)) { - if (PageHuge(head)) - isolate_huge_page(head, &cma_page_list); - else { + if (PageHuge(head)) { + if (!isolate_huge_page(head, &cma_page_list)) + isolation_error_count++; + } else { if (!PageLRU(head) && drain_allow) { lru_add_drain_all(); drain_allow = false; }
- if (!isolate_lru_page(head)) { - list_add_tail(&head->lru, &cma_page_list); - mod_node_page_state(page_pgdat(head), - NR_ISOLATED_ANON + - page_is_file_lru(head), - thp_nr_pages(head)); + if (isolate_lru_page(head)) { + isolation_error_count++; + continue; } + list_add_tail(&head->lru, &cma_page_list); + mod_node_page_state(page_pgdat(head), + NR_ISOLATED_ANON + + page_is_file_lru(head), + thp_nr_pages(head)); } } }
+ /* + * If list is empty, and no isolation errors, means that all pages are + * in the correct zone. + */ + if (list_empty(&cma_page_list) && !isolation_error_count) + return ret; + if (!list_empty(&cma_page_list)) { /* * drop the above get_user_pages reference. @@ -1612,23 +1624,19 @@ check_again: return ret > 0 ? -ENOMEM : ret; }
- /* - * We did migrate all the pages, Try to get the page references - * again migrating any new CMA pages which we failed to isolate - * earlier. - */ - ret = __get_user_pages_locked(mm, start, nr_pages, - pages, vmas, NULL, - gup_flags); - - if (ret > 0) { - nr_pages = ret; - drain_allow = true; - goto check_again; - } + /* We unpinned pages before migration, pin them again */ + ret = __get_user_pages_locked(mm, start, nr_pages, pages, vmas, + NULL, gup_flags); + if (ret <= 0) + return ret; + nr_pages = ret; }
- return ret; + /* + * check again because pages were unpinned, and we also might have + * had isolation errors and need more pages to migrate. + */ + goto check_again; } #else static long check_and_migrate_cma_pages(struct mm_struct *mm,
From: Marco Elver elver@google.com
[ Upstream commit 407f1d8c1b5f3ec66a6a3eb835d3b81c76440f4e ]
Patch series "kfence: optimize timer scheduling", v2.
We have observed that mostly-idle systems with KFENCE enabled wake up otherwise idle CPUs, preventing such to enter a lower power state. Debugging revealed that KFENCE spends too much active time in toggle_allocation_gate().
While the first version of KFENCE was using all the right bits to be scheduling optimal, and thus power efficient, by simply using wait_event() + wake_up(), that code was unfortunately removed.
As KFENCE was exposed to various different configs and tests, the scheduling optimal code slowly disappeared. First because of hung task warnings, and finally because of deadlocks when an allocation is made by timer code with debug objects enabled. Clearly, the "fixes" were not too friendly for devices that want to be power efficient.
Therefore, let's try a little harder to fix the hung task and deadlock problems that we have with wait_event() + wake_up(), while remaining as scheduling friendly and power efficient as possible.
Crucially, we need to defer the wake_up() to an irq_work, avoiding any potential for deadlock.
The result with this series is that on the devices where we observed a power regression, power usage returns back to baseline levels.
This patch (of 3):
On mostly-idle systems, we have observed that toggle_allocation_gate() is a cause of frequent wake-ups, preventing an otherwise idle CPU to go into a lower power state.
A late change in KFENCE's development, due to a potential deadlock [1], required changing the scheduling-friendly wait_event_timeout() and wake_up() to an open-coded wait-loop using schedule_timeout(). [1] https://lkml.kernel.org/r/000000000000c0645805b7f982e4@google.com
To avoid unnecessary wake-ups, switch to using wait_event_timeout().
Unfortunately, we still cannot use a version with direct wake_up() in __kfence_alloc() due to the same potential for deadlock as in [1]. Instead, add a level of indirection via an irq_work that is scheduled if we determine that the kfence_timer requires a wake_up().
Link: https://lkml.kernel.org/r/20210421105132.3965998-1-elver@google.com Link: https://lkml.kernel.org/r/20210421105132.3965998-2-elver@google.com Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") Signed-off-by: Marco Elver elver@google.com Cc: Alexander Potapenko glider@google.com Cc: Dmitry Vyukov dvyukov@google.com Cc: Jann Horn jannh@google.com Cc: Mark Rutland mark.rutland@arm.com Cc: Hillf Danton hdanton@sina.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- lib/Kconfig.kfence | 1 + mm/kfence/core.c | 45 +++++++++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence index 78f50ccb3b45..e641add33947 100644 --- a/lib/Kconfig.kfence +++ b/lib/Kconfig.kfence @@ -7,6 +7,7 @@ menuconfig KFENCE bool "KFENCE: low-overhead sampling-based memory safety error detector" depends on HAVE_ARCH_KFENCE && (SLAB || SLUB) select STACKTRACE + select IRQ_WORK help KFENCE is a low-overhead sampling-based detector of heap out-of-bounds access, use-after-free, and invalid-free errors. KFENCE is designed diff --git a/mm/kfence/core.c b/mm/kfence/core.c index d53c91f881a4..f0be2c5038b5 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -10,6 +10,7 @@ #include <linux/atomic.h> #include <linux/bug.h> #include <linux/debugfs.h> +#include <linux/irq_work.h> #include <linux/kcsan-checks.h> #include <linux/kfence.h> #include <linux/kmemleak.h> @@ -586,6 +587,17 @@ late_initcall(kfence_debugfs_init);
/* === Allocation Gate Timer ================================================ */
+#ifdef CONFIG_KFENCE_STATIC_KEYS +/* Wait queue to wake up allocation-gate timer task. */ +static DECLARE_WAIT_QUEUE_HEAD(allocation_wait); + +static void wake_up_kfence_timer(struct irq_work *work) +{ + wake_up(&allocation_wait); +} +static DEFINE_IRQ_WORK(wake_up_kfence_timer_work, wake_up_kfence_timer); +#endif + /* * Set up delayed work, which will enable and disable the static key. We need to * use a work queue (rather than a simple timer), since enabling and disabling a @@ -603,25 +615,13 @@ static void toggle_allocation_gate(struct work_struct *work) if (!READ_ONCE(kfence_enabled)) return;
- /* Enable static key, and await allocation to happen. */ atomic_set(&kfence_allocation_gate, 0); #ifdef CONFIG_KFENCE_STATIC_KEYS + /* Enable static key, and await allocation to happen. */ static_branch_enable(&kfence_allocation_key); - /* - * Await an allocation. Timeout after 1 second, in case the kernel stops - * doing allocations, to avoid stalling this worker task for too long. - */ - { - unsigned long end_wait = jiffies + HZ; - - do { - set_current_state(TASK_UNINTERRUPTIBLE); - if (atomic_read(&kfence_allocation_gate) != 0) - break; - schedule_timeout(1); - } while (time_before(jiffies, end_wait)); - __set_current_state(TASK_RUNNING); - } + + wait_event_timeout(allocation_wait, atomic_read(&kfence_allocation_gate), HZ); + /* Disable static key and reset timer. */ static_branch_disable(&kfence_allocation_key); #endif @@ -728,6 +728,19 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) */ if (atomic_read(&kfence_allocation_gate) || atomic_inc_return(&kfence_allocation_gate) > 1) return NULL; +#ifdef CONFIG_KFENCE_STATIC_KEYS + /* + * waitqueue_active() is fully ordered after the update of + * kfence_allocation_gate per atomic_inc_return(). + */ + if (waitqueue_active(&allocation_wait)) { + /* + * Calling wake_up() here may deadlock when allocations happen + * from within timer code. Use an irq_work to defer it. + */ + irq_work_queue(&wake_up_kfence_timer_work); + } +#endif
if (!READ_ONCE(kfence_enabled)) return NULL;
From: Fernando Fernandez Mancera ffmancera@riseup.net
[ Upstream commit cf754ae331be7cc192b951756a1dd031e9ed978a ]
When dumping the ethtool information from all the interfaces, the netlink reply should contain the NLM_F_MULTI flag. This flag allows userspace tools to identify that multiple messages are expected.
Link: https://bugzilla.redhat.com/1953847 Fixes: 365f9ae4ee36 ("ethtool: fix genlmsg_put() failure handling in ethnl_default_dumpit()") Signed-off-by: Fernando Fernandez Mancera ffmancera@riseup.net Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ethtool/netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 50d3c8896f91..25a55086d2b6 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -384,7 +384,8 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, int ret;
ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - ðtool_genl_family, 0, ctx->ops->reply_cmd); + ðtool_genl_family, NLM_F_MULTI, + ctx->ops->reply_cmd); if (!ehdr) return -EMSGSIZE;
From: Maciej Żenczykowski maze@google.com
[ Upstream commit 2c16db6c92b0ee4aa61e88366df82169e83c3f7e ]
Android userspace has been using TCA_KIND with a char[IFNAMESIZ] many-null-terminated buffer containing the string 'bpf'.
This works on 4.19 and ceases to work on 5.10.
I'm not entirely sure what fixes tag to use, but I think the issue was likely introduced in the below mentioned 5.4 commit.
Reported-by: Nucca Chen nuccachen@google.com Cc: Cong Wang xiyou.wangcong@gmail.com Cc: David Ahern dsahern@gmail.com Cc: David S. Miller davem@davemloft.net Cc: Jakub Kicinski jakub.kicinski@netronome.com Cc: Jamal Hadi Salim jhs@mojatatu.com Cc: Jiri Pirko jiri@mellanox.com Cc: Jiri Pirko jiri@resnulli.us Fixes: 62794fc4fbf5 ("net_sched: add max len check for TCA_KIND") Change-Id: I66dc281f165a2858fc29a44869a270a2d698a82b Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- lib/nlattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/nlattr.c b/lib/nlattr.c index 5b6116e81f9f..1d051ef66afe 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -828,7 +828,7 @@ int nla_strcmp(const struct nlattr *nla, const char *str) int attrlen = nla_len(nla); int d;
- if (attrlen > 0 && buf[attrlen - 1] == '\0') + while (attrlen > 0 && buf[attrlen - 1] == '\0') attrlen--;
d = attrlen - len;
From: Cong Wang cong.wang@bytedance.com
[ Upstream commit 8621436671f3a4bba5db57482e1ee604708bf1eb ]
syzbot is able to setup kTLS on an SMC socket which coincidentally uses sk_user_data too. Later, kTLS treats it as psock so triggers a refcnt warning. The root cause is that smc_setsockopt() simply calls TCP setsockopt() which includes TCP_ULP. I do not think it makes sense to setup kTLS on top of SMC sockets, so we should just disallow this setup.
It is hard to find a commit to blame, but we can apply this patch since the beginning of TCP_ULP.
Reported-and-tested-by: syzbot+b54a1ce86ba4a623b7f0@syzkaller.appspotmail.com Fixes: 734942cc4ea6 ("tcp: ULP infrastructure") Cc: John Fastabend john.fastabend@gmail.com Signed-off-by: Karsten Graul kgraul@linux.ibm.com Signed-off-by: Cong Wang cong.wang@bytedance.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/smc/af_smc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 47340b3b514f..cb23cca72c24 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -2162,6 +2162,9 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, struct smc_sock *smc; int val, rc;
+ if (level == SOL_TCP && optname == TCP_ULP) + return -EOPNOTSUPP; + smc = smc_sk(sk);
/* generic setsockopts reaching us here always apply to the @@ -2186,7 +2189,6 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, if (rc || smc->use_fallback) goto out; switch (optname) { - case TCP_ULP: case TCP_FASTOPEN: case TCP_FASTOPEN_CONNECT: case TCP_FASTOPEN_KEY:
From: Pablo Neira Ayuso pablo@netfilter.org
[ Upstream commit 5e024c325406470d1165a09c6feaf8ec897936be ]
Do not assume that the tcph->doff field is correct when parsing for TCP options, skb_header_pointer() might fail to fetch these bits.
Fixes: 11eeef41d5f6 ("netfilter: passive OS fingerprint xtables match") Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nfnetlink_osf.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c index 916a3c7f9eaf..79fbf37291f3 100644 --- a/net/netfilter/nfnetlink_osf.c +++ b/net/netfilter/nfnetlink_osf.c @@ -186,6 +186,8 @@ static const struct tcphdr *nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx *ctx,
ctx->optp = skb_header_pointer(skb, ip_hdrlen(skb) + sizeof(struct tcphdr), ctx->optsize, opts); + if (!ctx->optp) + return NULL; }
return tcp;
From: Pablo Neira Ayuso pablo@netfilter.org
[ Upstream commit 85dfd816fabfc16e71786eda0a33a7046688b5b0 ]
Release object name if userdata allocation fails.
Fixes: b131c96496b3 ("netfilter: nf_tables: add userdata support for nft_object") Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nf_tables_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 589d2f6978d3..878ed49d0c56 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -6246,9 +6246,9 @@ err_obj_ht: INIT_LIST_HEAD(&obj->list); return err; err_trans: - kfree(obj->key.name); -err_userdata: kfree(obj->udata); +err_userdata: + kfree(obj->key.name); err_strdup: if (obj->ops->destroy) obj->ops->destroy(&ctx, obj);
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 4cc7faa406975b460aa674606291dea197c1210c ]
When we converted this code to use dev_err_probe() we accidentally removed a return. It means that if devm_clk_get() it will lead to an Oops when we call clk_get_rate() on the next line.
Fixes: cf8ee6de2543 ("can: mcp251xfd: mcp251xfd_probe(): use dev_err_probe() to simplify error handling") Link: https://lore.kernel.org/r/YJANZf13Qxd5Mhr1@mwanda Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Manivannan Sadhasivam mani@kernel.org Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index 799e9d5d3481..15b04db6ed9c 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -2856,8 +2856,8 @@ static int mcp251xfd_probe(struct spi_device *spi)
clk = devm_clk_get(&spi->dev, NULL); if (IS_ERR(clk)) - dev_err_probe(&spi->dev, PTR_ERR(clk), - "Failed to get Oscillator (clock)!\n"); + return dev_err_probe(&spi->dev, PTR_ERR(clk), + "Failed to get Oscillator (clock)!\n"); freq = clk_get_rate(clk);
/* Sanity check */
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 4376ea42db8bfcac2bc3a30bba93917244a8c2d4 ]
This patch adds the missing can_rx_offload_del(), that must be called if mcp251xfd_register() fails.
Fixes: 55e5b97f003e ("can: mcp25xxfd: add driver for Microchip MCP25xxFD SPI CAN") Link: https://lore.kernel.org/r/20210504091838.1109047-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index 15b04db6ed9c..4a742aa5c417 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -2957,10 +2957,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
err = mcp251xfd_register(priv); if (err) - goto out_free_candev; + goto out_can_rx_offload_del;
return 0;
+ out_can_rx_offload_del: + can_rx_offload_del(&priv->offload); out_free_candev: spi->max_speed_hz = priv->spi_max_speed_hz_orig;
From: Frieder Schrempf frieder.schrempf@kontron.de
[ Upstream commit 03c427147b2d3e503af258711af4fc792b89b0af ]
Since 8ce8c0abcba3 the driver queues work via priv->restart_work when resuming after suspend, even when the interface was not previously enabled. This causes a null dereference error as the workqueue is only allocated and initialized in mcp251x_open().
To fix this we move the workqueue init to mcp251x_can_probe() as there is no reason to do it later and repeat it whenever mcp251x_open() is called.
Fixes: 8ce8c0abcba3 ("can: mcp251x: only reset hardware as required") Link: https://lore.kernel.org/r/17d5d714-b468-482f-f37a-482e3d6df84e@kontron.de Signed-off-by: Frieder Schrempf frieder.schrempf@kontron.de Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com [mkl: fix error handling in mcp251x_stop()] Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/spi/mcp251x.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index a57da43680d8..bd7d0251be10 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -956,8 +956,6 @@ static int mcp251x_stop(struct net_device *net)
priv->force_quit = 1; free_irq(spi->irq, priv); - destroy_workqueue(priv->wq); - priv->wq = NULL;
mutex_lock(&priv->mcp_lock);
@@ -1224,24 +1222,15 @@ static int mcp251x_open(struct net_device *net) goto out_close; }
- priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, - 0); - if (!priv->wq) { - ret = -ENOMEM; - goto out_clean; - } - INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); - INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); - ret = mcp251x_hw_wake(spi); if (ret) - goto out_free_wq; + goto out_free_irq; ret = mcp251x_setup(net, spi); if (ret) - goto out_free_wq; + goto out_free_irq; ret = mcp251x_set_normal_mode(spi); if (ret) - goto out_free_wq; + goto out_free_irq;
can_led_event(net, CAN_LED_EVENT_OPEN);
@@ -1250,9 +1239,7 @@ static int mcp251x_open(struct net_device *net)
return 0;
-out_free_wq: - destroy_workqueue(priv->wq); -out_clean: +out_free_irq: free_irq(spi->irq, priv); mcp251x_hw_sleep(spi); out_close: @@ -1373,6 +1360,15 @@ static int mcp251x_can_probe(struct spi_device *spi) if (ret) goto out_clk;
+ priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, + 0); + if (!priv->wq) { + ret = -ENOMEM; + goto out_clk; + } + INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); + INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); + priv->spi = spi; mutex_init(&priv->mcp_lock);
@@ -1417,6 +1413,8 @@ static int mcp251x_can_probe(struct spi_device *spi) return 0;
error_probe: + destroy_workqueue(priv->wq); + priv->wq = NULL; mcp251x_power_enable(priv->power, 0);
out_clk: @@ -1438,6 +1436,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
mcp251x_power_enable(priv->power, 0);
+ destroy_workqueue(priv->wq); + priv->wq = NULL; + clk_disable_unprepare(priv->clk);
free_candev(net);
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit e04b2cfe61072c7966e1a5fb73dd1feb30c206ed ]
The m_can_start_xmit() function checks if the cdev->tx_skb is NULL and returns with NETDEV_TX_BUSY in case tx_sbk is not NULL.
There is a race condition in the m_can_tx_work_queue(), where first the skb is send to the driver and then the case tx_sbk is set to NULL. A TX complete IRQ might come in between and wake the queue, which results in tx_skb not being cleared yet.
Fixes: f524f829b75a ("can: m_can: Create a m_can platform framework") Tested-by: Torin Cooper-Bennun torin@maxiluxsystems.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/m_can/m_can.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 0c8d36bc668c..f71127229caf 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1455,6 +1455,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev) int i; int putidx;
+ cdev->tx_skb = NULL; + /* Generate ID field for TX buffer Element */ /* Common to all supported M_CAN versions */ if (cf->can_id & CAN_EFF_FLAG) { @@ -1571,7 +1573,6 @@ static void m_can_tx_work_queue(struct work_struct *ws) tx_work);
m_can_tx_handler(cdev); - cdev->tx_skb = NULL; }
static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
From: Quentin Perret qperret@google.com
[ Upstream commit 6d2f8909a5fabb73fe2a63918117943986c39b6c ]
Util-clamp places tasks in different buckets based on their clamp values for performance reasons. However, the size of buckets is currently computed using a rounding division, which can lead to an off-by-one error in some configurations.
For instance, with 20 buckets, the bucket size will be 1024/20=51. A task with a clamp of 1024 will be mapped to bucket id 1024/51=20. Sadly, correct indexes are in range [0,19], hence leading to an out of bound memory access.
Clamp the bucket id to fix the issue.
Fixes: 69842cba9ace ("sched/uclamp: Add CPU's clamp buckets refcounting") Suggested-by: Qais Yousef qais.yousef@arm.com Signed-off-by: Quentin Perret qperret@google.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Vincent Guittot vincent.guittot@linaro.org Reviewed-by: Dietmar Eggemann dietmar.eggemann@arm.com Link: https://lkml.kernel.org/r/20210430151412.160913-1-qperret@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 17ad829a114c..814200541f8f 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -928,7 +928,7 @@ DEFINE_STATIC_KEY_FALSE(sched_uclamp_used);
static inline unsigned int uclamp_bucket_id(unsigned int clamp_value) { - return clamp_value / UCLAMP_BUCKET_DELTA; + return min_t(unsigned int, clamp_value / UCLAMP_BUCKET_DELTA, UCLAMP_BUCKETS - 1); }
static inline unsigned int uclamp_none(enum uclamp_id clamp_id)
From: Odin Ugedal odin@uged.al
[ Upstream commit 0258bdfaff5bd13c4d2383150b7097aecd6b6d82 ]
This fixes an issue where old load on a cfs_rq is not properly decayed, resulting in strange behavior where fairness can decrease drastically. Real workloads with equally weighted control groups have ended up getting a respective 99% and 1%(!!) of cpu time.
When an idle task is attached to a cfs_rq by attaching a pid to a cgroup, the old load of the task is attached to the new cfs_rq and sched_entity by attach_entity_cfs_rq. If the task is then moved to another cpu (and therefore cfs_rq) before being enqueued/woken up, the load will be moved to cfs_rq->removed from the sched_entity. Such a move will happen when enforcing a cpuset on the task (eg. via a cgroup) that force it to move.
The load will however not be removed from the task_group itself, making it look like there is a constant load on that cfs_rq. This causes the vruntime of tasks on other sibling cfs_rq's to increase faster than they are supposed to; causing severe fairness issues. If no other task is started on the given cfs_rq, and due to the cpuset it would not happen, this load would never be properly unloaded. With this patch the load will be properly removed inside update_blocked_averages. This also applies to tasks moved to the fair scheduling class and moved to another cpu, and this path will also fix that. For fork, the entity is queued right away, so this problem does not affect that.
This applies to cases where the new process is the first in the cfs_rq, issue introduced 3d30544f0212 ("sched/fair: Apply more PELT fixes"), and when there has previously been load on the cgroup but the cgroup was removed from the leaflist due to having null PELT load, indroduced in 039ae8bcf7a5 ("sched/fair: Fix O(nr_cgroups) in the load balancing path").
For a simple cgroup hierarchy (as seen below) with two equally weighted groups, that in theory should get 50/50 of cpu time each, it often leads to a load of 60/40 or 70/30.
parent/ cg-1/ cpu.weight: 100 cpuset.cpus: 1 cg-2/ cpu.weight: 100 cpuset.cpus: 1
If the hierarchy is deeper (as seen below), while keeping cg-1 and cg-2 equally weighted, they should still get a 50/50 balance of cpu time. This however sometimes results in a balance of 10/90 or 1/99(!!) between the task groups.
$ ps u -C stress USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 18568 1.1 0.0 3684 100 pts/12 R+ 13:36 0:00 stress --cpu 1 root 18580 99.3 0.0 3684 100 pts/12 R+ 13:36 0:09 stress --cpu 1
parent/ cg-1/ cpu.weight: 100 sub-group/ cpu.weight: 1 cpuset.cpus: 1 cg-2/ cpu.weight: 100 sub-group/ cpu.weight: 10000 cpuset.cpus: 1
This can be reproduced by attaching an idle process to a cgroup and moving it to a given cpuset before it wakes up. The issue is evident in many (if not most) container runtimes, and has been reproduced with both crun and runc (and therefore docker and all its "derivatives"), and with both cgroup v1 and v2.
Fixes: 3d30544f0212 ("sched/fair: Apply more PELT fixes") Fixes: 039ae8bcf7a5 ("sched/fair: Fix O(nr_cgroups) in the load balancing path") Signed-off-by: Odin Ugedal odin@uged.al Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Vincent Guittot vincent.guittot@linaro.org Link: https://lkml.kernel.org/r/20210501141950.23622-2-odin@uged.al Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/fair.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d078767f677f..edcabae5c658 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -10915,16 +10915,22 @@ static void propagate_entity_cfs_rq(struct sched_entity *se) { struct cfs_rq *cfs_rq;
+ list_add_leaf_cfs_rq(cfs_rq_of(se)); + /* Start to propagate at parent */ se = se->parent;
for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se);
- if (cfs_rq_throttled(cfs_rq)) - break; + if (!cfs_rq_throttled(cfs_rq)){ + update_load_avg(cfs_rq, se, UPDATE_TG); + list_add_leaf_cfs_rq(cfs_rq); + continue; + }
- update_load_avg(cfs_rq, se, UPDATE_TG); + if (list_add_leaf_cfs_rq(cfs_rq)) + break; } } #else
From: Alex Elder elder@linaro.org
[ Upstream commit 6a780f51f87b430cc69ebf4e859e7e9be720b283 ]
In gsi_irq_setup(), two registers are written with the intention of disabling inter-EE channel and event IRQs.
But the wrong registers are used (and defined); the ones used are read-only registers that indicate whether the interrupt condition is present.
Define the mask registers instead of the status registers, and use them to disable the inter-EE interrupt types.
Fixes: 46f748ccaf01 ("net: ipa: explicitly disallow inter-EE interrupts") Signed-off-by: Alex Elder elder@linaro.org Link: https://lore.kernel.org/r/20210505223636.232527-1-elder@linaro.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ipa/gsi.c | 4 ++-- drivers/net/ipa/gsi_reg.h | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 390d3403386a..144892060718 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -211,8 +211,8 @@ static void gsi_irq_setup(struct gsi *gsi) iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET);
/* The inter-EE registers are in the non-adjusted address range */ - iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_OFFSET); - iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET); + iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET); + iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET);
iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET); } diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index 1622d8cf8dea..48ef04afab79 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -53,15 +53,15 @@ #define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */
/* The two inter-EE IRQ register offsets are relative to gsi->virt_raw */ -#define GSI_INTER_EE_SRC_CH_IRQ_OFFSET \ - GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(GSI_EE_AP) -#define GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(ee) \ - (0x0000c018 + 0x1000 * (ee)) - -#define GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET \ - GSI_INTER_EE_N_SRC_EV_CH_IRQ_OFFSET(GSI_EE_AP) -#define GSI_INTER_EE_N_SRC_EV_CH_IRQ_OFFSET(ee) \ - (0x0000c01c + 0x1000 * (ee)) +#define GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET \ + GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(GSI_EE_AP) +#define GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(ee) \ + (0x0000c020 + 0x1000 * (ee)) + +#define GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET \ + GSI_INTER_EE_N_SRC_EV_CH_IRQ_MSK_OFFSET(GSI_EE_AP) +#define GSI_INTER_EE_N_SRC_EV_CH_IRQ_MSK_OFFSET(ee) \ + (0x0000c024 + 0x1000 * (ee))
/* All other register offsets are relative to gsi->virt */ #define GSI_CH_C_CNTXT_0_OFFSET(ch) \
From: Colin Ian King colin.king@canonical.com
[ Upstream commit f4bf74d82915708208bc9d0c9bd3f769f56bfbec ]
Currently the pde_is_permanent() check is being run on root multiple times rather than on the next proc directory entry. This looks like a copy-paste error. Fix this by replacing root with next.
Addresses-Coverity: ("Copy-paste error") Link: https://lkml.kernel.org/r/20210318122633.14222-1-colin.king@canonical.com Fixes: d919b33dafb3 ("proc: faster open/read/close with "permanent" files") Signed-off-by: Colin Ian King colin.king@canonical.com Acked-by: Christian Brauner christian.brauner@ubuntu.com Reviewed-by: Alexey Dobriyan adobriyan@gmail.com Cc: Greg Kroah-Hartman gregkh@google.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/proc/generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index bc86aa87cc41..5600da30e289 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -756,7 +756,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) while (1) { next = pde_subdir_first(de); if (next) { - if (unlikely(pde_is_permanent(root))) { + if (unlikely(pde_is_permanent(next))) { write_unlock(&proc_subdir_lock); WARN(1, "removing permanent /proc entry '%s/%s'", next->parent->name, next->name);
From: Jia-Ju Bai baijiaju1990@gmail.com
[ Upstream commit 31d82c2c787d5cf65fedd35ebbc0c1bd95c1a679 ]
When vzalloc() returns NULL to sha_regions, no error return code of kexec_calculate_store_digests() is assigned. To fix this bug, ret is assigned with -ENOMEM in this case.
Link: https://lkml.kernel.org/r/20210309083904.24321-1-baijiaju1990@gmail.com Fixes: a43cac0d9dc2 ("kexec: split kexec_file syscall code to kexec_file.c") Signed-off-by: Jia-Ju Bai baijiaju1990@gmail.com Reported-by: TOTE Robot oslab@tsinghua.edu.cn Acked-by: Baoquan He bhe@redhat.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/kexec_file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 5c3447cf7ad5..33400ff051a8 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -740,8 +740,10 @@ static int kexec_calculate_store_digests(struct kimage *image)
sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region); sha_regions = vzalloc(sha_region_sz); - if (!sha_regions) + if (!sha_regions) { + ret = -ENOMEM; goto out_free_desc; + }
desc->tfm = tfm;
From: David Hildenbrand david@redhat.com
[ Upstream commit 97f61c8f44ec9020708b97a51188170add4f3084 ]
Patch series "kernel/resource: make walk_system_ram_res() and walk_mem_res() search the whole tree", v2.
Playing with kdump+virtio-mem I noticed that kexec_file_load() does not consider System RAM added via dax/kmem and virtio-mem when preparing the elf header for kdump. Looking into the details, the logic used in walk_system_ram_res() and walk_mem_res() seems to be outdated.
walk_system_ram_range() already does the right thing, let's change walk_system_ram_res() and walk_mem_res(), and clean up.
Loading a kdump kernel via "kexec -p -s" ... will result in the kdump kernel to also dump dax/kmem and virtio-mem added System RAM now.
Note: kexec-tools on x86-64 also have to be updated to consider this memory in the kexec_load() case when processing /proc/iomem.
This patch (of 3):
It used to be true that we can have system RAM (IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY) only on the first level in the resource tree. However, this is no longer holds for driver-managed system RAM (i.e., added via dax/kmem and virtio-mem), which gets added on lower levels, for example, inside device containers.
We have two users of walk_system_ram_res(), which currently only consideres the first level:
a) kernel/kexec_file.c:kexec_walk_resources() -- We properly skip IORESOURCE_SYSRAM_DRIVER_MANAGED resources via locate_mem_hole_callback(), so even after this change, we won't be placing kexec images onto dax/kmem and virtio-mem added memory. No change.
b) arch/x86/kernel/crash.c:fill_up_crash_elf_data() -- we're currently not adding relevant ranges to the crash elf header, resulting in them not getting dumped via kdump.
This change fixes loading a crashkernel via kexec_file_load() and including dax/kmem and virtio-mem added System RAM in the crashdump on x86-64. Note that e.g,, arm64 relies on memblock data and, therefore, always considers all added System RAM already.
Let's find all IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY resources, making the function behave like walk_system_ram_range().
Link: https://lkml.kernel.org/r/20210325115326.7826-1-david@redhat.com Link: https://lkml.kernel.org/r/20210325115326.7826-2-david@redhat.com Fixes: ebf71552bb0e ("virtio-mem: Add parent resource for all added "System RAM"") Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM") Signed-off-by: David Hildenbrand david@redhat.com Reviewed-by: Dan Williams dan.j.williams@intel.com Acked-by: Baoquan He bhe@redhat.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Dan Williams dan.j.williams@intel.com Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Andy Shevchenko andriy.shevchenko@linux.intel.com Cc: Mauro Carvalho Chehab mchehab+huawei@kernel.org Cc: Dave Young dyoung@redhat.com Cc: Baoquan He bhe@redhat.com Cc: Vivek Goyal vgoyal@redhat.com Cc: Dave Hansen dave.hansen@linux.intel.com Cc: Keith Busch keith.busch@intel.com Cc: Michal Hocko mhocko@suse.com Cc: Qian Cai cai@lca.pw Cc: Oscar Salvador osalvador@suse.de Cc: Eric Biederman ebiederm@xmission.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Ingo Molnar mingo@redhat.com Cc: Borislav Petkov bp@alien8.de Cc: "H. Peter Anvin" hpa@zytor.com Cc: Tom Lendacky thomas.lendacky@amd.com Cc: Brijesh Singh brijesh.singh@amd.com Cc: "Eric W. Biederman" ebiederm@xmission.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/resource.c b/kernel/resource.c index 627e61b0c124..4efd6e912279 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -457,7 +457,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, { unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true, + return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false, arg, func); }
From: David Hildenbrand david@redhat.com
[ Upstream commit 3c9c797534364593b73ba6ab060a014af8934721 ]
It used to be true that we can have system RAM (IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY) only on the first level in the resource tree. However, this is no longer holds for driver-managed system RAM (i.e., added via dax/kmem and virtio-mem), which gets added on lower levels, for example, inside device containers.
IORESOURCE_SYSTEM_RAM is defined as IORESOURCE_MEM | IORESOURCE_SYSRAM and just a special type of IORESOURCE_MEM.
The function walk_mem_res() only considers the first level and is used in arch/x86/mm/ioremap.c:__ioremap_check_mem() only. We currently fail to identify System RAM added by dax/kmem and virtio-mem as "IORES_MAP_SYSTEM_RAM", for example, allowing for remapping of such "normal RAM" in __ioremap_caller().
Let's find all IORESOURCE_MEM | IORESOURCE_BUSY resources, making the function behave similar to walk_system_ram_res().
Link: https://lkml.kernel.org/r/20210325115326.7826-3-david@redhat.com Fixes: ebf71552bb0e ("virtio-mem: Add parent resource for all added "System RAM"") Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM") Signed-off-by: David Hildenbrand david@redhat.com Reviewed-by: Dan Williams dan.j.williams@intel.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Dan Williams dan.j.williams@intel.com Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Andy Shevchenko andriy.shevchenko@linux.intel.com Cc: Mauro Carvalho Chehab mchehab+huawei@kernel.org Cc: Dave Young dyoung@redhat.com Cc: Baoquan He bhe@redhat.com Cc: Vivek Goyal vgoyal@redhat.com Cc: Dave Hansen dave.hansen@linux.intel.com Cc: Keith Busch keith.busch@intel.com Cc: Michal Hocko mhocko@suse.com Cc: Qian Cai cai@lca.pw Cc: Oscar Salvador osalvador@suse.de Cc: Eric Biederman ebiederm@xmission.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Ingo Molnar mingo@redhat.com Cc: Borislav Petkov bp@alien8.de Cc: "H. Peter Anvin" hpa@zytor.com Cc: Tom Lendacky thomas.lendacky@amd.com Cc: Brijesh Singh brijesh.singh@amd.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/resource.c b/kernel/resource.c index 4efd6e912279..16e0c7e8ed24 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -470,7 +470,7 @@ int walk_mem_res(u64 start, u64 end, void *arg, { unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true, + return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false, arg, func); }
From: Eric Dumazet edumazet@google.com
[ Upstream commit a54754ec9891830ba548e2010c889e3c8146e449 ]
Number of buckets being stored in 32bit variables, we have to ensure that no overflows occur in nft_hash_buckets()
syzbot injected a size == 0x40000000 and reported:
UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 shift exponent 64 is too large for 64-bit type 'long unsigned int' CPU: 1 PID: 29539 Comm: syz-executor.4 Not tainted 5.12.0-rc7-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 __roundup_pow_of_two include/linux/log2.h:57 [inline] nft_hash_buckets net/netfilter/nft_set_hash.c:411 [inline] nft_hash_estimate.cold+0x19/0x1e net/netfilter/nft_set_hash.c:652 nft_select_set_ops net/netfilter/nf_tables_api.c:3586 [inline] nf_tables_newset+0xe62/0x3110 net/netfilter/nf_tables_api.c:4322 nfnetlink_rcv_batch+0xa09/0x24b0 net/netfilter/nfnetlink.c:488 nfnetlink_rcv_skb_batch net/netfilter/nfnetlink.c:612 [inline] nfnetlink_rcv+0x3af/0x420 net/netfilter/nfnetlink.c:630 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
Fixes: 0ed6389c483d ("netfilter: nf_tables: rename set implementations") Signed-off-by: Eric Dumazet edumazet@google.com Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Pablo Neira Ayuso pablo@netfilter.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/netfilter/nft_set_hash.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index bf618b7ec1ae..560c2cda52ee 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -406,9 +406,17 @@ static void nft_rhash_destroy(const struct nft_set *set) (void *)set); }
+/* Number of buckets is stored in u32, so cap our result to 1U<<31 */ +#define NFT_MAX_BUCKETS (1U << 31) + static u32 nft_hash_buckets(u32 size) { - return roundup_pow_of_two(size * 4 / 3); + u64 val = div_u64((u64)size * 4, 3); + + if (val >= NFT_MAX_BUCKETS) + return NFT_MAX_BUCKETS; + + return roundup_pow_of_two(val); }
static bool nft_rhash_estimate(const struct nft_set_desc *desc, u32 features,
From: Magnus Karlsson magnus.karlsson@intel.com
[ Upstream commit ae4393dfd472b194c90d75d2123105fb5ed59b04 ]
Commit 12738ac4754e ("i40e: Fix sparse errors in i40e_txrx.c") broke XDP support in the i40e driver. That commit was fixing a sparse error in the code by introducing a new variable xdp_res instead of overloading this into the skb pointer. The problem is that the code later uses the skb pointer in if statements and these where not extended to also test for the new xdp_res variable. Fix this by adding the correct tests for xdp_res in these places.
The skb pointer was used to store the result of the XDP program by overloading the results in the error pointer ERR_PTR(-result). Therefore, the allocation failure test that used to only test for !skb now need to be extended to also consider !xdp_res.
i40e_cleanup_headers() had a check that based on the skb value being an error pointer, i.e. a result from the XDP program != XDP_PASS, and if so start to process a new packet immediately, instead of populating skb fields and sending the skb to the stack. This check is not needed anymore, since we have added an explicit test for xdp_res being set and if so just do continue to pick the next packet from the NIC.
Fixes: 12738ac4754e ("i40e: Fix sparse errors in i40e_txrx.c") Acked-by: Jesper Dangaard Brouer brouer@redhat.com Tested-by: Jesper Dangaard Brouer brouer@redhat.com Reported-by: Jesper Dangaard Brouer brouer@redhat.com Reviewed-by: Maciej Fijalkowski maciej.fijalkowski@intel.com Signed-off-by: Magnus Karlsson magnus.karlsson@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 06b4271219b1..70b515049540 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1961,10 +1961,6 @@ static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb, union i40e_rx_desc *rx_desc)
{ - /* XDP packets use error pointer so abort at this point */ - if (IS_ERR(skb)) - return true; - /* ERR_MASK will only have valid bits if EOP set, and * what we are doing here is actually checking * I40E_RX_DESC_ERROR_RXE_SHIFT, since it is the zeroth bit in @@ -2534,7 +2530,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) }
/* exit if we failed to retrieve a buffer */ - if (!skb) { + if (!xdp_res && !skb) { rx_ring->rx_stats.alloc_buff_failed++; rx_buffer->pagecnt_bias++; break; @@ -2547,7 +2543,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) if (i40e_is_non_eop(rx_ring, rx_desc)) continue;
- if (i40e_cleanup_headers(rx_ring, skb, rx_desc)) { + if (xdp_res || i40e_cleanup_headers(rx_ring, skb, rx_desc)) { skb = NULL; continue; }
From: Yunjian Wang wangyunjian@huawei.com
[ Upstream commit 38318f23a7ef86a8b1862e5e8078c4de121960c3 ]
Currently the call to i40e_client_del_instance frees the object pf->cinst, however pf->cinst->lan_info is being accessed after the free. Fix this by adding the missing return.
Addresses-Coverity: ("Read from pointer after free") Fixes: 7b0b1a6d0ac9 ("i40e: Disable iWARP VSI PETCP_ENA flag on netdev down events") Signed-off-by: Yunjian Wang wangyunjian@huawei.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_client.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c index a2dba32383f6..32f3facbed1a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_client.c +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c @@ -375,6 +375,7 @@ void i40e_client_subtask(struct i40e_pf *pf) clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); i40e_client_del_instance(pf); + return; } } }
From: Jaroslaw Gawin jaroslawx.gawin@intel.com
[ Upstream commit 61343e6da7810de81d6b826698946ae4f9070819 ]
When FEC mode was changed the link didn't know it because the link was not reset and new parameters were not negotiated. Set a flag 'I40E_AQ_PHY_ENABLE_ATOMIC_LINK' in 'abilities' to restart the link and make it run with the new settings.
Fixes: 1d96340196f1 ("i40e: Add support FEC configuration for Fortville 25G") Signed-off-by: Jaroslaw Gawin jaroslawx.gawin@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Tested-by: Dave Switzer david.switzer@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 0e92668012e3..6f3b7e0faa13 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1409,7 +1409,8 @@ static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg)
memset(&config, 0, sizeof(config)); config.phy_type = abilities.phy_type; - config.abilities = abilities.abilities; + config.abilities = abilities.abilities | + I40E_AQ_PHY_ENABLE_ATOMIC_LINK; config.phy_type_ext = abilities.phy_type_ext; config.link_speed = abilities.link_speed; config.eee_capability = abilities.eee_capability;
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit 15395ec4685bd45a43d1b54b8fd9846b87e2c621 ]
Unlike other supported adapters, 2.5G and 5G use different PHY type identifiers for reading/writing PHY settings and for reading link status. This commit introduces separate PHY identifiers for these two operation types.
Fixes: 2e45d3f4677a ("i40e: Add support for X710 B/P & SFP+ cards") Signed-off-by: Dawid Lukwinski dawid.lukwinski@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Dave Switzer david.switzer@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 6 ++++-- drivers/net/ethernet/intel/i40e/i40e_common.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_type.h | 7 ++----- 4 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index ce626eace692..140b677f114d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1566,8 +1566,10 @@ enum i40e_aq_phy_type { I40E_PHY_TYPE_25GBASE_LR = 0x22, I40E_PHY_TYPE_25GBASE_AOC = 0x23, I40E_PHY_TYPE_25GBASE_ACC = 0x24, - I40E_PHY_TYPE_2_5GBASE_T = 0x30, - I40E_PHY_TYPE_5GBASE_T = 0x31, + I40E_PHY_TYPE_2_5GBASE_T = 0x26, + I40E_PHY_TYPE_5GBASE_T = 0x27, + I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS = 0x30, + I40E_PHY_TYPE_5GBASE_T_LINK_STATUS = 0x31, I40E_PHY_TYPE_MAX, I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD, I40E_PHY_TYPE_EMPTY = 0xFE, diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ec19e18305ec..ce35e064cf60 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1154,8 +1154,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) break; case I40E_PHY_TYPE_100BASE_TX: case I40E_PHY_TYPE_1000BASE_T: - case I40E_PHY_TYPE_2_5GBASE_T: - case I40E_PHY_TYPE_5GBASE_T: + case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: + case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: case I40E_PHY_TYPE_10GBASE_T: media = I40E_MEDIA_TYPE_BASET; break; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 6f3b7e0faa13..e8da7339137c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -841,8 +841,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 10000baseT_Full); break; case I40E_PHY_TYPE_10GBASE_T: - case I40E_PHY_TYPE_5GBASE_T: - case I40E_PHY_TYPE_2_5GBASE_T: + case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: + case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: case I40E_PHY_TYPE_1000BASE_T: case I40E_PHY_TYPE_100BASE_TX: ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 5c10faaca790..c81109a63e90 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -239,11 +239,8 @@ struct i40e_phy_info { #define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \ I40E_PHY_TYPE_OFFSET) /* Offset for 2.5G/5G PHY Types value to bit number conversion */ -#define I40E_PHY_TYPE_OFFSET2 (-10) -#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T + \ - I40E_PHY_TYPE_OFFSET2) -#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T + \ - I40E_PHY_TYPE_OFFSET2) +#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T) +#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T) #define I40E_HW_CAP_MAX_GPIO 30 /* Capabilities of a PF or a VF or the whole device */ struct i40e_hw_capabilities {
From: Arkadiusz Kubalewski arkadiusz.kubalewski@intel.com
[ Upstream commit 8085a36db71f54d2592426eb76bdf71b82479140 ]
Remove filters from being setup in case of software DCB and allow the LLDP frames to be properly transmitted to the wire.
It is not possible to transmit the LLDP frame out of the port, if they are filtered by control VSI. This prohibits software LLDP agent properly communicate its DCB capabilities to the neighbors.
Fixes: 4b208eaa8078 ("i40e: Add init and default config of software based DCB") Signed-off-by: Arkadiusz Kubalewski arkadiusz.kubalewski@intel.com Tested-by: Imam Hassan Reza Biswas imam.hassan.reza.biswas@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e.h | 1 - .../net/ethernet/intel/i40e/i40e_ethtool.c | 1 - drivers/net/ethernet/intel/i40e/i40e_main.c | 42 ------------------- 3 files changed, 44 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 15f93b355099..5069f690cf0b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -1142,7 +1142,6 @@ static inline bool i40e_is_sw_dcb(struct i40e_pf *pf) return !!(pf->flags & I40E_FLAG_DISABLE_FW_LLDP); }
-void i40e_set_lldp_forwarding(struct i40e_pf *pf, bool enable); #ifdef CONFIG_I40E_DCB void i40e_dcbnl_flush_apps(struct i40e_pf *pf, struct i40e_dcbx_config *old_cfg, diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e8da7339137c..93dd58fda272 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -5288,7 +5288,6 @@ flags_complete: i40e_aq_cfg_lldp_mib_change_event(&pf->hw, false, NULL); i40e_aq_stop_lldp(&pf->hw, true, false, NULL); } else { - i40e_set_lldp_forwarding(pf, false); status = i40e_aq_start_lldp(&pf->hw, false, NULL); if (status) { adq_err = pf->hw.aq.asq_last_status; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 527023ee4c07..ac4b44fc19f1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6878,40 +6878,6 @@ out: } #endif /* CONFIG_I40E_DCB */
-/** - * i40e_set_lldp_forwarding - set forwarding of lldp frames - * @pf: PF being configured - * @enable: if forwarding to OS shall be enabled - * - * Toggle forwarding of lldp frames behavior, - * When passing DCB control from firmware to software - * lldp frames must be forwarded to the software based - * lldp agent. - */ -void i40e_set_lldp_forwarding(struct i40e_pf *pf, bool enable) -{ - if (pf->lan_vsi == I40E_NO_VSI) - return; - - if (!pf->vsi[pf->lan_vsi]) - return; - - /* No need to check the outcome, commands may fail - * if desired value is already set - */ - i40e_aq_add_rem_control_packet_filter(&pf->hw, NULL, ETH_P_LLDP, - I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX | - I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC, - pf->vsi[pf->lan_vsi]->seid, 0, - enable, NULL, NULL); - - i40e_aq_add_rem_control_packet_filter(&pf->hw, NULL, ETH_P_LLDP, - I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX | - I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC, - pf->vsi[pf->lan_vsi]->seid, 0, - enable, NULL, NULL); -} - /** * i40e_print_link_message - print link up or down * @vsi: the VSI for which link needs a message @@ -10735,10 +10701,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) */ i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, pf->main_vsi_seid); -#ifdef CONFIG_I40E_DCB - if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) - i40e_set_lldp_forwarding(pf, true); -#endif /* CONFIG_I40E_DCB */
/* restart the VSIs that were rebuilt and running before the reset */ i40e_pf_unquiesce_all_vsi(pf); @@ -15753,10 +15715,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, pf->main_vsi_seid); -#ifdef CONFIG_I40E_DCB - if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) - i40e_set_lldp_forwarding(pf, true); -#endif /* CONFIG_I40E_DCB */
if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) || (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
From: Paolo Abeni pabeni@redhat.com
[ Upstream commit 578c18eff1627d6a911f08f4cf351eca41fdcc7d ]
If userspace exits before calling accept() on a listener that had at least one new connection ready, we get:
Attempt to release TCP socket in state 8
This happens because the mptcp socket gets cloned when the TCP connection is ready, but the socket is never exposed to userspace.
The client additionally sends a DATA_FIN, which brings connection into CLOSE_WAIT state. This in turn prevents the orphan+state reset fixup in mptcp_sock_destruct() from doing its job.
Fixes: 3721b9b64676b ("mptcp: Track received DATA_FIN sequence number and add related helpers") Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/185 Tested-by: Florian Westphal fw@strlen.de Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Mat Martineau mathew.j.martineau@linux.intel.com Link: https://lore.kernel.org/r/20210507001638.225468-1-mathew.j.martineau@linux.i... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/mptcp/subflow.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index d17d39ccdf34..4fe7acaa472f 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -524,8 +524,7 @@ static void mptcp_sock_destruct(struct sock *sk) * ESTABLISHED state and will not have the SOCK_DEAD flag. * Both result in warnings from inet_sock_destruct. */ - - if (sk->sk_state == TCP_ESTABLISHED) { + if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) { sk->sk_state = TCP_CLOSE; WARN_ON_ONCE(sk->sk_socket); sock_orphan(sk);
From: Vineet Gupta vgupta@synopsys.com
commit 3433adc8bd09fc9f29b8baddf33b4ecd1ecd2cdc upstream.
We have NR_syscall syscalls from [0 .. NR_syscall-1]. However the check for invalid syscall number is "> NR_syscall" as opposed to >=. This off-by-one error erronesously allows "NR_syscall" to be treated as valid syscall causeing out-of-bounds access into syscall-call table ensuing a crash (holes within syscall table have a invalid-entry handler but this is beyond the array implementing the table).
This problem showed up on v5.6 kernel when testing glibc 2.33 (v5.10 kernel capable, includng faccessat2 syscall 439). The v5.6 kernel has NR_syscalls=439 (0 to 438). Due to the bug, 439 passed by glibc was not handled as -ENOSYS but processed leading to a crash.
Link: https://github.com/foss-for-synopsys-dwc-arc-processors/linux/issues/48 Reported-by: Shahab Vahedi shahab@synopsys.com Cc: stable@vger.kernel.org Signed-off-by: Vineet Gupta vgupta@synopsys.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arc/kernel/entry.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -177,7 +177,7 @@ tracesys:
; Do the Sys Call as we normally would. ; Validate the Sys Call number - cmp r8, NR_syscalls + cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi tracesys_exit
@@ -255,7 +255,7 @@ ENTRY(EV_Trap) ;============ Normal syscall case
; syscall num shd not exceed the total system calls avail - cmp r8, NR_syscalls + cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi .Lret_from_system_call
From: Vladimir Isaev isaev@synopsys.com
commit c5f756d8c6265ebb1736a7787231f010a3b782e5 upstream.
32-bit PAGE_MASK can not be used as a mask for physical addresses when PAE is enabled. PAGE_MASK_PHYS must be used for physical addresses instead of PAGE_MASK.
Without this, init gets SIGSEGV if pte_modify was called:
| potentially unexpected fatal signal 11. | Path: /bin/busybox | CPU: 0 PID: 1 Comm: init Not tainted 5.12.0-rc5-00003-g1e43c377a79f-dirty | Insn could not be fetched | @No matching VMA found | ECR: 0x00040000 EFA: 0x00000000 ERET: 0x00000000 | STAT: 0x80080082 [IE U ] BTA: 0x00000000 | SP: 0x5f9ffe44 FP: 0x00000000 BLK: 0xaf3d4 | LPS: 0x000d093e LPE: 0x000d0950 LPC: 0x00000000 | r00: 0x00000002 r01: 0x5f9fff14 r02: 0x5f9fff20 | ... | Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
Signed-off-by: Vladimir Isaev isaev@synopsys.com Reported-by: kernel test robot lkp@intel.com Cc: Vineet Gupta vgupta@synopsys.com Cc: stable@vger.kernel.org Signed-off-by: Vineet Gupta vgupta@synopsys.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arc/include/asm/page.h | 12 ++++++++++++ arch/arc/include/asm/pgtable.h | 12 +++--------- arch/arc/include/uapi/asm/page.h | 1 - arch/arc/mm/ioremap.c | 5 +++-- arch/arc/mm/tlb.c | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-)
--- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -7,6 +7,18 @@
#include <uapi/asm/page.h>
+#ifdef CONFIG_ARC_HAS_PAE40 + +#define MAX_POSSIBLE_PHYSMEM_BITS 40 +#define PAGE_MASK_PHYS (0xff00000000ull | PAGE_MASK) + +#else /* CONFIG_ARC_HAS_PAE40 */ + +#define MAX_POSSIBLE_PHYSMEM_BITS 32 +#define PAGE_MASK_PHYS PAGE_MASK + +#endif /* CONFIG_ARC_HAS_PAE40 */ + #ifndef __ASSEMBLY__
#define clear_page(paddr) memset((paddr), 0, PAGE_SIZE) --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -107,8 +107,8 @@ #define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
/* Set of bits not changed in pte_modify */ -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL) - +#define _PAGE_CHG_MASK (PAGE_MASK_PHYS | _PAGE_ACCESSED | _PAGE_DIRTY | \ + _PAGE_SPECIAL) /* More Abbrevaited helpers */ #define PAGE_U_NONE __pgprot(___DEF) #define PAGE_U_R __pgprot(___DEF | _PAGE_READ) @@ -132,13 +132,7 @@ #define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ) #define PTE_BITS_RWX (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
-#ifdef CONFIG_ARC_HAS_PAE40 -#define PTE_BITS_NON_RWX_IN_PD1 (0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE) -#define MAX_POSSIBLE_PHYSMEM_BITS 40 -#else -#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK | _PAGE_CACHEABLE) -#define MAX_POSSIBLE_PHYSMEM_BITS 32 -#endif +#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE)
/************************************************************************** * Mapping of vm_flags (Generic VM) to PTE flags (arch specific) --- a/arch/arc/include/uapi/asm/page.h +++ b/arch/arc/include/uapi/asm/page.h @@ -33,5 +33,4 @@
#define PAGE_MASK (~(PAGE_SIZE-1))
- #endif /* _UAPI__ASM_ARC_PAGE_H */ --- a/arch/arc/mm/ioremap.c +++ b/arch/arc/mm/ioremap.c @@ -53,9 +53,10 @@ EXPORT_SYMBOL(ioremap); void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size, unsigned long flags) { + unsigned int off; unsigned long vaddr; struct vm_struct *area; - phys_addr_t off, end; + phys_addr_t end; pgprot_t prot = __pgprot(flags);
/* Don't allow wraparound, zero size */ @@ -72,7 +73,7 @@ void __iomem *ioremap_prot(phys_addr_t p
/* Mappings have to be page-aligned */ off = paddr & ~PAGE_MASK; - paddr &= PAGE_MASK; + paddr &= PAGE_MASK_PHYS; size = PAGE_ALIGN(end + 1) - paddr;
/* --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -576,7 +576,7 @@ void update_mmu_cache(struct vm_area_str pte_t *ptep) { unsigned long vaddr = vaddr_unaligned & PAGE_MASK; - phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK; + phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK_PHYS; struct page *page = pfn_to_page(pte_pfn(*ptep));
create_tlb(vma, vaddr, ptep);
From: Vladimir Isaev isaev@synopsys.com
commit 1d5e4640e5df15252398c1b621f6bd432f2d7f17 upstream.
Commit 4af22ded0ecf ("arc: fix memory initialization for systems with two memory banks") fixed highmem, but for the PAE case it causes bug messages:
| BUG: Bad page state in process swapper pfn:80000 | page:(ptrval) refcount:0 mapcount:1 mapping:00000000 index:0x0 pfn:0x80000 flags: 0x0() | raw: 00000000 00000100 00000122 00000000 00000000 00000000 00000000 00000000 | raw: 00000000 | page dumped because: nonzero mapcount | Modules linked in: | CPU: 0 PID: 0 Comm: swapper Not tainted 5.12.0-rc5-00003-g1e43c377a79f #1
This is because the fix expects highmem to be always less than lowmem and uses min_low_pfn as an upper zone border for highmem.
max_high_pfn should be ok for both highmem and highmem+PAE cases.
Fixes: 4af22ded0ecf ("arc: fix memory initialization for systems with two memory banks") Signed-off-by: Vladimir Isaev isaev@synopsys.com Cc: Mike Rapoport rppt@linux.ibm.com Cc: stable@vger.kernel.org #5.8 onwards Signed-off-by: Vineet Gupta vgupta@synopsys.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arc/mm/init.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
--- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -157,7 +157,16 @@ void __init setup_arch_memory(void) min_high_pfn = PFN_DOWN(high_mem_start); max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
- max_zone_pfn[ZONE_HIGHMEM] = min_low_pfn; + /* + * max_high_pfn should be ok here for both HIGHMEM and HIGHMEM+PAE. + * For HIGHMEM without PAE max_high_pfn should be less than + * min_low_pfn to guarantee that these two regions don't overlap. + * For PAE case highmem is greater than lowmem, so it is natural + * to use max_high_pfn. + * + * In both cases, holes should be handled by pfn_valid(). + */ + max_zone_pfn[ZONE_HIGHMEM] = max_high_pfn;
high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
From: Eric Dumazet edumazet@google.com
commit 0d3ae948741ac6d80e39ab27b45297367ee477de upstream.
Removes this annoying warning:
arch/sh/kernel/traps.c: In function ‘nmi_trap_handler’: arch/sh/kernel/traps.c:183:15: warning: unused variable ‘cpu’ [-Wunused-variable] 183 | unsigned int cpu = smp_processor_id();
Fixes: fe3f1d5d7cd3 ("sh: Get rid of nmi_count()") Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210414170517.1205430-1-eric.dumazet@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/sh/kernel/traps.c | 1 - 1 file changed, 1 deletion(-)
--- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -180,7 +180,6 @@ static inline void arch_ftrace_nmi_exit(
BUILD_TRAP_HANDLER(nmi) { - unsigned int cpu = smp_processor_id(); TRAP_HANDLER_DECL;
arch_ftrace_nmi_enter();
From: Michael Ellerman mpe@ellerman.id.au
commit 8ec7791bae1327b1c279c5cd6e929c3b12daaf0a upstream.
The STF (store-to-load forwarding) barrier mitigation can be enabled/disabled at runtime via a debugfs file (stf_barrier), which causes the kernel to patch itself to enable/disable the relevant mitigations.
However depending on which mitigation we're using, it may not be safe to do that patching while other CPUs are active. For example the following crash:
User access of kernel address (c00000003fff5af0) - exploit attempt? (uid: 0) segfault (11) at c00000003fff5af0 nip 7fff8ad12198 lr 7fff8ad121f8 code 1 code: 40820128 e93c00d0 e9290058 7c292840 40810058 38600000 4bfd9a81 e8410018 code: 2c030006 41810154 3860ffb6 e9210098 <e94d8ff0> 7d295279 39400000 40820a3c
Shows that we returned to userspace without restoring the user r13 value, due to executing the partially patched STF exit code.
Fix it by doing the patching under stop machine. The CPUs that aren't doing the patching will be spinning in the core of the stop machine logic. That is currently sufficient for our purposes, because none of the patching we do is to that code or anywhere in the vicinity.
Fixes: a048a07d7f45 ("powerpc/64s: Add support for a store forwarding barrier at kernel entry/exit") Cc: stable@vger.kernel.org # v4.17+ Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210506044959.1298123-1-mpe@ellerman.id.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/lib/feature-fixups.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
--- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -14,6 +14,7 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/sched/mm.h> +#include <linux/stop_machine.h> #include <asm/cputable.h> #include <asm/code-patching.h> #include <asm/page.h> @@ -227,11 +228,25 @@ static void do_stf_exit_barrier_fixups(e : "unknown"); }
+static int __do_stf_barrier_fixups(void *data) +{ + enum stf_barrier_type *types = data; + + do_stf_entry_barrier_fixups(*types); + do_stf_exit_barrier_fixups(*types); + + return 0; +}
void do_stf_barrier_fixups(enum stf_barrier_type types) { - do_stf_entry_barrier_fixups(types); - do_stf_exit_barrier_fixups(types); + /* + * The call to the fallback entry flush, and the fallback/sync-ori exit + * flush can not be safely patched in/out while other CPUs are executing + * them. So call __do_stf_barrier_fixups() on one CPU while all other CPUs + * spin in the stop machine core with interrupts hard disabled. + */ + stop_machine(__do_stf_barrier_fixups, &types, NULL); }
void do_uaccess_flush_fixups(enum l1d_flush_type types)
From: Jouni Roivas jouni.roivas@tuxera.com
commit c3187cf32216313fb316084efac4dab3a8459b1d upstream.
I believe there are some issues introduced by commit 31651c607151 ("hfsplus: avoid deadlock on file truncation")
HFS+ has extent records which always contains 8 extents. In case the first extent record in catalog file gets full, new ones are allocated from extents overflow file.
In case shrinking truncate happens to middle of an extent record which locates in extents overflow file, the logic in hfsplus_file_truncate() was changed so that call to hfs_brec_remove() is not guarded any more.
Right action would be just freeing the extents that exceed the new size inside extent record by calling hfsplus_free_extents(), and then check if the whole extent record should be removed. However since the guard (blk_cnt > start) is now after the call to hfs_brec_remove(), this has unfortunate effect that the last matching extent record is removed unconditionally.
To reproduce this issue, create a file which has at least 10 extents, and then perform shrinking truncate into middle of the last extent record, so that the number of remaining extents is not under or divisible by 8. This causes the last extent record (8 extents) to be removed totally instead of truncating into middle of it. Thus this causes corruption, and lost data.
Fix for this is simply checking if the new truncated end is below the start of this extent record, making it safe to remove the full extent record. However call to hfs_brec_remove() can't be moved to it's previous place since we're dropping ->tree_lock and it can cause a race condition and the cached info being invalidated possibly corrupting the node data.
Another issue is related to this one. When entering into the block (blk_cnt > start) we are not holding the ->tree_lock. We break out from the loop not holding the lock, but hfs_find_exit() does unlock it. Not sure if it's possible for someone else to take the lock under our feet, but it can cause hard to debug errors and premature unlocking. Even if there's no real risk of it, the locking should still always be kept in balance. Thus taking the lock now just before the check.
Link: https://lkml.kernel.org/r/20210429165139.3082828-1-jouni.roivas@tuxera.com Fixes: 31651c607151f ("hfsplus: avoid deadlock on file truncation") Signed-off-by: Jouni Roivas jouni.roivas@tuxera.com Reviewed-by: Anton Altaparmakov anton@tuxera.com Cc: Anatoly Trosinenko anatoly.trosinenko@gmail.com Cc: Viacheslav Dubeyko slava@dubeyko.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/hfsplus/extents.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); if (res) break; - hfs_brec_remove(&fd);
- mutex_unlock(&fd.tree->tree_lock); start = hip->cached_start; + if (blk_cnt <= start) + hfs_brec_remove(&fd); + mutex_unlock(&fd.tree->tree_lock); hfsplus_free_extents(sb, hip->cached_extents, alloc_cnt - start, alloc_cnt - blk_cnt); hfsplus_dump_extent(hip->cached_extents); + mutex_lock(&fd.tree->tree_lock); if (blk_cnt > start) { hip->extent_state |= HFSPLUS_EXT_DIRTY; break; @@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode alloc_cnt = start; hip->cached_start = hip->cached_blocks = 0; hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); - mutex_lock(&fd.tree->tree_lock); } hfs_find_exit(&fd);
From: Phillip Lougher phillip@squashfs.org.uk
commit d6e621de1fceb3b098ebf435ef7ea91ec4838a1a upstream.
Sysbot has reported a "divide error" which has been identified as being caused by a corrupted file_size value within the file inode. This value has been corrupted to a much larger value than expected.
Calculate_skip() is passed i_size_read(inode) >> msblk->block_log. Due to the file_size value corruption this overflows the int argument/variable in that function, leading to the divide error.
This patch changes the function to use u64. This will accommodate any unexpectedly large values due to corruption.
The value returned from calculate_skip() is clamped to be never more than SQUASHFS_CACHED_BLKS - 1, or 7. So file_size corruption does not lead to an unexpectedly large return result here.
Link: https://lkml.kernel.org/r/20210507152618.9447-1-phillip@squashfs.org.uk Signed-off-by: Phillip Lougher phillip@squashfs.org.uk Reported-by: syzbot+e8f781243ce16ac2f962@syzkaller.appspotmail.com Reported-by: syzbot+7b98870d4fec9447b951@syzkaller.appspotmail.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/squashfs/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/fs/squashfs/file.c +++ b/fs/squashfs/file.c @@ -211,11 +211,11 @@ failure: * If the skip factor is limited in this way then the file will use multiple * slots. */ -static inline int calculate_skip(int blocks) +static inline int calculate_skip(u64 blocks) { - int skip = blocks / ((SQUASHFS_META_ENTRIES + 1) + u64 skip = blocks / ((SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); - return min(SQUASHFS_CACHED_BLKS - 1, skip + 1); + return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1); }
From: Axel Rasmussen axelrasmussen@google.com
commit 7ed9d238c7dbb1fdb63ad96a6184985151b0171c upstream.
Consider the following sequence of events:
1. Userspace issues a UFFD ioctl, which ends up calling into shmem_mfill_atomic_pte(). We successfully account the blocks, we shmem_alloc_page(), but then the copy_from_user() fails. We return -ENOENT. We don't release the page we allocated. 2. Our caller detects this error code, tries the copy_from_user() after dropping the mmap_lock, and retries, calling back into shmem_mfill_atomic_pte(). 3. Meanwhile, let's say another process filled up the tmpfs being used. 4. So shmem_mfill_atomic_pte() fails to account blocks this time, and immediately returns - without releasing the page.
This triggers a BUG_ON in our caller, which asserts that the page should always be consumed, unless -ENOENT is returned.
To fix this, detect if we have such a "dangling" page when accounting fails, and if so, release it before returning.
Link: https://lkml.kernel.org/r/20210428230858.348400-1-axelrasmussen@google.com Fixes: cb658a453b93 ("userfaultfd: shmem: avoid leaking blocks and used blocks in UFFDIO_COPY") Signed-off-by: Axel Rasmussen axelrasmussen@google.com Reported-by: Hugh Dickins hughd@google.com Acked-by: Hugh Dickins hughd@google.com Reviewed-by: Peter Xu peterx@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/shmem.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/mm/shmem.c +++ b/mm/shmem.c @@ -2375,8 +2375,18 @@ static int shmem_mfill_atomic_pte(struct pgoff_t offset, max_off;
ret = -ENOMEM; - if (!shmem_inode_acct_block(inode, 1)) + if (!shmem_inode_acct_block(inode, 1)) { + /* + * We may have got a page, returned -ENOENT triggering a retry, + * and now we find ourselves with -ENOMEM. Release the page, to + * avoid a BUG_ON in our caller. + */ + if (unlikely(*pagep)) { + put_page(*pagep); + *pagep = NULL; + } goto out; + }
if (!*pagep) { page = shmem_alloc_page(gfp, info, pgoff);
From: Peter Collingbourne pcc@google.com
commit f649dc0e0d7b509c75570ee403723660f5b72ec7 upstream.
These tests deliberately access these arrays out of bounds, which will cause the dynamic local bounds checks inserted by CONFIG_UBSAN_LOCAL_BOUNDS to fail and panic the kernel. To avoid this problem, access the arrays via volatile pointers, which will prevent the compiler from being able to determine the array bounds.
These accesses use volatile pointers to char (char *volatile) rather than the more conventional pointers to volatile char (volatile char *) because we want to prevent the compiler from making inferences about the pointer itself (i.e. its array bounds), not the data that it refers to.
Link: https://lkml.kernel.org/r/20210507025915.1464056-1-pcc@google.com Link: https://linux-review.googlesource.com/id/I90b1713fbfa1bf68ff895aef099ea77b98... Signed-off-by: Peter Collingbourne pcc@google.com Tested-by: Alexander Potapenko glider@google.com Reviewed-by: Andrey Konovalov andreyknvl@gmail.com Cc: Peter Collingbourne pcc@google.com Cc: George Popescu georgepope@android.com Cc: Elena Petrova lenaptr@google.com Cc: Evgenii Stepanov eugenis@google.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- lib/test_kasan.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-)
--- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -646,8 +646,20 @@ static char global_array[10];
static void kasan_global_oob(struct kunit *test) { - volatile int i = 3; - char *p = &global_array[ARRAY_SIZE(global_array) + i]; + /* + * Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS + * from failing here and panicing the kernel, access the array via a + * volatile pointer, which will prevent the compiler from being able to + * determine the array bounds. + * + * This access uses a volatile pointer to char (char *volatile) rather + * than the more conventional pointer to volatile char (volatile char *) + * because we want to prevent the compiler from making inferences about + * the pointer itself (i.e. its array bounds), not the data that it + * refers to. + */ + char *volatile array = global_array; + char *p = &array[ARRAY_SIZE(global_array) + 3];
/* Only generic mode instruments globals. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); @@ -695,8 +707,9 @@ static void ksize_uaf(struct kunit *test static void kasan_stack_oob(struct kunit *test) { char stack_array[10]; - volatile int i = OOB_TAG_OFF; - char *p = &stack_array[ARRAY_SIZE(stack_array) + i]; + /* See comment in kasan_global_oob. */ + char *volatile array = stack_array; + char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF];
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK);
@@ -707,7 +720,9 @@ static void kasan_alloca_oob_left(struct { volatile int i = 10; char alloca_array[i]; - char *p = alloca_array - 1; + /* See comment in kasan_global_oob. */ + char *volatile array = alloca_array; + char *p = array - 1;
/* Only generic mode instruments dynamic allocas. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); @@ -720,7 +735,9 @@ static void kasan_alloca_oob_right(struc { volatile int i = 10; char alloca_array[i]; - char *p = alloca_array + i; + /* See comment in kasan_global_oob. */ + char *volatile array = alloca_array; + char *p = array + i;
/* Only generic mode instruments dynamic allocas. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
From: Peter Xu peterx@redhat.com
commit 22247efd822e6d263f3c8bd327f3f769aea9b1d9 upstream.
Patch series "mm/hugetlb: Fix issues on file sealing and fork", v2.
Hugh reported issue with F_SEAL_FUTURE_WRITE not applied correctly to hugetlbfs, which I can easily verify using the memfd_test program, which seems that the program is hardly run with hugetlbfs pages (as by default shmem).
Meanwhile I found another probably even more severe issue on that hugetlb fork won't wr-protect child cow pages, so child can potentially write to parent private pages. Patch 2 addresses that.
After this series applied, "memfd_test hugetlbfs" should start to pass.
This patch (of 2):
F_SEAL_FUTURE_WRITE is missing for hugetlb starting from the first day. There is a test program for that and it fails constantly.
$ ./memfd_test hugetlbfs memfd-hugetlb: CREATE memfd-hugetlb: BASIC memfd-hugetlb: SEAL-WRITE memfd-hugetlb: SEAL-FUTURE-WRITE mmap() didn't fail as expected Aborted (core dumped)
I think it's probably because no one is really running the hugetlbfs test.
Fix it by checking FUTURE_WRITE also in hugetlbfs_file_mmap() as what we do in shmem_mmap(). Generalize a helper for that.
Link: https://lkml.kernel.org/r/20210503234356.9097-1-peterx@redhat.com Link: https://lkml.kernel.org/r/20210503234356.9097-2-peterx@redhat.com Fixes: ab3948f58ff84 ("mm/memfd: add an F_SEAL_FUTURE_WRITE seal to memfd") Signed-off-by: Peter Xu peterx@redhat.com Reported-by: Hugh Dickins hughd@google.com Reviewed-by: Mike Kravetz mike.kravetz@oracle.com Cc: Joel Fernandes (Google) joel@joelfernandes.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/hugetlbfs/inode.c | 5 +++++ include/linux/mm.h | 32 ++++++++++++++++++++++++++++++++ mm/shmem.c | 22 ++++------------------ 3 files changed, 41 insertions(+), 18 deletions(-)
--- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -131,6 +131,7 @@ static void huge_pagevec_release(struct static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file_inode(file); + struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode); loff_t len, vma_len; int ret; struct hstate *h = hstate_file(file); @@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct fi vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; vma->vm_ops = &hugetlb_vm_ops;
+ ret = seal_check_future_write(info->seals, vma); + if (ret) + return ret; + /* * page based offset in vm_pgoff could be sufficiently large to * overflow a loff_t when converted to byte offset. This can --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3170,5 +3170,37 @@ extern int sysctl_nr_trim_pages;
void mem_dump_obj(void *object);
+/** + * seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it + * @seals: the seals to check + * @vma: the vma to operate on + * + * Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on + * the vma flags. Return 0 if check pass, or <0 for errors. + */ +static inline int seal_check_future_write(int seals, struct vm_area_struct *vma) +{ + if (seals & F_SEAL_FUTURE_WRITE) { + /* + * New PROT_WRITE and MAP_SHARED mmaps are not allowed when + * "future write" seal active. + */ + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE)) + return -EPERM; + + /* + * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as + * MAP_SHARED and read-only, take care to not allow mprotect to + * revert protections on such mappings. Do this only for shared + * mappings. For private mappings, don't need to mask + * VM_MAYWRITE as we still want them to be COW-writable. + */ + if (vma->vm_flags & VM_SHARED) + vma->vm_flags &= ~(VM_MAYWRITE); + } + + return 0; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2258,25 +2258,11 @@ out_nomem: static int shmem_mmap(struct file *file, struct vm_area_struct *vma) { struct shmem_inode_info *info = SHMEM_I(file_inode(file)); + int ret;
- if (info->seals & F_SEAL_FUTURE_WRITE) { - /* - * New PROT_WRITE and MAP_SHARED mmaps are not allowed when - * "future write" seal active. - */ - if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE)) - return -EPERM; - - /* - * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as - * MAP_SHARED and read-only, take care to not allow mprotect to - * revert protections on such mappings. Do this only for shared - * mappings. For private mappings, don't need to mask - * VM_MAYWRITE as we still want them to be COW-writable. - */ - if (vma->vm_flags & VM_SHARED) - vma->vm_flags &= ~(VM_MAYWRITE); - } + ret = seal_check_future_write(info->seals, vma); + if (ret) + return ret;
/* arm64 - allow memory tagging on RAM-based files */ vma->vm_flags |= VM_MTE_ALLOWED;
From: Peter Xu peterx@redhat.com
commit 84894e1c42e9f25c17f2888e0c0e1505cb727538 upstream.
When rework early cow of pinned hugetlb pages, we moved huge_ptep_get() upper but overlooked a side effect that the huge_ptep_get() will fetch the pte after wr-protection. After moving it upwards, we need explicit wr-protect of child pte or we will keep the write bit set in the child process, which could cause data corrution where the child can write to the original page directly.
This issue can also be exposed by "memfd_test hugetlbfs" kselftest.
Link: https://lkml.kernel.org/r/20210503234356.9097-3-peterx@redhat.com Fixes: 4eae4efa2c299 ("hugetlb: do early cow when page pinned on src mm") Signed-off-by: Peter Xu peterx@redhat.com Reviewed-by: Mike Kravetz mike.kravetz@oracle.com Cc: Hugh Dickins hughd@google.com Cc: Joel Fernandes (Google) joel@joelfernandes.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/hugetlb.c | 1 + 1 file changed, 1 insertion(+)
--- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3905,6 +3905,7 @@ again: * See Documentation/vm/mmu_notifier.rst */ huge_ptep_set_wrprotect(src, addr, src_pte); + entry = huge_pte_wrprotect(entry); }
page_dup_rmap(ptepage, true);
From: Tejun Heo tj@kernel.org
commit e9f4eee9a0023ba22db9560d4cc6ee63f933dae8 upstream.
When the weight of an active iocg is updated, weight_updated() is called which in turn calls __propagate_weights() to update the active and inuse weights so that the effective hierarchical weights are update accordingly.
The current implementation is incorrect for inner active nodes. For an active leaf iocg, inuse can be any value between 1 and active and the difference represents how much the iocg is donating. When weight is updated, as long as inuse is clamped between 1 and the new weight, we're alright and this is what __propagate_weights() currently implements.
However, that's not how an active inner node's inuse is set. An inner node's inuse is solely determined by the ratio between the sums of inuse's and active's of its children - ie. they're results of propagating the leaves' active and inuse weights upwards. __propagate_weights() incorrectly applies the same clamping as for a leaf when an active inner node's weight is updated. Consider a hierarchy which looks like the following with saturating workloads in AA and BB.
R / \ A B | | AA BB
1. For both A and B, active=100, inuse=100, hwa=0.5, hwi=0.5.
2. echo 200 > A/io.weight
3. __propagate_weights() update A's active to 200 and leave inuse at 100 as it's already between 1 and the new active, making A:active=200, A:inuse=100. As R's active_sum is updated along with A's active, A:hwa=2/3, B:hwa=1/3. However, because the inuses didn't change, the hwi's remain unchanged at 0.5.
4. The weight of A is now twice that of B but AA and BB still have the same hwi of 0.5 and thus are doing the same amount of IOs.
Fix it by making __propgate_weights() always calculate the inuse of an active inner iocg based on the ratio of child_inuse_sum to child_active_sum.
Signed-off-by: Tejun Heo tj@kernel.org Reported-by: Dan Schatzberg dschatzberg@fb.com Fixes: 7caa47151ab2 ("blkcg: implement blk-iocost") Cc: stable@vger.kernel.org # v5.4+ Link: https://lore.kernel.org/r/YJsxnLZV1MnBcqjj@slm.duckdns.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/blk-iocost.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
--- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1073,7 +1073,17 @@ static void __propagate_weights(struct i
lockdep_assert_held(&ioc->lock);
- inuse = clamp_t(u32, inuse, 1, active); + /* + * For an active leaf node, its inuse shouldn't be zero or exceed + * @active. An active internal node's inuse is solely determined by the + * inuse to active ratio of its children regardless of @inuse. + */ + if (list_empty(&iocg->active_list) && iocg->child_active_sum) { + inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum, + iocg->child_active_sum); + } else { + inuse = clamp_t(u32, inuse, 1, active); + }
iocg->last_inuse = iocg->inuse; if (save) @@ -1090,7 +1100,7 @@ static void __propagate_weights(struct i /* update the level sums */ parent->child_active_sum += (s32)(active - child->active); parent->child_inuse_sum += (s32)(inuse - child->inuse); - /* apply the udpates */ + /* apply the updates */ child->active = active; child->inuse = inuse;
From: Huang Rui ray.huang@amd.com
commit 3743d55b289c203d8f77b7cd47c24926b9d186ae upstream.
Some AMD Ryzen generations has different calculation method on maximum performance. 255 is not for all ASICs, some specific generations should use 166 as the maximum performance. Otherwise, it will report incorrect frequency value like below:
~ → lscpu | grep MHz CPU MHz: 3400.000 CPU max MHz: 7228.3198 CPU min MHz: 2200.0000
[ mingo: Tidied up whitespace use. ] [ Alexander Monakov amonakov@ispras.ru: fix 225 -> 255 typo. ]
Fixes: 41ea667227ba ("x86, sched: Calculate frequency invariance for AMD systems") Fixes: 3c55e94c0ade ("cpufreq: ACPI: Extend frequency tables to cover boost frequencies") Reported-by: Jason Bagavatsingham jason.bagavatsingham@gmail.com Fixed-by: Alexander Monakov amonakov@ispras.ru Reviewed-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Huang Rui ray.huang@amd.com Signed-off-by: Ingo Molnar mingo@kernel.org Tested-by: Jason Bagavatsingham jason.bagavatsingham@gmail.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210425073451.2557394-1-ray.huang@amd.com Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=211791 Signed-off-by: Ingo Molnar mingo@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/processor.h | 2 ++ arch/x86/kernel/cpu/amd.c | 16 ++++++++++++++++ arch/x86/kernel/smpboot.c | 2 +- drivers/cpufreq/acpi-cpufreq.c | 6 +++++- 4 files changed, 24 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -804,8 +804,10 @@ DECLARE_PER_CPU(u64, msr_misc_features_s
#ifdef CONFIG_CPU_SUP_AMD extern u32 amd_get_nodes_per_socket(void); +extern u32 amd_get_highest_perf(void); #else static inline u32 amd_get_nodes_per_socket(void) { return 0; } +static inline u32 amd_get_highest_perf(void) { return 0; } #endif
static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1170,3 +1170,19 @@ void set_dr_addr_mask(unsigned long mask break; } } + +u32 amd_get_highest_perf(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) || + (c->x86_model >= 0x70 && c->x86_model < 0x80))) + return 166; + + if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) || + (c->x86_model >= 0x40 && c->x86_model < 0x70))) + return 166; + + return 255; +} +EXPORT_SYMBOL_GPL(amd_get_highest_perf); --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -2046,7 +2046,7 @@ static bool amd_set_max_freq_ratio(void) return false; }
- highest_perf = perf_caps.highest_perf; + highest_perf = amd_get_highest_perf(); nominal_perf = perf_caps.nominal_perf;
if (!highest_perf || !nominal_perf) { --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -646,7 +646,11 @@ static u64 get_max_boost_ratio(unsigned return 0; }
- highest_perf = perf_caps.highest_perf; + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + highest_perf = amd_get_highest_perf(); + else + highest_perf = perf_caps.highest_perf; + nominal_perf = perf_caps.nominal_perf;
if (!highest_perf || !nominal_perf) {
From: Peter Collingbourne pcc@google.com
commit 37a8024d265564eba680575df6421f19db21dfce upstream.
A valid implementation choice for the ChooseRandomNonExcludedTag() pseudocode function used by IRG is to behave in the same way as with GCR_EL1.RRND=0. This would mean that RGSR_EL1.SEED is used as an LFSR which must have a non-zero value in order for IRG to properly produce pseudorandom numbers. However, RGSR_EL1 is reset to an UNKNOWN value on soft reset and thus may reset to 0. Therefore we must initialize RGSR_EL1.SEED to a non-zero value in order to ensure that IRG behaves as expected.
Signed-off-by: Peter Collingbourne pcc@google.com Fixes: 3b714d24ef17 ("arm64: mte: CPU feature detection and initial sysreg configuration") Cc: stable@vger.kernel.org # 5.10 Link: https://linux-review.googlesource.com/id/I2b089b6c7d6f17ee37e2f0db7df5ad5bcc... Acked-by: Mark Rutland mark.rutland@arm.com Link: https://lore.kernel.org/r/20210507185905.1745402-1-pcc@google.com Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/mm/proc.S | 12 ++++++++++++ 1 file changed, 12 insertions(+)
--- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -444,6 +444,18 @@ SYM_FUNC_START(__cpu_setup) mov x10, #(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK) msr_s SYS_GCR_EL1, x10
+ /* + * If GCR_EL1.RRND=1 is implemented the same way as RRND=0, then + * RGSR_EL1.SEED must be non-zero for IRG to produce + * pseudorandom numbers. As RGSR_EL1 is UNKNOWN out of reset, we + * must initialize it. + */ + mrs x10, CNTVCT_EL0 + ands x10, x10, #SYS_RGSR_EL1_SEED_MASK + csinc x10, x10, xzr, ne + lsl x10, x10, #SYS_RGSR_EL1_SEED_SHIFT + msr_s SYS_RGSR_EL1, x10 + /* clear any pending tag check faults in TFSR*_EL1 */ msr_s SYS_TFSR_EL1, xzr msr_s SYS_TFSRE0_EL1, xzr
From: Catalin Marinas catalin.marinas@arm.com
commit 588a513d34257fdde95a9f0df0202e31998e85c6 upstream.
To ensure that instructions are observable in a new mapping, the arm64 set_pte_at() implementation cleans the D-cache and invalidates the I-cache to the PoU. As an optimisation, this is only done on executable mappings and the PG_dcache_clean page flag is set to avoid future cache maintenance on the same page.
When two different processes map the same page (e.g. private executable file or shared mapping) there's a potential race on checking and setting PG_dcache_clean via set_pte_at() -> __sync_icache_dcache(). While on the fault paths the page is locked (PG_locked), mprotect() does not take the page lock. The result is that one process may see the PG_dcache_clean flag set but the I/D cache maintenance not yet performed.
Avoid test_and_set_bit(PG_dcache_clean) in favour of separate test_bit() and set_bit(). In the rare event of a race, the cache maintenance is done twice.
Signed-off-by: Catalin Marinas catalin.marinas@arm.com Cc: stable@vger.kernel.org Cc: Will Deacon will@kernel.org Cc: Steven Price steven.price@arm.com Reviewed-by: Steven Price steven.price@arm.com Acked-by: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20210514095001.13236-1-catalin.marinas@arm.com Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/mm/flush.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c @@ -55,8 +55,10 @@ void __sync_icache_dcache(pte_t pte) { struct page *page = pte_page(pte);
- if (!test_and_set_bit(PG_dcache_clean, &page->flags)) + if (!test_bit(PG_dcache_clean, &page->flags)) { sync_icache_aliases(page_address(page), page_size(page)); + set_bit(PG_dcache_clean, &page->flags); + } } EXPORT_SYMBOL_GPL(__sync_icache_dcache);
From: Filipe Manana fdmanana@suse.com
commit f9baa501b4fd6962257853d46ddffbc21f27e344 upstream.
There are a few exceptional cases where cloning an inline extent needs to copy the inline extent data into a page of the destination inode.
When this happens, we end up starting a transaction while having a dirty page for the destination inode and while having the range locked in the destination's inode iotree too. Because when reserving metadata space for a transaction we may need to flush existing delalloc in case there is not enough free space, we have a mechanism in place to prevent a deadlock, which was introduced in commit 3d45f221ce627d ("btrfs: fix deadlock when cloning inline extent and low on free metadata space").
However when using qgroups, a transaction also reserves metadata qgroup space, which can also result in flushing delalloc in case there is not enough available space at the moment. When this happens we deadlock, since flushing delalloc requires locking the file range in the inode's iotree and the range was already locked at the very beginning of the clone operation, before attempting to start the transaction.
When this issue happens, stack traces like the following are reported:
[72747.556262] task:kworker/u81:9 state:D stack: 0 pid: 225 ppid: 2 flags:0x00004000 [72747.556268] Workqueue: writeback wb_workfn (flush-btrfs-1142) [72747.556271] Call Trace: [72747.556273] __schedule+0x296/0x760 [72747.556277] schedule+0x3c/0xa0 [72747.556279] io_schedule+0x12/0x40 [72747.556284] __lock_page+0x13c/0x280 [72747.556287] ? generic_file_readonly_mmap+0x70/0x70 [72747.556325] extent_write_cache_pages+0x22a/0x440 [btrfs] [72747.556331] ? __set_page_dirty_nobuffers+0xe7/0x160 [72747.556358] ? set_extent_buffer_dirty+0x5e/0x80 [btrfs] [72747.556362] ? update_group_capacity+0x25/0x210 [72747.556366] ? cpumask_next_and+0x1a/0x20 [72747.556391] extent_writepages+0x44/0xa0 [btrfs] [72747.556394] do_writepages+0x41/0xd0 [72747.556398] __writeback_single_inode+0x39/0x2a0 [72747.556403] writeback_sb_inodes+0x1ea/0x440 [72747.556407] __writeback_inodes_wb+0x5f/0xc0 [72747.556410] wb_writeback+0x235/0x2b0 [72747.556414] ? get_nr_inodes+0x35/0x50 [72747.556417] wb_workfn+0x354/0x490 [72747.556420] ? newidle_balance+0x2c5/0x3e0 [72747.556424] process_one_work+0x1aa/0x340 [72747.556426] worker_thread+0x30/0x390 [72747.556429] ? create_worker+0x1a0/0x1a0 [72747.556432] kthread+0x116/0x130 [72747.556435] ? kthread_park+0x80/0x80 [72747.556438] ret_from_fork+0x1f/0x30
[72747.566958] Workqueue: btrfs-flush_delalloc btrfs_work_helper [btrfs] [72747.566961] Call Trace: [72747.566964] __schedule+0x296/0x760 [72747.566968] ? finish_wait+0x80/0x80 [72747.566970] schedule+0x3c/0xa0 [72747.566995] wait_extent_bit.constprop.68+0x13b/0x1c0 [btrfs] [72747.566999] ? finish_wait+0x80/0x80 [72747.567024] lock_extent_bits+0x37/0x90 [btrfs] [72747.567047] btrfs_invalidatepage+0x299/0x2c0 [btrfs] [72747.567051] ? find_get_pages_range_tag+0x2cd/0x380 [72747.567076] __extent_writepage+0x203/0x320 [btrfs] [72747.567102] extent_write_cache_pages+0x2bb/0x440 [btrfs] [72747.567106] ? update_load_avg+0x7e/0x5f0 [72747.567109] ? enqueue_entity+0xf4/0x6f0 [72747.567134] extent_writepages+0x44/0xa0 [btrfs] [72747.567137] ? enqueue_task_fair+0x93/0x6f0 [72747.567140] do_writepages+0x41/0xd0 [72747.567144] __filemap_fdatawrite_range+0xc7/0x100 [72747.567167] btrfs_run_delalloc_work+0x17/0x40 [btrfs] [72747.567195] btrfs_work_helper+0xc2/0x300 [btrfs] [72747.567200] process_one_work+0x1aa/0x340 [72747.567202] worker_thread+0x30/0x390 [72747.567205] ? create_worker+0x1a0/0x1a0 [72747.567208] kthread+0x116/0x130 [72747.567211] ? kthread_park+0x80/0x80 [72747.567214] ret_from_fork+0x1f/0x30
[72747.569686] task:fsstress state:D stack: 0 pid:841421 ppid:841417 flags:0x00000000 [72747.569689] Call Trace: [72747.569691] __schedule+0x296/0x760 [72747.569694] schedule+0x3c/0xa0 [72747.569721] try_flush_qgroup+0x95/0x140 [btrfs] [72747.569725] ? finish_wait+0x80/0x80 [72747.569753] btrfs_qgroup_reserve_data+0x34/0x50 [btrfs] [72747.569781] btrfs_check_data_free_space+0x5f/0xa0 [btrfs] [72747.569804] btrfs_buffered_write+0x1f7/0x7f0 [btrfs] [72747.569810] ? path_lookupat.isra.48+0x97/0x140 [72747.569833] btrfs_file_write_iter+0x81/0x410 [btrfs] [72747.569836] ? __kmalloc+0x16a/0x2c0 [72747.569839] do_iter_readv_writev+0x160/0x1c0 [72747.569843] do_iter_write+0x80/0x1b0 [72747.569847] vfs_writev+0x84/0x140 [72747.569869] ? btrfs_file_llseek+0x38/0x270 [btrfs] [72747.569873] do_writev+0x65/0x100 [72747.569876] do_syscall_64+0x33/0x40 [72747.569879] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[72747.569899] task:fsstress state:D stack: 0 pid:841424 ppid:841417 flags:0x00004000 [72747.569903] Call Trace: [72747.569906] __schedule+0x296/0x760 [72747.569909] schedule+0x3c/0xa0 [72747.569936] try_flush_qgroup+0x95/0x140 [btrfs] [72747.569940] ? finish_wait+0x80/0x80 [72747.569967] __btrfs_qgroup_reserve_meta+0x36/0x50 [btrfs] [72747.569989] start_transaction+0x279/0x580 [btrfs] [72747.570014] clone_copy_inline_extent+0x332/0x490 [btrfs] [72747.570041] btrfs_clone+0x5b7/0x7a0 [btrfs] [72747.570068] ? lock_extent_bits+0x64/0x90 [btrfs] [72747.570095] btrfs_clone_files+0xfc/0x150 [btrfs] [72747.570122] btrfs_remap_file_range+0x3d8/0x4a0 [btrfs] [72747.570126] do_clone_file_range+0xed/0x200 [72747.570131] vfs_clone_file_range+0x37/0x110 [72747.570134] ioctl_file_clone+0x7d/0xb0 [72747.570137] do_vfs_ioctl+0x138/0x630 [72747.570140] __x64_sys_ioctl+0x62/0xc0 [72747.570143] do_syscall_64+0x33/0x40 [72747.570146] entry_SYSCALL_64_after_hwframe+0x44/0xa9
So fix this by skipping the flush of delalloc for an inode that is flagged with BTRFS_INODE_NO_DELALLOC_FLUSH, meaning it is currently under such a special case of cloning an inline extent, when flushing delalloc during qgroup metadata reservation.
The special cases for cloning inline extents were added in kernel 5.7 by by commit 05a5a7621ce66c ("Btrfs: implement full reflink support for inline extents"), while having qgroup metadata space reservation flushing delalloc when low on space was added in kernel 5.9 by commit c53e9653605dbf ("btrfs: qgroup: try to flush qgroup space when we get -EDQUOT"). So use a "Fixes:" tag for the later commit to ease stable kernel backports.
Reported-by: Wang Yugui wangyugui@e16-tech.com Link: https://lore.kernel.org/linux-btrfs/20210421083137.31E3.409509F4@e16-tech.co... Fixes: c53e9653605dbf ("btrfs: qgroup: try to flush qgroup space when we get -EDQUOT") CC: stable@vger.kernel.org # 5.9+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Filipe Manana fdmanana@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/ctree.h | 2 +- fs/btrfs/inode.c | 4 ++-- fs/btrfs/ioctl.c | 2 +- fs/btrfs/qgroup.c | 2 +- fs/btrfs/send.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-)
--- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3110,7 +3110,7 @@ int btrfs_truncate_inode_items(struct bt struct btrfs_inode *inode, u64 new_size, u32 min_type);
-int btrfs_start_delalloc_snapshot(struct btrfs_root *root); +int btrfs_start_delalloc_snapshot(struct btrfs_root *root, bool in_reclaim_context); int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr, bool in_reclaim_context); int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end, --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -9672,7 +9672,7 @@ out: return ret; }
-int btrfs_start_delalloc_snapshot(struct btrfs_root *root) +int btrfs_start_delalloc_snapshot(struct btrfs_root *root, bool in_reclaim_context) { struct writeback_control wbc = { .nr_to_write = LONG_MAX, @@ -9685,7 +9685,7 @@ int btrfs_start_delalloc_snapshot(struct if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) return -EROFS;
- return start_delalloc_inodes(root, &wbc, true, false); + return start_delalloc_inodes(root, &wbc, true, in_reclaim_context); }
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr, --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1046,7 +1046,7 @@ static noinline int btrfs_mksnapshot(con */ btrfs_drew_read_lock(&root->snapshot_lock);
- ret = btrfs_start_delalloc_snapshot(root); + ret = btrfs_start_delalloc_snapshot(root, false); if (ret) goto out;
--- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -3579,7 +3579,7 @@ static int try_flush_qgroup(struct btrfs return 0; }
- ret = btrfs_start_delalloc_snapshot(root); + ret = btrfs_start_delalloc_snapshot(root, true); if (ret < 0) goto out; btrfs_wait_ordered_extents(root, U64_MAX, 0, (u64)-1); --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -7139,7 +7139,7 @@ static int flush_delalloc_roots(struct s int i;
if (root) { - ret = btrfs_start_delalloc_snapshot(root); + ret = btrfs_start_delalloc_snapshot(root, false); if (ret) return ret; btrfs_wait_ordered_extents(root, U64_MAX, 0, U64_MAX); @@ -7147,7 +7147,7 @@ static int flush_delalloc_roots(struct s
for (i = 0; i < sctx->clone_roots_cnt; i++) { root = sctx->clone_roots[i].root; - ret = btrfs_start_delalloc_snapshot(root); + ret = btrfs_start_delalloc_snapshot(root, false); if (ret) return ret; btrfs_wait_ordered_extents(root, U64_MAX, 0, U64_MAX);
From: Filipe Manana fdmanana@suse.com
commit adbd914dcde0b03bfc08ffe40b81f31b0457833f upstream.
On a zoned filesystem, sometimes we need to split an ordered extent into 3 different ordered extents. The original ordered extent is shortened, at the front and at the rear, and we create two other new ordered extents to represent the trimmed parts of the original ordered extent.
After adjusting the original ordered extent, we create an ordered extent to represent the pre-range, and that may fail with ENOMEM for example. After that we always try to create the ordered extent for the post-range, and if that happens to succeed we end up returning success to the caller as we overwrite the 'ret' variable which contained the previous error.
This means we end up with a file range for which there is no ordered extent, which results in the range never getting a new file extent item pointing to the new data location. And since the split operation did not return an error, writeback does not fail and the inode's mapping is not flagged with an error, resulting in a subsequent fsync not reporting an error either.
It's possibly very unlikely to have the creation of the post-range ordered extent succeed after the creation of the pre-range ordered extent failed, but it's not impossible.
So fix this by making sure we only create the post-range ordered extent if there was no error creating the ordered extent for the pre-range.
Fixes: d22002fd37bd97 ("btrfs: zoned: split ordered extent when bio is sent") CC: stable@vger.kernel.org # 5.12+ Signed-off-by: Filipe Manana fdmanana@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/ordered-data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -995,7 +995,7 @@ int btrfs_split_ordered_extent(struct bt
if (pre) ret = clone_ordered_extent(ordered, 0, pre); - if (post) + if (ret == 0 && post) ret = clone_ordered_extent(ordered, pre + ordered->disk_num_bytes, post);
From: Filipe Manana fdmanana@suse.com
commit 626e9f41f7c281ba3e02843702f68471706aa6d9 upstream.
When doing a fast fsync on a file, there is a race which can result in the fsync returning success to user space without logging the inode and without durably persisting new data.
The following example shows one possible scenario for this:
$ mkfs.btrfs -f /dev/sdc $ mount /dev/sdc /mnt
$ touch /mnt/bar $ xfs_io -f -c "pwrite -S 0xab 0 1M" -c "fsync" /mnt/baz
# Now we have: # file bar == inode 257 # file baz == inode 258
$ mv /mnt/baz /mnt/foo
# Now we have: # file bar == inode 257 # file foo == inode 258
$ xfs_io -c "pwrite -S 0xcd 0 1M" /mnt/foo
# fsync bar before foo, it is important to trigger the race. $ xfs_io -c "fsync" /mnt/bar $ xfs_io -c "fsync" /mnt/foo
# After this: # inode 257, file bar, is empty # inode 258, file foo, has 1M filled with 0xcd
<power failure>
# Replay the log: $ mount /dev/sdc /mnt
# After this point file foo should have 1M filled with 0xcd and not 0xab
The following steps explain how the race happens:
1) Before the first fsync of inode 258, when it has the "baz" name, its ->logged_trans is 0, ->last_sub_trans is 0 and ->last_log_commit is -1. The inode also has the full sync flag set;
2) After the first fsync, we set inode 258 ->logged_trans to 6, which is the generation of the current transaction, and set ->last_log_commit to 0, which is the current value of ->last_sub_trans (done at btrfs_log_inode()).
The full sync flag is cleared from the inode during the fsync.
The log sub transaction that was committed had an ID of 0 and when we synced the log, at btrfs_sync_log(), we incremented root->log_transid from 0 to 1;
3) During the rename:
We update inode 258, through btrfs_update_inode(), and that causes its ->last_sub_trans to be set to 1 (the current log transaction ID), and ->last_log_commit remains with a value of 0.
After updating inode 258, because we have previously logged the inode in the previous fsync, we log again the inode through the call to btrfs_log_new_name(). This results in updating the inode's ->last_log_commit from 0 to 1 (the current value of its ->last_sub_trans).
The ->last_sub_trans of inode 257 is updated to 1, which is the ID of the next log transaction;
4) Then a buffered write against inode 258 is made. This leaves the value of ->last_sub_trans as 1 (the ID of the current log transaction, stored at root->log_transid);
5) Then an fsync against inode 257 (or any other inode other than 258), happens. This results in committing the log transaction with ID 1, which results in updating root->last_log_commit to 1 and bumping root->log_transid from 1 to 2;
6) Then an fsync against inode 258 starts. We flush delalloc and wait only for writeback to complete, since the full sync flag is not set in the inode's runtime flags - we do not wait for ordered extents to complete.
Then, at btrfs_sync_file(), we call btrfs_inode_in_log() before the ordered extent completes. The call returns true:
static inline bool btrfs_inode_in_log(...) { bool ret = false;
spin_lock(&inode->lock); if (inode->logged_trans == generation && inode->last_sub_trans <= inode->last_log_commit && inode->last_sub_trans <= inode->root->last_log_commit) ret = true; spin_unlock(&inode->lock); return ret; }
generation has a value of 6 (fs_info->generation), ->logged_trans also has a value of 6 (set when we logged the inode during the first fsync and when logging it during the rename), ->last_sub_trans has a value of 1, set during the rename (step 3), ->last_log_commit also has a value of 1 (set in step 3) and root->last_log_commit has a value of 1, which was set in step 5 when fsyncing inode 257.
As a consequence we don't log the inode, any new extents and do not sync the log, resulting in a data loss if a power failure happens after the fsync and before the current transaction commits. Also, because we do not log the inode, after a power failure the mtime and ctime of the inode do not match those we had before.
When the ordered extent completes before we call btrfs_inode_in_log(), then the call returns false and we log the inode and sync the log, since at the end of ordered extent completion we update the inode and set ->last_sub_trans to 2 (the value of root->log_transid) and ->last_log_commit to 1.
This problem is found after removing the check for the emptiness of the inode's list of modified extents in the recent commit 209ecbb8585bf6 ("btrfs: remove stale comment and logic from btrfs_inode_in_log()"), added in the 5.13 merge window. However checking the emptiness of the list is not really the way to solve this problem, and was never intended to, because while that solves the problem for COW writes, the problem persists for NOCOW writes because in that case the list is always empty.
In the case of NOCOW writes, even though we wait for the writeback to complete before returning from btrfs_sync_file(), we end up not logging the inode, which has a new mtime/ctime, and because we don't sync the log, we never issue disk barriers (send REQ_PREFLUSH to the device) since that only happens when we sync the log (when we write super blocks at btrfs_sync_log()). So effectively, for a NOCOW case, when we return from btrfs_sync_file() to user space, we are not guaranteeing that the data is durably persisted on disk.
Also, while the example above uses a rename exchange to show how the problem happens, it is not the only way to trigger it. An alternative could be adding a new hard link to inode 258, since that also results in calling btrfs_log_new_name() and updating the inode in the log. An example reproducer using the addition of a hard link instead of a rename operation:
$ mkfs.btrfs -f /dev/sdc $ mount /dev/sdc /mnt
$ touch /mnt/bar $ xfs_io -f -c "pwrite -S 0xab 0 1M" -c "fsync" /mnt/foo
$ ln /mnt/foo /mnt/foo_link $ xfs_io -c "pwrite -S 0xcd 0 1M" /mnt/foo
$ xfs_io -c "fsync" /mnt/bar $ xfs_io -c "fsync" /mnt/foo
<power failure>
# Replay the log: $ mount /dev/sdc /mnt
# After this point file foo often has 1M filled with 0xab and not 0xcd
The reasons leading to the final fsync of file foo, inode 258, not persisting the new data are the same as for the previous example with a rename operation.
So fix by never skipping logging and log syncing when there are still any ordered extents in flight. To avoid making the conditional if statement that checks if logging an inode is needed harder to read, place all the logic into an helper function with separate if statements to make it more manageable and easier to read.
A test case for fstests will follow soon.
For NOCOW writes, the problem existed before commit b5e6c3e170b770 ("btrfs: always wait on ordered extents at fsync time"), introduced in kernel 4.19, then it went away with that commit since we started to always wait for ordered extent completion before logging.
The problem came back again once the fast fsync path was changed again to avoid waiting for ordered extent completion, in commit 487781796d3022 ("btrfs: make fast fsyncs wait only for writeback"), added in kernel 5.10.
However, for COW writes, the race only happens after the recent commit 209ecbb8585bf6 ("btrfs: remove stale comment and logic from btrfs_inode_in_log()"), introduced in the 5.13 merge window. For NOCOW writes, the bug existed before that commit. So tag 5.10+ as the release for stable backports.
CC: stable@vger.kernel.org # 5.10+ Signed-off-by: Filipe Manana fdmanana@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/file.c | 35 +++++++++++++++++++++++++---------- fs/btrfs/tree-log.c | 3 ++- 2 files changed, 27 insertions(+), 11 deletions(-)
--- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2067,6 +2067,30 @@ static int start_ordered_ops(struct inod return ret; }
+static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx) +{ + struct btrfs_inode *inode = BTRFS_I(ctx->inode); + struct btrfs_fs_info *fs_info = inode->root->fs_info; + + if (btrfs_inode_in_log(inode, fs_info->generation) && + list_empty(&ctx->ordered_extents)) + return true; + + /* + * If we are doing a fast fsync we can not bail out if the inode's + * last_trans is <= then the last committed transaction, because we only + * update the last_trans of the inode during ordered extent completion, + * and for a fast fsync we don't wait for that, we only wait for the + * writeback to complete. + */ + if (inode->last_trans <= fs_info->last_trans_committed && + (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags) || + list_empty(&ctx->ordered_extents))) + return true; + + return false; +} + /* * fsync call for both files and directories. This logs the inode into * the tree log instead of forcing full commits whenever possible. @@ -2185,17 +2209,8 @@ int btrfs_sync_file(struct file *file, l
atomic_inc(&root->log_batch);
- /* - * If we are doing a fast fsync we can not bail out if the inode's - * last_trans is <= then the last committed transaction, because we only - * update the last_trans of the inode during ordered extent completion, - * and for a fast fsync we don't wait for that, we only wait for the - * writeback to complete. - */ smp_mb(); - if (btrfs_inode_in_log(BTRFS_I(inode), fs_info->generation) || - (BTRFS_I(inode)->last_trans <= fs_info->last_trans_committed && - (full_sync || list_empty(&ctx.ordered_extents)))) { + if (skip_inode_logging(&ctx)) { /* * We've had everything committed since the last time we were * modified so clear this flag in case it was set for whatever --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -6060,7 +6060,8 @@ static int btrfs_log_inode_parent(struct * (since logging them is pointless, a link count of 0 means they * will never be accessible). */ - if (btrfs_inode_in_log(inode, trans->transid) || + if ((btrfs_inode_in_log(inode, trans->transid) && + list_empty(&ctx->ordered_extents)) || inode->vfs_inode.i_nlink == 0) { ret = BTRFS_NO_LOG_SYNC; goto end_no_trans;
From: Tom Rix trix@redhat.com
commit 77364faf21b4105ee5adbb4844fdfb461334d249 upstream.
Static analysis reports this problem
free-space-cache.c:3965:2: warning: Undefined or garbage value returned return ret; ^~~~~~~~~~
ret is set in the node handling loop. Treat doing nothing as a success and initialize ret to 0, although it's unlikely the loop would be skipped. We always have block groups, but as it could lead to transaction abort in the caller it's better to be safe.
CC: stable@vger.kernel.org # 5.12+ Signed-off-by: Tom Rix trix@redhat.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/free-space-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -3942,7 +3942,7 @@ static int cleanup_free_space_cache_v1(s { struct btrfs_block_group *block_group; struct rb_node *node; - int ret; + int ret = 0;
btrfs_info(fs_info, "cleaning free space cache v1");
From: Naohiro Aota naohiro.aota@wdc.com
commit 784daf2b9628f2d0117f1f0b578cfe5ab6634919 upstream.
The fstests test case generic/475 creates a dm-linear device that gets changed to a dm-error device. This leads to errors in loading the block group's zone information when running on a zoned file system, ultimately resulting in a list corruption. When running on a kernel with list debugging enabled this leads to the following crash.
BTRFS: error (device dm-2) in cleanup_transaction:1953: errno=-5 IO failure kernel BUG at lib/list_debug.c:54! invalid opcode: 0000 [#1] SMP PTI CPU: 1 PID: 2433 Comm: umount Tainted: G W 5.12.0+ #1018 RIP: 0010:__list_del_entry_valid.cold+0x1d/0x47 RSP: 0018:ffffc90001473df0 EFLAGS: 00010296 RAX: 0000000000000054 RBX: ffff8881038fd000 RCX: ffffc90001473c90 RDX: 0000000100001a31 RSI: 0000000000000003 RDI: 0000000000000003 RBP: ffff888308871108 R08: 0000000000000003 R09: 0000000000000001 R10: 3961373532383838 R11: 6666666620736177 R12: ffff888308871000 R13: ffff8881038fd088 R14: ffff8881038fdc78 R15: dead000000000100 FS: 00007f353c9b1540(0000) GS:ffff888627d00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f353cc2c710 CR3: 000000018e13c000 CR4: 00000000000006a0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: btrfs_free_block_groups+0xc9/0x310 [btrfs] close_ctree+0x2ee/0x31a [btrfs] ? call_rcu+0x8f/0x270 ? mutex_lock+0x1c/0x40 generic_shutdown_super+0x67/0x100 kill_anon_super+0x14/0x30 btrfs_kill_super+0x12/0x20 [btrfs] deactivate_locked_super+0x31/0x90 cleanup_mnt+0x13e/0x1b0 task_work_run+0x63/0xb0 exit_to_user_mode_loop+0xd9/0xe0 exit_to_user_mode_prepare+0x3e/0x60 syscall_exit_to_user_mode+0x1d/0x50 entry_SYSCALL_64_after_hwframe+0x44/0xae
As dm-error has no support for zones, btrfs will run it's zone emulation mode on this device. The zone emulation mode emulates conventional zones, so bail out if the zone bitmap that gets populated on mount sees the zone as sequential while we're thinking it's a conventional zone when creating a block group.
Note: this scenario is unlikely in a real wold application and can only happen by this (ab)use of device-mapper targets.
CC: stable@vger.kernel.org # 5.12+ Signed-off-by: Naohiro Aota naohiro.aota@wdc.com Signed-off-by: Johannes Thumshirn johannes.thumshirn@wdc.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/zoned.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -1126,6 +1126,11 @@ int btrfs_load_block_group_zone_info(str goto out; }
+ if (zone.type == BLK_ZONE_TYPE_CONVENTIONAL) { + ret = -EIO; + goto out; + } + switch (zone.cond) { case BLK_ZONE_COND_OFFLINE: case BLK_ZONE_COND_READONLY:
From: Kai-Heng Feng kai.heng.feng@canonical.com
commit 227545b9a08c68778ddd89428f99c351fc9315ac upstream.
Screen flickers rapidly when two 4K 60Hz monitors are in use. This issue doesn't happen when one monitor is 4K 60Hz (pixelclock 594MHz) and another one is 4K 30Hz (pixelclock 297MHz).
The issue is gone after setting "power_dpm_force_performance_level" to "high". Following the indication, we found that the issue occurs when sclk is too low.
So resolve the issue by disabling sclk switching when there are two monitors requires high pixelclock (> 297MHz).
v2: - Only apply the fix to Oland. Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_pm.c | 8 ++++++++ drivers/gpu/drm/radeon/si_dpm.c | 3 +++ 3 files changed, 12 insertions(+)
--- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1558,6 +1558,7 @@ struct radeon_dpm { void *priv; u32 new_active_crtcs; int new_active_crtc_count; + int high_pixelclock_count; u32 current_active_crtcs; int current_active_crtc_count; bool single_display; --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1775,6 +1775,7 @@ static void radeon_pm_compute_clocks_dpm struct drm_device *ddev = rdev->ddev; struct drm_crtc *crtc; struct radeon_crtc *radeon_crtc; + struct radeon_connector *radeon_connector;
if (!rdev->pm.dpm_enabled) return; @@ -1784,6 +1785,7 @@ static void radeon_pm_compute_clocks_dpm /* update active crtc counts */ rdev->pm.dpm.new_active_crtcs = 0; rdev->pm.dpm.new_active_crtc_count = 0; + rdev->pm.dpm.high_pixelclock_count = 0; if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { @@ -1791,6 +1793,12 @@ static void radeon_pm_compute_clocks_dpm if (crtc->enabled) { rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id); rdev->pm.dpm.new_active_crtc_count++; + if (!radeon_crtc->connector) + continue; + + radeon_connector = to_radeon_connector(radeon_crtc->connector); + if (radeon_connector->pixelclock_for_modeset > 297000) + rdev->pm.dpm.high_pixelclock_count++; } } } --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2979,6 +2979,9 @@ static void si_apply_state_adjust_rules( (rdev->pdev->device == 0x6605)) { max_sclk = 75000; } + + if (rdev->pm.dpm.high_pixelclock_count > 1) + disable_sclk_switching = true; }
if (rps->vce_active) {
From: David Ward david.ward@gatech.edu
commit fe1c97d008f86f672f0e9265f180c22451ca3b9f upstream.
It is stored in dynamically allocated memory, so sysfs_bin_attr_init() must be called to initialize it. (Note: "initialization" only sets the .attr.key member in this struct; it does not change the value of any other members.)
Otherwise, when CONFIG_DEBUG_LOCK_ALLOC=y this message appears during boot:
BUG: key ffff9248900cd148 has not been registered!
Fixes: 9037246bb2da ("drm/amd/display: Add sysfs interface for set/get srm") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1586 Reported-by: Mikhail Gavrilov mikhail.v.gavrilov@gmail.com Signed-off-by: David Ward david.ward@gatech.edu Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -644,6 +644,7 @@ struct hdcp_workqueue *hdcp_create_workq
/* File created at /sys/class/drm/card0/device/hdcp_srm*/ hdcp_work[0].attr = data_attr; + sysfs_bin_attr_init(&hdcp_work[0].attr);
if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr)) DRM_WARN("Failed to create device file hdcp_srm");
From: Ville Syrjälä ville.syrjala@linux.intel.com
commit 4819d16d91145966ce03818a95169df1fd56b299 upstream.
Gen2 tiles are 2KiB in size so i915_gem_object_get_tile_row_size() can in fact return <4KiB, which leads to div-by-zero here. Avoid that.
Not sure i915_gem_object_get_tile_row_size() is entirely sane anyway since it doesn't account for the different tile layouts on i8xx/i915...
I'm not able to hit this before commit 6846895fde05 ("drm/i915: Replace PIN_NONFAULT with calls to PIN_NOEVICT") and it looks like I also need to run recent version of Mesa. With those in place xonotic trips on this quite easily on my 85x.
Cc: stable@vger.kernel.org Reviewed-by: Chris Wilson chris@chris-wilson.co.uk Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210421153401.13847-2-ville.s... (cherry picked from commit ed52c62d386f764194e0184fdb905d5f24194cae) Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -189,7 +189,7 @@ compute_partial_view(const struct drm_i9 struct i915_ggtt_view view;
if (i915_gem_object_is_tiled(obj)) - chunk = roundup(chunk, tile_row_pages(obj)); + chunk = roundup(chunk, tile_row_pages(obj) ?: 1);
view.type = I915_GGTT_VIEW_PARTIAL; view.partial.offset = rounddown(page_offset, chunk);
From: Kai-Heng Feng kai.heng.feng@canonical.com
commit a5c936add6a23c15c6ae538ab7a12f80751fdf0f upstream.
Screen flickers on Innolux eDP 1.3 panel when clock rate 540000 is in use.
According to the panel vendor, though clock rate 540000 is advertised, but the max clock rate it really supports is 270000.
Ville Syrjälä mentioned that fast and narrow also breaks some eDP 1.4 panel, so use slow and wide training for all panels to resolve the issue.
User also confirmed that the new strategy doesn't introduce any regression on XPS 9380.
v2: - Use slow and wide for everything.
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3384 Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210421052054.1434718-1-kai.h... (cherry picked from commit acca7762eb71bc05a8f28d29320d193150051f79) Fixes: 2bbd6dba84d4 ("drm/i915: Try to use fast+narrow link on eDP again and fall back to the old max strategy on failure") Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_dp.c | 59 ++------------------------------ 1 file changed, 5 insertions(+), 54 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1174,44 +1174,6 @@ intel_dp_compute_link_config_wide(struct return -EINVAL; }
-/* Optimize link config in order: max bpp, min lanes, min clock */ -static int -intel_dp_compute_link_config_fast(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config, - const struct link_config_limits *limits) -{ - const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - int bpp, clock, lane_count; - int mode_rate, link_clock, link_avail; - - for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { - int output_bpp = intel_dp_output_bpp(pipe_config->output_format, bpp); - - mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, - output_bpp); - - for (lane_count = limits->min_lane_count; - lane_count <= limits->max_lane_count; - lane_count <<= 1) { - for (clock = limits->min_clock; clock <= limits->max_clock; clock++) { - link_clock = intel_dp->common_rates[clock]; - link_avail = intel_dp_max_data_rate(link_clock, - lane_count); - - if (mode_rate <= link_avail) { - pipe_config->lane_count = lane_count; - pipe_config->pipe_bpp = bpp; - pipe_config->port_clock = link_clock; - - return 0; - } - } - } - } - - return -EINVAL; -} - static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc) { int i, num_bpc; @@ -1461,22 +1423,11 @@ intel_dp_compute_link_config(struct inte intel_dp_can_bigjoiner(intel_dp)) pipe_config->bigjoiner = true;
- if (intel_dp_is_edp(intel_dp)) - /* - * Optimize for fast and narrow. eDP 1.3 section 3.3 and eDP 1.4 - * section A.1: "It is recommended that the minimum number of - * lanes be used, using the minimum link rate allowed for that - * lane configuration." - * - * Note that we fall back to the max clock and lane count for eDP - * panels that fail with the fast optimal settings (see - * intel_dp->use_max_params), in which case the fast vs. wide - * choice doesn't matter. - */ - ret = intel_dp_compute_link_config_fast(intel_dp, pipe_config, &limits); - else - /* Optimize for slow and wide. */ - ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits); + /* + * Optimize for slow and wide for everything, because there are some + * eDP 1.3 and 1.4 panels don't work well with fast and narrow. + */ + ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
/* enable compression if the mode doesn't fit available BW */ drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
From: Benjamin Segall bsegall@google.com
commit 262de4102c7bb8e59f26a967a8ffe8cce85cc537 upstream.
single_task_running() is usually more general than need_resched() but CFS_BANDWIDTH throttling will use resched_task() when there is just one task to get the task to block. This was causing long-need_resched warnings and was likely allowing VMs to overrun their quota when halt polling.
Signed-off-by: Ben Segall bsegall@google.com Signed-off-by: Venkatesh Srinivas venkateshs@chromium.org Message-Id: 20210429162233.116849-1-venkateshs@chromium.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Cc: stable@vger.kernel.org Reviewed-by: Jim Mattson jmattson@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- virt/kvm/kvm_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2838,7 +2838,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcp goto out; } poll_end = cur = ktime_get(); - } while (single_task_running() && ktime_before(cur, stop)); + } while (single_task_running() && !need_resched() && + ktime_before(cur, stop)); }
prepare_to_rcuwait(&vcpu->wait);
From: Jonathan Marek jonathan@marek.ca
[ Upstream commit 4b95d371fb001185af84d177e69a23d55bd0167a ]
mmu500 targets don't have a "cx_mem" region, set llc_mmio to NULL in that case to avoid the IS_ERR() condition in a6xx_llc_activate().
Fixes: 3d247123b5a1 ("drm/msm/a6xx: Add support for using system cache on MMU500 based targets") Signed-off-by: Jonathan Marek jonathan@marek.ca Link: https://lore.kernel.org/r/20210424014927.1661-1-jonathan@marek.ca Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index d553f62f4eeb..b4d8e1b01ee4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1153,10 +1153,6 @@ static void a6xx_llc_slices_init(struct platform_device *pdev, { struct device_node *phandle;
- a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx"); - if (IS_ERR(a6xx_gpu->llc_mmio)) - return; - /* * There is a different programming path for targets with an mmu500 * attached, so detect if that is the case @@ -1166,6 +1162,11 @@ static void a6xx_llc_slices_init(struct platform_device *pdev, of_device_is_compatible(phandle, "arm,mmu-500")); of_node_put(phandle);
+ if (a6xx_gpu->have_mmu500) + a6xx_gpu->llc_mmio = NULL; + else + a6xx_gpu->llc_mmio = msm_ioremap(pdev, "cx_mem", "gpu_cx"); + a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU); a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
From: Wanpeng Li wanpengli@tencent.com
[ Upstream commit d981dd15498b188636ec5a7d8ad485e650f63d8d ]
Commit ee66e453db13d (KVM: lapic: Busy wait for timer to expire when using hv_timer) tries to set ktime->expired_tscdeadline by checking ktime->hv_timer_in_use since lapic timer oneshot/periodic modes which are emulated by vmx preemption timer also get advanced, they leverage the same vmx preemption timer logic with tsc-deadline mode. However, ktime->hv_timer_in_use is cleared before apic_timer_expired() handling, let's delay this clearing in preemption-disabled region.
Fixes: ee66e453db13d ("KVM: lapic: Busy wait for timer to expire when using hv_timer") Reviewed-by: Sean Christopherson seanjc@google.com Signed-off-by: Wanpeng Li wanpengli@tencent.com Message-Id: 1619608082-4187-1-git-send-email-wanpengli@tencent.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/lapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 49a839d0567a..fa023f3feb25 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1913,8 +1913,8 @@ void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu) if (!apic->lapic_timer.hv_timer_in_use) goto out; WARN_ON(rcuwait_active(&vcpu->wait)); - cancel_hv_timer(apic); apic_timer_expired(apic, false); + cancel_hv_timer(apic);
if (apic_lvtt_period(apic) && apic->lapic_timer.period) { advance_periodic_target_expiration(apic);
From: Kuogee Hsieh khsieh@codeaurora.org
[ Upstream commit f2f46b878777e0d3f885c7ddad48f477b4dea247 ]
Initialize audio_comp when audio starts and wait for audio_comp at dp_display_disable(). This will take care of both dongle unplugged and display off (suspend) cases.
Changes in v2: -- add dp_display_signal_audio_start()
Changes in v3: -- restore dp_display_handle_plugged_change() at dp_hpd_unplug_handle().
Changes in v4: -- none
Signed-off-by: Kuogee Hsieh khsieh@codeaurora.org Reviewed-by: Stephen Boyd swboyd@chromium.org Tested-by: Stephen Boyd swboyd@chromium.org Fixes: c703d5789590 ("drm/msm/dp: trigger unplug event in msm_dp_display_disable") Link: https://lore.kernel.org/r/1619048258-8717-3-git-send-email-khsieh@codeaurora... Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/dp/dp_audio.c | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 11 +++++++++-- drivers/gpu/drm/msm/dp/dp_display.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 82a8673ab8da..d7e4a39a904e 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -527,6 +527,7 @@ int dp_audio_hw_params(struct device *dev, dp_audio_setup_acr(audio); dp_audio_safe_to_exit_level(audio); dp_audio_enable(audio, true); + dp_display_signal_audio_start(dp_display); dp_display->audio_enabled = true;
end: diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 5a39da6e1eaf..f3d74f8f35fe 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -178,6 +178,15 @@ static int dp_del_event(struct dp_display_private *dp_priv, u32 event) return 0; }
+void dp_display_signal_audio_start(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + reinit_completion(&dp->audio_comp); +} + void dp_display_signal_audio_complete(struct msm_dp *dp_display) { struct dp_display_private *dp; @@ -651,7 +660,6 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
/* signal the disconnect event early to ensure proper teardown */ - reinit_completion(&dp->audio_comp); dp_display_handle_plugged_change(g_dp_display, false);
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | @@ -898,7 +906,6 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data) /* wait only if audio was enabled */ if (dp_display->audio_enabled) { /* signal the disconnect event */ - reinit_completion(&dp->audio_comp); dp_display_handle_plugged_change(dp_display, false); if (!wait_for_completion_timeout(&dp->audio_comp, HZ * 5)) diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 6092ba1ed85e..5173c89eedf7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -34,6 +34,7 @@ int dp_display_get_modes(struct msm_dp *dp_display, int dp_display_request_irq(struct msm_dp *dp_display); bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); +void dp_display_signal_audio_start(struct msm_dp *dp_display); void dp_display_signal_audio_complete(struct msm_dp *dp_display);
#endif /* _DP_DISPLAY_H_ */
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 594b27e677b35f9734b1969d175ebc6146741109 ]
Nothing prevents the following:
pvclock_gtod_notify() queue_work(system_long_wq, &pvclock_gtod_work); ... remove_module(kvm); ... work_queue_run() pvclock_gtod_work() <- UAF
Ditto for any other operation on that workqueue list head which touches pvclock_gtod_work after module removal.
Cancel the work in kvm_arch_exit() to prevent that.
Fixes: 16e8d74d2da9 ("KVM: x86: notifier for clocksource changes") Signed-off-by: Thomas Gleixner tglx@linutronix.de Message-Id: 87czu4onry.ffs@nanos.tec.linutronix.de Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3406ff421c1a..f1fd52eddabf 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8096,6 +8096,7 @@ void kvm_arch_exit(void) cpuhp_remove_state_nocalls(CPUHP_AP_X86_KVM_CLK_ONLINE); #ifdef CONFIG_X86_64 pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier); + cancel_work_sync(&pvclock_gtod_work); #endif kvm_x86_ops.hardware_enable = NULL; kvm_mmu_module_exit();
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 3f804f6d201ca93adf4c3df04d1bfd152c1129d6 ]
syzbot reported a possible deadlock in pvclock_gtod_notify():
CPU 0 CPU 1 write_seqcount_begin(&tk_core.seq); pvclock_gtod_notify() spin_lock(&pool->lock); queue_work(..., &pvclock_gtod_work) ktime_get() spin_lock(&pool->lock); do { seq = read_seqcount_begin(tk_core.seq) ... } while (read_seqcount_retry(&tk_core.seq, seq);
While this is unlikely to happen, it's possible.
Delegate queue_work() to irq_work() which postpones it until the tk_core.seq write held region is left and interrupts are reenabled.
Fixes: 16e8d74d2da9 ("KVM: x86: notifier for clocksource changes") Reported-by: syzbot+6beae4000559d41d80f8@syzkaller.appspotmail.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Message-Id: 87h7jgm1zy.ffs@nanos.tec.linutronix.de Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/x86.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f1fd52eddabf..c37c23c6b178 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7964,6 +7964,18 @@ static void pvclock_gtod_update_fn(struct work_struct *work)
static DECLARE_WORK(pvclock_gtod_work, pvclock_gtod_update_fn);
+/* + * Indirection to move queue_work() out of the tk_core.seq write held + * region to prevent possible deadlocks against time accessors which + * are invoked with work related locks held. + */ +static void pvclock_irq_work_fn(struct irq_work *w) +{ + queue_work(system_long_wq, &pvclock_gtod_work); +} + +static DEFINE_IRQ_WORK(pvclock_irq_work, pvclock_irq_work_fn); + /* * Notification about pvclock gtod data update. */ @@ -7975,13 +7987,14 @@ static int pvclock_gtod_notify(struct notifier_block *nb, unsigned long unused,
update_pvclock_gtod(tk);
- /* disable master clock if host does not trust, or does not - * use, TSC based clocksource. + /* + * Disable master clock if host does not trust, or does not use, + * TSC based clocksource. Delegate queue_work() to irq_work as + * this is invoked with tk_core.seq write held. */ if (!gtod_is_based_on_tsc(gtod->clock.vclock_mode) && atomic_read(&kvm_guest_has_master_clock) != 0) - queue_work(system_long_wq, &pvclock_gtod_work); - + irq_work_queue(&pvclock_irq_work); return 0; }
@@ -8096,6 +8109,7 @@ void kvm_arch_exit(void) cpuhp_remove_state_nocalls(CPUHP_AP_X86_KVM_CLK_ONLINE); #ifdef CONFIG_X86_64 pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier); + irq_work_sync(&pvclock_irq_work); cancel_work_sync(&pvclock_gtod_work); #endif kvm_x86_ops.hardware_enable = NULL;
From: Tom Lendacky thomas.lendacky@amd.com
[ Upstream commit ce7ea0cfdc2e9ff31d12da31c3226deddb9644f5 ]
When an SEV-ES guest is running, the GHCB is unmapped as part of the vCPU run support. However, kvm_vcpu_unmap() triggers an RCU dereference warning with CONFIG_PROVE_LOCKING=y because the SRCU lock is released before invoking the vCPU run support.
Move the GHCB unmapping into the prepare_guest_switch callback, which is invoked while still holding the SRCU lock, eliminating the RCU dereference warning.
Fixes: 291bd20d5d88 ("KVM: SVM: Add initial support for a VMGEXIT VMEXIT") Reported-by: Borislav Petkov bp@alien8.de Signed-off-by: Tom Lendacky thomas.lendacky@amd.com Message-Id: b2f9b79d15166f2c3e4375c0d9bc3268b7696455.1620332081.git.thomas.lendacky@amd.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/svm/sev.c | 5 +---- arch/x86/kvm/svm/svm.c | 3 +++ arch/x86/kvm/svm/svm.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index ba56f677cc09..dbc6214d69de 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -1668,7 +1668,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) return -EINVAL; }
-static void pre_sev_es_run(struct vcpu_svm *svm) +void sev_es_unmap_ghcb(struct vcpu_svm *svm) { if (!svm->ghcb) return; @@ -1704,9 +1704,6 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) struct svm_cpu_data *sd = per_cpu(svm_data, cpu); int asid = sev_get_asid(svm->vcpu.kvm);
- /* Perform any SEV-ES pre-run actions */ - pre_sev_es_run(svm); - /* Assign the asid allocated with this SEV guest */ svm->asid = asid;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 276d3c728628..5364458cf60b 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1416,6 +1416,9 @@ static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu); unsigned int i;
+ if (sev_es_guest(vcpu->kvm)) + sev_es_unmap_ghcb(svm); + if (svm->guest_state_loaded) return;
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 39e071fdab0c..98da0b91f273 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -571,6 +571,7 @@ void sev_es_init_vmcb(struct vcpu_svm *svm); void sev_es_create_vcpu(struct vcpu_svm *svm); void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector); void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu); +void sev_es_unmap_ghcb(struct vcpu_svm *svm);
/* vmenter.S */
From: Vivek Goyal vgoyal@redhat.com
[ Upstream commit 698ab77aebffe08b312fbcdddeb0e8bd08b78717 ]
Dan mentioned that he is not very fond of passing around a boolean true/false to specify if only next waiter should be woken up or all waiters should be woken up. He instead prefers that we introduce an enum and make it very explicity at the callsite itself. Easier to read code.
This patch should not introduce any change of behavior.
Reviewed-by: Greg Kurz groug@kaod.org Reviewed-by: Jan Kara jack@suse.cz Suggested-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Vivek Goyal vgoyal@redhat.com Link: https://lore.kernel.org/r/20210428190314.1865312-2-vgoyal@redhat.com Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dax.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c index b3d27fdc6775..5ecee51c44ee 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -144,6 +144,16 @@ struct wait_exceptional_entry_queue { struct exceptional_entry_key key; };
+/** + * enum dax_wake_mode: waitqueue wakeup behaviour + * @WAKE_ALL: wake all waiters in the waitqueue + * @WAKE_NEXT: wake only the first waiter in the waitqueue + */ +enum dax_wake_mode { + WAKE_ALL, + WAKE_NEXT, +}; + static wait_queue_head_t *dax_entry_waitqueue(struct xa_state *xas, void *entry, struct exceptional_entry_key *key) { @@ -182,7 +192,8 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait, * The important information it's conveying is whether the entry at * this index used to be a PMD entry. */ -static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all) +static void dax_wake_entry(struct xa_state *xas, void *entry, + enum dax_wake_mode mode) { struct exceptional_entry_key key; wait_queue_head_t *wq; @@ -196,7 +207,7 @@ static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all) * must be in the waitqueue and the following check will see them. */ if (waitqueue_active(wq)) - __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key); + __wake_up(wq, TASK_NORMAL, mode == WAKE_ALL ? 0 : 1, &key); }
/* @@ -268,7 +279,7 @@ static void put_unlocked_entry(struct xa_state *xas, void *entry) { /* If we were the only waiter woken, wake the next one */ if (entry && !dax_is_conflict(entry)) - dax_wake_entry(xas, entry, false); + dax_wake_entry(xas, entry, WAKE_NEXT); }
/* @@ -286,7 +297,7 @@ static void dax_unlock_entry(struct xa_state *xas, void *entry) old = xas_store(xas, entry); xas_unlock_irq(xas); BUG_ON(!dax_is_locked(old)); - dax_wake_entry(xas, entry, false); + dax_wake_entry(xas, entry, WAKE_NEXT); }
/* @@ -524,7 +535,7 @@ static void *grab_mapping_entry(struct xa_state *xas,
dax_disassociate_entry(entry, mapping, false); xas_store(xas, NULL); /* undo the PMD join */ - dax_wake_entry(xas, entry, true); + dax_wake_entry(xas, entry, WAKE_ALL); mapping->nrexceptional--; entry = NULL; xas_set(xas, index); @@ -937,7 +948,7 @@ static int dax_writeback_one(struct xa_state *xas, struct dax_device *dax_dev, xas_lock_irq(xas); xas_store(xas, entry); xas_clear_mark(xas, PAGECACHE_TAG_DIRTY); - dax_wake_entry(xas, entry, false); + dax_wake_entry(xas, entry, WAKE_NEXT);
trace_dax_writeback_one(mapping->host, index, count); return ret;
From: Vivek Goyal vgoyal@redhat.com
[ Upstream commit 4c3d043d271d4d629aa2328796cdfc96b37d3b3c ]
As of now put_unlocked_entry() always wakes up next waiter. In next patches we want to wake up all waiters at one callsite. Hence, add a parameter to the function.
This patch does not introduce any change of behavior.
Reviewed-by: Greg Kurz groug@kaod.org Reviewed-by: Jan Kara jack@suse.cz Suggested-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Vivek Goyal vgoyal@redhat.com Link: https://lore.kernel.org/r/20210428190314.1865312-3-vgoyal@redhat.com Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dax.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c index 5ecee51c44ee..56eb1c759ca5 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -275,11 +275,11 @@ static void wait_entry_unlocked(struct xa_state *xas, void *entry) finish_wait(wq, &ewait.wait); }
-static void put_unlocked_entry(struct xa_state *xas, void *entry) +static void put_unlocked_entry(struct xa_state *xas, void *entry, + enum dax_wake_mode mode) { - /* If we were the only waiter woken, wake the next one */ if (entry && !dax_is_conflict(entry)) - dax_wake_entry(xas, entry, WAKE_NEXT); + dax_wake_entry(xas, entry, mode); }
/* @@ -633,7 +633,7 @@ struct page *dax_layout_busy_page_range(struct address_space *mapping, entry = get_unlocked_entry(&xas, 0); if (entry) page = dax_busy_page(entry); - put_unlocked_entry(&xas, entry); + put_unlocked_entry(&xas, entry, WAKE_NEXT); if (page) break; if (++scanned % XA_CHECK_SCHED) @@ -675,7 +675,7 @@ static int __dax_invalidate_entry(struct address_space *mapping, mapping->nrexceptional--; ret = 1; out: - put_unlocked_entry(&xas, entry); + put_unlocked_entry(&xas, entry, WAKE_NEXT); xas_unlock_irq(&xas); return ret; } @@ -954,7 +954,7 @@ static int dax_writeback_one(struct xa_state *xas, struct dax_device *dax_dev, return ret;
put_unlocked: - put_unlocked_entry(xas, entry); + put_unlocked_entry(xas, entry, WAKE_NEXT); return ret; }
@@ -1695,7 +1695,7 @@ dax_insert_pfn_mkwrite(struct vm_fault *vmf, pfn_t pfn, unsigned int order) /* Did we race with someone splitting entry or so? */ if (!entry || dax_is_conflict(entry) || (order == 0 && !dax_is_pte_entry(entry))) { - put_unlocked_entry(&xas, entry); + put_unlocked_entry(&xas, entry, WAKE_NEXT); xas_unlock_irq(&xas); trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf, VM_FAULT_NOPAGE);
From: Vivek Goyal vgoyal@redhat.com
[ Upstream commit 237388320deffde7c2d65ed8fc9eef670dc979b3 ]
I am seeing missed wakeups which ultimately lead to a deadlock when I am using virtiofs with DAX enabled and running "make -j". I had to mount virtiofs as rootfs and also reduce to dax window size to 256M to reproduce the problem consistently.
So here is the problem. put_unlocked_entry() wakes up waiters only if entry is not null as well as !dax_is_conflict(entry). But if I call multiple instances of invalidate_inode_pages2() in parallel, then I can run into a situation where there are waiters on this index but nobody will wake these waiters.
invalidate_inode_pages2() invalidate_inode_pages2_range() invalidate_exceptional_entry2() dax_invalidate_mapping_entry_sync() __dax_invalidate_entry() { xas_lock_irq(&xas); entry = get_unlocked_entry(&xas, 0); ... ... dax_disassociate_entry(entry, mapping, trunc); xas_store(&xas, NULL); ... ... put_unlocked_entry(&xas, entry); xas_unlock_irq(&xas); }
Say a fault in in progress and it has locked entry at offset say "0x1c". Now say three instances of invalidate_inode_pages2() are in progress (A, B, C) and they all try to invalidate entry at offset "0x1c". Given dax entry is locked, all tree instances A, B, C will wait in wait queue.
When dax fault finishes, say A is woken up. It will store NULL entry at index "0x1c" and wake up B. When B comes along it will find "entry=0" at page offset 0x1c and it will call put_unlocked_entry(&xas, 0). And this means put_unlocked_entry() will not wake up next waiter, given the current code. And that means C continues to wait and is not woken up.
This patch fixes the issue by waking up all waiters when a dax entry has been invalidated. This seems to fix the deadlock I am facing and I can make forward progress.
Reported-by: Sergio Lopez slp@redhat.com Fixes: ac401cc78242 ("dax: New fault locking") Reviewed-by: Jan Kara jack@suse.cz Suggested-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Vivek Goyal vgoyal@redhat.com Link: https://lore.kernel.org/r/20210428190314.1865312-4-vgoyal@redhat.com Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/dax.c b/fs/dax.c index 56eb1c759ca5..df5485b4bddf 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -675,7 +675,7 @@ static int __dax_invalidate_entry(struct address_space *mapping, mapping->nrexceptional--; ret = 1; out: - put_unlocked_entry(&xas, entry, WAKE_NEXT); + put_unlocked_entry(&xas, entry, WAKE_ALL); xas_unlock_irq(&xas); return ret; }
From: Zhen Lei thunder.leizhen@huawei.com
[ Upstream commit dbc03e81586fc33e4945263fd6e09e22eb4b980f ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: a4574f63edc6 ("mm/memremap_pages: convert to 'struct range'") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhen Lei thunder.leizhen@huawei.com Reviewed-by: Juergen Gross jgross@suse.com Link: https://lore.kernel.org/r/20210508021913.1727-1-thunder.leizhen@huawei.com Signed-off-by: Juergen Gross jgross@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/xen/unpopulated-alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-alloc.c index e64e6befc63b..87e6b7db892f 100644 --- a/drivers/xen/unpopulated-alloc.c +++ b/drivers/xen/unpopulated-alloc.c @@ -39,8 +39,10 @@ static int fill_list(unsigned int nr_pages) }
pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL); - if (!pgmap) + if (!pgmap) { + ret = -ENOMEM; goto err_pgmap; + }
pgmap->type = MEMORY_DEVICE_GENERIC; pgmap->range = (struct range) {
From: Jiri Olsa jolsa@kernel.org
[ Upstream commit ad1237c30d975535a669746496cbed136aa5a045 ]
Justin reported broken build with LIBBPF_DYNAMIC=1.
When linking libbpf dynamically we need to use perf's hashmap object, because it's not exported in libbpf.so (only in libbpf.a).
Following build is now passing:
$ make LIBBPF_DYNAMIC=1 BUILD: Doing 'make -j8' parallel build ... $ ldd perf | grep libbpf libbpf.so.0 => /lib64/libbpf.so.0 (0x00007fa7630db000)
Fixes: eee19501926d ("perf tools: Grab a copy of libbpf's hashmap") Reported-by: Justin M. Forbes jforbes@redhat.com Signed-off-by: Jiri Olsa jolsa@kernel.org Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Ian Rogers irogers@google.com Cc: Mark Rutland mark.rutland@arm.com Cc: Michael Petlan mpetlan@redhat.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20210508205020.617984-1-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/Makefile.config | 1 + tools/perf/util/Build | 7 +++++++ 2 files changed, 8 insertions(+)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index d8e59d31399a..c955cd683e22 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -530,6 +530,7 @@ ifndef NO_LIBELF ifdef LIBBPF_DYNAMIC ifeq ($(feature-libbpf), 1) EXTLIBS += -lbpf + $(call detected,CONFIG_LIBBPF_DYNAMIC) else dummy := $(error Error: No libbpf devel library found, please install libbpf-devel); endif diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e3e12f9d4733..5a296ac69415 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -141,7 +141,14 @@ perf-$(CONFIG_LIBELF) += symbol-elf.o perf-$(CONFIG_LIBELF) += probe-file.o perf-$(CONFIG_LIBELF) += probe-event.o
+ifdef CONFIG_LIBBPF_DYNAMIC + hashmap := 1 +endif ifndef CONFIG_LIBBPF + hashmap := 1 +endif + +ifdef hashmap perf-y += hashmap.o endif
From: Jack Pham jackp@codeaurora.org
[ Upstream commit bb9c74a5bd1462499fe5ccb1e3c5ac40dcfa9139 ]
As part of commit e81a7018d93a ("usb: dwc3: allocate gadget structure dynamically") the dwc3_gadget_release() was added which will free the dwc->gadget structure upon the device's removal when usb_del_gadget_udc() is called in dwc3_gadget_exit().
However, simply freeing the gadget results a dangling pointer situation: the endpoints created in dwc3_gadget_init_endpoints() have their dep->endpoint.ep_list members chained off the list_head anchored at dwc->gadget->ep_list. Thus when dwc->gadget is freed, the first dwc3_ep in the list now has a dangling prev pointer and likewise for the next pointer of the dwc3_ep at the tail of the list. The dwc3_gadget_free_endpoints() that follows will result in a use-after-free when it calls list_del().
This was caught by enabling KASAN and performing a driver unbind. The recent commit 568262bf5492 ("usb: dwc3: core: Add shutdown callback for dwc3") also exposes this as a panic during shutdown.
There are a few possibilities to fix this. One could be to perform a list_del() of the gadget->ep_list itself which removes it from the rest of the dwc3_ep chain.
Another approach is what this patch does, by splitting up the usb_del_gadget_udc() call into its separate "del" and "put" components. This allows dwc3_gadget_free_endpoints() to be called before the gadget is finally freed with usb_put_gadget().
Fixes: e81a7018d93a ("usb: dwc3: allocate gadget structure dynamically") Reviewed-by: Peter Chen peter.chen@kernel.org Signed-off-by: Jack Pham jackp@codeaurora.org Link: https://lore.kernel.org/r/20210501093558.7375-1-jackp@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f85eda6bc988..5fd27160c336 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4024,8 +4024,9 @@ int dwc3_gadget_init(struct dwc3 *dwc)
void dwc3_gadget_exit(struct dwc3 *dwc) { - usb_del_gadget_udc(dwc->gadget); + usb_del_gadget(dwc->gadget); dwc3_gadget_free_endpoints(dwc); + usb_put_gadget(dwc->gadget); dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, dwc->bounce_addr); kfree(dwc->setup_buf);
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit 8edb79af88efc6e49e735f9baf61d9f0748b881f ]
When devm_request_threaded_irq() fails, we should decrease the runtime PM counter to keep the counter balanced. But when iio_device_register() fails, we need not to decrease it because we have already decreased it before.
Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Reviewed-by: Linus Walleij linus.walleij@linaro.org Fixes: 97d642e23037 ("iio: light: Add a driver for Sharp GP2AP002x00F") Link: https://lore.kernel.org/r/20210407034927.16882-1-dinghao.liu@zju.edu.cn Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/light/gp2ap002.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index 7ba7aa59437c..040d8429a6e0 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -583,7 +583,7 @@ static int gp2ap002_probe(struct i2c_client *client, "gp2ap002", indio_dev); if (ret) { dev_err(dev, "unable to request IRQ\n"); - goto out_disable_vio; + goto out_put_pm; } gp2ap002->irq = client->irq;
@@ -613,8 +613,9 @@ static int gp2ap002_probe(struct i2c_client *client,
return 0;
-out_disable_pm: +out_put_pm: pm_runtime_put_noidle(dev); +out_disable_pm: pm_runtime_disable(dev); out_disable_vio: regulator_disable(gp2ap002->vio);
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit a2fa9242e89f27696515699fe0f0296bf1ac1815 ]
When lidar_write_control() fails, a pairing PM usage counter decrement is needed to keep the counter balanced.
Fixes: 4ac4e086fd8c5 ("iio: pulsedlight-lidar-lite: add runtime PM") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Link: https://lore.kernel.org/r/20210412053204.4889-1-dinghao.liu@zju.edu.cn Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index c685f10b5ae4..cc206bfa09c7 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -160,6 +160,7 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); if (ret < 0) { dev_err(&client->dev, "cannot send start measurement command"); + pm_runtime_put_noidle(&client->dev); return ret; }
From: Alexandru Ardelean aardelean@deviqon.com
[ Upstream commit 7061803522ee7876df1ca18cdd1e1551f761352d ]
During commit 067fda1c065ff ("iio: hid-sensors: move triggered buffer setup into hid_sensor_setup_trigger"), the iio_triggered_buffer_{setup,cleanup}() functions got moved under the hid-sensor-trigger module.
The above change works fine, if any of the sensors get built. However, when only the common hid-sensor-trigger module gets built (and none of the drivers), then the IIO_TRIGGERED_BUFFER symbol isn't selected/enforced.
Previously, each driver would enforce/select the IIO_TRIGGERED_BUFFER symbol. With this change the HID_SENSOR_IIO_TRIGGER (for the hid-sensor-trigger module) will enforce that IIO_TRIGGERED_BUFFER gets selected.
All HID sensor drivers select the HID_SENSOR_IIO_TRIGGER symbol. So, this change removes the IIO_TRIGGERED_BUFFER enforcement from each driver.
Fixes: 067fda1c065ff ("iio: hid-sensors: move triggered buffer setup into hid_sensor_setup_trigger") Reported-by: Thomas Deutschmann whissi@gentoo.org Cc: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Signed-off-by: Alexandru Ardelean aardelean@deviqon.com Acked-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Link: https://lore.kernel.org/r/20210414084955.260117-1-aardelean@deviqon.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/accel/Kconfig | 1 - drivers/iio/common/hid-sensors/Kconfig | 1 + drivers/iio/gyro/Kconfig | 1 - drivers/iio/humidity/Kconfig | 1 - drivers/iio/light/Kconfig | 2 -- drivers/iio/magnetometer/Kconfig | 1 - drivers/iio/orientation/Kconfig | 2 -- drivers/iio/pressure/Kconfig | 1 - drivers/iio/temperature/Kconfig | 1 - 9 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 2e0c62c39155..8acf277b8b25 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -211,7 +211,6 @@ config DMARD10 config HID_SENSOR_ACCEL_3D depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID Accelerometers 3D" diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index 24d492567336..2a3dd3b907be 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -19,6 +19,7 @@ config HID_SENSOR_IIO_TRIGGER tristate "Common module (trigger) for all HID Sensor IIO drivers" depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER help Say yes here to build trigger support for HID sensors. Triggers will be send if all requested attributes were read. diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 5824f2edf975..20b5ac7ab66a 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -111,7 +111,6 @@ config FXAS21002C_SPI config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID Gyroscope 3D" diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 6549fcf6db69..2de5494e7c22 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -52,7 +52,6 @@ config HID_SENSOR_HUMIDITY tristate "HID Environmental humidity sensor" depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER help diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 33ad4dd0b5c7..917f9becf9c7 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -256,7 +256,6 @@ config ISL29125 config HID_SENSOR_ALS depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID ALS" @@ -270,7 +269,6 @@ config HID_SENSOR_ALS config HID_SENSOR_PROX depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID PROX" diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index 5d4ffd66032e..74ad5701c6c2 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -95,7 +95,6 @@ config MAG3110 config HID_SENSOR_MAGNETOMETER_3D depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID Magenetometer 3D" diff --git a/drivers/iio/orientation/Kconfig b/drivers/iio/orientation/Kconfig index a505583cc2fd..396cbbb867f4 100644 --- a/drivers/iio/orientation/Kconfig +++ b/drivers/iio/orientation/Kconfig @@ -9,7 +9,6 @@ menu "Inclinometer sensors" config HID_SENSOR_INCLINOMETER_3D depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID Inclinometer 3D" @@ -20,7 +19,6 @@ config HID_SENSOR_INCLINOMETER_3D config HID_SENSOR_DEVICE_ROTATION depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID Device Rotation" diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 689b978db4f9..fc0d3cfca418 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -79,7 +79,6 @@ config DPS310 config HID_SENSOR_PRESS depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER tristate "HID PRESS" diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index f1f2a1499c9e..4df60082c1fa 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -45,7 +45,6 @@ config HID_SENSOR_TEMP tristate "HID Environmental temperature sensor" depends on HID_SENSOR_HUB select IIO_BUFFER - select IIO_TRIGGERED_BUFFER select HID_SENSOR_IIO_COMMON select HID_SENSOR_IIO_TRIGGER help
From: Alexandru Ardelean aardelean@deviqon.com
[ Upstream commit af0670b0bf1b116fd729b1b1011cf814bc34e12e ]
When the ioctl() mechanism was introduced in IIO core to centralize the registration of all ioctls in one place via commit 8dedcc3eee3ac ("iio: core: centralize ioctl() calls to the main chardev"), the return code was changed from ENODEV to EINVAL, when the ioctl code isn't known.
This was done by accident.
This change reverts back to the old behavior, where if the ioctl() code isn't known, ENODEV is returned (vs EINVAL).
This was brought into perspective by this patch: https://lore.kernel.org/linux-iio/20210428150815.136150-1-paul@crapouillou.n...
Fixes: 8dedcc3eee3ac ("iio: core: centralize ioctl() calls to the main chardev") Signed-off-by: Alexandru Ardelean aardelean@deviqon.com Reviewed-by: Nuno Sá nuno.sa@analog.com Tested-by: Paul Cercueil paul@crapouillou.net Reviewed-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/industrialio-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 7db761afa578..2050d341746b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1734,7 +1734,6 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (!indio_dev->info) goto out_unlock;
- ret = -EINVAL; list_for_each_entry(h, &iio_dev_opaque->ioctl_handlers, entry) { ret = h->ioctl(indio_dev, filp, cmd, arg); if (ret != IIO_IOCTL_UNHANDLED) @@ -1742,7 +1741,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) }
if (ret == IIO_IOCTL_UNHANDLED) - ret = -EINVAL; + ret = -ENODEV;
out_unlock: mutex_unlock(&indio_dev->info_exist_lock);
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit a60a34366e0d09ca002c966dd7c43a68c28b1f82 ]
'retval' is known to be -ENODEV here. This is a hard-coded default error code which is not useful in the error message. Moreover, another error message is printed at the end of the error handling path. The corresponding error code (-ENOMEM) is more informative.
So remove simplify the first error message.
While at it, also remove the useless initialization of 'retval'.
Fixes: 7d50195f6c50 ("usb: host: Faraday fotg210-hcd driver") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/94531bcff98e46d4f9c20183a90b7f47f699126c.162033341... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/host/fotg210-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 5617ef30530a..f0e4a315cc81 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -5568,7 +5568,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct resource *res; int irq; - int retval = -ENODEV; + int retval; struct fotg210_hcd *fotg210;
if (usb_disabled()) @@ -5588,7 +5588,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev) hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev, dev_name(dev)); if (!hcd) { - dev_err(dev, "failed to create hcd with err %d\n", retval); + dev_err(dev, "failed to create hcd\n"); retval = -ENOMEM; goto fail_create_hcd; }
From: Eddie James eajames@linux.ibm.com
[ Upstream commit 5216dff22dc2bbbbe6f00335f9fd2879670e753b ]
The poll rate limiter time was initialized at zero. This breaks the comparison in time_after if jiffies is large. Switch to storing the next update time rather than the previous time, and initialize the time when the device is probed.
Fixes: c10e753d43eb ("hwmon (occ): Add sensor types and versions") Signed-off-by: Eddie James eajames@linux.ibm.com Link: https://lore.kernel.org/r/20210429151336.18980-1-eajames@linux.ibm.com Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hwmon/occ/common.c | 5 +++-- drivers/hwmon/occ/common.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 7a5e539b567b..580e63d7daa0 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -217,9 +217,9 @@ int occ_update_response(struct occ *occ) return rc;
/* limit the maximum rate of polling the OCC */ - if (time_after(jiffies, occ->last_update + OCC_UPDATE_FREQUENCY)) { + if (time_after(jiffies, occ->next_update)) { rc = occ_poll(occ); - occ->last_update = jiffies; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; } else { rc = occ->last_error; } @@ -1164,6 +1164,7 @@ int occ_setup(struct occ *occ, const char *name) return rc; }
+ occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; occ_parse_poll_response(occ);
rc = occ_setup_sensor_attrs(occ); diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h index 67e6968b8978..e6df719770e8 100644 --- a/drivers/hwmon/occ/common.h +++ b/drivers/hwmon/occ/common.h @@ -99,7 +99,7 @@ struct occ { u8 poll_cmd_data; /* to perform OCC poll command */ int (*send_cmd)(struct occ *occ, u8 *cmd);
- unsigned long last_update; + unsigned long next_update; struct mutex lock; /* lock OCC access */
struct device *hwmon;
From: Kyle Tso kyletso@google.com
[ Upstream commit f1fbd950b59b67bc5c202216c8e1c6ca8c99a3b4 ]
Not_Supported Message is acceptable in VDM AMS. Redirect the VDM state machine to VDM_STATE_DONE when receiving Not_Supported and finish the VDM AMS.
Also, after the loop in vdm_state_machine_work, add more conditions of VDM states to clear the vdm_sm_running flag because those are all stopping states when leaving the loop.
In addition, finish the VDM AMS if the port partner responds BUSY.
Fixes: 8dea75e11380 ("usb: typec: tcpm: Protocol Error handling") Fixes: 8d3a0578ad1a ("usb: typec: tcpm: Respond Wait if VDM state machine is running") Reviewed-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Kyle Tso kyletso@google.com Link: https://lore.kernel.org/r/20210507062300.1945009-3-kyletso@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/typec/tcpm/tcpm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 1a086ba254d2..7386f3e2cb69 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -1877,7 +1877,6 @@ static void vdm_run_state_machine(struct tcpm_port *port) }
if (res < 0) { - port->vdm_sm_running = false; return; } } @@ -1893,6 +1892,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) port->vdo_data[0] = port->vdo_retry; port->vdo_count = 1; port->vdm_state = VDM_STATE_READY; + tcpm_ams_finish(port); break; case VDM_STATE_BUSY: port->vdm_state = VDM_STATE_ERR_TMOUT; @@ -1958,7 +1958,7 @@ static void vdm_state_machine_work(struct kthread_work *work) port->vdm_state != VDM_STATE_BUSY && port->vdm_state != VDM_STATE_SEND_MESSAGE);
- if (port->vdm_state == VDM_STATE_ERR_TMOUT) + if (port->vdm_state < VDM_STATE_READY) port->vdm_sm_running = false;
mutex_unlock(&port->lock); @@ -2549,6 +2549,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, port->sink_cap_done = true; tcpm_set_state(port, ready_state(port), 0); break; + case SRC_READY: + case SNK_READY: + if (port->vdm_state > VDM_STATE_READY) { + port->vdm_state = VDM_STATE_DONE; + if (tcpm_vdm_ams(port)) + tcpm_ams_finish(port); + mod_vdm_delayed_work(port, 0); + break; + } + fallthrough; default: tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit d9ff1096a840dddea3d5cfa2149ff7da9f499fb2 ]
'ret' is known to be 0 here. Initialize 'ret' with the expected error code before using it.
Fixes: 0990366bab3c ("usb: musb: Add support for MediaTek musb controller") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/69f514dc7134e3c917cad208e73cc650cb9e2bd6.162015987... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/musb/mediatek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c index eebeadd26946..6b92d037d8fc 100644 --- a/drivers/usb/musb/mediatek.c +++ b/drivers/usb/musb/mediatek.c @@ -518,8 +518,8 @@ static int mtk_musb_probe(struct platform_device *pdev)
glue->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); if (IS_ERR(glue->xceiv)) { - dev_err(dev, "fail to getting usb-phy %d\n", ret); ret = PTR_ERR(glue->xceiv); + dev_err(dev, "fail to getting usb-phy %d\n", ret); goto err_unregister_usb_phy; }
From: Andy Shevchenko andy.shevchenko@gmail.com
[ Upstream commit 8370e5b093080c03cf89f7ebf0bef6984545429e ]
In each iteration fwnode_for_each_available_child_node() bumps a reference counting of a loop variable followed by dropping in on a next iteration,
Since in error case the loop is broken, we have to drop a reference count by ourselves. Do it for port_fwnode in error case during ->probe().
Fixes: b0bd407e94b0 ("hwmon: (ltc2992) Add support") Cc: Alexandru Tachici alexandru.tachici@analog.com Signed-off-by: Andy Shevchenko andy.shevchenko@gmail.com Link: https://lore.kernel.org/r/20210510100136.3303142-1-andy.shevchenko@gmail.com Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hwmon/ltc2992.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c index 4382105bf142..2a4bed0ab226 100644 --- a/drivers/hwmon/ltc2992.c +++ b/drivers/hwmon/ltc2992.c @@ -900,11 +900,15 @@ static int ltc2992_parse_dt(struct ltc2992_state *st)
fwnode_for_each_available_child_node(fwnode, child) { ret = fwnode_property_read_u32(child, "reg", &addr); - if (ret < 0) + if (ret < 0) { + fwnode_handle_put(child); return ret; + }
- if (addr > 1) + if (addr > 1) { + fwnode_handle_put(child); return -EINVAL; + }
ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val); if (!ret)
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 0c8bd174f0fc131bc9dfab35cd8784f59045da87 ]
If 'acpi_device_set_name()' fails, we must free 'acpi_device_bus_id->bus_id' or there is a (potential) memory leak.
Fixes: eb50aaf960e3 ("ACPI: scan: Use unique number for instance_no") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/acpi/scan.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 6efe7edd7b1e..345777bf7af9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -701,6 +701,7 @@ int acpi_device_add(struct acpi_device *device,
result = acpi_device_set_name(device, acpi_device_bus_id); if (result) { + kfree_const(acpi_device_bus_id->bus_id); kfree(acpi_device_bus_id); goto err_unlock; }
From: Omar Sandoval osandov@fb.com
[ Upstream commit efed9a3337e341bd0989161b97453b52567bc59d ]
__blk_mq_sched_bio_merge() gets the ctx and hctx for the current CPU and passes the hctx to ->bio_merge(). kyber_bio_merge() then gets the ctx for the current CPU again and uses that to get the corresponding Kyber context in the passed hctx. However, the thread may be preempted between the two calls to blk_mq_get_ctx(), and the ctx returned the second time may no longer correspond to the passed hctx. This "works" accidentally most of the time, but it can cause us to read garbage if the second ctx came from an hctx with more ctx's than the first one (i.e., if ctx->index_hw[hctx->type] > hctx->nr_ctx).
This manifested as this UBSAN array index out of bounds error reported by Jakub:
UBSAN: array-index-out-of-bounds in ../kernel/locking/qspinlock.c:130:9 index 13106 is out of range for type 'long unsigned int [128]' Call Trace: dump_stack+0xa4/0xe5 ubsan_epilogue+0x5/0x40 __ubsan_handle_out_of_bounds.cold.13+0x2a/0x34 queued_spin_lock_slowpath+0x476/0x480 do_raw_spin_lock+0x1c2/0x1d0 kyber_bio_merge+0x112/0x180 blk_mq_submit_bio+0x1f5/0x1100 submit_bio_noacct+0x7b0/0x870 submit_bio+0xc2/0x3a0 btrfs_map_bio+0x4f0/0x9d0 btrfs_submit_data_bio+0x24e/0x310 submit_one_bio+0x7f/0xb0 submit_extent_page+0xc4/0x440 __extent_writepage_io+0x2b8/0x5e0 __extent_writepage+0x28d/0x6e0 extent_write_cache_pages+0x4d7/0x7a0 extent_writepages+0xa2/0x110 do_writepages+0x8f/0x180 __writeback_single_inode+0x99/0x7f0 writeback_sb_inodes+0x34e/0x790 __writeback_inodes_wb+0x9e/0x120 wb_writeback+0x4d2/0x660 wb_workfn+0x64d/0xa10 process_one_work+0x53a/0xa80 worker_thread+0x69/0x5b0 kthread+0x20b/0x240 ret_from_fork+0x1f/0x30
Only Kyber uses the hctx, so fix it by passing the request_queue to ->bio_merge() instead. BFQ and mq-deadline just use that, and Kyber can map the queues itself to avoid the mismatch.
Fixes: a6088845c2bf ("block: kyber: make kyber more friendly with merging") Reported-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Omar Sandoval osandov@fb.com Link: https://lore.kernel.org/r/c7598605401a48d5cfeadebb678abd10af22b83f.162069132... Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/bfq-iosched.c | 3 +-- block/blk-mq-sched.c | 8 +++++--- block/kyber-iosched.c | 5 +++-- block/mq-deadline.c | 3 +-- include/linux/elevator.h | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 20ba5db0f61c..bc319931d2b3 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -2263,10 +2263,9 @@ static void bfq_remove_request(struct request_queue *q,
}
-static bool bfq_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, +static bool bfq_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { - struct request_queue *q = hctx->queue; struct bfq_data *bfqd = q->elevator->elevator_data; struct request *free = NULL; /* diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index e1e997af89a0..fdeb9773b55c 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -348,14 +348,16 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { struct elevator_queue *e = q->elevator; - struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); - struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); + struct blk_mq_ctx *ctx; + struct blk_mq_hw_ctx *hctx; bool ret = false; enum hctx_type type;
if (e && e->type->ops.bio_merge) - return e->type->ops.bio_merge(hctx, bio, nr_segs); + return e->type->ops.bio_merge(q, bio, nr_segs);
+ ctx = blk_mq_get_ctx(q); + hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); type = hctx->type; if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE) || list_empty_careful(&ctx->rq_lists[type])) diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c index 33d34d69cade..79b69d7046d6 100644 --- a/block/kyber-iosched.c +++ b/block/kyber-iosched.c @@ -560,11 +560,12 @@ static void kyber_limit_depth(unsigned int op, struct blk_mq_alloc_data *data) } }
-static bool kyber_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, +static bool kyber_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { + struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); + struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); struct kyber_hctx_data *khd = hctx->sched_data; - struct blk_mq_ctx *ctx = blk_mq_get_ctx(hctx->queue); struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw[hctx->type]]; unsigned int sched_domain = kyber_sched_domain(bio->bi_opf); struct list_head *rq_list = &kcq->rq_list[sched_domain]; diff --git a/block/mq-deadline.c b/block/mq-deadline.c index f3631a287466..3aabcd2a7893 100644 --- a/block/mq-deadline.c +++ b/block/mq-deadline.c @@ -461,10 +461,9 @@ static int dd_request_merge(struct request_queue *q, struct request **rq, return ELEVATOR_NO_MERGE; }
-static bool dd_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, +static bool dd_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { - struct request_queue *q = hctx->queue; struct deadline_data *dd = q->elevator->elevator_data; struct request *free = NULL; bool ret; diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 1fe8e105b83b..dcb2f9022c1d 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -34,7 +34,7 @@ struct elevator_mq_ops { void (*depth_updated)(struct blk_mq_hw_ctx *);
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *); - bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *, unsigned int); + bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int); int (*request_merge)(struct request_queue *q, struct request **, struct bio *); void (*request_merged)(struct request_queue *, struct request *, enum elv_merge); void (*requests_merged)(struct request_queue *, struct request *, struct request *);
From: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com
[ Upstream commit 608a969046e6e0567d05a166be66c77d2dd8220b ]
When handling rw commands, for inline bio case we only consider transfer size. This works well when req->sg_cnt fits into the req->inline_bvec, but it will result in the warning in __bio_add_page() when req->sg_cnt > NVMET_MAX_INLINE_BVEC.
Consider an I/O size 32768 and first page is not aligned to the page boundary, then I/O is split in following manner :-
[ 2206.256140] nvmet: sg->length 3440 sg->offset 656 [ 2206.256144] nvmet: sg->length 4096 sg->offset 0 [ 2206.256148] nvmet: sg->length 4096 sg->offset 0 [ 2206.256152] nvmet: sg->length 4096 sg->offset 0 [ 2206.256155] nvmet: sg->length 4096 sg->offset 0 [ 2206.256159] nvmet: sg->length 4096 sg->offset 0 [ 2206.256163] nvmet: sg->length 4096 sg->offset 0 [ 2206.256166] nvmet: sg->length 4096 sg->offset 0 [ 2206.256170] nvmet: sg->length 656 sg->offset 0
Now the req->transfer_size == NVMET_MAX_INLINE_DATA_LEN i.e. 32768, but the req->sg_cnt is (9) > NVMET_MAX_INLINE_BIOVEC which is (8). This will result in the following warning message :-
nvmet_bdev_execute_rw() bio_add_page() __bio_add_page() WARN_ON_ONCE(bio_full(bio, len));
This scenario is very hard to reproduce on the nvme-loop transport only with rw commands issued with the passthru IOCTL interface from the host application and the data buffer is allocated with the malloc() and not the posix_memalign().
Fixes: 73383adfad24 ("nvmet: don't split large I/Os unconditionally") Signed-off-by: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com Reviewed-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/io-cmd-bdev.c | 2 +- drivers/nvme/target/nvmet.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 9a8b3726a37c..429263ca9b97 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -258,7 +258,7 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
sector = nvmet_lba_to_sect(req->ns, req->cmd->rw.slba);
- if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) { + if (nvmet_use_inline_bvec(req)) { bio = &req->b.inline_bio; bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec)); } else { diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 4b84edb49f22..5aad34b106dc 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -614,4 +614,10 @@ static inline sector_t nvmet_lba_to_sect(struct nvmet_ns *ns, __le64 lba) return le64_to_cpu(lba) << (ns->blksize_shift - SECTOR_SHIFT); }
+static inline bool nvmet_use_inline_bvec(struct nvmet_req *req) +{ + return req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN && + req->sg_cnt <= NVMET_MAX_INLINE_BIOVEC; +} + #endif /* _NVMET_H */
From: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com
[ Upstream commit ab96de5def854d8fc51280b6a20597e64b14ac31 ]
When handling passthru commands, for inline bio allocation we only consider the transfer size. This works well when req->sg_cnt fits into the req->inline_bvec, but it will result in the early return from bio_add_hw_page() when req->sg_cnt > NVMET_MAX_INLINE_BVEC.
Consider an I/O of size 32768 and first buffer is not aligned to the page boundary, then I/O is split in following manner :-
[ 2206.256140] nvmet: sg->length 3440 sg->offset 656 [ 2206.256144] nvmet: sg->length 4096 sg->offset 0 [ 2206.256148] nvmet: sg->length 4096 sg->offset 0 [ 2206.256152] nvmet: sg->length 4096 sg->offset 0 [ 2206.256155] nvmet: sg->length 4096 sg->offset 0 [ 2206.256159] nvmet: sg->length 4096 sg->offset 0 [ 2206.256163] nvmet: sg->length 4096 sg->offset 0 [ 2206.256166] nvmet: sg->length 4096 sg->offset 0 [ 2206.256170] nvmet: sg->length 656 sg->offset 0
Now the req->transfer_size == NVMET_MAX_INLINE_DATA_LEN i.e. 32768, but the req->sg_cnt is (9) > NVMET_MAX_INLINE_BIOVEC which is (8). This will result in early return in the following code path :-
nvmet_bdev_execute_rw() bio_add_pc_page() bio_add_hw_page() if (bio_full(bio, len)) return 0;
Use previously introduced helper nvmet_use_inline_bvec() to consider req->sg_cnt when using inline bio. This only affects nvme-loop transport.
Fixes: dab3902b19a0 ("nvmet: use inline bio for passthru fast path") Signed-off-by: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com Reviewed-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/passthru.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index 2798944899b7..39b1473f7204 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -194,7 +194,7 @@ static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq) if (req->sg_cnt > BIO_MAX_VECS) return -EINVAL;
- if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) { + if (nvmet_use_inline_bvec(req)) { bio = &req->p.inline_bio; bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec)); } else {
From: Michal Kalderon michal.kalderon@marvell.com
[ Upstream commit 8cc365f9559b86802afc0208389f5c8d46b4ad61 ]
When running some traffic and taking down the link on peer, a retry counter exceeded error is received. This leads to nvmet_rdma_error_comp which tried accessing the cq_context to obtain the queue. The cq_context is no longer valid after the fix to use shared CQ mechanism and should be obtained similar to how it is obtained in other functions from the wc->qp.
[ 905.786331] nvmet_rdma: SEND for CQE 0x00000000e3337f90 failed with status transport retry counter exceeded (12). [ 905.832048] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048 [ 905.839919] PGD 0 P4D 0 [ 905.842464] Oops: 0000 1 SMP NOPTI [ 905.846144] CPU: 13 PID: 1557 Comm: kworker/13:1H Kdump: loaded Tainted: G OE --------- - - 4.18.0-304.el8.x86_64 #1 [ 905.872135] RIP: 0010:nvmet_rdma_error_comp+0x5/0x1b [nvmet_rdma] [ 905.878259] Code: 19 4f c0 e8 89 b3 a5 f6 e9 5b e0 ff ff 0f b7 75 14 4c 89 ea 48 c7 c7 08 1a 4f c0 e8 71 b3 a5 f6 e9 4b e0 ff ff 0f 1f 44 00 00 <48> 8b 47 48 48 85 c0 74 08 48 89 c7 e9 98 bf 49 00 e9 c3 e3 ff ff [ 905.897135] RSP: 0018:ffffab601c45fe28 EFLAGS: 00010246 [ 905.902387] RAX: 0000000000000065 RBX: ffff9e729ea2f800 RCX: 0000000000000000 [ 905.909558] RDX: 0000000000000000 RSI: ffff9e72df9567c8 RDI: 0000000000000000 [ 905.916731] RBP: ffff9e729ea2b400 R08: 000000000000074d R09: 0000000000000074 [ 905.923903] R10: 0000000000000000 R11: ffffab601c45fcc0 R12: 0000000000000010 [ 905.931074] R13: 0000000000000000 R14: 0000000000000010 R15: ffff9e729ea2f400 [ 905.938247] FS: 0000000000000000(0000) GS:ffff9e72df940000(0000) knlGS:0000000000000000 [ 905.938249] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 905.950067] nvmet_rdma: SEND for CQE 0x00000000c7356cca failed with status transport retry counter exceeded (12). [ 905.961855] CR2: 0000000000000048 CR3: 000000678d010004 CR4: 00000000007706e0 [ 905.961855] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 905.961856] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 905.961857] PKRU: 55555554 [ 906.010315] Call Trace: [ 906.012778] __ib_process_cq+0x89/0x170 [ib_core] [ 906.017509] ib_cq_poll_work+0x26/0x80 [ib_core] [ 906.022152] process_one_work+0x1a7/0x360 [ 906.026182] ? create_worker+0x1a0/0x1a0 [ 906.030123] worker_thread+0x30/0x390 [ 906.033802] ? create_worker+0x1a0/0x1a0 [ 906.037744] kthread+0x116/0x130 [ 906.040988] ? kthread_flush_work_fn+0x10/0x10 [ 906.045456] ret_from_fork+0x1f/0x40
Fixes: ca0f1a8055be2 ("nvmet-rdma: use new shared CQ mechanism") Signed-off-by: Shai Malin smalin@marvell.com Signed-off-by: Michal Kalderon michal.kalderon@marvell.com Reviewed-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/rdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 6c1f3ab7649c..7d607f435e36 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -700,7 +700,7 @@ static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc) { struct nvmet_rdma_rsp *rsp = container_of(wc->wr_cqe, struct nvmet_rdma_rsp, send_cqe); - struct nvmet_rdma_queue *queue = cq->cq_context; + struct nvmet_rdma_queue *queue = wc->qp->qp_context;
nvmet_rdma_release_rsp(rsp);
@@ -786,7 +786,7 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc) { struct nvmet_rdma_rsp *rsp = container_of(wc->wr_cqe, struct nvmet_rdma_rsp, write_cqe); - struct nvmet_rdma_queue *queue = cq->cq_context; + struct nvmet_rdma_queue *queue = wc->qp->qp_context; struct rdma_cm_id *cm_id = rsp->queue->cm_id; u16 status;
From: Chao Yu yuchao0@huawei.com
[ Upstream commit a12cc5b423d4f36dc1a1ea3911e49cf9dff43898 ]
In error path of f2fs_write_compressed_pages(), it needs to call f2fs_compress_free_page() to release temporary page.
Fixes: 5e6bbde95982 ("f2fs: introduce mempool for {,de}compress intermediate page allocation") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/compress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 77fa342de38f..146a8eb3891b 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1383,7 +1383,8 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, for (i = 0; i < cc->nr_cpages; i++) { if (!cc->cpages[i]) continue; - f2fs_put_page(cc->cpages[i], 1); + f2fs_compress_free_page(cc->cpages[i]); + cc->cpages[i] = NULL; } out_put_cic: kmem_cache_free(cic_entry_slab, cic);
From: Chao Yu yuchao0@huawei.com
[ Upstream commit a949dc5f2c5cfe0c910b664650f45371254c0744 ]
pos_fsstress testcase complains a panic as belew:
------------[ cut here ]------------ kernel BUG at fs/f2fs/compress.c:1082! invalid opcode: 0000 [#1] SMP PTI CPU: 4 PID: 2753477 Comm: kworker/u16:2 Tainted: G OE 5.12.0-rc1-custom #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 Workqueue: writeback wb_workfn (flush-252:16) RIP: 0010:prepare_compress_overwrite+0x4c0/0x760 [f2fs] Call Trace: f2fs_prepare_compress_overwrite+0x5f/0x80 [f2fs] f2fs_write_cache_pages+0x468/0x8a0 [f2fs] f2fs_write_data_pages+0x2a4/0x2f0 [f2fs] do_writepages+0x38/0xc0 __writeback_single_inode+0x44/0x2a0 writeback_sb_inodes+0x223/0x4d0 __writeback_inodes_wb+0x56/0xf0 wb_writeback+0x1dd/0x290 wb_workfn+0x309/0x500 process_one_work+0x220/0x3c0 worker_thread+0x53/0x420 kthread+0x12f/0x150 ret_from_fork+0x22/0x30
The root cause is truncate() may race with overwrite as below, so that one reference count left in page can not guarantee the page attaching in mapping tree all the time, after truncation, later find_lock_page() may return NULL pointer.
- prepare_compress_overwrite - f2fs_pagecache_get_page - unlock_page - f2fs_setattr - truncate_setsize - truncate_inode_page - delete_from_page_cache - find_lock_page
Fix this by avoiding referencing updated page.
Fixes: 4c8ff7095bef ("f2fs: support data compression") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/compress.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 146a8eb3891b..b7ab3bdf2259 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -123,19 +123,6 @@ static void f2fs_unlock_rpages(struct compress_ctx *cc, int len) f2fs_drop_rpages(cc, len, true); }
-static void f2fs_put_rpages_mapping(struct address_space *mapping, - pgoff_t start, int len) -{ - int i; - - for (i = 0; i < len; i++) { - struct page *page = find_get_page(mapping, start + i); - - put_page(page); - put_page(page); - } -} - static void f2fs_put_rpages_wbc(struct compress_ctx *cc, struct writeback_control *wbc, bool redirty, int unlock) { @@ -1048,7 +1035,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, }
if (PageUptodate(page)) - unlock_page(page); + f2fs_put_page(page, 1); else f2fs_compress_ctx_add_page(cc, page); } @@ -1058,32 +1045,34 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size, &last_block_in_bio, false, true); + f2fs_put_rpages(cc); f2fs_destroy_compress_ctx(cc); if (ret) - goto release_pages; + goto out; if (bio) f2fs_submit_bio(sbi, bio, DATA);
ret = f2fs_init_compress_ctx(cc); if (ret) - goto release_pages; + goto out; }
for (i = 0; i < cc->cluster_size; i++) { f2fs_bug_on(sbi, cc->rpages[i]);
page = find_lock_page(mapping, start_idx + i); - f2fs_bug_on(sbi, !page); + if (!page) { + /* page can be truncated */ + goto release_and_retry; + }
f2fs_wait_on_page_writeback(page, DATA, true, true); - f2fs_compress_ctx_add_page(cc, page); - f2fs_put_page(page, 0);
if (!PageUptodate(page)) { +release_and_retry: + f2fs_put_rpages(cc); f2fs_unlock_rpages(cc, i + 1); - f2fs_put_rpages_mapping(mapping, start_idx, - cc->cluster_size); f2fs_destroy_compress_ctx(cc); goto retry; } @@ -1115,10 +1104,10 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, }
unlock_pages: + f2fs_put_rpages(cc); f2fs_unlock_rpages(cc, i); -release_pages: - f2fs_put_rpages_mapping(mapping, start_idx, i); f2fs_destroy_compress_ctx(cc); +out: return ret; }
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 8bfbfb0ddd706b1ce2e89259ecc45f192c0ec2bf ]
In f2fs_destroy_compress_ctx(), after f2fs_destroy_compress_ctx(), cc.cluster_idx will be cleared w/ NULL_CLUSTER, f2fs_cluster_blocks() may check wrong cluster metadata, fix it.
Fixes: 4c8ff7095bef ("f2fs: support data compression") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/compress.c | 17 +++++++++-------- fs/f2fs/data.c | 6 +++--- fs/f2fs/f2fs.h | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index b7ab3bdf2259..66dd525a8554 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -151,13 +151,14 @@ int f2fs_init_compress_ctx(struct compress_ctx *cc) return cc->rpages ? 0 : -ENOMEM; }
-void f2fs_destroy_compress_ctx(struct compress_ctx *cc) +void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse) { page_array_free(cc->inode, cc->rpages, cc->cluster_size); cc->rpages = NULL; cc->nr_rpages = 0; cc->nr_cpages = 0; - cc->cluster_idx = NULL_CLUSTER; + if (!reuse) + cc->cluster_idx = NULL_CLUSTER; }
void f2fs_compress_ctx_add_page(struct compress_ctx *cc, struct page *page) @@ -1046,7 +1047,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size, &last_block_in_bio, false, true); f2fs_put_rpages(cc); - f2fs_destroy_compress_ctx(cc); + f2fs_destroy_compress_ctx(cc, true); if (ret) goto out; if (bio) @@ -1073,7 +1074,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, release_and_retry: f2fs_put_rpages(cc); f2fs_unlock_rpages(cc, i + 1); - f2fs_destroy_compress_ctx(cc); + f2fs_destroy_compress_ctx(cc, true); goto retry; } } @@ -1106,7 +1107,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc, unlock_pages: f2fs_put_rpages(cc); f2fs_unlock_rpages(cc, i); - f2fs_destroy_compress_ctx(cc); + f2fs_destroy_compress_ctx(cc, true); out: return ret; } @@ -1142,7 +1143,7 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata, set_cluster_dirty(&cc);
f2fs_put_rpages_wbc(&cc, NULL, false, 1); - f2fs_destroy_compress_ctx(&cc); + f2fs_destroy_compress_ctx(&cc, false);
return first_index; } @@ -1361,7 +1362,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, f2fs_put_rpages(cc); page_array_free(cc->inode, cc->cpages, cc->nr_cpages); cc->cpages = NULL; - f2fs_destroy_compress_ctx(cc); + f2fs_destroy_compress_ctx(cc, false); return 0;
out_destroy_crypt: @@ -1523,7 +1524,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, err = f2fs_write_raw_pages(cc, submitted, wbc, io_type); f2fs_put_rpages_wbc(cc, wbc, false, 0); destroy_out: - f2fs_destroy_compress_ctx(cc); + f2fs_destroy_compress_ctx(cc, false); return err; }
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 4e5257c763d0..8804a5d51380 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2276,7 +2276,7 @@ static int f2fs_mpage_readpages(struct inode *inode, max_nr_pages, &last_block_in_bio, rac != NULL, false); - f2fs_destroy_compress_ctx(&cc); + f2fs_destroy_compress_ctx(&cc, false); if (ret) goto set_error_page; } @@ -2321,7 +2321,7 @@ static int f2fs_mpage_readpages(struct inode *inode, max_nr_pages, &last_block_in_bio, rac != NULL, false); - f2fs_destroy_compress_ctx(&cc); + f2fs_destroy_compress_ctx(&cc, false); } } #endif @@ -3022,7 +3022,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping, } } if (f2fs_compressed_file(inode)) - f2fs_destroy_compress_ctx(&cc); + f2fs_destroy_compress_ctx(&cc, false); #endif if (retry) { index = 0; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index eaf6f62206de..f3fabb1edfe9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3950,7 +3950,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc); void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed); void f2fs_put_page_dic(struct page *page); int f2fs_init_compress_ctx(struct compress_ctx *cc); -void f2fs_destroy_compress_ctx(struct compress_ctx *cc); +void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse); void f2fs_init_compress_info(struct f2fs_sb_info *sbi); int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi); void f2fs_destroy_page_array_cache(struct f2fs_sb_info *sbi);
From: Gautham R. Shenoy ego@linux.vnet.ibm.com
[ Upstream commit 02dbb7246c5bbbbe1607ebdc546ba5c454a664b1 ]
In commit:
9fe1f127b913 ("sched/fair: Merge select_idle_core/cpu()")
in select_idle_cpu(), we check if an idle core is present in the LLC of the target CPU via the flag "has_idle_cores". We look for the idle core in select_idle_cores(). If select_idle_cores() isn't able to find an idle core/CPU, we need to unset the has_idle_cores flag in the LLC of the target to prevent other CPUs from going down this route.
However, the current code is unsetting it in the LLC of the current CPU instead of the target CPU. This patch fixes this issue.
Fixes: 9fe1f127b913 ("sched/fair: Merge select_idle_core/cpu()") Signed-off-by: Gautham R. Shenoy ego@linux.vnet.ibm.com Signed-off-by: Ingo Molnar mingo@kernel.org Reviewed-by: Vincent Guittot vincent.guittot@linaro.org Reviewed-by: Srikar Dronamraju srikar@linux.vnet.ibm.com Acked-by: Mel Gorman mgorman@techsingularity.net Link: https://lore.kernel.org/r/1620746169-13996-1-git-send-email-ego@linux.vnet.i... Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index edcabae5c658..a073a839cd06 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6212,7 +6212,7 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool }
if (has_idle_core) - set_idle_cores(this, false); + set_idle_cores(target, false);
if (sched_feat(SIS_PROP) && !has_idle_core) { time = cpu_clock(this) - time;
From: Sun Ke sunke32@huawei.com
[ Upstream commit 79ebe9110fa458d58f1fceb078e2068d7ad37390 ]
Open /dev/nbdX first, the config_refs will be 1 and the pointers in nbd_device are still null. Disconnect /dev/nbdX, then reference a null recv_workq. The protection by config_refs in nbd_genl_disconnect is useless.
[ 656.366194] BUG: kernel NULL pointer dereference, address: 0000000000000020 [ 656.368943] #PF: supervisor write access in kernel mode [ 656.369844] #PF: error_code(0x0002) - not-present page [ 656.370717] PGD 10cc87067 P4D 10cc87067 PUD 1074b4067 PMD 0 [ 656.371693] Oops: 0002 [#1] SMP [ 656.372242] CPU: 5 PID: 7977 Comm: nbd-client Not tainted 5.11.0-rc5-00040-g76c057c84d28 #1 [ 656.373661] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014 [ 656.375904] RIP: 0010:mutex_lock+0x29/0x60 [ 656.376627] Code: 00 0f 1f 44 00 00 55 48 89 fd 48 83 05 6f d7 fe 08 01 e8 7a c3 ff ff 48 83 05 6a d7 fe 08 01 31 c0 65 48 8b 14 25 00 6d 01 00 <f0> 48 0f b1 55 d [ 656.378934] RSP: 0018:ffffc900005eb9b0 EFLAGS: 00010246 [ 656.379350] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 [ 656.379915] RDX: ffff888104cf2600 RSI: ffffffffaae8f452 RDI: 0000000000000020 [ 656.380473] RBP: 0000000000000020 R08: 0000000000000000 R09: ffff88813bd6b318 [ 656.381039] R10: 00000000000000c7 R11: fefefefefefefeff R12: ffff888102710b40 [ 656.381599] R13: ffffc900005eb9e0 R14: ffffffffb2930680 R15: ffff88810770ef00 [ 656.382166] FS: 00007fdf117ebb40(0000) GS:ffff88813bd40000(0000) knlGS:0000000000000000 [ 656.382806] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 656.383261] CR2: 0000000000000020 CR3: 0000000100c84000 CR4: 00000000000006e0 [ 656.383819] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 656.384370] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 656.384927] Call Trace: [ 656.385111] flush_workqueue+0x92/0x6c0 [ 656.385395] nbd_disconnect_and_put+0x81/0xd0 [ 656.385716] nbd_genl_disconnect+0x125/0x2a0 [ 656.386034] genl_family_rcv_msg_doit.isra.0+0x102/0x1b0 [ 656.386422] genl_rcv_msg+0xfc/0x2b0 [ 656.386685] ? nbd_ioctl+0x490/0x490 [ 656.386954] ? genl_family_rcv_msg_doit.isra.0+0x1b0/0x1b0 [ 656.387354] netlink_rcv_skb+0x62/0x180 [ 656.387638] genl_rcv+0x34/0x60 [ 656.387874] netlink_unicast+0x26d/0x590 [ 656.388162] netlink_sendmsg+0x398/0x6c0 [ 656.388451] ? netlink_rcv_skb+0x180/0x180 [ 656.388750] ____sys_sendmsg+0x1da/0x320 [ 656.389038] ? ____sys_recvmsg+0x130/0x220 [ 656.389334] ___sys_sendmsg+0x8e/0xf0 [ 656.389605] ? ___sys_recvmsg+0xa2/0xf0 [ 656.389889] ? handle_mm_fault+0x1671/0x21d0 [ 656.390201] __sys_sendmsg+0x6d/0xe0 [ 656.390464] __x64_sys_sendmsg+0x23/0x30 [ 656.390751] do_syscall_64+0x45/0x70 [ 656.391017] entry_SYSCALL_64_after_hwframe+0x44/0xa9
To fix it, just add if (nbd->recv_workq) to nbd_disconnect_and_put().
Fixes: e9e006f5fcf2 ("nbd: fix max number of supported devs") Signed-off-by: Sun Ke sunke32@huawei.com Reviewed-by: Josef Bacik josef@toxicpanda.com Link: https://lore.kernel.org/r/20210512114331.1233964-2-sunke32@huawei.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/block/nbd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 4ff71b579cfc..974da561b8e5 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1980,7 +1980,8 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd) * config ref and try to destroy the workqueue from inside the work * queue. */ - flush_workqueue(nbd->recv_workq); + if (nbd->recv_workq) + flush_workqueue(nbd->recv_workq); if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, &nbd->config->runtime_flags)) nbd_config_put(nbd);
From: Nicholas Piggin npiggin@gmail.com
[ Upstream commit 4ec5feec1ad029bdf7d49bc50ccc0c195eeabe93 ]
scv support introduced the notion of code that implicitly soft-masks irqs due to the instruction addresses. This is required because scv enters the kernel with MSR[EE]=1.
If a NMI (including soft-NMI) interrupt hits when we are implicitly soft-masked then its regs->softe does not reflect this because it is derived from the explicit soft mask state (paca->irq_soft_mask). This makes arch_irq_disabled_regs(regs) return false.
This can trigger a warning in the soft-NMI watchdog code (shown below). Fix it by having NMI interrupts set regs->softe to disabled in case of interrupting an implicit soft-masked region.
------------[ cut here ]------------ WARNING: CPU: 41 PID: 1103 at arch/powerpc/kernel/watchdog.c:259 soft_nmi_interrupt+0x3e4/0x5f0 CPU: 41 PID: 1103 Comm: (spawn) Not tainted NIP: c000000000039534 LR: c000000000039234 CTR: c000000000009a00 REGS: c000007fffbcf940 TRAP: 0700 Not tainted MSR: 9000000000021033 <SF,HV,ME,IR,DR,RI,LE> CR: 22042482 XER: 200400ad CFAR: c000000000039260 IRQMASK: 3 GPR00: c000000000039204 c000007fffbcfbe0 c000000001d6c300 0000000000000003 GPR04: 00007ffffa45d078 0000000000000000 0000000000000008 0000000000000020 GPR08: 0000007ffd4e0000 0000000000000000 c000007ffffceb00 7265677368657265 GPR12: 9000000000009033 c000007ffffceb00 00000f7075bf4480 000000000000002a GPR16: 00000f705745a528 00007ffffa45ddd8 00000f70574d0008 0000000000000000 GPR20: 00000f7075c58d70 00000f7057459c38 0000000000000001 0000000000000040 GPR24: 0000000000000000 0000000000000029 c000000001dae058 0000000000000029 GPR28: 0000000000000000 0000000000000800 0000000000000009 c000007fffbcfd60 NIP [c000000000039534] soft_nmi_interrupt+0x3e4/0x5f0 LR [c000000000039234] soft_nmi_interrupt+0xe4/0x5f0 Call Trace: [c000007fffbcfbe0] [c000000000039204] soft_nmi_interrupt+0xb4/0x5f0 (unreliable) [c000007fffbcfcf0] [c00000000000c0e8] soft_nmi_common+0x138/0x1c4 --- interrupt: 900 at end_real_trampolines+0x0/0x1000 NIP: c000000000003000 LR: 00007ca426adb03c CTR: 900000000280f033 REGS: c000007fffbcfd60 TRAP: 0900 MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 44042482 XER: 200400ad CFAR: 00007ca426946020 IRQMASK: 0 GPR00: 00000000000000ad 00007ffffa45d050 00007ca426b07f00 0000000000000035 GPR04: 00007ffffa45d078 0000000000000000 0000000000000008 0000000000000020 GPR08: 0000000000000000 0000000000100000 0000000010000000 00007ffffa45d110 GPR12: 0000000000000001 00007ca426d4e680 00000f7075bf4480 000000000000002a GPR16: 00000f705745a528 00007ffffa45ddd8 00000f70574d0008 0000000000000000 GPR20: 00000f7075c58d70 00000f7057459c38 0000000000000001 0000000000000040 GPR24: 0000000000000000 00000f7057473f68 0000000000000003 000000000000041b GPR28: 00007ffffa45d4c4 0000000000000035 0000000000000000 00000f7057473f68 NIP [c000000000003000] end_real_trampolines+0x0/0x1000 LR [00007ca426adb03c] 0x7ca426adb03c --- interrupt: 900 Instruction dump: 60000000 60000000 60420000 38600001 482b3ae5 60000000 e93f0138 a36d0008 7daa6b78 71290001 7f7907b4 4082fd34 <0fe00000> 4bfffd2c 60420000 ea6100a8 ---[ end trace dc75f67d819779da ]---
Fixes: 118178e62e2e ("powerpc: move NMI entry/exit code into wrapper") Reported-by: Cédric Le Goater clg@kaod.org Signed-off-by: Nicholas Piggin npiggin@gmail.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210503111708.758261-1-npiggin@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/interrupt.h | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h index e8d09a841373..31ed5356590a 100644 --- a/arch/powerpc/include/asm/interrupt.h +++ b/arch/powerpc/include/asm/interrupt.h @@ -138,6 +138,13 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte local_paca->irq_soft_mask = IRQS_ALL_DISABLED; local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+ if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !(regs->msr & MSR_PR) && + regs->nip < (unsigned long)__end_interrupts) { + // Kernel code running below __end_interrupts is + // implicitly soft-masked. + regs->softe = IRQS_ALL_DISABLED; + } + /* Don't do any per-CPU operations until interrupt state is fixed */ #endif /* Allow DEC and PMI to be traced when they are soft-NMI */
From: Ming Lei ming.lei@redhat.com
[ Upstream commit 03f26d8f11403295de445b6e4e0e57ac57755791 ]
In case of shared sbitmap, request won't be held in plug list any more sine commit 32bc15afed04 ("blk-mq: Facilitate a shared sbitmap per tagset"), this way makes request merge from flush plug list & batching submission not possible, so cause performance regression.
Yanhui reports performance regression when running sequential IO test(libaio, 16 jobs, 8 depth for each job) in VM, and the VM disk is emulated with image stored on xfs/megaraid_sas.
Fix the issue by recovering original behavior to allow to hold request in plug list.
Cc: Yanhui Ma yama@redhat.com Cc: John Garry john.garry@huawei.com Cc: Bart Van Assche bvanassche@acm.org Cc: kashyap.desai@broadcom.com Fixes: 32bc15afed04 ("blk-mq: Facilitate a shared sbitmap per tagset") Signed-off-by: Ming Lei ming.lei@redhat.com Link: https://lore.kernel.org/r/20210514022052.1047665-1-ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c index d4d7c1caa439..c0b740be62ad 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2216,8 +2216,9 @@ blk_qc_t blk_mq_submit_bio(struct bio *bio) /* Bypass scheduler for flush requests */ blk_insert_flush(rq); blk_mq_run_hw_queue(data.hctx, true); - } else if (plug && (q->nr_hw_queues == 1 || q->mq_ops->commit_rqs || - !blk_queue_nonrot(q))) { + } else if (plug && (q->nr_hw_queues == 1 || + blk_mq_is_sbitmap_shared(rq->mq_hctx->flags) || + q->mq_ops->commit_rqs || !blk_queue_nonrot(q))) { /* * Use plugging if we have a ->commit_rqs() hook as well, as * we know the driver uses bd->last in a smart fashion.
From: Bart Van Assche bvanassche@acm.org
[ Upstream commit 630ef623ed26c18a457cdc070cf24014e50129c2 ]
If a tag set is shared across request queues (e.g. SCSI LUNs) then the block layer core keeps track of the number of active request queues in tags->active_queues. blk_mq_tag_busy() and blk_mq_tag_idle() update that atomic counter if the hctx flag BLK_MQ_F_TAG_QUEUE_SHARED is set. Make sure that blk_mq_exit_queue() calls blk_mq_tag_idle() before that flag is cleared by blk_mq_del_queue_tag_set().
Cc: Christoph Hellwig hch@infradead.org Cc: Ming Lei ming.lei@redhat.com Cc: Hannes Reinecke hare@suse.com Fixes: 0d2602ca30e4 ("blk-mq: improve support for shared tags maps") Signed-off-by: Bart Van Assche bvanassche@acm.org Reviewed-by: Ming Lei ming.lei@redhat.com Link: https://lore.kernel.org/r/20210513171529.7977-1-bvanassche@acm.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/blk-mq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c index c0b740be62ad..0e120547ccb7 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3270,10 +3270,12 @@ EXPORT_SYMBOL(blk_mq_init_allocated_queue); /* tags can _not_ be used after returning from blk_mq_exit_queue */ void blk_mq_exit_queue(struct request_queue *q) { - struct blk_mq_tag_set *set = q->tag_set; + struct blk_mq_tag_set *set = q->tag_set;
- blk_mq_del_queue_tag_set(q); + /* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */ blk_mq_exit_hw_queues(q, set, set->nr_hw_queues); + /* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */ + blk_mq_del_queue_tag_set(q); }
static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
From: Marcel Hamer marcel@solidxs.se
commit e17b02d4970913233d543c79c9c66e72cac05bdd upstream.
When extcon is used in combination with dwc3, it is assumed that the dwc3 registers are untouched and as such are only configured if VBUS is valid or ID is tied to ground.
In case VBUS is not valid or ID is floating, the registers are not configured as such during driver initialization, causing a wrong default state during boot.
If the registers are not in a default state, because they are for instance touched by a boot loader, this can cause for a kernel error.
Signed-off-by: Marcel Hamer marcel@solidxs.se Link: https://lore.kernel.org/r/20210427122118.1948340-1-marcel@solidxs.se Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-omap.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -437,8 +437,13 @@ static int dwc3_omap_extcon_register(str
if (extcon_get_state(edev, EXTCON_USB) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); + else + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); + if (extcon_get_state(edev, EXTCON_USB_HOST) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + else + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
omap->edev = edev; }
From: Ferry Toth ftoth@exalondelft.nl
commit 04357fafea9c7ed34525eb9680c760245c3bb958 upstream.
On Intel Merrifield LPM is causing host to reset port after a timeout. By disabling LPM entirely this is prevented.
Fixes: 066c09593454 ("usb: dwc3: pci: Enable extcon driver for Intel Merrifield") Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Signed-off-by: Ferry Toth ftoth@exalondelft.nl Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210425150947.5862-1-ftoth@exalondelft.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-pci.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -123,6 +123,7 @@ static const struct property_entry dwc3_ PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), + PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), {} };
From: Maximilian Luz luzmaximilian@gmail.com
commit ca09b1bea63ab83f4cca3a2ae8bc4f597ec28851 upstream.
On some devices (specifically the SC8180x based Surface Pro X with QCOM04A6) HC halt / xhci_halt() times out during boot. Manually binding the xhci-hcd driver at some point later does not exhibit this behavior. To work around this, double XHCI_MAX_HALT_USEC, which also resolves this issue.
Cc: stable@vger.kernel.org Signed-off-by: Maximilian Luz luzmaximilian@gmail.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20210512080816.866037-5-mathias.nyman@linux.intel.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-ext-caps.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -7,8 +7,9 @@ * Author: Sarah Sharp * Some code borrowed from the Linux EHCI driver. */ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) + +/* HC should halt within 16 ms, but use 32 ms as some hosts take longer */ +#define XHCI_MAX_HALT_USEC (32 * 1000) /* HC not running - set to 1 when run/stop bit is cleared. */ #define XHCI_STS_HALT (1<<0)
From: Phil Elwell phil@raspberrypi.com
commit 75a41ce46bae6cbe7d3bb2584eb844291d642874 upstream.
The dwc2 gadget support maps and unmaps DMA buffers as necessary. When mapping and unmapping it uses the direction of the endpoint to select the direction of the DMA transfer, but this fails for Control OUT transfers because the unmap occurs after the endpoint direction has been reversed for the status phase.
A possible solution would be to unmap the buffer before the direction is changed, but a safer, less invasive fix is to remember the buffer direction independently of the endpoint direction.
Fixes: fe0b94abcdf6 ("usb: dwc2: gadget: manage ep0 state in software") Acked-by: Minas Harutyunyan Minas.Harutyunyan@synopsys.com Cc: stable stable@vger.kernel.org Signed-off-by: Phil Elwell phil@raspberrypi.com Link: https://lore.kernel.org/r/20210506112200.2893922-1-phil@raspberrypi.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/gadget.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -112,6 +112,7 @@ struct dwc2_hsotg_req; * @debugfs: File entry for debugfs file for this endpoint. * @dir_in: Set to true if this endpoint is of the IN direction, which * means that it is sending data to the Host. + * @map_dir: Set to the value of dir_in when the DMA buffer is mapped. * @index: The index for the endpoint registers. * @mc: Multi Count - number of transactions per microframe * @interval: Interval for periodic endpoints, in frames or microframes. @@ -161,6 +162,7 @@ struct dwc2_hsotg_ep { unsigned short fifo_index;
unsigned char dir_in; + unsigned char map_dir; unsigned char index; unsigned char mc; u16 interval; --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -422,7 +422,7 @@ static void dwc2_hsotg_unmap_dma(struct { struct usb_request *req = &hs_req->req;
- usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in); + usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->map_dir); }
/* @@ -1242,6 +1242,7 @@ static int dwc2_hsotg_map_dma(struct dwc { int ret;
+ hs_ep->map_dir = hs_ep->dir_in; ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in); if (ret) goto dma_error;
From: Chunfeng Yun chunfeng.yun@mediatek.com
commit 975f94c7d6c306b833628baa9aec3f79db1eb3a1 upstream.
This may happen if the port becomes resume status exactly when usb_port_resume() gets port status, it still need provide a TRSMCRY time before access the device.
CC: stable@vger.kernel.org Reported-by: Tianping Fang tianping.fang@mediatek.com Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com Link: https://lore.kernel.org/r/20210512020738.52961-1-chunfeng.yun@mediatek.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/core/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3593,9 +3593,6 @@ int usb_port_resume(struct usb_device *u * sequence. */ status = hub_port_status(hub, port1, &portstatus, &portchange); - - /* TRSMRCY = 10 msec */ - msleep(10); }
SuspendCleared: @@ -3610,6 +3607,9 @@ int usb_port_resume(struct usb_device *u usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_SUSPEND); } + + /* TRSMRCY = 10 msec */ + msleep(10); }
if (udev->persist_enabled)
From: Zhen Lei thunder.leizhen@huawei.com
commit 0b2b149e918f6dddb4ea53615551bf7bc131f875 upstream.
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: 6dd2565989b4 ("usb: dwc3: add imx8mp dwc3 glue layer driver") Reported-by: Hulk Robot hulkci@huawei.com Acked-by: Felipe Balbi balbi@kernel.org Signed-off-by: Zhen Lei thunder.leizhen@huawei.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210508015310.1627-1-thunder.leizhen@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/dwc3-imx8mp.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/dwc3/dwc3-imx8mp.c +++ b/drivers/usb/dwc3/dwc3-imx8mp.c @@ -167,6 +167,7 @@ static int dwc3_imx8mp_probe(struct plat
dwc3_np = of_get_child_by_name(node, "dwc3"); if (!dwc3_np) { + err = -ENODEV; dev_err(dev, "failed to find dwc3 core child\n"); goto disable_rpm; }
From: Jack Pham jackp@codeaurora.org
commit d1d90dd27254c44d087ad3f8b5b3e4fff0571f45 upstream.
commit 72704f876f50 ("dwc3: gadget: Implement the suspend entry event handler") introduced (nearly 5 years ago!) an interrupt handler for U3/L1-L2 suspend events. The problem is that these events aren't currently enabled in the DEVTEN register so the handler is never even invoked. Fix this simply by enabling the corresponding bit in dwc3_gadget_enable_irq() using the same revision check as found in the handler.
Fixes: 72704f876f50 ("dwc3: gadget: Implement the suspend entry event handler") Acked-by: Felipe Balbi balbi@kernel.org Signed-off-by: Jack Pham jackp@codeaurora.org Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210428090111.3370-1-jackp@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2302,6 +2302,10 @@ static void dwc3_gadget_enable_irq(struc if (DWC3_VER_IS_PRIOR(DWC3, 250A)) reg |= DWC3_DEVTEN_ULSTCNGEN;
+ /* On 2.30a and above this bit enables U3/L2-L1 Suspend Events */ + if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) + reg |= DWC3_DEVTEN_EOPFEN; + dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); }
From: Wesley Cheng wcheng@codeaurora.org
commit 18ffa988dbae69cc6e9949cddd9606f6fe533894 upstream.
If an error is received when issuing a start or update transfer command, the error handler will stop all active requests (including the current USB request), and call dwc3_gadget_giveback() to notify function drivers of the requests which have been stopped. Avoid returning an error for kick transfer during EP queue, to remove duplicate cleanup operations on the request being queued.
Fixes: 8d99087c2db8 ("usb: dwc3: gadget: Properly handle failed kick_transfer") cc: stable@vger.kernel.org Signed-off-by: Wesley Cheng wcheng@codeaurora.org Link: https://lore.kernel.org/r/1620410119-24971-1-git-send-email-wcheng@codeauror... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1676,7 +1676,9 @@ static int __dwc3_gadget_ep_queue(struct } }
- return __dwc3_gadget_kick_transfer(dep); + __dwc3_gadget_kick_transfer(dep); + + return 0; }
static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
From: Kyle Tso kyletso@google.com
commit 2e2b8d15adc2f6ab2d4aa0550e241b9742a436a0 upstream.
After receiving Sink Capabilities Message in GET_SINK_CAP AMS, it is incorrect to call tcpm_pd_handle_state because the Message is expected and the current state is not Ready states. The result of this incorrect operation ends in Soft Reset which is definitely wrong. Simply forwarding to Ready States is enough to finish the AMS.
Fixes: 8dea75e11380 ("usb: typec: tcpm: Protocol Error handling") Reviewed-by: Guenter Roeck linux@roeck-us.net Acked-by: Heikki Krogerus heikki.krogerus@linux.intel.com Signed-off-by: Kyle Tso kyletso@google.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210503171849.2605302-1-kyletso@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/tcpm/tcpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2387,7 +2387,7 @@ static void tcpm_pd_data_request(struct port->nr_sink_caps = cnt; port->sink_cap_done = true; if (port->ams == GET_SINK_CAPABILITIES) - tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0); + tcpm_set_state(port, ready_state(port), 0); /* Unexpected Sink Capabilities */ else tcpm_pd_handle_msg(port,
From: Jack Pham jackp@codeaurora.org
commit 1f4642b72be79757f050924a9b9673b6a02034bc upstream.
commit 4dbc6a4ef06d ("usb: typec: ucsi: save power data objects in PD mode") introduced retrieval of the PDOs when connected to a PD-capable source. But only the first 4 PDOs are received since that is the maximum number that can be fetched at a time given the MESSAGE_IN length limitation (16 bytes). However, as per the PD spec a connected source may advertise up to a maximum of 7 PDOs.
If such a source is connected it's possible the PPM could have negotiated a power contract with one of the PDOs at index greater than 4, and would be reflected in the request data object's (RDO) object position field. This would result in an out-of-bounds access when the rdo_index() is used to index into the src_pdos array in ucsi_psy_get_voltage_now().
With the help of the UBSAN -fsanitize=array-bounds checker enabled this exact issue is revealed when connecting to a PD source adapter that advertise 5 PDOs and the PPM enters a contract having selected the 5th one.
[ 151.545106][ T70] Unexpected kernel BRK exception at EL1 [ 151.545112][ T70] Internal error: BRK handler: f2005512 [#1] PREEMPT SMP ... [ 151.545499][ T70] pc : ucsi_psy_get_prop+0x208/0x20c [ 151.545507][ T70] lr : power_supply_show_property+0xc0/0x328 ... [ 151.545542][ T70] Call trace: [ 151.545544][ T70] ucsi_psy_get_prop+0x208/0x20c [ 151.545546][ T70] power_supply_uevent+0x1a4/0x2f0 [ 151.545550][ T70] dev_uevent+0x200/0x384 [ 151.545555][ T70] kobject_uevent_env+0x1d4/0x7e8 [ 151.545557][ T70] power_supply_changed_work+0x174/0x31c [ 151.545562][ T70] process_one_work+0x244/0x6f0 [ 151.545564][ T70] worker_thread+0x3e0/0xa64
We can resolve this by instead retrieving and storing up to the maximum of 7 PDOs in the con->src_pdos array. This would involve two calls to the GET_PDOS command.
Fixes: 992a60ed0d5e ("usb: typec: ucsi: register with power_supply class") Fixes: 4dbc6a4ef06d ("usb: typec: ucsi: save power data objects in PD mode") Cc: stable@vger.kernel.org Reported-and-tested-by: Subbaraman Narayanamurthy subbaram@codeaurora.org Reviewed-by: Heikki Krogerus heikki.krogerus@linux.intel.com Signed-off-by: Jack Pham jackp@codeaurora.org Link: https://lore.kernel.org/r/20210503074611.30973-1-jackp@codeaurora.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/ucsi/ucsi.c | 41 ++++++++++++++++++++++++++++++++--------- drivers/usb/typec/ucsi/ucsi.h | 6 ++++-- 2 files changed, 36 insertions(+), 11 deletions(-)
--- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -495,7 +495,8 @@ static void ucsi_unregister_altmodes(str } }
-static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner) +static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner, + u32 *pdos, int offset, int num_pdos) { struct ucsi *ucsi = con->ucsi; u64 command; @@ -503,17 +504,39 @@ static void ucsi_get_pdos(struct ucsi_co
command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num); command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); - command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1); + command |= UCSI_GET_PDOS_PDO_OFFSET(offset); + command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1); command |= UCSI_GET_PDOS_SRC_PDOS; - ret = ucsi_send_command(ucsi, command, con->src_pdos, - sizeof(con->src_pdos)); - if (ret < 0) { + ret = ucsi_send_command(ucsi, command, pdos + offset, + num_pdos * sizeof(u32)); + if (ret < 0) dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); + if (ret == 0 && offset == 0) + dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n"); + + return ret; +} + +static void ucsi_get_src_pdos(struct ucsi_connector *con, int is_partner) +{ + int ret; + + /* UCSI max payload means only getting at most 4 PDOs at a time */ + ret = ucsi_get_pdos(con, 1, con->src_pdos, 0, UCSI_MAX_PDOS); + if (ret < 0) return; - } + con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */ - if (ret == 0) - dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n"); + if (con->num_pdos < UCSI_MAX_PDOS) + return; + + /* get the remaining PDOs, if any */ + ret = ucsi_get_pdos(con, 1, con->src_pdos, UCSI_MAX_PDOS, + PDO_MAX_OBJECTS - UCSI_MAX_PDOS); + if (ret < 0) + return; + + con->num_pdos += ret / sizeof(u32); }
static void ucsi_pwr_opmode_change(struct ucsi_connector *con) @@ -522,7 +545,7 @@ static void ucsi_pwr_opmode_change(struc case UCSI_CONSTAT_PWR_OPMODE_PD: con->rdo = con->status.request_data_obj; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD); - ucsi_get_pdos(con, 1); + ucsi_get_src_pdos(con, 1); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: con->rdo = 0; --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -8,6 +8,7 @@ #include <linux/power_supply.h> #include <linux/types.h> #include <linux/usb/typec.h> +#include <linux/usb/pd.h> #include <linux/usb/role.h>
/* -------------------------------------------------------------------------- */ @@ -134,7 +135,9 @@ void ucsi_connector_change(struct ucsi *
/* GET_PDOS command bits */ #define UCSI_GET_PDOS_PARTNER_PDO(_r_) ((u64)(_r_) << 23) +#define UCSI_GET_PDOS_PDO_OFFSET(_r_) ((u64)(_r_) << 24) #define UCSI_GET_PDOS_NUM_PDOS(_r_) ((u64)(_r_) << 32) +#define UCSI_MAX_PDOS (4) #define UCSI_GET_PDOS_SRC_PDOS ((u64)1 << 34)
/* -------------------------------------------------------------------------- */ @@ -302,7 +305,6 @@ struct ucsi {
#define UCSI_MAX_SVID 5 #define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) -#define UCSI_MAX_PDOS (4)
#define UCSI_TYPEC_VSAFE5V 5000 #define UCSI_TYPEC_1_5_CURRENT 1500 @@ -330,7 +332,7 @@ struct ucsi_connector { struct power_supply *psy; struct power_supply_desc psy_desc; u32 rdo; - u32 src_pdos[UCSI_MAX_PDOS]; + u32 src_pdos[PDO_MAX_OBJECTS]; int num_pdos;
struct usb_role_switch *usb_role_sw;
From: Andy Shevchenko andy.shevchenko@gmail.com
commit b9a0866a5bdf6a4643a52872ada6be6184c6f4f2 upstream.
device_for_each_child_node() bumps a reference counting of a returned variable. We have to balance it whenever we return to the caller.
Fixes: c1b0bc2dabfa ("usb: typec: Add support for UCSI interface") Cc: Heikki Krogerus heikki.krogerus@linux.intel.com Reviewed-by: Heikki Krogerus heikki.krogerus@linux.intel.com Signed-off-by: Andy Shevchenko andy.shevchenko@gmail.com Link: https://lore.kernel.org/r/20210504222337.3151726-1-andy.shevchenko@gmail.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/ucsi/ucsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1022,6 +1022,7 @@ static const struct typec_operations ucs .pr_set = ucsi_pr_swap };
+/* Caller must call fwnode_handle_put() after use */ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con) { struct fwnode_handle *fwnode; @@ -1056,7 +1057,7 @@ static int ucsi_register_port(struct ucs command |= UCSI_CONNECTOR_NUMBER(con->num); ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); if (ret < 0) - goto out; + goto out_unlock;
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) cap->data = TYPEC_PORT_DRD; @@ -1174,6 +1175,8 @@ static int ucsi_register_port(struct ucs trace_ucsi_register_port(con->num, &con->status);
out: + fwnode_handle_put(cap->fwnode); +out_unlock: mutex_unlock(&con->lock); return ret; }
From: Abhijeet Rao abhijeet.rao@intel.com
commit b813511135e8b84fa741afdfbab4937919100bef upstream.
In the same way as Intel Tiger Lake TCSS (Type-C Subsystem) the Alder Lake TCSS xHCI needs to be runtime suspended whenever possible to allow the TCSS hardware block to enter D3cold and thus save energy.
Cc: stable@vger.kernel.org Signed-off-by: Abhijeet Rao abhijeet.rao@intel.com Signed-off-by: Nikunj A. Dadhania nikunj.dadhania@intel.com Signed-off-by: Azhar Shaikh azhar.shaikh@intel.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20210512080816.866037-2-mathias.nyman@linux.intel.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -57,6 +57,7 @@ #define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba @@ -243,7 +244,8 @@ static void xhci_pci_quirks(struct devic pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
From: Mathias Nyman mathias.nyman@linux.intel.com
commit 9b6a126ae58d9edfdde2d5f2e87f7615ea5e0155 upstream.
Commit 9ebf30007858 ("xhci: Fix halted endpoint at stop endpoint command completion") in 5.12 changes how cancelled URBs are given back.
To cancel a URB xhci driver needs to stop the endpoint first. To clear a halted endpoint xhci driver needs to reset the endpoint.
In rare cases when an endpoint halt (error) races with a endpoint stop we need to clear the reset before removing, and giving back the cancelled URB.
The above change in 5.12 takes care of this, but it also relies on the reset endpoint completion handler to give back the cancelled URBs.
There are cases when driver refuses to queue reset endpoint commands, for example when a link suddenly goes to an inactive error state. In this case the cancelled URB is never given back.
Fix this by giving back the URB in the stop endpoint if queuing a reset endpoint command fails.
Fixes: 9ebf30007858 ("xhci: Fix halted endpoint at stop endpoint command completion") CC: stable@vger.kernel.org # 5.12 Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20210512080816.866037-3-mathias.nyman@linux.intel.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-ring.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
--- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -863,7 +863,7 @@ done: return ret; }
-static void xhci_handle_halted_endpoint(struct xhci_hcd *xhci, +static int xhci_handle_halted_endpoint(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, unsigned int stream_id, struct xhci_td *td, enum xhci_ep_reset_type reset_type) @@ -876,7 +876,7 @@ static void xhci_handle_halted_endpoint( * Device will be reset soon to recover the link so don't do anything */ if (ep->vdev->flags & VDEV_PORT_ERROR) - return; + return -ENODEV;
/* add td to cancelled list and let reset ep handler take care of it */ if (reset_type == EP_HARD_RESET) { @@ -889,16 +889,18 @@ static void xhci_handle_halted_endpoint(
if (ep->ep_state & EP_HALTED) { xhci_dbg(xhci, "Reset ep command already pending\n"); - return; + return 0; }
err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type); if (err) - return; + return err;
ep->ep_state |= EP_HALTED;
xhci_ring_cmd_db(xhci); + + return 0; }
/* @@ -1015,6 +1017,7 @@ static void xhci_handle_cmd_stop_ep(stru struct xhci_td *td = NULL; enum xhci_ep_reset_type reset_type; struct xhci_command *command; + int err;
if (unlikely(TRB_TO_SUSPEND_PORT(le32_to_cpu(trb->generic.field[3])))) { if (!xhci->devs[slot_id]) @@ -1059,7 +1062,10 @@ static void xhci_handle_cmd_stop_ep(stru td->status = -EPROTO; } /* reset ep, reset handler cleans up cancelled tds */ - xhci_handle_halted_endpoint(xhci, ep, 0, td, reset_type); + err = xhci_handle_halted_endpoint(xhci, ep, 0, td, + reset_type); + if (err) + break; xhci_stop_watchdog_timer_in_irq(xhci, ep); return; case EP_STATE_RUNNING:
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
commit dda32c00c9a0fa103b5d54ef72c477b7aa993679 upstream.
'xhci_urb_enqueue()' is passed a 'mem_flags' argument, because "URBs may be submitted in interrupt context" (see comment related to 'usb_submit_urb()' in 'drivers/usb/core/urb.c')
So this flag should be used in all the calling chain. Up to now, 'xhci_check_maxpacket()' which is only called from 'xhci_urb_enqueue()', uses GFP_KERNEL.
Be safe and pass the mem_flags to this function as well.
Fixes: ddba5cd0aeff ("xhci: Use command structures when queuing commands on the command ring") Cc: stable@vger.kernel.org Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20210512080816.866037-4-mathias.nyman@linux.intel.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1514,7 +1514,7 @@ static int xhci_configure_endpoint(struc * we need to issue an evaluate context command and wait on it. */ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, - unsigned int ep_index, struct urb *urb) + unsigned int ep_index, struct urb *urb, gfp_t mem_flags) { struct xhci_container_ctx *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; @@ -1545,7 +1545,7 @@ static int xhci_check_maxpacket(struct x * changes max packet sizes. */
- command = xhci_alloc_command(xhci, true, GFP_KERNEL); + command = xhci_alloc_command(xhci, true, mem_flags); if (!command) return -ENOMEM;
@@ -1639,7 +1639,7 @@ static int xhci_urb_enqueue(struct usb_h */ if (urb->dev->speed == USB_SPEED_FULL) { ret = xhci_check_maxpacket(xhci, slot_id, - ep_index, urb); + ep_index, urb, mem_flags); if (ret < 0) { xhci_urb_free_priv(urb_priv); urb->hcpriv = NULL;
From: Sandeep Singh sandeep.singh@amd.com
commit 3c128781d8da463761495aaf8898c9ecb4e71528 upstream.
One of AMD xhci controller require reset on resume. Occasionally AMD xhci controller does not respond to Stop endpoint command. Once the issue happens controller goes into bad state and in that case controller needs to be reset.
Cc: stable@vger.kernel.org Signed-off-by: Sandeep Singh sandeep.singh@amd.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20210512080816.866037-6-mathias.nyman@linux.intel.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -167,8 +167,10 @@ static void xhci_pci_quirks(struct devic (pdev->device == 0x15e0 || pdev->device == 0x15e1)) xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
- if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5) + if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5) { xhci->quirks |= XHCI_DISABLE_SPARSE; + xhci->quirks |= XHCI_RESET_ON_RESUME; + }
if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH;
From: Tomasz Duszynski tomasz.duszynski@octakon.com
commit 901f84de0e16bde10a72d7eb2f2eb73fcde8fa1a upstream.
Currently ioctl handlers are removed twice. For the first time during iio_device_unregister() then later on inside iio_device_unregister_eventset() and iio_buffers_free_sysfs_and_mask(). Double free leads to kernel panic.
Fix this by not touching ioctl handlers list directly but rather letting code responsible for registration call the matching cleanup routine itself.
Fixes: 8dedcc3eee3ac ("iio: core: centralize ioctl() calls to the main chardev") Signed-off-by: Tomasz Duszynski tomasz.duszynski@octakon.com Acked-by: Alexandru Ardelean ardeleanalex@gmail.com Cc: Stable@vger.kernel.org Link: https://lore.kernel.org/r/20210423080244.2790-1-tomasz.duszynski@octakon.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/industrialio-core.c | 6 ------ 1 file changed, 6 deletions(-)
--- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1863,9 +1863,6 @@ EXPORT_SYMBOL(__iio_device_register); **/ void iio_device_unregister(struct iio_dev *indio_dev) { - struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); - struct iio_ioctl_handler *h, *t; - cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
mutex_lock(&indio_dev->info_exist_lock); @@ -1876,9 +1873,6 @@ void iio_device_unregister(struct iio_de
indio_dev->info = NULL;
- list_for_each_entry_safe(h, t, &iio_dev_opaque->ioctl_handlers, entry) - list_del(&h->entry); - iio_device_wakeup_eventset(indio_dev); iio_buffer_wakeup_poll(indio_dev);
From: Dmitry Osipenko digetx@gmail.com
commit f73c730774d88a14d7b60feee6d0e13570f99499 upstream.
The raw temperature value is a 16-bit signed integer. The sign casting is missing in the code, which results in a wrong temperature reported by userspace tools, fix it.
Cc: stable@vger.kernel.org Fixes: 3904b28efb2c ("iio: gyro: Add driver for the MPU-3050 gyroscope") Datasheet: https://www.cdiweb.com/datasheets/invensense/mpu-3000a.pdf Tested-by: Maxim Schwalm maxim.schwalm@gmail.com # Asus TF700T Tested-by: Svyatoslav Ryhel clamor95@gmail.com # Asus TF201 Reported-by: Svyatoslav Ryhel clamor95@gmail.com Reviewed-by: Andy Shevchenko Andy.Shevchenko@gmail.com Reviewed-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Dmitry Osipenko digetx@gmail.com Acked-by: Jean-Baptiste Maneyrol jmaneyrol@invensense.com Link: https://lore.kernel.org/r/20210423020959.5023-1-digetx@gmail.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/gyro/mpu3050-core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
--- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -272,7 +272,16 @@ static int mpu3050_read_raw(struct iio_d case IIO_CHAN_INFO_OFFSET: switch (chan->type) { case IIO_TEMP: - /* The temperature scaling is (x+23000)/280 Celsius */ + /* + * The temperature scaling is (x+23000)/280 Celsius + * for the "best fit straight line" temperature range + * of -30C..85C. The 23000 includes room temperature + * offset of +35C, 280 is the precision scale and x is + * the 16-bit signed integer reported by hardware. + * + * Temperature value itself represents temperature of + * the sensor die. + */ *val = 23000; return IIO_VAL_INT; default: @@ -329,7 +338,7 @@ static int mpu3050_read_raw(struct iio_d goto out_read_raw_unlock; }
- *val = be16_to_cpu(raw_val); + *val = (s16)be16_to_cpu(raw_val); ret = IIO_VAL_INT;
goto out_read_raw_unlock;
From: Colin Ian King colin.king@canonical.com
commit af0e1871d79cfbb91f732d2c6fa7558e45c31038 upstream.
The lux_val returned from tsl2583_get_lux can potentially be zero, so check for this to avoid a division by zero and an overflowed gain_trim_val.
Fixes clang scan-build warning:
drivers/iio/light/tsl2583.c:345:40: warning: Either the condition 'lux_val<0' is redundant or there is division by zero at line 345. [zerodivcond]
Fixes: ac4f6eee8fe8 ("staging: iio: TAOS tsl258x: Device driver") Signed-off-by: Colin Ian King colin.king@canonical.com Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/light/tsl2583.c | 8 ++++++++ 1 file changed, 8 insertions(+)
--- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -341,6 +341,14 @@ static int tsl2583_als_calibrate(struct return lux_val; }
+ /* Avoid division by zero of lux_value later on */ + if (lux_val == 0) { + dev_err(&chip->client->dev, + "%s: lux_val of 0 will produce out of range trim_value\n", + __func__); + return -ENODATA; + } + gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target) * chip->als_settings.als_gain_trim) / lux_val); if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
From: Oliver Neukum oneukum@suse.com
commit 18abf874367456540846319574864e6ff32752e2 upstream.
We have a cycle of callbacks scheduling works which submit URBs with those callbacks. This needs to be blocked, stopped and unblocked to untangle the circle.
Signed-off-by: Oliver Neukum oneukum@suse.com Link: https://lore.kernel.org/r/20210426092622.20433-1-oneukum@suse.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/class/cdc-wdm.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
--- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -321,12 +321,23 @@ exit:
}
-static void kill_urbs(struct wdm_device *desc) +static void poison_urbs(struct wdm_device *desc) { /* the order here is essential */ - usb_kill_urb(desc->command); - usb_kill_urb(desc->validity); - usb_kill_urb(desc->response); + usb_poison_urb(desc->command); + usb_poison_urb(desc->validity); + usb_poison_urb(desc->response); +} + +static void unpoison_urbs(struct wdm_device *desc) +{ + /* + * the order here is not essential + * it is symmetrical just to be nice + */ + usb_unpoison_urb(desc->response); + usb_unpoison_urb(desc->validity); + usb_unpoison_urb(desc->command); }
static void free_urbs(struct wdm_device *desc) @@ -741,11 +752,12 @@ static int wdm_release(struct inode *ino if (!desc->count) { if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup\n"); - kill_urbs(desc); + poison_urbs(desc); spin_lock_irq(&desc->iuspin); desc->resp_count = 0; spin_unlock_irq(&desc->iuspin); desc->manage_power(desc->intf, 0); + unpoison_urbs(desc); } else { /* must avoid dev_printk here as desc->intf is invalid */ pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__); @@ -1037,9 +1049,9 @@ static void wdm_disconnect(struct usb_in wake_up_all(&desc->wait); mutex_lock(&desc->rlock); mutex_lock(&desc->wlock); + poison_urbs(desc); cancel_work_sync(&desc->rxwork); cancel_work_sync(&desc->service_outs_intr); - kill_urbs(desc); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock);
@@ -1080,9 +1092,10 @@ static int wdm_suspend(struct usb_interf set_bit(WDM_SUSPENDING, &desc->flags); spin_unlock_irq(&desc->iuspin); /* callback submits work - order is essential */ - kill_urbs(desc); + poison_urbs(desc); cancel_work_sync(&desc->rxwork); cancel_work_sync(&desc->service_outs_intr); + unpoison_urbs(desc); } if (!PMSG_IS_AUTO(message)) { mutex_unlock(&desc->wlock); @@ -1140,7 +1153,7 @@ static int wdm_pre_reset(struct usb_inte wake_up_all(&desc->wait); mutex_lock(&desc->rlock); mutex_lock(&desc->wlock); - kill_urbs(desc); + poison_urbs(desc); cancel_work_sync(&desc->rxwork); cancel_work_sync(&desc->service_outs_intr); return 0; @@ -1151,6 +1164,7 @@ static int wdm_post_reset(struct usb_int struct wdm_device *desc = wdm_find_device(intf); int rv;
+ unpoison_urbs(desc); clear_bit(WDM_OVERFLOW, &desc->flags); clear_bit(WDM_RESETTING, &desc->flags); rv = recover_from_urb_loss(desc);
From: Alexandre Belloni alexandre.belloni@bootlin.com
commit e09784a8a751e539dffc94d43bc917b0ac1e934a upstream.
RTC drivers used to leave .set_alarm() NULL in order to signal the RTC device doesn't support alarms. The drivers are now clearing the RTC_FEATURE_ALARM bit for that purpose in order to keep the rtc_class_ops structure const. So now, .set_alarm() is set unconditionally and this possibly causes the alarmtimer code to select an RTC device that doesn't support alarms.
Test RTC_FEATURE_ALARM instead of relying on ops->set_alarm to determine whether alarms are available.
Fixes: 7ae41220ef58 ("rtc: introduce features bitfield") Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210511014516.563031-1-alexandre.belloni@bootlin.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/time/alarmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -92,7 +92,7 @@ static int alarmtimer_rtc_add_device(str if (rtcdev) return -EBUSY;
- if (!rtc->ops->set_alarm) + if (!test_bit(RTC_FEATURE_ALARM, rtc->features)) return -1; if (!device_may_wakeup(rtc->dev.parent)) return -1;
From: Juergen Gross jgross@suse.com
commit 970655aa9b42461f8394e4457307005bdeee14d9 upstream.
Commit d3eeb1d77c5d0af ("xen/gntdev: use mmu_interval_notifier_insert") introduced an error in gntdev_mmap(): in case the call of mmu_interval_notifier_insert_locked() fails the exit path should not call mmu_interval_notifier_remove(), as this might result in NULL dereferences.
One reason for failure is e.g. a signal pending for the running process.
Fixes: d3eeb1d77c5d0af ("xen/gntdev: use mmu_interval_notifier_insert") Cc: stable@vger.kernel.org Reported-by: Marek Marczykowski-Górecki marmarek@invisiblethingslab.com Tested-by: Marek Marczykowski-Górecki marmarek@invisiblethingslab.com Signed-off-by: Juergen Gross jgross@suse.com Reviewed-by: Luca Fancellu luca.fancellu@arm.com Link: https://lore.kernel.org/r/20210423054038.26696-1-jgross@suse.com Signed-off-by: Juergen Gross jgross@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/xen/gntdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -1017,8 +1017,10 @@ static int gntdev_mmap(struct file *flip err = mmu_interval_notifier_insert_locked( &map->notifier, vma->vm_mm, vma->vm_start, vma->vm_end - vma->vm_start, &gntdev_mmu_ops); - if (err) + if (err) { + map->vma = NULL; goto out_unlock_put; + } } mutex_unlock(&priv->lock);
From: Sean Christopherson seanjc@google.com
commit 85d0011264da24be08ae907d7f29983a597ca9b1 upstream.
Do not advertise emulation support for RDPID if RDTSCP is unsupported. RDPID emulation subtly relies on MSR_TSC_AUX to exist in hardware, as both vmx_get_msr() and svm_get_msr() will return an error if the MSR is unsupported, i.e. ctxt->ops->get_msr() will fail and the emulator will inject a #UD.
Note, RDPID emulation also relies on RDTSCP being enabled in the guest, but this is a KVM bug and will eventually be fixed.
Fixes: fb6d4d340e05 ("KVM: x86: emulate RDPID") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210504171734.1434054-3-seanjc@google.com Reviewed-by: Jim Mattson jmattson@google.com Reviewed-by: Reiji Watanabe reijiw@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/cpuid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -589,7 +589,8 @@ static int __do_cpuid_func_emulated(stru case 7: entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; entry->eax = 0; - entry->ecx = F(RDPID); + if (kvm_cpu_cap_has(X86_FEATURE_RDTSCP)) + entry->ecx = F(RDPID); ++array->nent; default: break;
From: Sean Christopherson seanjc@google.com
commit 2183de4161b90bd3851ccd3910c87b2c9adfc6ed upstream.
Add a dedicated intercept enum for RDPID instead of piggybacking RDTSCP. Unlike VMX's ENABLE_RDTSCP, RDPID is not bound to SVM's RDTSCP intercept.
Fixes: fb6d4d340e05 ("KVM: x86: emulate RDPID") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210504171734.1434054-5-seanjc@google.com Reviewed-by: Jim Mattson jmattson@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/emulate.c | 2 +- arch/x86/kvm/kvm_emulate.h | 1 + arch/x86/kvm/vmx/vmx.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-)
--- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4502,7 +4502,7 @@ static const struct opcode group8[] = { * from the register case of group9. */ static const struct gprefix pfx_0f_c7_7 = { - N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp), + N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdpid), };
--- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -468,6 +468,7 @@ enum x86_intercept { x86_intercept_clgi, x86_intercept_skinit, x86_intercept_rdtscp, + x86_intercept_rdpid, x86_intercept_icebp, x86_intercept_wbinvd, x86_intercept_monitor, --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7391,8 +7391,9 @@ static int vmx_check_intercept(struct kv /* * RDPID causes #UD if disabled through secondary execution controls. * Because it is marked as EmulateOnUD, we need to intercept it here. + * Note, RDPID is hidden behind ENABLE_RDTSCP. */ - case x86_intercept_rdtscp: + case x86_intercept_rdpid: if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_RDTSCP)) { exception->vector = UD_VECTOR; exception->error_code_valid = false;
From: Sean Christopherson seanjc@google.com
commit 36fa06f9ff39f23e03cd8206dc6bbb7711c23be6 upstream.
Allow userspace to enable RDPID for a guest without also enabling RDTSCP. Aside from checking for RDPID support in the obvious flows, VMX also needs to set ENABLE_RDTSCP=1 when RDPID is exposed.
For the record, there is no known scenario where enabling RDPID without RDTSCP is desirable. But, both AMD and Intel architectures allow for the condition, i.e. this is purely to make KVM more architecturally accurate.
Fixes: 41cd02c6f7f6 ("kvm: x86: Expose RDPID in KVM_GET_SUPPORTED_CPUID") Cc: stable@vger.kernel.org Reported-by: Reiji Watanabe reijiw@google.com Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210504171734.1434054-8-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/svm/svm.c | 6 ++++-- arch/x86/kvm/vmx/vmx.c | 27 +++++++++++++++++++++++---- arch/x86/kvm/x86.c | 3 ++- 3 files changed, 29 insertions(+), 7 deletions(-)
--- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2741,7 +2741,8 @@ static int svm_get_msr(struct kvm_vcpu * if (!boot_cpu_has(X86_FEATURE_RDTSCP)) return 1; if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) + !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) && + !guest_cpuid_has(vcpu, X86_FEATURE_RDPID)) return 1; msr_info->data = svm->tsc_aux; break; @@ -2952,7 +2953,8 @@ static int svm_set_msr(struct kvm_vcpu * return 1;
if (!msr->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) + !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) && + !guest_cpuid_has(vcpu, X86_FEATURE_RDPID)) return 1;
/* --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1734,7 +1734,8 @@ static void setup_msrs(struct vcpu_vmx * if (update_transition_efer(vmx)) vmx_setup_uret_msr(vmx, MSR_EFER);
- if (guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDTSCP)) + if (guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDTSCP) || + guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDPID)) vmx_setup_uret_msr(vmx, MSR_TSC_AUX);
vmx_setup_uret_msr(vmx, MSR_IA32_TSX_CTRL); @@ -1933,7 +1934,8 @@ static int vmx_get_msr(struct kvm_vcpu * break; case MSR_TSC_AUX: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) + !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) && + !guest_cpuid_has(vcpu, X86_FEATURE_RDPID)) return 1; goto find_uret_msr; case MSR_IA32_DEBUGCTLMSR: @@ -2230,7 +2232,8 @@ static int vmx_set_msr(struct kvm_vcpu * break; case MSR_TSC_AUX: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) + !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) && + !guest_cpuid_has(vcpu, X86_FEATURE_RDPID)) return 1; /* Check reserved bit, higher 32 bits should be zero */ if ((data >> 32) != 0) @@ -4302,7 +4305,23 @@ static void vmx_compute_secondary_exec_c xsaves_enabled, false); }
- vmx_adjust_sec_exec_feature(vmx, &exec_control, rdtscp, RDTSCP); + /* + * RDPID is also gated by ENABLE_RDTSCP, turn on the control if either + * feature is exposed to the guest. This creates a virtualization hole + * if both are supported in hardware but only one is exposed to the + * guest, but letting the guest execute RDTSCP or RDPID when either one + * is advertised is preferable to emulating the advertised instruction + * in KVM on #UD, and obviously better than incorrectly injecting #UD. + */ + if (cpu_has_vmx_rdtscp()) { + bool rdpid_or_rdtscp_enabled = + guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) || + guest_cpuid_has(vcpu, X86_FEATURE_RDPID); + + vmx_adjust_secondary_exec_control(vmx, &exec_control, + SECONDARY_EXEC_ENABLE_RDTSCP, + rdpid_or_rdtscp_enabled, false); + } vmx_adjust_sec_exec_feature(vmx, &exec_control, invpcid, INVPCID);
vmx_adjust_sec_exec_exiting(vmx, &exec_control, rdrand, RDRAND); --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5864,7 +5864,8 @@ static void kvm_init_msr_list(void) continue; break; case MSR_TSC_AUX: - if (!kvm_cpu_cap_has(X86_FEATURE_RDTSCP)) + if (!kvm_cpu_cap_has(X86_FEATURE_RDTSCP) && + !kvm_cpu_cap_has(X86_FEATURE_RDPID)) continue; break; case MSR_IA32_UMWAIT_CONTROL:
From: Vitaly Kuznetsov vkuznets@redhat.com
commit f5c7e8425f18fdb9bdb7d13340651d7876890329 upstream.
When enlightened VMCS is in use and nested state is migrated with vmx_get_nested_state()/vmx_set_nested_state() KVM can't map evmcs page right away: evmcs gpa is not 'struct kvm_vmx_nested_state_hdr' and we can't read it from VP assist page because userspace may decide to restore HV_X64_MSR_VP_ASSIST_PAGE after restoring nested state (and QEMU, for example, does exactly that). To make sure eVMCS is mapped /vmx_set_nested_state() raises KVM_REQ_GET_NESTED_STATE_PAGES request.
Commit f2c7ef3ba955 ("KVM: nSVM: cancel KVM_REQ_GET_NESTED_STATE_PAGES on nested vmexit") added KVM_REQ_GET_NESTED_STATE_PAGES clearing to nested_vmx_vmexit() to make sure MSR permission bitmap is not switched when an immediate exit from L2 to L1 happens right after migration (caused by a pending event, for example). Unfortunately, in the exact same situation we still need to have eVMCS mapped so nested_sync_vmcs12_to_shadow() reflects changes in VMCS12 to eVMCS.
As a band-aid, restore nested_get_evmcs_page() when clearing KVM_REQ_GET_NESTED_STATE_PAGES in nested_vmx_vmexit(). The 'fix' is far from being ideal as we can't easily propagate possible failures and even if we could, this is most likely already too late to do so. The whole 'KVM_REQ_GET_NESTED_STATE_PAGES' idea for mapping eVMCS after migration seems to be fragile as we diverge too much from the 'native' path when vmptr loading happens on vmx_set_nested_state().
Fixes: f2c7ef3ba955 ("KVM: nSVM: cancel KVM_REQ_GET_NESTED_STATE_PAGES on nested vmexit") Signed-off-by: Vitaly Kuznetsov vkuznets@redhat.com Message-Id: 20210503150854.1144255-2-vkuznets@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/vmx/nested.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)
--- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3100,15 +3100,8 @@ static bool nested_get_evmcs_page(struct nested_vmx_handle_enlightened_vmptrld(vcpu, false);
if (evmptrld_status == EVMPTRLD_VMFAIL || - evmptrld_status == EVMPTRLD_ERROR) { - pr_debug_ratelimited("%s: enlightened vmptrld failed\n", - __func__); - vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; - vcpu->run->internal.suberror = - KVM_INTERNAL_ERROR_EMULATION; - vcpu->run->internal.ndata = 0; + evmptrld_status == EVMPTRLD_ERROR) return false; - } }
return true; @@ -3196,8 +3189,16 @@ static bool nested_get_vmcs12_pages(stru
static bool vmx_get_nested_state_pages(struct kvm_vcpu *vcpu) { - if (!nested_get_evmcs_page(vcpu)) + if (!nested_get_evmcs_page(vcpu)) { + pr_debug_ratelimited("%s: enlightened vmptrld failed\n", + __func__); + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->internal.suberror = + KVM_INTERNAL_ERROR_EMULATION; + vcpu->run->internal.ndata = 0; + return false; + }
if (is_guest_mode(vcpu) && !nested_get_vmcs12_pages(vcpu)) return false; @@ -4424,7 +4425,15 @@ void nested_vmx_vmexit(struct kvm_vcpu * /* trying to cancel vmlaunch/vmresume is a bug */ WARN_ON_ONCE(vmx->nested.nested_run_pending);
- kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); + if (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) { + /* + * KVM_REQ_GET_NESTED_STATE_PAGES is also used to map + * Enlightened VMCS after migration and we still need to + * do that when something is forcing L2->L1 exit prior to + * the first L2 run. + */ + (void)nested_get_evmcs_page(vcpu); + }
/* Service the TLB flush request for L2 before switching to L1. */ if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu))
From: Sean Christopherson seanjc@google.com
commit 8aec21c04caa2000f91cf8822ae0811e4b0c3971 upstream.
Clear KVM's RDPID capability if the ENABLE_RDTSCP secondary exec control is unsupported. Despite being enumerated in a separate CPUID flag, RDPID is bundled under the same VMCS control as RDTSCP and will #UD in VMX non-root if ENABLE_RDTSCP is not enabled.
Fixes: 41cd02c6f7f6 ("kvm: x86: Expose RDPID in KVM_GET_SUPPORTED_CPUID") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210504171734.1434054-2-seanjc@google.com Reviewed-by: Jim Mattson jmattson@google.com Reviewed-by: Reiji Watanabe reijiw@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/vmx/vmx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7352,9 +7352,11 @@ static __init void vmx_set_cpu_caps(void if (!cpu_has_vmx_xsaves()) kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
- /* CPUID 0x80000001 */ - if (!cpu_has_vmx_rdtscp()) + /* CPUID 0x80000001 and 0x7 (RDPID) */ + if (!cpu_has_vmx_rdtscp()) { kvm_cpu_cap_clear(X86_FEATURE_RDTSCP); + kvm_cpu_cap_clear(X86_FEATURE_RDPID); + }
if (cpu_has_vmx_waitpkg()) kvm_cpu_cap_check_and_set(X86_FEATURE_WAITPKG);
From: Sean Christopherson seanjc@google.com
commit 5104d7ffcf24749939bea7fdb5378d186473f890 upstream.
Disable preemption when probing a user return MSR via RDSMR/WRMSR. If the MSR holds a different value per logical CPU, the WRMSR could corrupt the host's value if KVM is preempted between the RDMSR and WRMSR, and then rescheduled on a different CPU.
Opportunistically land the helper in common x86, SVM will use the helper in a future commit.
Fixes: 4be534102624 ("KVM: VMX: Initialize vmx->guest_msrs[] right after allocation") Cc: stable@vger.kernel.org Cc: Xiaoyao Li xiaoyao.li@intel.com Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210504171734.1434054-6-seanjc@google.com Reviewed-by: Jim Mattson jmattson@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/vmx/vmx.c | 5 +---- arch/x86/kvm/x86.c | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-)
--- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1753,6 +1753,7 @@ int kvm_pv_send_ipi(struct kvm *kvm, uns unsigned long icr, int op_64_bit);
void kvm_define_user_return_msr(unsigned index, u32 msr); +int kvm_probe_user_return_msr(u32 msr); int kvm_set_user_return_msr(unsigned index, u64 val, u64 mask);
u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc); --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6914,12 +6914,9 @@ static int vmx_create_vcpu(struct kvm_vc
for (i = 0; i < ARRAY_SIZE(vmx_uret_msrs_list); ++i) { u32 index = vmx_uret_msrs_list[i]; - u32 data_low, data_high; int j = vmx->nr_uret_msrs;
- if (rdmsr_safe(index, &data_low, &data_high) < 0) - continue; - if (wrmsr_safe(index, data_low, data_high) < 0) + if (kvm_probe_user_return_msr(index)) continue;
vmx->guest_uret_msrs[j].slot = i; --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -335,6 +335,22 @@ static void kvm_on_user_return(struct us } }
+int kvm_probe_user_return_msr(u32 msr) +{ + u64 val; + int ret; + + preempt_disable(); + ret = rdmsrl_safe(msr, &val); + if (ret) + goto out; + ret = wrmsrl_safe(msr, val); +out: + preempt_enable(); + return ret; +} +EXPORT_SYMBOL_GPL(kvm_probe_user_return_msr); + void kvm_define_user_return_msr(unsigned slot, u32 msr) { BUG_ON(slot >= KVM_MAX_NR_USER_RETURN_MSRS);
From: Matthew Wilcox (Oracle) willy@infradead.org
commit 9ddb3c14afba8bc5950ed297f02d4ae05ff35cd1 upstream.
32-bit architectures which expect 8-byte alignment for 8-byte integers and need 64-bit DMA addresses (arm, mips, ppc) had their struct page inadvertently expanded in 2019. When the dma_addr_t was added, it forced the alignment of the union to 8 bytes, which inserted a 4 byte gap between 'flags' and the union.
Fix this by storing the dma_addr_t in one or two adjacent unsigned longs. This restores the alignment to that of an unsigned long. We always store the low bits in the first word to prevent the PageTail bit from being inadvertently set on a big endian platform. If that happened, get_user_pages_fast() racing against a page which was freed and reallocated to the page_pool could dereference a bogus compound_head(), which would be hard to trace back to this cause.
Link: https://lkml.kernel.org/r/20210510153211.1504886-1-willy@infradead.org Fixes: c25fff7171be ("mm: add dma_addr_t to struct page") Signed-off-by: Matthew Wilcox (Oracle) willy@infradead.org Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org Acked-by: Jesper Dangaard Brouer brouer@redhat.com Acked-by: Vlastimil Babka vbabka@suse.cz Tested-by: Matteo Croce mcroce@linux.microsoft.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/mm_types.h | 4 ++-- include/net/page_pool.h | 12 +++++++++++- net/core/page_pool.c | 12 +++++++----- 3 files changed, 20 insertions(+), 8 deletions(-)
--- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -97,10 +97,10 @@ struct page { }; struct { /* page_pool used by netstack */ /** - * @dma_addr: might require a 64-bit value even on + * @dma_addr: might require a 64-bit value on * 32-bit architectures. */ - dma_addr_t dma_addr; + unsigned long dma_addr[2]; }; struct { /* slab, slob and slub */ union { --- a/include/net/page_pool.h +++ b/include/net/page_pool.h @@ -198,7 +198,17 @@ static inline void page_pool_recycle_dir
static inline dma_addr_t page_pool_get_dma_addr(struct page *page) { - return page->dma_addr; + dma_addr_t ret = page->dma_addr[0]; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16; + return ret; +} + +static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr) +{ + page->dma_addr[0] = addr; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + page->dma_addr[1] = upper_32_bits(addr); }
static inline bool is_page_pool_compiled_in(void) --- a/net/core/page_pool.c +++ b/net/core/page_pool.c @@ -174,8 +174,10 @@ static void page_pool_dma_sync_for_devic struct page *page, unsigned int dma_sync_size) { + dma_addr_t dma_addr = page_pool_get_dma_addr(page); + dma_sync_size = min(dma_sync_size, pool->p.max_len); - dma_sync_single_range_for_device(pool->p.dev, page->dma_addr, + dma_sync_single_range_for_device(pool->p.dev, dma_addr, pool->p.offset, dma_sync_size, pool->p.dma_dir); } @@ -226,7 +228,7 @@ static struct page *__page_pool_alloc_pa put_page(page); return NULL; } - page->dma_addr = dma; + page_pool_set_dma_addr(page, dma);
if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV) page_pool_dma_sync_for_device(pool, page, pool->p.max_len); @@ -294,13 +296,13 @@ void page_pool_release_page(struct page_ */ goto skip_dma_unmap;
- dma = page->dma_addr; + dma = page_pool_get_dma_addr(page);
- /* When page is unmapped, it cannot be returned our pool */ + /* When page is unmapped, it cannot be returned to our pool */ dma_unmap_page_attrs(pool->p.dev, dma, PAGE_SIZE << pool->p.order, pool->p.dma_dir, DMA_ATTR_SKIP_CPU_SYNC); - page->dma_addr = 0; + page_pool_set_dma_addr(page, 0); skip_dma_unmap: /* This may be the last page returned, releasing the pool, so * it is not safe to reference pool afterwards.
From: Maciej W. Rozycki macro@orcam.me.uk
commit c49f71f60754acbff37505e1d16ca796bf8a8140 upstream.
Our current MIPS platform `__div64_32' handler is inactive, because it is incorrectly only enabled for 64-bit configurations, for which generic `do_div' code does not call it anyway.
The handler is not suitable for being called from there though as it only calculates 32 bits of the quotient under the assumption the 64-bit divident has been suitably reduced. Code for such reduction used to be there, however it has been incorrectly removed with commit c21004cd5b4c ("MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0."), which should have only updated an obsoleted constraint for an inline asm involving $hi and $lo register outputs, while possibly wiring the original MIPS variant of the `do_div' macro as `__div64_32' handler for the generic `do_div' implementation
Correct the handler as follows then:
- Revert most of the commit referred, however retaining the current formatting, except for the final two instructions of the inline asm sequence, which the original commit missed. Omit the original 64-bit parts though.
- Rename the original `do_div' macro to `__div64_32'. Use the combined `x' constraint referring to the MD accumulator as a whole, replacing the original individual `h' and `l' constraints used for $hi and $lo registers respectively, of which `h' has been obsoleted with GCC 4.4. Update surrounding code accordingly.
We have since removed support for GCC versions before 4.9, so no need for a special arrangement here; GCC has supported the `x' constraint since forever anyway, or at least going back to 1991.
- Rename the `__base' local variable in `__div64_32' to `__radix' to avoid a conflict with a local variable in `do_div'.
- Actually enable this code for 32-bit rather than 64-bit configurations by qualifying it with BITS_PER_LONG being 32 instead of 64. Include <asm/bitsperlong.h> for this macro rather than <linux/types.h> as we don't need anything else.
- Finally include <asm-generic/div64.h> last rather than first.
This has passed correctness verification with test_div64 and reduced the module's average execution time down to 1.0668s and 0.2629s from 2.1529s and 0.5647s respectively for an R3400 CPU @40MHz and a 5Kc CPU @160MHz. For a reference 64-bit `do_div' code where we have the DDIVU instruction available to do the whole calculation right away averages at 0.0660s for the latter CPU.
Fixes: c21004cd5b4c ("MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0.") Reported-by: Huacai Chen chenhuacai@kernel.org Signed-off-by: Maciej W. Rozycki macro@orcam.me.uk Cc: stable@vger.kernel.org # v2.6.30+ Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/include/asm/div64.h | 57 ++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 16 deletions(-)
--- a/arch/mips/include/asm/div64.h +++ b/arch/mips/include/asm/div64.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2004 Maciej W. Rozycki + * Copyright (C) 2000, 2004, 2021 Maciej W. Rozycki * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) * * This file is subject to the terms and conditions of the GNU General Public @@ -9,25 +9,18 @@ #ifndef __ASM_DIV64_H #define __ASM_DIV64_H
-#include <asm-generic/div64.h> - -#if BITS_PER_LONG == 64 +#include <asm/bitsperlong.h>
-#include <linux/types.h> +#if BITS_PER_LONG == 32
/* * No traps on overflows for any of these... */
-#define __div64_32(n, base) \ -({ \ +#define do_div64_32(res, high, low, base) ({ \ unsigned long __cf, __tmp, __tmp2, __i; \ unsigned long __quot32, __mod32; \ - unsigned long __high, __low; \ - unsigned long long __n; \ \ - __high = *__n >> 32; \ - __low = __n; \ __asm__( \ " .set push \n" \ " .set noat \n" \ @@ -51,18 +44,50 @@ " subu %0, %0, %z6 \n" \ " addiu %2, %2, 1 \n" \ "3: \n" \ - " bnez %4, 0b\n\t" \ - " srl %5, %1, 0x1f\n\t" \ + " bnez %4, 0b \n" \ + " srl %5, %1, 0x1f \n" \ " .set pop" \ : "=&r" (__mod32), "=&r" (__tmp), \ "=&r" (__quot32), "=&r" (__cf), \ "=&r" (__i), "=&r" (__tmp2) \ - : "Jr" (base), "0" (__high), "1" (__low)); \ + : "Jr" (base), "0" (high), "1" (low)); \ \ - (__n) = __quot32; \ + (res) = __quot32; \ __mod32; \ })
-#endif /* BITS_PER_LONG == 64 */ +#define __div64_32(n, base) ({ \ + unsigned long __upper, __low, __high, __radix; \ + unsigned long long __modquot; \ + unsigned long long __quot; \ + unsigned long long __div; \ + unsigned long __mod; \ + \ + __div = (*n); \ + __radix = (base); \ + \ + __high = __div >> 32; \ + __low = __div; \ + __upper = __high; \ + \ + if (__high) { \ + __asm__("divu $0, %z1, %z2" \ + : "=x" (__modquot) \ + : "Jr" (__high), "Jr" (__radix)); \ + __upper = __modquot >> 32; \ + __high = __modquot; \ + } \ + \ + __mod = do_div64_32(__low, __upper, __low, __radix); \ + \ + __quot = __high; \ + __quot = __quot << 32 | __low; \ + (*n) = __quot; \ + __mod; \ +}) + +#endif /* BITS_PER_LONG == 32 */ + +#include <asm-generic/div64.h>
#endif /* __ASM_DIV64_H */
From: Maciej W. Rozycki macro@orcam.me.uk
commit c1d337d45ec0a802299688e17d568c4e3a585895 upstream.
We already check the high part of the divident against zero to avoid the costly DIVU instruction in that case, needed to reduce the high part of the divident, so we may well check against the divisor instead and set the high part of the quotient to zero right away. We need to treat the high part the divident in that case though as the remainder that would be calculated by the DIVU instruction we avoided.
This has passed correctness verification with test_div64 and reduced the module's average execution time down to 1.0445s and 0.2619s from 1.0668s and 0.2629s respectively for an R3400 CPU @40MHz and a 5Kc CPU @160MHz.
Signed-off-by: Maciej W. Rozycki macro@orcam.me.uk Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/include/asm/div64.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/arch/mips/include/asm/div64.h +++ b/arch/mips/include/asm/div64.h @@ -68,9 +68,11 @@ \ __high = __div >> 32; \ __low = __div; \ - __upper = __high; \ \ - if (__high) { \ + if (__high < __radix) { \ + __upper = __high; \ + __high = 0; \ + } else { \ __asm__("divu $0, %z1, %z2" \ : "=x" (__modquot) \ : "Jr" (__high), "Jr" (__radix)); \
From: Maciej W. Rozycki macro@orcam.me.uk
commit 25ab14cbe9d1b66fda44c71a2db7582a31b6f5cd upstream.
Remove the inline asm with a DIVU instruction from `__div64_32' and use plain C code for the intended DIVMOD calculation instead. GCC is smart enough to know that both the quotient and the remainder are calculated with single DIVU, so with ISAs up to R5 the same instruction is actually produced with overall similar code.
For R6 compiled code will work, but separate DIVU and MODU instructions will be produced, which are also interlocked, so scalar implementations will likely not perform as well as older ISAs with their asynchronous MD unit. Likely still faster then the generic algorithm though.
This removes a compilation error for R6 however where the original DIVU instruction is not supported anymore and the MDU accumulator registers have been removed and consequently GCC complains as to a constraint it cannot find a register for:
In file included from ./include/linux/math.h:5, from ./include/linux/kernel.h:13, from mm/page-writeback.c:15: ./include/linux/math64.h: In function 'div_u64_rem': ./arch/mips/include/asm/div64.h:76:17: error: inconsistent operand constraints in an 'asm' 76 | __asm__("divu $0, %z1, %z2" \ | ^~~~~~~ ./include/asm-generic/div64.h:245:25: note: in expansion of macro '__div64_32' 245 | __rem = __div64_32(&(n), __base); \ | ^~~~~~~~~~ ./include/linux/math64.h:91:22: note: in expansion of macro 'do_div' 91 | *remainder = do_div(dividend, divisor); | ^~~~~~
This has passed correctness verification with test_div64 and reduced the module's average execution time down to 1.0404s from 1.0445s with R3400 @40MHz. The module's MIPS I machine code has also shrunk by 12 bytes or 3 instructions.
Signed-off-by: Maciej W. Rozycki macro@orcam.me.uk Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/include/asm/div64.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
--- a/arch/mips/include/asm/div64.h +++ b/arch/mips/include/asm/div64.h @@ -58,7 +58,6 @@
#define __div64_32(n, base) ({ \ unsigned long __upper, __low, __high, __radix; \ - unsigned long long __modquot; \ unsigned long long __quot; \ unsigned long long __div; \ unsigned long __mod; \ @@ -73,11 +72,8 @@ __upper = __high; \ __high = 0; \ } else { \ - __asm__("divu $0, %z1, %z2" \ - : "=x" (__modquot) \ - : "Jr" (__high), "Jr" (__radix)); \ - __upper = __modquot >> 32; \ - __high = __modquot; \ + __upper = __high % __radix; \ + __high /= __radix; \ } \ \ __mod = do_div64_32(__low, __upper, __low, __radix); \
From: Tony Lindgren tony@atomide.com
commit 3efe7a878a11c13b5297057bfc1e5639ce1241ce upstream.
There is a timer wrap issue on dra7 for the ARM architected timer. In a typical clock configuration the timer fails to wrap after 388 days.
To work around the issue, we need to use timer-ti-dm timers instead.
Let's prepare for adding support for percpu timers by adding a common dmtimer_clkevt_init_common() and call it from dmtimer_clockevent_init(). This patch makes no intentional functional changes.
Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210323074326.28302-2-tony@atomide.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/clocksource/timer-ti-dm-systimer.c | 68 ++++++++++++++++++----------- 1 file changed, 44 insertions(+), 24 deletions(-)
--- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -530,17 +530,17 @@ static void omap_clockevent_unidle(struc writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup); }
-static int __init dmtimer_clockevent_init(struct device_node *np) +static int __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt, + struct device_node *np, + unsigned int features, + const struct cpumask *cpumask, + const char *name, + int rating) { - struct dmtimer_clockevent *clkevt; struct clock_event_device *dev; struct dmtimer_systimer *t; int error;
- clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL); - if (!clkevt) - return -ENOMEM; - t = &clkevt->t; dev = &clkevt->dev;
@@ -548,25 +548,23 @@ static int __init dmtimer_clockevent_ini * We mostly use cpuidle_coupled with ARM local timers for runtime, * so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here. */ - dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - dev->rating = 300; + dev->features = features; + dev->rating = rating; dev->set_next_event = dmtimer_set_next_event; dev->set_state_shutdown = dmtimer_clockevent_shutdown; dev->set_state_periodic = dmtimer_set_periodic; dev->set_state_oneshot = dmtimer_clockevent_shutdown; dev->set_state_oneshot_stopped = dmtimer_clockevent_shutdown; dev->tick_resume = dmtimer_clockevent_shutdown; - dev->cpumask = cpu_possible_mask; + dev->cpumask = cpumask;
dev->irq = irq_of_parse_and_map(np, 0); - if (!dev->irq) { - error = -ENXIO; - goto err_out_free; - } + if (!dev->irq) + return -ENXIO;
error = dmtimer_systimer_setup(np, &clkevt->t); if (error) - goto err_out_free; + return error;
clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ);
@@ -578,32 +576,54 @@ static int __init dmtimer_clockevent_ini writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl);
error = request_irq(dev->irq, dmtimer_clockevent_interrupt, - IRQF_TIMER, "clockevent", clkevt); + IRQF_TIMER, name, clkevt); if (error) goto err_out_unmap;
writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena); writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
- pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n", - of_find_property(np, "ti,timer-alwon", NULL) ? + pr_info("TI gptimer %s: %s%lu Hz at %pOF\n", + name, of_find_property(np, "ti,timer-alwon", NULL) ? "always-on " : "", t->rate, np->parent);
- clockevents_config_and_register(dev, t->rate, - 3, /* Timer internal resynch latency */ + return 0; + +err_out_unmap: + iounmap(t->base); + + return error; +} + +static int __init dmtimer_clockevent_init(struct device_node *np) +{ + struct dmtimer_clockevent *clkevt; + int error; + + clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL); + if (!clkevt) + return -ENOMEM; + + error = dmtimer_clkevt_init_common(clkevt, np, + CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + cpu_possible_mask, "clockevent", + 300); + if (error) + goto err_out_free; + + clockevents_config_and_register(&clkevt->dev, clkevt->t.rate, + 3, /* Timer internal resync latency */ 0xffffffff);
if (of_machine_is_compatible("ti,am33xx") || of_machine_is_compatible("ti,am43")) { - dev->suspend = omap_clockevent_idle; - dev->resume = omap_clockevent_unidle; + clkevt->dev.suspend = omap_clockevent_idle; + clkevt->dev.resume = omap_clockevent_unidle; }
return 0;
-err_out_unmap: - iounmap(t->base); - err_out_free: kfree(clkevt);
From: Tony Lindgren tony@atomide.com
commit 25de4ce5ed02994aea8bc111d133308f6fd62566 upstream.
There is a timer wrap issue on dra7 for the ARM architected timer. In a typical clock configuration the timer fails to wrap after 388 days.
To work around the issue, we need to use timer-ti-dm percpu timers instead.
Let's configure dmtimer3 and 4 as percpu timers by default, and warn about the issue if the dtb is not configured properly.
Let's do this as a single patch so it can be backported to v5.8 and later kernels easily. Note that this patch depends on earlier timer-ti-dm systimer posted mode fixes, and a preparatory clockevent patch "clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue".
For more information, please see the errata for "AM572x Sitara Processors Silicon Revisions 1.1, 2.0":
https://www.ti.com/lit/er/sprz429m/sprz429m.pdf
The concept is based on earlier reference patches done by Tero Kristo and Keerthy.
Cc: Keerthy j-keerthy@ti.com Cc: Tero Kristo kristo@kernel.org Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210323074326.28302-3-tony@atomide.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm/boot/dts/dra7-l4.dtsi | 4 - arch/arm/boot/dts/dra7.dtsi | 20 +++++++ drivers/clocksource/timer-ti-dm-systimer.c | 76 +++++++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 4 files changed, 99 insertions(+), 2 deletions(-)
--- a/arch/arm/boot/dts/dra7-l4.dtsi +++ b/arch/arm/boot/dts/dra7-l4.dtsi @@ -1168,7 +1168,7 @@ }; };
- target-module@34000 { /* 0x48034000, ap 7 46.0 */ + timer3_target: target-module@34000 { /* 0x48034000, ap 7 46.0 */ compatible = "ti,sysc-omap4-timer", "ti,sysc"; reg = <0x34000 0x4>, <0x34010 0x4>; @@ -1195,7 +1195,7 @@ }; };
- target-module@36000 { /* 0x48036000, ap 9 4e.0 */ + timer4_target: target-module@36000 { /* 0x48036000, ap 9 4e.0 */ compatible = "ti,sysc-omap4-timer", "ti,sysc"; reg = <0x36000 0x4>, <0x36010 0x4>; --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -46,6 +46,7 @@
timer { compatible = "arm,armv7-timer"; + status = "disabled"; /* See ARM architected timer wrap erratum i940 */ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, @@ -1241,3 +1242,22 @@ assigned-clock-parents = <&sys_32k_ck>; }; }; + +/* Local timers, see ARM architected timer wrap erratum i940 */ +&timer3_target { + ti,no-reset-on-init; + ti,no-idle; + timer@0 { + assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER3_CLKCTRL 24>; + assigned-clock-parents = <&timer_sys_clk_div>; + }; +}; + +&timer4_target { + ti,no-reset-on-init; + ti,no-idle; + timer@0 { + assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 24>; + assigned-clock-parents = <&timer_sys_clk_div>; + }; +}; --- a/drivers/clocksource/timer-ti-dm-systimer.c +++ b/drivers/clocksource/timer-ti-dm-systimer.c @@ -2,6 +2,7 @@ #include <linux/clk.h> #include <linux/clocksource.h> #include <linux/clockchips.h> +#include <linux/cpuhotplug.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> @@ -630,6 +631,78 @@ err_out_free: return error; }
+/* Dmtimer as percpu timer. See dra7 ARM architected timer wrap erratum i940 */ +static DEFINE_PER_CPU(struct dmtimer_clockevent, dmtimer_percpu_timer); + +static int __init dmtimer_percpu_timer_init(struct device_node *np, int cpu) +{ + struct dmtimer_clockevent *clkevt; + int error; + + if (!cpu_possible(cpu)) + return -EINVAL; + + if (!of_property_read_bool(np->parent, "ti,no-reset-on-init") || + !of_property_read_bool(np->parent, "ti,no-idle")) + pr_warn("Incomplete dtb for percpu dmtimer %pOF\n", np->parent); + + clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu); + + error = dmtimer_clkevt_init_common(clkevt, np, CLOCK_EVT_FEAT_ONESHOT, + cpumask_of(cpu), "percpu-dmtimer", + 500); + if (error) + return error; + + return 0; +} + +/* See TRM for timer internal resynch latency */ +static int omap_dmtimer_starting_cpu(unsigned int cpu) +{ + struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu); + struct clock_event_device *dev = &clkevt->dev; + struct dmtimer_systimer *t = &clkevt->t; + + clockevents_config_and_register(dev, t->rate, 3, ULONG_MAX); + irq_force_affinity(dev->irq, cpumask_of(cpu)); + + return 0; +} + +static int __init dmtimer_percpu_timer_startup(void) +{ + struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, 0); + struct dmtimer_systimer *t = &clkevt->t; + + if (t->sysc) { + cpuhp_setup_state(CPUHP_AP_TI_GP_TIMER_STARTING, + "clockevents/omap/gptimer:starting", + omap_dmtimer_starting_cpu, NULL); + } + + return 0; +} +subsys_initcall(dmtimer_percpu_timer_startup); + +static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa) +{ + struct device_node *arm_timer; + + arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + if (of_device_is_available(arm_timer)) { + pr_warn_once("ARM architected timer wrap issue i940 detected\n"); + return 0; + } + + if (pa == 0x48034000) /* dra7 dmtimer3 */ + return dmtimer_percpu_timer_init(np, 0); + else if (pa == 0x48036000) /* dra7 dmtimer4 */ + return dmtimer_percpu_timer_init(np, 1); + + return 0; +} + /* Clocksource */ static struct dmtimer_clocksource * to_dmtimer_clocksource(struct clocksource *cs) @@ -763,6 +836,9 @@ static int __init dmtimer_systimer_init( if (clockevent == pa) return dmtimer_clockevent_init(np);
+ if (of_machine_is_compatible("ti,dra7")) + return dmtimer_percpu_quirk_init(np, pa); + return 0; }
--- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -135,6 +135,7 @@ enum cpuhp_state { CPUHP_AP_RISCV_TIMER_STARTING, CPUHP_AP_CLINT_TIMER_STARTING, CPUHP_AP_CSKY_TIMER_STARTING, + CPUHP_AP_TI_GP_TIMER_STARTING, CPUHP_AP_HYPERV_TIMER_STARTING, CPUHP_AP_KVM_STARTING, CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
From: Badhri Jagan Sridharan badhri@google.com
commit 374157ff88ae1a7f7927331cbc72c1ec11994e8a upstream.
"usb: typec: tcpm: Address incorrect values of tcpm psy for pps supply" introduced a regression for req_out_volt and req_op_curr calculation.
req_out_volt should consider the newly calculated max voltage instead of previously accepted max voltage by the port partner. Likewise, req_op_curr should consider the newly calculated max current instead of previously accepted max current by the port partner.
Fixes: e3a072022487 ("usb: typec: tcpm: Address incorrect values of tcpm psy for pps supply") Reviewed-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Badhri Jagan Sridharan badhri@google.com Link: https://lore.kernel.org/r/20210415050121.1928298-1-badhri@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/typec/tcpm/tcpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -3145,10 +3145,10 @@ static unsigned int tcpm_pd_select_pps_a port->pps_data.req_max_volt = min(pdo_pps_apdo_max_voltage(src), pdo_pps_apdo_max_voltage(snk)); port->pps_data.req_max_curr = min_pps_apdo_current(src, snk); - port->pps_data.req_out_volt = min(port->pps_data.max_volt, - max(port->pps_data.min_volt, + port->pps_data.req_out_volt = min(port->pps_data.req_max_volt, + max(port->pps_data.req_min_volt, port->pps_data.req_out_volt)); - port->pps_data.req_op_curr = min(port->pps_data.max_curr, + port->pps_data.req_op_curr = min(port->pps_data.req_max_curr, port->pps_data.req_op_curr); }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
commit b4104180a2efb85f55e1ba1407885c9421970338 upstream.
syzbot can trigger the WARN() in init_uevent_argv() which isn't the nicest as the code does properly recover and handle the error. So change the WARN() call to pr_warn() and provide some more information on what the buffer size that was needed.
Link: https://lore.kernel.org/r/20201107082206.GA19079@kroah.com Cc: "Rafael J. Wysocki" rafael@kernel.org Cc: linux-kernel@vger.kernel.org Reported-by: syzbot+92340f7b2b4789907fdb@syzkaller.appspotmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/20210405094852.1348499-1-gregkh@linuxfoundation.or... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- lib/kobject_uevent.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -251,12 +251,13 @@ static int kobj_usermode_filter(struct k
static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem) { + int buffer_size = sizeof(env->buf) - env->buflen; int len;
- len = strlcpy(&env->buf[env->buflen], subsystem, - sizeof(env->buf) - env->buflen); - if (len >= (sizeof(env->buf) - env->buflen)) { - WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n"); + len = strlcpy(&env->buf[env->buflen], subsystem, buffer_size); + if (len >= buffer_size) { + pr_warn("init_uevent_argv: buffer size of %d too small, needed %d\n", + buffer_size, len); return -ENOMEM; }
From: Lv Yunlong lyl2019@mail.ustc.edu.cn
commit ea995218dddba171fecd05496c69617c5ef3c5b8 upstream.
Our code analyzer reported a double free bug.
In gen8_preallocate_top_level_pdp, pde and pde->pt.base are allocated via alloc_pd(vm) with one reference. If pin_pt_dma() failed, pde->pt.base is freed by i915_gem_object_put() with a reference dropped. Then free_pd calls free_px() defined in intel_ppgtt.c, which calls i915_gem_object_put() to put pde->pt.base again.
As pde->pt.base is protected by refcount, so the second put will not free pde->pt.base actually. But, maybe it is better to remove the first put?
Fixes: 82adf901138cc ("drm/i915/gt: Shrink i915_page_directory's slab bucket") Signed-off-by: Lv Yunlong lyl2019@mail.ustc.edu.cn Reviewed-by: Matthew Auld matthew.auld@intel.com Signed-off-by: Matthew Auld matthew.auld@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210426124340.4238-1-lyl2019@... (cherry picked from commit ac69496fe65cca0611d5917b7d232730ff605bc7) Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 1 - 1 file changed, 1 deletion(-)
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -630,7 +630,6 @@ static int gen8_preallocate_top_level_pd
err = pin_pt_dma(vm, pde->pt.base); if (err) { - i915_gem_object_put(pde->pt.base); free_pd(vm, pde); return err; }
From: Kuogee Hsieh khsieh@codeaurora.org
commit d9aa6571b28ba0022de1e48801ff03a1854c7ef2 upstream.
Link status is different from display connected status in the case of something like an Apple dongle where the type-c plug can be connected, and therefore the link is connected, but no sink is connected until an HDMI cable is plugged into the dongle. The sink_count of DPCD of dongle will increase to 1 once an HDMI cable is plugged into the dongle so that display connected status will become true. This checking also apply at pm_resume.
Changes in v4: -- none
Fixes: 94e58e2d06e3 ("drm/msm/dp: reset dp controller only at boot up and pm_resume") Reported-by: Stephen Boyd swboyd@chromium.org Reviewed-by: Stephen Boyd swboyd@chromium.org Tested-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Kuogee Hsieh khsieh@codeaurora.org Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets") Link: https://lore.kernel.org/r/1619048258-8717-2-git-send-email-khsieh@codeaurora... Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/msm/dp/dp_display.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -595,10 +595,8 @@ static int dp_connect_pending_timeout(st mutex_lock(&dp->event_mutex);
state = dp->hpd_state; - if (state == ST_CONNECT_PENDING) { - dp_display_enable(dp, 0); + if (state == ST_CONNECT_PENDING) dp->hpd_state = ST_CONNECTED; - }
mutex_unlock(&dp->event_mutex);
@@ -677,10 +675,8 @@ static int dp_disconnect_pending_timeout mutex_lock(&dp->event_mutex);
state = dp->hpd_state; - if (state == ST_DISCONNECT_PENDING) { - dp_display_disable(dp, 0); + if (state == ST_DISCONNECT_PENDING) dp->hpd_state = ST_DISCONNECTED; - }
mutex_unlock(&dp->event_mutex);
@@ -1279,7 +1275,12 @@ static int dp_pm_resume(struct device *d
status = dp_catalog_link_is_connected(dp->catalog);
- if (status) + /* + * can not declared display is connected unless + * HDMI cable is plugged in and sink_count of + * dongle become 1 + */ + if (status && dp->link->sink_count) dp->dp_display.is_connected = true; else dp->dp_display.is_connected = false;
From: Ville Syrjälä ville.syrjala@linux.intel.com
commit 04d019961fd15de92874575536310243a0d4c5c5 upstream.
We've defined C0DRB3/C1DRB3 as 16 bit registers, so access them as such.
Fixes: 1c8242c3a4b2 ("drm/i915: Use unchecked writes for setting up the fences") Reviewed-by: Chris Wilson chris@chris-wilson.co.uk Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210421153401.13847-3-ville.s... (cherry picked from commit f765a5b48c667bdada5e49d5e0f23f8c0687b21b) Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -670,8 +670,8 @@ static void detect_bit_6_swizzle(struct * banks of memory are paired and unswizzled on the * uneven portion, so leave that as unknown. */ - if (intel_uncore_read(uncore, C0DRB3) == - intel_uncore_read(uncore, C1DRB3)) { + if (intel_uncore_read16(uncore, C0DRB3) == + intel_uncore_read16(uncore, C1DRB3)) { swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; }
From: Tvrtko Ursulin tvrtko.ursulin@intel.com
commit a915fe5e9601c632417ef5261af70788d7d23a8a upstream.
__i915_active_call annotation is required on the retire callback to ensure correct function alignment.
Signed-off-by: Tvrtko Ursulin tvrtko.ursulin@intel.com Fixes: a21ce8ad12d2 ("drm/i915/overlay: Switch to using i915_active tracking") Cc: Chris Wilson chris@chris-wilson.co.uk Cc: Matthew Auld matthew.auld@intel.com Reviewed-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210429083530.849546-1-tvrtko... (cherry picked from commit d8e44e4dd221ee283ea60a6fb87bca08807aa0ab) Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -383,7 +383,7 @@ static void intel_overlay_off_tail(struc i830_overlay_clock_gating(dev_priv, true); }
-static void +__i915_active_call static void intel_overlay_last_flip_retire(struct i915_active *active) { struct intel_overlay *overlay =
From: Stéphane Marchesin marcheu@chromium.org
commit 402be8a101190969fc7ff122d07e262df86e132b upstream.
The retire logic uses the 2 lower bits of the pointer to the retire function to store flags. However, the auto_retire function is not guaranteed to be aligned to a multiple of 4, which causes crashes as we jump to the wrong address, for example like this:
2021-04-24T18:03:53.804300Z WARNING kernel: [ 516.876901] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI 2021-04-24T18:03:53.804310Z WARNING kernel: [ 516.876906] CPU: 7 PID: 146 Comm: kworker/u16:6 Tainted: G U 5.4.105-13595-g3cd84167b2df #1 2021-04-24T18:03:53.804311Z WARNING kernel: [ 516.876907] Hardware name: Google Volteer2/Volteer2, BIOS Google_Volteer2.13672.76.0 02/22/2021 2021-04-24T18:03:53.804312Z WARNING kernel: [ 516.876911] Workqueue: events_unbound active_work 2021-04-24T18:03:53.804313Z WARNING kernel: [ 516.876914] RIP: 0010:auto_retire+0x1/0x20 2021-04-24T18:03:53.804314Z WARNING kernel: [ 516.876916] Code: e8 01 f2 ff ff eb 02 31 db 48 89 d8 5b 5d c3 0f 1f 44 00 00 55 48 89 e5 f0 ff 87 c8 00 00 00 0f 88 ab 47 4a 00 31 c0 5d c3 0f <1f> 44 00 00 55 48 89 e5 f0 ff 8f c8 00 00 00 0f 88 9a 47 4a 00 74 2021-04-24T18:03:53.804319Z WARNING kernel: [ 516.876918] RSP: 0018:ffff9b4d809fbe38 EFLAGS: 00010286 2021-04-24T18:03:53.804320Z WARNING kernel: [ 516.876919] RAX: 0000000000000007 RBX: ffff927915079600 RCX: 0000000000000007 2021-04-24T18:03:53.804320Z WARNING kernel: [ 516.876921] RDX: ffff9b4d809fbe40 RSI: 0000000000000286 RDI: ffff927915079600 2021-04-24T18:03:53.804321Z WARNING kernel: [ 516.876922] RBP: ffff9b4d809fbe68 R08: 8080808080808080 R09: fefefefefefefeff 2021-04-24T18:03:53.804321Z WARNING kernel: [ 516.876924] R10: 0000000000000010 R11: ffffffff92e44bd8 R12: ffff9279150796a0 2021-04-24T18:03:53.804322Z WARNING kernel: [ 516.876925] R13: ffff92791c368180 R14: ffff927915079640 R15: 000000001c867605 2021-04-24T18:03:53.804323Z WARNING kernel: [ 516.876926] FS: 0000000000000000(0000) GS:ffff92791ffc0000(0000) knlGS:0000000000000000 2021-04-24T18:03:53.804323Z WARNING kernel: [ 516.876928] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 2021-04-24T18:03:53.804324Z WARNING kernel: [ 516.876929] CR2: 0000239514955000 CR3: 00000007f82da001 CR4: 0000000000760ee0 2021-04-24T18:03:53.804325Z WARNING kernel: [ 516.876930] PKRU: 55555554 2021-04-24T18:03:53.804325Z WARNING kernel: [ 516.876931] Call Trace: 2021-04-24T18:03:53.804326Z WARNING kernel: [ 516.876935] __active_retire+0x77/0xcf 2021-04-24T18:03:53.804326Z WARNING kernel: [ 516.876939] process_one_work+0x1da/0x394 2021-04-24T18:03:53.804327Z WARNING kernel: [ 516.876941] worker_thread+0x216/0x375 2021-04-24T18:03:53.804327Z WARNING kernel: [ 516.876944] kthread+0x147/0x156 2021-04-24T18:03:53.804335Z WARNING kernel: [ 516.876946] ? pr_cont_work+0x58/0x58 2021-04-24T18:03:53.804335Z WARNING kernel: [ 516.876948] ? kthread_blkcg+0x2e/0x2e 2021-04-24T18:03:53.804336Z WARNING kernel: [ 516.876950] ret_from_fork+0x1f/0x40 2021-04-24T18:03:53.804336Z WARNING kernel: [ 516.876952] Modules linked in: cdc_mbim cdc_ncm cdc_wdm xt_cgroup rfcomm cmac algif_hash algif_skcipher af_alg xt_MASQUERADE uinput snd_soc_rt5682_sdw snd_soc_rt5682 snd_soc_max98373_sdw snd_soc_max98373 snd_soc_rl6231 regmap_sdw snd_soc_sof_sdw snd_soc_hdac_hdmi snd_soc_dmic snd_hda_codec_hdmi snd_sof_pci snd_sof_intel_hda_common intel_ipu6_psys snd_sof_xtensa_dsp soundwire_intel soundwire_generic_allocation soundwire_cadence snd_sof_intel_hda snd_sof snd_soc_hdac_hda snd_soc_acpi_intel_match snd_soc_acpi snd_hda_ext_core soundwire_bus snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core intel_ipu6_isys videobuf2_dma_contig videobuf2_v4l2 videobuf2_common videobuf2_memops mei_hdcp intel_ipu6 ov2740 ov8856 at24 sx9310 dw9768 v4l2_fwnode cros_ec_typec intel_pmc_mux roles acpi_als typec fuse iio_trig_sysfs cros_ec_light_prox cros_ec_lid_angle cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer cros_ec_sensors_ring kfifo_buf industrialio cros_ec_sensorhub 2021-04-24T18:03:53.804337Z WARNING kernel: [ 516.876972] cdc_ether usbnet iwlmvm lzo_rle lzo_compress iwl7000_mac80211 iwlwifi zram cfg80211 r8152 mii btusb btrtl btintel btbcm bluetooth ecdh_generic ecc joydev 2021-04-24T18:03:53.804337Z EMERG kernel: [ 516.879169] gsmi: Log Shutdown Reason 0x03
This change fixes this by aligning the function.
Signed-off-by: Stéphane Marchesin marcheu@chromium.org Fixes: 229007e02d69 ("drm/i915: Wrap i915_active in a simple kreffed struct") Signed-off-by: Tvrtko Ursulin tvrtko.ursulin@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210429031021.1218091-1-march... (cherry picked from commit ca419f407b43cc89942ebc297c7a63d94abbcae4) Signed-off-by: Jani Nikula jani.nikula@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/i915_active.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -1156,7 +1156,8 @@ static int auto_active(struct i915_activ return 0; }
-static void auto_retire(struct i915_active *ref) +__i915_active_call static void +auto_retire(struct i915_active *ref) { i915_active_put(ref); }
From: Paweł Chmiel pawel.mikolaj.chmiel@gmail.com
commit 34138a59b92c1a30649a18ec442d2e61f3bc34dd upstream.
This clock must be always enabled to allow access to any registers in fsys1 CMU. Until proper solution based on runtime PM is applied (similar to what was done for Exynos5433), mark that clock as critical so it won't be disabled.
It was observed on Samsung Galaxy S6 device (based on Exynos7420), where UFS module is probed before pmic used to power that device. In this case defer probe was happening and that clock was disabled by UFS driver, causing whole boot to hang on next CMU access.
Fixes: 753195a749a6 ("clk: samsung: exynos7: Correct CMU_FSYS1 clocks names") Signed-off-by: Paweł Chmiel pawel.mikolaj.chmiel@gmail.com Acked-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/linux-clk/20201024154346.9589-1-pawel.mikolaj.chmiel... [s.nawrocki: Added comment in the code] Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/clk/samsung/clk-exynos7.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -537,8 +537,13 @@ static const struct samsung_gate_clock t GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200", ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0), + /* + * This clock is required for the CMU_FSYS1 registers access, keep it + * enabled permanently until proper runtime PM support is added. + */ GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200", - ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0), + ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT | + CLK_IS_CRITICAL, 0),
GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m", "dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11,
From: Enric Balletbo i Serra enric.balletbo@collabora.com
commit 022b02b4505ecea5eda02b18683531e49f7d8eb7 upstream.
Add the power domains names to the power domain struct so we have meaningful name for every power domain. This also removes the following debugfs error message.
[ 2.242068] debugfs: Directory 'power-domain' with parent 'pm_genpd' already present! [ 2.249949] debugfs: Directory 'power-domain' with parent 'pm_genpd' already present! [ 2.257784] debugfs: Directory 'power-domain' with parent 'pm_genpd' already present! ...
Fixes: 59b644b01cf4 ("soc: mediatek: Add MediaTek SCPSYS power domains") Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Reviewed-by: Hsin-Yi Wang hsinyi@chromium.org Link: https://lore.kernel.org/r/20210225175000.824661-1-enric.balletbo@collabora.c... Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/mediatek/mt8173-pm-domains.h | 10 ++++++++++ drivers/soc/mediatek/mtk-pm-domains.c | 6 +++++- drivers/soc/mediatek/mtk-pm-domains.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-)
--- a/drivers/soc/mediatek/mt8173-pm-domains.h +++ b/drivers/soc/mediatek/mt8173-pm-domains.h @@ -12,24 +12,28 @@
static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { [MT8173_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = PWR_STATUS_VDEC, .ctl_offs = SPM_VDE_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8173_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = PWR_STATUS_VENC, .ctl_offs = SPM_VEN_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = PWR_STATUS_ISP, .ctl_offs = SPM_ISP_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(13, 12), }, [MT8173_POWER_DOMAIN_MM] = { + .name = "mm", .sta_mask = PWR_STATUS_DISP, .ctl_offs = SPM_DIS_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -40,18 +44,21 @@ static const struct scpsys_domain_data s }, }, [MT8173_POWER_DOMAIN_VENC_LT] = { + .name = "venc_lt", .sta_mask = PWR_STATUS_VENC_LT, .ctl_offs = SPM_VEN2_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = PWR_STATUS_AUDIO, .ctl_offs = SPM_AUDIO_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_USB] = { + .name = "usb", .sta_mask = PWR_STATUS_USB, .ctl_offs = SPM_USB_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -59,18 +66,21 @@ static const struct scpsys_domain_data s .caps = MTK_SCPD_ACTIVE_WAKEUP, }, [MT8173_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", .sta_mask = PWR_STATUS_MFG_ASYNC, .ctl_offs = SPM_MFG_ASYNC_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = 0, }, [MT8173_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", .sta_mask = PWR_STATUS_MFG_2D, .ctl_offs = SPM_MFG_2D_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(13, 12), }, [MT8173_POWER_DOMAIN_MFG] = { + .name = "mfg", .sta_mask = PWR_STATUS_MFG, .ctl_offs = SPM_MFG_PWR_CON, .sram_pdn_bits = GENMASK(13, 8), --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -438,7 +438,11 @@ generic_pm_domain *scpsys_add_one_domain goto err_unprepare_subsys_clocks; }
- pd->genpd.name = node->name; + if (!pd->data->name) + pd->genpd.name = node->name; + else + pd->genpd.name = pd->data->name; + pd->genpd.power_off = scpsys_power_off; pd->genpd.power_on = scpsys_power_on;
--- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -76,6 +76,7 @@ struct scpsys_bus_prot_data {
/** * struct scpsys_domain_data - scp domain data for power on/off flow + * @name: The name of the power domain. * @sta_mask: The mask for power on/off status bit. * @ctl_offs: The offset for main power control register. * @sram_pdn_bits: The mask for sram power control bits. @@ -85,6 +86,7 @@ struct scpsys_bus_prot_data { * @bp_smi: bus protection for smi subsystem */ struct scpsys_domain_data { + const char *name; u32 sta_mask; int ctl_offs; u32 sram_pdn_bits;
From: Enric Balletbo i Serra enric.balletbo@collabora.com
commit e57b8112258ed46dff23b49d6e400f54a8dbf1c3 upstream.
Add the power domains names for the mt8183 SoC. This removes the debugfs errors like the following:
debugfs: Directory 'power-domain' with parent 'pm_genpd' already present!
Fixes: eb9fa767fbe1 ("soc: mediatek: pm-domains: Add support for mt8183") Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Reviewed-by: Hsin-Yi Wang hsinyi@chromium.org Link: https://lore.kernel.org/r/20210225175000.824661-2-enric.balletbo@collabora.c... Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/mediatek/mt8183-pm-domains.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
--- a/drivers/soc/mediatek/mt8183-pm-domains.h +++ b/drivers/soc/mediatek/mt8183-pm-domains.h @@ -12,12 +12,14 @@
static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { [MT8183_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = PWR_STATUS_AUDIO, .ctl_offs = 0x0314, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8183_POWER_DOMAIN_CONN] = { + .name = "conn", .sta_mask = PWR_STATUS_CONN, .ctl_offs = 0x032c, .sram_pdn_bits = 0, @@ -28,12 +30,14 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", .sta_mask = PWR_STATUS_MFG_ASYNC, .ctl_offs = 0x0334, .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, }, [MT8183_POWER_DOMAIN_MFG] = { + .name = "mfg", .sta_mask = PWR_STATUS_MFG, .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), @@ -41,18 +45,21 @@ static const struct scpsys_domain_data s .caps = MTK_SCPD_DOMAIN_SUPPLY, }, [MT8183_POWER_DOMAIN_MFG_CORE0] = { + .name = "mfg_core0", .sta_mask = BIT(7), .ctl_offs = 0x034c, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8183_POWER_DOMAIN_MFG_CORE1] = { + .name = "mfg_core1", .sta_mask = BIT(20), .ctl_offs = 0x0310, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8183_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", .sta_mask = PWR_STATUS_MFG_2D, .ctl_offs = 0x0348, .sram_pdn_bits = GENMASK(8, 8), @@ -65,6 +72,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_DISP] = { + .name = "disp", .sta_mask = PWR_STATUS_DISP, .ctl_offs = 0x030c, .sram_pdn_bits = GENMASK(8, 8), @@ -83,6 +91,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_CAM] = { + .name = "cam", .sta_mask = BIT(25), .ctl_offs = 0x0344, .sram_pdn_bits = GENMASK(9, 8), @@ -105,6 +114,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = PWR_STATUS_ISP, .ctl_offs = 0x0308, .sram_pdn_bits = GENMASK(9, 8), @@ -127,6 +137,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = BIT(31), .ctl_offs = 0x0300, .sram_pdn_bits = GENMASK(8, 8), @@ -139,6 +150,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = PWR_STATUS_VENC, .ctl_offs = 0x0304, .sram_pdn_bits = GENMASK(11, 8), @@ -151,6 +163,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_VPU_TOP] = { + .name = "vpu_top", .sta_mask = BIT(26), .ctl_offs = 0x0324, .sram_pdn_bits = GENMASK(8, 8), @@ -177,6 +190,7 @@ static const struct scpsys_domain_data s }, }, [MT8183_POWER_DOMAIN_VPU_CORE0] = { + .name = "vpu_core0", .sta_mask = BIT(27), .ctl_offs = 0x33c, .sram_pdn_bits = GENMASK(11, 8), @@ -194,6 +208,7 @@ static const struct scpsys_domain_data s .caps = MTK_SCPD_SRAM_ISO, }, [MT8183_POWER_DOMAIN_VPU_CORE1] = { + .name = "vpu_core1", .sta_mask = BIT(28), .ctl_offs = 0x0340, .sram_pdn_bits = GENMASK(11, 8),
From: Enric Balletbo i Serra enric.balletbo@collabora.com
commit 3edc01bc53c639b1c98f57e7f1c026aae6a25a62 upstream.
Add the power domains names for the mt8192 SoC.
Fixes: a49d5e7a89d6 ("soc: mediatek: pm-domains: Add support for mt8192") Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Reviewed-by: Hsin-Yi Wang hsinyi@chromium.org Link: https://lore.kernel.org/r/20210225175000.824661-3-enric.balletbo@collabora.c... Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/mediatek/mt8192-pm-domains.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
--- a/drivers/soc/mediatek/mt8192-pm-domains.h +++ b/drivers/soc/mediatek/mt8192-pm-domains.h @@ -12,6 +12,7 @@
static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { [MT8192_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = BIT(21), .ctl_offs = 0x0354, .sram_pdn_bits = GENMASK(8, 8), @@ -24,6 +25,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_CONN] = { + .name = "conn", .sta_mask = PWR_STATUS_CONN, .ctl_offs = 0x0304, .sram_pdn_bits = 0, @@ -45,12 +47,14 @@ static const struct scpsys_domain_data s .caps = MTK_SCPD_KEEP_DEFAULT_OFF, }, [MT8192_POWER_DOMAIN_MFG0] = { + .name = "mfg0", .sta_mask = BIT(2), .ctl_offs = 0x0308, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG1] = { + .name = "mfg1", .sta_mask = BIT(3), .ctl_offs = 0x030c, .sram_pdn_bits = GENMASK(8, 8), @@ -75,36 +79,42 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_MFG2] = { + .name = "mfg2", .sta_mask = BIT(4), .ctl_offs = 0x0310, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG3] = { + .name = "mfg3", .sta_mask = BIT(5), .ctl_offs = 0x0314, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG4] = { + .name = "mfg4", .sta_mask = BIT(6), .ctl_offs = 0x0318, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG5] = { + .name = "mfg5", .sta_mask = BIT(7), .ctl_offs = 0x031c, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG6] = { + .name = "mfg6", .sta_mask = BIT(8), .ctl_offs = 0x0320, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_DISP] = { + .name = "disp", .sta_mask = BIT(20), .ctl_offs = 0x0350, .sram_pdn_bits = GENMASK(8, 8), @@ -133,6 +143,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_IPE] = { + .name = "ipe", .sta_mask = BIT(14), .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), @@ -149,6 +160,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = BIT(12), .ctl_offs = 0x0330, .sram_pdn_bits = GENMASK(8, 8), @@ -165,6 +177,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_ISP2] = { + .name = "isp2", .sta_mask = BIT(13), .ctl_offs = 0x0334, .sram_pdn_bits = GENMASK(8, 8), @@ -181,6 +194,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_MDP] = { + .name = "mdp", .sta_mask = BIT(19), .ctl_offs = 0x034c, .sram_pdn_bits = GENMASK(8, 8), @@ -197,6 +211,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = BIT(17), .ctl_offs = 0x0344, .sram_pdn_bits = GENMASK(8, 8), @@ -213,6 +228,7 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = BIT(15), .ctl_offs = 0x033c, .sram_pdn_bits = GENMASK(8, 8), @@ -229,12 +245,14 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_VDEC2] = { + .name = "vdec2", .sta_mask = BIT(16), .ctl_offs = 0x0340, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM] = { + .name = "cam", .sta_mask = BIT(23), .ctl_offs = 0x035c, .sram_pdn_bits = GENMASK(8, 8), @@ -263,18 +281,21 @@ static const struct scpsys_domain_data s }, }, [MT8192_POWER_DOMAIN_CAM_RAWA] = { + .name = "cam_rawa", .sta_mask = BIT(24), .ctl_offs = 0x0360, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM_RAWB] = { + .name = "cam_rawb", .sta_mask = BIT(25), .ctl_offs = 0x0364, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM_RAWC] = { + .name = "cam_rawc", .sta_mask = BIT(26), .ctl_offs = 0x0368, .sram_pdn_bits = GENMASK(8, 8),
From: Fabio Estevam festevam@gmail.com
commit c2357dd9cbafc8ed37156e32c24884cfa8380b2f upstream.
When building with CONFIG_OF not set, the following clang build warning is seen:
drivers/staging/media/rkvdec/rkvdec.c:967:34: warning: unused variable 'of_rkvdec_match' [-Wunused-const-variable]
Fix the warning by removing the unnecessary of_match_ptr().
Reported-by: kernel test robot lkp@intel.com Fixes: cd33c830448b ("media: rkvdec: Add the rkvdec driver") Signed-off-by: Fabio Estevam festevam@gmail.com Reviewed-by: Ezequiel Garcia ezequiel@collabora.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/media/rkvdec/rkvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -1072,7 +1072,7 @@ static struct platform_driver rkvdec_dri .remove = rkvdec_remove, .driver = { .name = "rkvdec", - .of_match_table = of_match_ptr(of_rkvdec_match), + .of_match_table = of_rkvdec_match, .pm = &rkvdec_pm_ops, }, };
From: Qii Wang qii.wang@mediatek.com
commit 63ce8e3df8f6deca2da52eaf064751ad4018b46e upstream.
There are some omissions in the previous patch about replacing I2C_MAX_FAST_MODE__FREQ with I2C_MAX_FAST_MODE_PLUS_FREQ and need to fix it.
Fixes: b44658e755b5("i2c: mediatek: Send i2c master code at more than 1MHz") Signed-off-by: Qii Wang qii.wang@mediatek.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/i2c/busses/i2c-mt65xx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -564,7 +564,7 @@ static const struct i2c_spec_values *mtk
static int mtk_i2c_max_step_cnt(unsigned int target_speed) { - if (target_speed > I2C_MAX_FAST_MODE_FREQ) + if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) return MAX_HS_STEP_CNT_DIV; else return MAX_STEP_CNT_DIV; @@ -635,7 +635,7 @@ static int mtk_i2c_check_ac_timing(struc if (sda_min > sda_max) return -3;
- if (check_speed > I2C_MAX_FAST_MODE_FREQ) { + if (check_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) { if (i2c->dev_comp->ltiming_adjust) { i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (high_cnt << 8); @@ -850,7 +850,7 @@ static int mtk_i2c_do_transfer(struct mt
control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) & ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); - if ((i2c->speed_hz > I2C_MAX_FAST_MODE_FREQ) || (left_num >= 1)) + if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1)) control_reg |= I2C_CONTROL_RS;
if (i2c->op == I2C_MASTER_WRRD) @@ -1067,7 +1067,8 @@ static int mtk_i2c_transfer(struct i2c_a } }
- if (i2c->auto_restart && num >= 2 && i2c->speed_hz > I2C_MAX_FAST_MODE_FREQ) + if (i2c->auto_restart && num >= 2 && + i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) /* ignore the first restart irq after the master code, * otherwise the first transfer will be discarded. */
From: Niklas Söderlund niklas.soderlund+renesas@ragnatech.se
commit 9468e7b031876935230182628f8d5f216c071784 upstream.
When adding support for V3U (r8a779a0) it was incorrectly recorded it supports four nodes, while in fact it supports five. The fifth node is named TSC0 and breaks the existing naming schema starting at 1. Work around this by separately defining the reg property for V3U and others.
Restore the maximum number of nodes to three for other compatibles as it was before erroneously increasing it for V3U.
Fixes: d7fdfb6541f3be88 ("dt-bindings: thermal: rcar-gen3-thermal: Add r8a779a0 support") Signed-off-by: Niklas Söderlund niklas.soderlund+renesas@ragnatech.se Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210310110716.3297544-1-niklas.soderlund+renesas@... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml | 43 ++++++++-- 1 file changed, 35 insertions(+), 8 deletions(-)
--- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml @@ -28,14 +28,7 @@ properties: - renesas,r8a77980-thermal # R-Car V3H - renesas,r8a779a0-thermal # R-Car V3U
- reg: - minItems: 2 - maxItems: 4 - items: - - description: TSC1 registers - - description: TSC2 registers - - description: TSC3 registers - - description: TSC4 registers + reg: true
interrupts: items: @@ -71,8 +64,25 @@ if: enum: - renesas,r8a779a0-thermal then: + properties: + reg: + minItems: 2 + maxItems: 3 + items: + - description: TSC1 registers + - description: TSC2 registers + - description: TSC3 registers required: - interrupts +else: + properties: + reg: + items: + - description: TSC0 registers + - description: TSC1 registers + - description: TSC2 registers + - description: TSC3 registers + - description: TSC4 registers
additionalProperties: false
@@ -111,3 +121,20 @@ examples: }; }; }; + - | + #include <dt-bindings/clock/r8a779a0-cpg-mssr.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/r8a779a0-sysc.h> + + tsc_r8a779a0: thermal@e6190000 { + compatible = "renesas,r8a779a0-thermal"; + reg = <0xe6190000 0x200>, + <0xe6198000 0x200>, + <0xe61a0000 0x200>, + <0xe61a8000 0x200>, + <0xe61b0000 0x200>; + clocks = <&cpg CPG_MOD 919>; + power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; + resets = <&cpg 919>; + #thermal-sensor-cells = <1>; + };
From: Geert Uytterhoeven geert+renesas@glider.be
commit e86ff34cc44a49aeae2af74444560b17a0a96c78 upstream.
The serial console is located on the Falcon CPU board. Hence move serial console configuration from the main Falcon DTS file to the DTS file that describes the CPU board.
Fixes: 63070d7c2270e8de ("arm64: dts: renesas: Add Renesas Falcon boards support") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Wolfram Sang wsa+renesas@sang-engineering.com Tested-by: Wolfram Sang wsa+renesas@sang-engineering.com Reviewed-by: Niklas Söderlund niklas.soderlund+renesas@ragnatech.se Link: https://lore.kernel.org/r/20210316154705.2433528-2-geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi | 8 ++++++++ arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-)
--- a/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779a0-falcon-cpu.dtsi @@ -12,6 +12,14 @@ model = "Renesas Falcon CPU board"; compatible = "renesas,falcon-cpu", "renesas,r8a779a0";
+ aliases { + serial0 = &scif0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + memory@48000000 { device_type = "memory"; /* first 128MB is reserved for secure area. */ --- a/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts +++ b/arch/arm64/boot/dts/renesas/r8a779a0-falcon.dts @@ -14,11 +14,6 @@
aliases { ethernet0 = &avb0; - serial0 = &scif0; - }; - - chosen { - stdout-path = "serial0:115200n8"; }; };
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
commit 94c34600b6173a2b9dd7d9694a42d86fb8768e62 upstream.
The commit 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy information") has support for DP part of USB3+DP combo PHYs. However this change is not backwards compatible, placing additional requirements onto qcom,sc7180-qmp-usb3-phy and qcom,sdm845-qmp-usb3-phy device nodes (to include separate DP part, etc). However the aforementioned nodes do not inclue DP part, they strictly follow the schema defined in the qcom,qmp-phy.yaml file. Move those compatibles, leaving qcom,qmp-usb3-dp-phy.yaml to describe only real "combo" USB3+DP device nodes.
Fixes: 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy information") Cc: Stephen Boyd swboyd@chromium.org Cc: Sandeep Maheswaram sanm@codeaurora.org Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Acked-by: Rob Herring robh@kernel.org Reviewed-by: Stephen Boyd swboyd@chromium.org Reviewed-by: Bjorn Andersson bjorn.andersson@linaro.org Link: https://lore.kernel.org/r/20210331151614.3810197-2-dmitry.baryshkov@linaro.o... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml | 2 ++ Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-)
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml @@ -25,11 +25,13 @@ properties: - qcom,msm8998-qmp-pcie-phy - qcom,msm8998-qmp-ufs-phy - qcom,msm8998-qmp-usb3-phy + - qcom,sc7180-qmp-usb3-phy - qcom,sc8180x-qmp-ufs-phy - qcom,sc8180x-qmp-usb3-phy - qcom,sdm845-qhp-pcie-phy - qcom,sdm845-qmp-pcie-phy - qcom,sdm845-qmp-ufs-phy + - qcom,sdm845-qmp-usb3-phy - qcom,sdm845-qmp-usb3-uni-phy - qcom,sm8150-qmp-ufs-phy - qcom,sm8150-qmp-usb3-phy --- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml @@ -14,9 +14,7 @@ properties: compatible: enum: - qcom,sc7180-qmp-usb3-dp-phy - - qcom,sc7180-qmp-usb3-phy - qcom,sdm845-qmp-usb3-dp-phy - - qcom,sdm845-qmp-usb3-phy reg: items: - description: Address and length of PHY's USB serdes block.
From: Zhen Lei thunder.leizhen@huawei.com
commit a7277a73984114b38dcb62c8548850800ffe864e upstream.
The compatible strings "mediatek,*" appears two times, remove one of them.
Fixes: e69f5dc623f9 ("dt-bindings: serial: Convert 8250 to json-schema") Signed-off-by: Zhen Lei thunder.leizhen@huawei.com Link: https://lore.kernel.org/r/20210422090857.583-1-thunder.leizhen@huawei.com Signed-off-by: Rob Herring robh@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/serial/8250.yaml | 5 ----- 1 file changed, 5 deletions(-)
--- a/Documentation/devicetree/bindings/serial/8250.yaml +++ b/Documentation/devicetree/bindings/serial/8250.yaml @@ -94,11 +94,6 @@ properties: - mediatek,mt7623-btif - const: mediatek,mtk-btif - items: - - enum: - - mediatek,mt7622-btif - - mediatek,mt7623-btif - - const: mediatek,mtk-btif - - items: - const: mrvl,mmp-uart - const: intel,xscale-uart - items:
From: Geert Uytterhoeven geert+renesas@glider.be
commit 62b3b3660aff66433d71f142ab6ed2baaea25025 upstream.
scripts/checkpatch.pl -f drivers/pci/controller/pcie-rcar-host.c:
WARNING: DT compatible string "renesas,pcie-r8a7779" appears un-documented -- check ./Documentation/devicetree/bindings/ #853: FILE: drivers/pci/controller/pcie-rcar-host.c:853: + { .compatible = "renesas,pcie-r8a7779",
Re-add the compatible value for R-Car H1, which was lost during the json-schema conversion. Make the "resets" property optional on R-Car H1, as it is not present yet on R-Car Gen1 SoCs.
Fixes: 0d69ce3c2c63d4db ("dt-bindings: PCI: rcar-pci-host: Convert bindings to json-schema") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Link: https://lore.kernel.org/r/fb0bb969cd0e5872ab5eac70e070242c0d8a5b81.161970020... Signed-off-by: Rob Herring robh@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/devicetree/bindings/pci/rcar-pci-host.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml +++ b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml @@ -17,6 +17,7 @@ allOf: properties: compatible: oneOf: + - const: renesas,pcie-r8a7779 # R-Car H1 - items: - enum: - renesas,pcie-r8a7742 # RZ/G1H @@ -74,7 +75,16 @@ required: - clocks - clock-names - power-domains - - resets + +if: + not: + properties: + compatible: + contains: + const: renesas,pcie-r8a7779 +then: + required: + - resets
unevaluatedProperties: false
From: Kees Cook keescook@chromium.org
commit 312723a0b34d6d110aa4427a982536bb36ab8471 upstream.
Since debugfs_allow is only set at boot time during __init, make it read-only after being set.
Fixes: a24c6f7bc923 ("debugfs: Add access restriction option") Cc: Peter Enderborg peter.enderborg@sony.com Reviewed-by: Peter Enderborg peter.enderborg@sony.com Signed-off-by: Kees Cook keescook@chromium.org Link: https://lore.kernel.org/r/20210405213959.3079432-1-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/debugfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -35,7 +35,7 @@ static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; -static unsigned int debugfs_allow = DEFAULT_DEBUGFS_ALLOW_BITS; +static unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS;
/* * Don't allow access attributes to be changed whilst the kernel is locked down
From: Arnd Bergmann arnd@arndb.de
commit fcdf3c34b7abdcbb49690c94c7fa6ce224dc9749 upstream.
Using no_printk() for jbd_debug() revealed two warnings:
fs/jbd2/recovery.c: In function 'fc_do_one_pass': fs/jbd2/recovery.c:256:30: error: format '%d' expects a matching 'int' argument [-Werror=format=] 256 | jbd_debug(3, "Processing fast commit blk with seq %d"); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fs/ext4/fast_commit.c: In function 'ext4_fc_replay_add_range': fs/ext4/fast_commit.c:1732:30: error: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Werror=format=] 1732 | jbd_debug(1, "Converting from %d to %d %lld",
The first one was added incorrectly, and was also missing a few newlines in debug output, and the second one happened when the type of an argument changed.
Reported-by: kernel test robot lkp@intel.com Fixes: d556435156b7 ("jbd2: avoid -Wempty-body warnings") Fixes: 6db074618969 ("ext4: use BIT() macro for BH_** state bits") Fixes: 5b849b5f96b4 ("jbd2: fast commit recovery path") Signed-off-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20210409201211.1866633-1-arnd@kernel.org Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/ext4/fast_commit.c | 2 +- fs/jbd2/recovery.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-)
--- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -1736,7 +1736,7 @@ static int ext4_fc_replay_add_range(stru }
/* Range is mapped and needs a state change */ - jbd_debug(1, "Converting from %d to %d %lld", + jbd_debug(1, "Converting from %ld to %d %lld", map.m_flags & EXT4_MAP_UNWRITTEN, ext4_ext_is_unwritten(ex), map.m_pblk); ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c @@ -245,15 +245,14 @@ static int fc_do_one_pass(journal_t *jou return 0;
while (next_fc_block <= journal->j_fc_last) { - jbd_debug(3, "Fast commit replay: next block %ld", + jbd_debug(3, "Fast commit replay: next block %ld\n", next_fc_block); err = jread(&bh, journal, next_fc_block); if (err) { - jbd_debug(3, "Fast commit replay: read error"); + jbd_debug(3, "Fast commit replay: read error\n"); break; }
- jbd_debug(3, "Processing fast commit blk with seq %d"); err = journal->j_fc_replay_callback(journal, bh, pass, next_fc_block - journal->j_fc_first, expected_commit_id);
From: Christoph Hellwig hch@lst.de
commit 53fe2a30bc168db9700e00206d991ff934973cf1 upstream.
Do not call nvme_configure_apst when the controller is not live, given that nvme_configure_apst will fail due the lack of an admin queue when the controller is being torn down and nvme_set_latency_tolerance is called from dev_pm_qos_hide_latency_tolerance.
Fixes: 510a405d945b("nvme: fix memory leak for power latency tolerance") Reported-by: Peng Liu liupeng17@lenovo.com Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Keith Busch kbusch@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/nvme/host/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2681,7 +2681,8 @@ static void nvme_set_latency_tolerance(s
if (ctrl->ps_max_latency_us != latency) { ctrl->ps_max_latency_us = latency; - nvme_configure_apst(ctrl); + if (ctrl->state == NVME_CTRL_LIVE) + nvme_configure_apst(ctrl); } }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
commit a4856e15e58b54977f1c0c0299309ad4d1f13365 upstream.
commit 66c705d07d784 ("SoC: rsnd: add interrupt support for SSI BUSIF buffer") adds __rsnd_ssi_interrupt() checks for BUSIF status, but is using "break" at for loop. This means it is not checking all status. Let's check all BUSIF status.
Fixes: commit 66c705d07d784 ("SoC: rsnd: add interrupt support for SSI BUSIF buffer") Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/874kgh1jsw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/soc/sh/rcar/ssi.c | 2 -- 1 file changed, 2 deletions(-)
--- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -797,7 +797,6 @@ static void __rsnd_ssi_interrupt(struct SSI_SYS_STATUS(i * 2), 0xf << (id * 4)); stop = true; - break; } } break; @@ -815,7 +814,6 @@ static void __rsnd_ssi_interrupt(struct SSI_SYS_STATUS((i * 2) + 1), 0xf << 4); stop = true; - break; } } break;
On 5/17/2021 6:57 AM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels:
Tested-by: Florian Fainelli f.fainelli@gmail.com
On Mon, 17 May 2021 15:57:46 +0200, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.12: 12 builds: 12 pass, 0 fail 28 boots: 28 pass, 0 fail 104 tests: 104 pass, 0 fail
Linux version: 5.12.5-rc1-g8c6ba5015aff Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter jonathanh@nvidia.com
Jon
On 5/17/21 7:57 AM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Tested-by: Shuah Khan skhan@linuxfoundation.org
thanks, -- Shuah
On Mon, 17 May 2021 15:57:46 +0200, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
5.12.5-rc1 Successfully Compiled and booted on my Raspberry PI 4b (8g) (bcm2711)
Tested-by: Fox Chen foxhlchen@gmail.com
On Mon, 17 May 2021 at 19:33, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Tested-by: Linux Kernel Functional Testing lkft@linaro.org
## Build * kernel: 5.12.5-rc1 * git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git * git branch: linux-5.12.y * git commit: 8c6ba5015affe5c570b32cf542f58218e4dfebf1 * git describe: v5.12.4-364-g8c6ba5015aff * test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.12.y/build/v5.12....
## No regressions (compared to v5.12.4)
## Fixes (compared to v5.12.4) * mips, build - clang-10-allnoconfig - clang-10-defconfig - clang-10-tinyconfig - clang-11-allnoconfig - clang-11-defconfig - clang-11-tinyconfig - clang-12-allnoconfig - clang-12-defconfig - clang-12-tinyconfig
## Test result summary total: 76409, pass: 63868, fail: 1049, skip: 10771, xfail: 721,
## Build Summary * arc: 10 total, 10 passed, 0 failed * arm: 193 total, 193 passed, 0 failed * arm64: 27 total, 27 passed, 0 failed * dragonboard-410c: 1 total, 1 passed, 0 failed * hi6220-hikey: 1 total, 1 passed, 0 failed * i386: 26 total, 26 passed, 0 failed * juno-r2: 1 total, 1 passed, 0 failed * mips: 45 total, 45 passed, 0 failed * parisc: 9 total, 9 passed, 0 failed * powerpc: 27 total, 27 passed, 0 failed * riscv: 21 total, 21 passed, 0 failed * s390: 18 total, 18 passed, 0 failed * sh: 18 total, 18 passed, 0 failed * sparc: 9 total, 9 passed, 0 failed * x15: 1 total, 0 passed, 1 failed * x86: 1 total, 1 passed, 0 failed * x86_64: 27 total, 27 passed, 0 failed
## Test suites summary * fwts * igt-gpu-tools * install-android-platform-tools-r2600 * kselftest-android * kselftest-bpf * kselftest-breakpoints * kselftest-capabilities * kselftest-cgroup * kselftest-clone3 * kselftest-core * kselftest-cpu-hotplug * kselftest-cpufreq * kselftest-drivers * kselftest-efivarfs * kselftest-filesystems * kselftest-firmware * kselftest-fpu * kselftest-futex * kselftest-gpio * kselftest-intel_pstate * kselftest-ipc * kselftest-ir * kselftest-kcmp * kselftest-kexec * kselftest-kvm * kselftest-lib * kselftest-livepatch * kselftest-lkdtm * kselftest-membarrier * kselftest-memfd * kselftest-memory-hotplug * kselftest-mincore * kselftest-mount * kselftest-mqueue * kselftest-net * kselftest-netfilter * kselftest-nsfs * kselftest-openat2 * kselftest-pid_namespace * kselftest-pidfd * kselftest-proc * kselftest-pstore * kselftest-ptrace * kselftest-rseq * kselftest-rtc * kselftest-seccomp * kselftest-sigaltstack * kselftest-size * kselftest-splice * kselftest-static_keys * kselftest-sync * kselftest-sysctl * kselftest-timens * kselftest-timers * kselftest-tmpfs * kselftest-tpm2 * kselftest-user * kselftest-vm * kselftest-x86 * kselftest-zram * kunit * kvm-unit-tests * libhugetlbfs * linux-log-parser * ltp-cap_bounds-tests * ltp-commands-tests * ltp-containers-tests * ltp-controllers-tests * ltp-cpuhotplug-tests * ltp-crypto-tests * ltp-cve-tests * ltp-dio-tests * ltp-fcntl-locktests-tests * ltp-filecaps-tests * ltp-fs-tests * ltp-fs_bind-tests * ltp-fs_perms_simple-tests * ltp-fsx-tests * ltp-hugetlb-tests * ltp-io-tests * ltp-ipc-tests * ltp-math-tests * ltp-mm-tests * ltp-nptl-tests * ltp-open-posix-tests * ltp-pty-tests * ltp-sched-tests * ltp-securebits-tests * ltp-syscalls-tests * ltp-tracing-tests * network-basic-tests * packetdrill * perf * rcutorture * ssuite * v4l2-compliance
-- Linaro LKFT https://lkft.linaro.org
On Mon, May 17, 2021 at 03:57:46PM +0200, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.12.5 release. There are 363 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 19 May 2021 14:02:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.12.5-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.12.y and the diffstat can be found below.
thanks,
greg k-h
On Tiger Lake x86_64 kernel: - regression on: [PATCH 5.12 081/363] net: bridge: propagate error code and extack from br_mc_disabled_update - remaining tests ok.
Tested-by: Rudi Heitbaum rudi@heitbaum.com
linux-stable-mirror@lists.linaro.org