This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.9.12-rc1
Likun Gao Likun.Gao@amd.com drm/amdgpu: add rlc iram and dram firmware support
Xiaochen Shen xiaochen.shen@intel.com x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
Xiaochen Shen xiaochen.shen@intel.com x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
Anand K Mistry amistry@google.com x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
Gabriele Paoloni gabriele.paoloni@intel.com x86/mce: Do not overwrite no_way_out if mce_end() fails
Chen Baozi chenbaozi@phytium.com.cn irqchip/exiu: Fix the index of fwspec for IRQ type
Zhang Qilong zhangqilong3@huawei.com usb: gadget: Fix memleak in gadgetfs_fill_super
penghao penghao@uniontech.com USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z TIO built-in usb-audio card
Alan Stern stern@rowland.harvard.edu USB: core: Fix regression in Hercules audio card
Zhang Qilong zhangqilong3@huawei.com usb: gadget: f_midi: Fix memleak in f_midi_alloc
Alan Stern stern@rowland.harvard.edu USB: core: Change %pK for __user pointers to %px
Nathan Chancellor natechancellor@gmail.com spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
Masami Hiramatsu mhiramat@kernel.org perf probe: Fix to die_entrypc() returns error correctly
Namhyung Kim namhyung@kernel.org perf stat: Use proper cpu for shadow stats
Namhyung Kim namhyung@kernel.org perf record: Synthesize cgroup events only if needed
Marc Kleine-Budde mkl@pengutronix.de can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
Marc Kleine-Budde mkl@pengutronix.de can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from request_threaded_irq()'s flags
Yixian Liu liuyixian@huawei.com RDMA/hns: Bugfix for memory window mtpt configuration
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Fix retry_cnt and rnr_cnt when querying QP
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Fix wrong field of SRQ number the device supports
Kaixu Xia kaixuxia@tencent.com platform/x86: toshiba_acpi: Fix the wrong variable assignment
Benjamin Berg bberg@redhat.com platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time
Marc Kleine-Budde mkl@pengutronix.de can: gs_usb: fix endianess problem with candleLight firmware
Matti Hamalainen ccr@tnsp.org drm/nouveau: fix relocations applying logic and a double-free
Min Li min.li.xe@renesas.com ptp: clockmatrix: bug fix for idtcm_strverscmp
Vladimir Oltean vladimir.oltean@nxp.com enetc: Let the hardware auto-advance the taprio base-time of 0
Antonio Borneo antonio.borneo@st.com net: stmmac: fix incorrect merge of patch upstream
Randy Dunlap rdunlap@infradead.org RISC-V: fix barrier() use in <vdso/processor.h>
Anup Patel anup.patel@wdc.com RISC-V: Add missing jump label initialization
Nathan Chancellor natechancellor@gmail.com riscv: Explicitly specify the build id style in vDSO Makefile again
Geert Uytterhoeven geert@linux-m68k.org efi: EFI_EARLYCON should depend on EFI
Ard Biesheuvel ardb@kernel.org efivarfs: revert "fix memory leak in efivarfs_create()"
Amadeusz Sławiński amadeuszx.slawinski@linux.intel.com efi/efivars: Set generic ops before loading SSDT
Dipen Patel dipenp@nvidia.com arm64: tegra: Wrong AON HSP reg property size
Lu Baolu baolu.lu@linux.intel.com x86/tboot: Don't disable swiotlb when iommu is forced on
Rui Miguel Silva rui.silva@linaro.org optee: add writeback to valid memory type
Lijun Pan ljp@linux.ibm.com ibmvnic: enhance resetting status check during module exit
Lijun Pan ljp@linux.ibm.com ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
Lijun Pan ljp@linux.ibm.com ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
Shay Agroskin shayagr@amazon.com net: ena: fix packet's addresses for rx_offset feature
Shay Agroskin shayagr@amazon.com net: ena: set initial DMA width to avoid intel iommu issue
Shay Agroskin shayagr@amazon.com net: ena: handle bad request id in ena_netdev
Krzysztof Kozlowski krzk@kernel.org nfc: s3fwrn5: use signed integer for parsing GPIO numbers
Lincoln Ramsay lincoln.ramsay@opengear.com aquantia: Remove the build_skb path
Joseph Qi joseph.qi@linux.alibaba.com io_uring: fix shift-out-of-bounds when round up cq size
Clark Wang xiaoning.wang@nxp.com spi: imx: fix the unbalanced spi runtime pm management
Manish Narani manish.narani@xilinx.com firmware: xilinx: Fix SD DLL node reset issue
Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com i40e: Fix removing driver while bare-metal VFs pass traffic
Xiongfeng Wang wangxiongfeng2@huawei.com IB/mthca: fix return value of error branch in mthca_init_cq()
Shameer Kolothum shameerali.kolothum.thodi@huawei.com iommu: Check return of __iommu_attach_device()
Stephen Rothwell sfr@canb.auug.org.au powerpc/64s: Fix allnoconfig build since uaccess flush
Lijun Pan ljp@linux.ibm.com ibmvnic: notify peers when failover and migration happen
Lijun Pan ljp@linux.ibm.com ibmvnic: fix call_netdevice_notifiers in do_reset
Jamie Iles jamie@nuviainc.com bonding: wait for sysfs kobject destruction before freeing struct slave
CK Hu ck.hu@mediatek.com drm/mediatek: dsi: Modify horizontal front/back porch byte formula
Julian Wiedmann jwi@linux.ibm.com s390/qeth: fix tear down of async TX buffers
Julian Wiedmann jwi@linux.ibm.com s390/qeth: fix af_iucv notification race
Julian Wiedmann jwi@linux.ibm.com s390/qeth: make af_iucv TX notification call more robust
Ioana Ciornei ioana.ciornei@nxp.com dpaa2-eth: select XGMAC_MDIO for MDIO bus support
Raju Rangoju rajur@chelsio.com cxgb4: fix the panic caused by non smac rewrite
Eric Biggers ebiggers@google.com block/keyslot-manager: prevent crash when num_slots=1
Michael Chan michael.chan@broadcom.com bnxt_en: Release PCI regions when DMA mask setup fails during probe.
Dexuan Cui decui@microsoft.com video: hyperv_fb: Fix the cache type when mapping the VRAM
Zhang Changzhong zhangchangzhong@huawei.com bnxt_en: fix error return code in bnxt_init_board()
Zhang Changzhong zhangchangzhong@huawei.com bnxt_en: fix error return code in bnxt_init_one()
Stanley Chu stanley.chu@mediatek.com scsi: ufs: Fix race between shutdown and runtime resume flow
Marc Kleine-Budde mkl@pengutronix.de ARM: dts: dra76x: m_can: fix order of clocks
Grygorii Strashko grygorii.strashko@ti.com bus: ti-sysc: suppress err msg for timers used as clockevent/source
Arnd Bergmann arnd@arndb.de arch: pgtable: define MAX_POSSIBLE_PHYSMEM_BITS where needed
Bryan O'Donoghue bryan.odonoghue@linaro.org phy: qualcomm: Fix 28 nm Hi-Speed USB PHY OF dependency
Bryan O'Donoghue bryan.odonoghue@linaro.org phy: qualcomm: usb: Fix SuperSpeed PHY OF dependency
Peter Chen peter.chen@nxp.com usb: cdns3: gadget: calculate TD_SIZE based on TD
Peter Chen peter.chen@nxp.com usb: cdns3: gadget: fix some endian issues
Taehee Yoo ap420073@gmail.com batman-adv: set .owner to THIS_MODULE
Qu Wenruo wqu@suse.com btrfs: qgroup: don't commit transaction when we already hold the handle
Collin Walling walling@linux.ibm.com KVM: s390: remove diag318 reset code
Janosch Frank frankja@linux.ibm.com KVM: s390: pv: Mark mm as protected after the set secure parameters and improve cleanup
Avraham Stern avraham.stern@intel.com iwlwifi: mvm: write queue_sync_state only for sync
Emmanuel Grumbach emmanuel.grumbach@intel.com iwlwifi: mvm: properly cancel a session protection for P2P
Emmanuel Grumbach emmanuel.grumbach@intel.com iwlwifi: mvm: use the HOT_SPOT_CMD to cancel an AUX ROC
Marc Zyngier maz@kernel.org phy: tegra: xusb: Fix dangling pointer on probe failure
Tony Lindgren tony@atomide.com ARM: OMAP2+: Manage MPU state properly for omap_enter_idle_coupled()
Tony Lindgren tony@atomide.com bus: ti-sysc: Fix bogus resetdone warning on enable for cpsw
Tony Lindgren tony@atomide.com bus: ti-sysc: Fix reset status check for modules with quirks
Andrew Lunn andrew@lunn.ch net: dsa: mv88e6xxx: Wait for EEPROM done after HW reset
Thomas Gleixner tglx@linutronix.de x86/dumpstack: Do not try to access user space code of other tasks
Laurent Pinchart laurent.pinchart@ideasonboard.com xtensa: uaccess: Add missing __user to strncpy_from_user() prototype
Sami Tolvanen samitolvanen@google.com perf/x86: fix sysfs type mismatches
Boqun Feng boqun.feng@gmail.com lockdep: Put graph lock/unlock under lock_recursion protection
Mike Christie michael.christie@oracle.com scsi: target: iscsi: Fix cmd abort fabric stop race
Lee Duncan lduncan@suse.com scsi: libiscsi: Fix NOP race condition
Sugar Zhang sugar.zhang@rock-chips.com dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
Dmitry Osipenko digetx@gmail.com cpuidle: tegra: Annotate tegra_pm_set_cpu_in_lp2() with RCU_NONIDLE
Mike Christie michael.christie@oracle.com vhost scsi: fix cmd completion race
Mike Christie michael.christie@oracle.com vhost scsi: alloc cmds per vq instead of session
Mike Christie michael.christie@oracle.com vhost: add helper to check if a vq has been setup
Laurent Vivier lvivier@redhat.com vdpasim: fix "mac_pton" undefined error
Jisheng Zhang Jisheng.Zhang@synaptics.com net: stmmac: dwmac_lib: enlarge dma reset timeout
Jens Axboe axboe@kernel.dk io_uring: handle -EOPNOTSUPP on path resolution
Minwoo Im minwoo.im.dev@gmail.com nvme: free sq/cq dbbuf pointers when dbbuf set fails
Jens Axboe axboe@kernel.dk proc: don't allow async path resolution of /proc/self components
Hans de Goede hdegoede@redhat.com HID: Add Logitech Dinovo Edge battery quirk
Hans de Goede hdegoede@redhat.com HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo Edge
Daniel Latypov dlatypov@google.com kunit: fix display of failed expectations for strings
Brian Masney bmasney@redhat.com x86/xen: don't unbind uninitialized lock_kicker_irq
Marc Ferland ferlandm@amotus.ca dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
Chris Ye lzye@google.com HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
Necip Fazil Yildiran fazilyildiran@gmail.com staging: ralink-gdma: fix kconfig dependency bug for DMA_RALINK
Pablo Ceballos pceballos@google.com HID: hid-sensor-hub: Fix issue with devices with no report ID
Hans de Goede hdegoede@redhat.com Input: i8042 - allow insmod to succeed on devices without an i8042 controller
Jiri Kosina jkosina@suse.cz HID: add support for Sega Saturn
Frank Yang puilp0502@gmail.com HID: cypress: Support Varmilo Keyboards' media hotkeys
Hans de Goede hdegoede@redhat.com HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
Martijn van de Streek martijn@zeewinde.xyz HID: uclogic: Add ID for Trust Flex Design Tablet
Rodrigo Siqueira Rodrigo.Siqueira@amd.com drm/amd/display: Avoid HDCP initialization in devices without output
Kenneth Feng kenneth.feng@amd.com drm/amd/amdgpu: fix null pointer in runtime pm
Likun Gao Likun.Gao@amd.com drm/amdgpu: update golden setting for sienna_cichlid
Sonny Jiang sonny.jiang@amd.com drm/amdgpu: fix a page fault
Will Deacon will@kernel.org arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
Will Deacon will@kernel.org arm64: pgtable: Fix pte_accessible()
JC Kuo jckuo@nvidia.com arm64: tegra: Fix USB_VBUS_EN0 regulator on Jetson TX1
Jon Hunter jonathanh@nvidia.com arm64: tegra: Correct the UART for Jetson Xavier NX
Hui Su sh_def@163.com trace: fix potenial dangerous pointer
Pavel Begunkov asml.silence@gmail.com io_uring: fix ITER_BVEC check
Sonny Jiang sonny.jiang@amd.com drm/amdgpu: fix SI UVD firmware validate resume fail
Amit Sunil Dhamne amit.sunil.dhamne@xilinx.com firmware: xilinx: Use hash-table for api feature check
David Woodhouse dwmw@amazon.co.uk iommu/vt-d: Don't read VCCAP register unless it exists
Paolo Bonzini pbonzini@redhat.com KVM: x86: Fix split-irqchip vs interrupt injection window request
Paolo Bonzini pbonzini@redhat.com KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
Zenghui Yu yuzenghui@huawei.com KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace
Cédric Le Goater clg@kaod.org KVM: PPC: Book3S HV: XIVE: Fix possible oops when accessing ESB page
Nicholas Piggin npiggin@gmail.com powerpc/64s/exception: KVM Fix for host DSI being taken in HPT guest MMU context
Nicholas Piggin npiggin@gmail.com powerpc/64s: Fix KVM system reset handling when CONFIG_PPC_PSERIES=y
Namjae Jeon namjae.jeon@samsung.com cifs: fix a memleak with modefromsid
Rohith Surabattula rohiths@microsoft.com smb3: Handle error case during offload read path
Rohith Surabattula rohiths@microsoft.com smb3: Avoid Mid pending list corruption
Rohith Surabattula rohiths@microsoft.com smb3: Call cifs reconnect from demultiplex thread
Hugh Dickins hughd@google.com mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)
Sven Schnelle svens@linux.ibm.com s390: fix fpu restore in entry.S
Biwen Li biwen.li@nxp.com rtc: pcf2127: fix a bug when not specify interrupts property
Filipe Manana fdmanana@suse.com btrfs: fix lockdep splat when reading qgroup config on mount
Johannes Thumshirn johannes.thumshirn@wdc.com btrfs: don't access possibly stale fs_info data for printing duplicate device
David Sterba dsterba@suse.com btrfs: tree-checker: add missing returns after data_ref alignment checks
Daniel Xu dxu@dxuuu.xyz btrfs: tree-checker: add missing return after error in root_item
Filipe Manana fdmanana@suse.com btrfs: fix missing delalloc new bit for new delalloc ranges
Shiraz Saleem shiraz.saleem@intel.com RDMA/i40iw: Address an mmap handler exploit in i40iw
Dennis Dalessandro dennis.dalessandro@cornelisnetworks.com IB/hfi1: Ensure correct mm is used at all times
Florian Klink flokli@flokli.de ipv4: use IS_ENABLED instead of ifdef
Lukas Wunner lukas@wunner.de spi: bcm2835: Fix use-after-free on unbind
Lukas Wunner lukas@wunner.de spi: bcm-qspi: Fix use-after-free on unbind
Pavel Begunkov asml.silence@gmail.com io_uring: order refnode recycling
Pavel Begunkov asml.silence@gmail.com io_uring: get an active ref_node from files_data
-------------
Diffstat:
Makefile | 4 +- arch/arc/include/asm/pgtable.h | 2 + arch/arm/boot/dts/dra76x.dtsi | 4 +- arch/arm/include/asm/pgtable-2level.h | 2 + arch/arm/include/asm/pgtable-3level.h | 2 + arch/arm/mach-omap2/cpuidle44xx.c | 8 +- .../arm64/boot/dts/nvidia/tegra194-p3668-0000.dtsi | 2 +- arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +- arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 20 +- arch/arm64/include/asm/pgtable.h | 34 +-- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 22 +- arch/mips/include/asm/pgtable-32.h | 3 + arch/powerpc/include/asm/book3s/32/pgtable.h | 2 + arch/powerpc/include/asm/book3s/64/kup-radix.h | 2 + arch/powerpc/include/asm/nohash/32/pgtable.h | 2 + arch/powerpc/kernel/exceptions-64s.S | 13 +- arch/powerpc/kvm/book3s_xive_native.c | 7 + arch/riscv/include/asm/pgtable-32.h | 2 + arch/riscv/include/asm/vdso/processor.h | 2 + arch/riscv/kernel/setup.c | 1 + arch/riscv/kernel/vdso/Makefile | 2 +- arch/s390/kernel/asm-offsets.c | 10 +- arch/s390/kernel/entry.S | 2 + arch/s390/kvm/kvm-s390.c | 4 +- arch/s390/kvm/pv.c | 3 +- arch/s390/mm/gmap.c | 2 + arch/x86/events/intel/cstate.c | 6 +- arch/x86/events/intel/uncore.c | 4 +- arch/x86/events/intel/uncore.h | 12 +- arch/x86/events/rapl.c | 14 +- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kernel/cpu/bugs.c | 4 +- arch/x86/kernel/cpu/mce/core.c | 6 +- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 65 +++--- arch/x86/kernel/dumpstack.c | 23 +- arch/x86/kernel/tboot.c | 5 +- arch/x86/kvm/irq.c | 85 +++---- arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/x86.c | 18 +- arch/x86/xen/spinlock.c | 12 +- arch/xtensa/include/asm/uaccess.h | 2 +- block/keyslot-manager.c | 7 + drivers/bus/ti-sysc.c | 29 ++- drivers/cpuidle/cpuidle-tegra.c | 4 +- drivers/dma/pl330.c | 2 +- drivers/dma/xilinx/xilinx_dma.c | 4 +- drivers/firmware/efi/Kconfig | 2 +- drivers/firmware/efi/efi.c | 2 +- drivers/firmware/xilinx/zynqmp.c | 65 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 10 + drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 11 + drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 41 +++- drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h | 4 +- drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 20 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/mediatek/mtk_dsi.c | 61 ++--- drivers/gpu/drm/nouveau/nouveau_gem.c | 8 +- drivers/hid/hid-cypress.c | 44 +++- drivers/hid/hid-ids.h | 9 + drivers/hid/hid-input.c | 3 + drivers/hid/hid-ite.c | 61 ++++- drivers/hid/hid-logitech-hidpp.c | 6 + drivers/hid/hid-quirks.c | 5 + drivers/hid/hid-sensor-hub.c | 3 +- drivers/hid/hid-uclogic-core.c | 2 + drivers/hid/hid-uclogic-params.c | 2 + drivers/infiniband/hw/hfi1/file_ops.c | 4 +- drivers/infiniband/hw/hfi1/hfi.h | 2 +- drivers/infiniband/hw/hfi1/mmu_rb.c | 68 +++--- drivers/infiniband/hw/hfi1/mmu_rb.h | 16 +- drivers/infiniband/hw/hfi1/user_exp_rcv.c | 12 +- drivers/infiniband/hw/hfi1/user_exp_rcv.h | 6 + drivers/infiniband/hw/hfi1/user_sdma.c | 13 +- drivers/infiniband/hw/hfi1/user_sdma.h | 7 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +- drivers/infiniband/hw/i40iw/i40iw_main.c | 5 - drivers/infiniband/hw/i40iw/i40iw_verbs.c | 37 +-- drivers/infiniband/hw/mthca/mthca_cq.c | 10 +- drivers/input/serio/i8042.c | 12 +- drivers/iommu/intel/dmar.c | 3 +- drivers/iommu/intel/iommu.c | 4 +- drivers/iommu/iommu.c | 10 +- drivers/irqchip/irq-sni-exiu.c | 2 +- drivers/net/bonding/bond_main.c | 61 +++-- drivers/net/bonding/bond_sysfs_slave.c | 18 +- drivers/net/can/m_can/m_can.c | 4 +- drivers/net/can/usb/gs_usb.c | 131 ++++++----- drivers/net/dsa/mv88e6xxx/chip.c | 2 + drivers/net/dsa/mv88e6xxx/global1.c | 31 +++ drivers/net/dsa/mv88e6xxx/global1.h | 1 + drivers/net/ethernet/amazon/ena/ena_eth_com.c | 3 + drivers/net/ethernet/amazon/ena/ena_netdev.c | 80 +++---- drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 126 +++++------ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 3 +- drivers/net/ethernet/freescale/dpaa2/Kconfig | 1 + drivers/net/ethernet/freescale/enetc/enetc_qos.c | 14 +- drivers/net/ethernet/ibm/ibmvnic.c | 17 +- drivers/net/ethernet/ibm/ibmvnic.h | 3 +- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 22 +- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 ++- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 2 +- .../net/wireless/intel/iwlwifi/fw/api/time-event.h | 8 +- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 + .../net/wireless/intel/iwlwifi/mvm/time-event.c | 103 ++++++--- drivers/nfc/s3fwrn5/i2c.c | 4 +- drivers/nvme/host/pci.c | 15 ++ drivers/phy/qualcomm/Kconfig | 4 +- drivers/phy/tegra/xusb.c | 1 + drivers/platform/x86/thinkpad_acpi.c | 1 + drivers/platform/x86/toshiba_acpi.c | 3 +- drivers/ptp/ptp_clockmatrix.c | 49 ++-- drivers/rtc/rtc-pcf2127.c | 4 +- drivers/s390/net/qeth_core.h | 9 +- drivers/s390/net/qeth_core_main.c | 82 ++++--- drivers/scsi/libiscsi.c | 23 +- drivers/scsi/ufs/ufshcd.c | 6 +- drivers/spi/spi-bcm-qspi.c | 34 +-- drivers/spi/spi-bcm2835.c | 27 +-- drivers/spi/spi-bcm2835aux.c | 3 +- drivers/spi/spi-imx.c | 1 + drivers/staging/ralink-gdma/Kconfig | 1 + drivers/target/iscsi/iscsi_target.c | 17 +- drivers/tee/optee/call.c | 3 +- drivers/usb/cdns3/gadget.c | 80 +++---- drivers/usb/core/devio.c | 14 +- drivers/usb/core/quirks.c | 10 + drivers/usb/gadget/function/f_midi.c | 10 +- drivers/usb/gadget/legacy/inode.c | 3 + drivers/vdpa/Kconfig | 1 + drivers/vhost/scsi.c | 249 ++++++++++++--------- drivers/vhost/vhost.c | 6 + drivers/vhost/vhost.h | 1 + drivers/video/fbdev/hyperv_fb.c | 7 +- fs/btrfs/file.c | 57 ----- fs/btrfs/inode.c | 58 +++++ fs/btrfs/qgroup.c | 22 +- fs/btrfs/tests/inode-tests.c | 12 +- fs/btrfs/tree-checker.c | 3 + fs/btrfs/volumes.c | 8 +- fs/cifs/cifsacl.c | 1 + fs/cifs/smb2ops.c | 88 ++++++-- fs/efivarfs/inode.c | 2 + fs/efivarfs/super.c | 1 - fs/io_uring.c | 66 ++++-- fs/proc/self.c | 7 + include/kunit/test.h | 2 +- include/linux/firmware/xlnx-zynqmp.h | 4 - include/linux/pgtable.h | 13 ++ include/linux/platform_data/ti-sysc.h | 1 + include/net/bonding.h | 8 + include/scsi/libiscsi.h | 3 + include/trace/events/writeback.h | 8 +- kernel/locking/lockdep.c | 6 +- mm/filemap.c | 8 + mm/page-writeback.c | 6 - net/batman-adv/log.c | 1 + net/ipv4/fib_frontend.c | 2 +- tools/perf/util/dwarf-aux.c | 8 + tools/perf/util/stat-display.c | 5 +- tools/perf/util/synthetic-events.c | 3 + 168 files changed, 1701 insertions(+), 1098 deletions(-)
From: Pavel Begunkov asml.silence@gmail.com
commit 1e5d770bb8a23dd01e28e92f4fb0b1093c8bdbe6 upstream.
An active ref_node always can be found in ctx->files_data, it's much safer to get it this way instead of poking into files_data->ref_list.
Signed-off-by: Pavel Begunkov asml.silence@gmail.com Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/io_uring.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6854,9 +6854,8 @@ static int io_sqe_files_unregister(struc return -ENXIO;
spin_lock(&data->lock); - if (!list_empty(&data->ref_list)) - ref_node = list_first_entry(&data->ref_list, - struct fixed_file_ref_node, node); + ref_node = container_of(data->cur_refs, struct fixed_file_ref_node, + refs); spin_unlock(&data->lock); if (ref_node) percpu_ref_kill(&ref_node->refs);
From: Pavel Begunkov asml.silence@gmail.com
commit e297822b20e7fe683e107aea46e6402adcf99c70 upstream.
Don't recycle a refnode until we're done with all requests of nodes ejected before.
Signed-off-by: Pavel Begunkov asml.silence@gmail.com Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -200,6 +200,7 @@ struct fixed_file_ref_node { struct list_head file_list; struct fixed_file_data *file_data; struct llist_node llist; + bool done; };
struct fixed_file_data { @@ -7106,10 +7107,6 @@ static void __io_file_put_work(struct fi kfree(pfile); }
- spin_lock(&file_data->lock); - list_del(&ref_node->node); - spin_unlock(&file_data->lock); - percpu_ref_exit(&ref_node->refs); kfree(ref_node); percpu_ref_put(&file_data->refs); @@ -7136,17 +7133,33 @@ static void io_file_put_work(struct work static void io_file_data_ref_zero(struct percpu_ref *ref) { struct fixed_file_ref_node *ref_node; + struct fixed_file_data *data; struct io_ring_ctx *ctx; - bool first_add; + bool first_add = false; int delay = HZ;
ref_node = container_of(ref, struct fixed_file_ref_node, refs); - ctx = ref_node->file_data->ctx; + data = ref_node->file_data; + ctx = data->ctx; + + spin_lock(&data->lock); + ref_node->done = true; + + while (!list_empty(&data->ref_list)) { + ref_node = list_first_entry(&data->ref_list, + struct fixed_file_ref_node, node); + /* recycle ref nodes in order */ + if (!ref_node->done) + break; + list_del(&ref_node->node); + first_add |= llist_add(&ref_node->llist, &ctx->file_put_llist); + } + spin_unlock(&data->lock); +
- if (percpu_ref_is_dying(&ctx->file_data->refs)) + if (percpu_ref_is_dying(&data->refs)) delay = 0;
- first_add = llist_add(&ref_node->llist, &ctx->file_put_llist); if (!delay) mod_delayed_work(system_wq, &ctx->file_put_work, 0); else if (first_add) @@ -7170,6 +7183,7 @@ static struct fixed_file_ref_node *alloc INIT_LIST_HEAD(&ref_node->node); INIT_LIST_HEAD(&ref_node->file_list); ref_node->file_data = ctx->file_data; + ref_node->done = false; return ref_node; }
@@ -7297,7 +7311,7 @@ static int io_sqe_files_register(struct
ctx->file_data->cur_refs = &ref_node->refs; spin_lock(&ctx->file_data->lock); - list_add(&ref_node->node, &ctx->file_data->ref_list); + list_add_tail(&ref_node->node, &ctx->file_data->ref_list); spin_unlock(&ctx->file_data->lock); percpu_ref_get(&ctx->file_data->refs); return ret; @@ -7442,7 +7456,7 @@ static int __io_sqe_files_update(struct if (needs_switch) { percpu_ref_kill(data->cur_refs); spin_lock(&data->lock); - list_add(&ref_node->node, &data->ref_list); + list_add_tail(&ref_node->node, &data->ref_list); data->cur_refs = &ref_node->refs; spin_unlock(&data->lock); percpu_ref_get(&ctx->file_data->refs);
From: Lukas Wunner lukas@wunner.de
commit 63c5395bb7a9777a33f0e7b5906f2c0170a23692 upstream
bcm_qspi_remove() calls spi_unregister_master() even though bcm_qspi_probe() calls devm_spi_register_master(). The spi_master is therefore unregistered and freed twice on unbind.
Moreover, since commit 0392727c261b ("spi: bcm-qspi: Handle clock probe deferral"), bcm_qspi_probe() leaks the spi_master allocation if the call to devm_clk_get_optional() fails.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound and also avoids the spi_master leak on probe.
While at it, fix an ordering issue in bcm_qspi_remove() wherein spi_unregister_master() is called after uninitializing the hardware, disabling the clock and freeing an IRQ data structure. The correct order is to call spi_unregister_master() *before* those teardown steps because bus accesses may still be ongoing until that function returns.
Fixes: fa236a7ef240 ("spi: bcm-qspi: Add Broadcom MSPI driver") Signed-off-by: Lukas Wunner lukas@wunner.de Cc: stable@vger.kernel.org # v4.9+: 123456789abc: spi: Introduce device-managed SPI controller allocation Cc: stable@vger.kernel.org # v4.9+ Cc: Kamal Dasu kdasu.kdev@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Tested-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/5e31a9a59fd1c0d0b795b2fe219f25e5ee855f9d.160512103... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/spi/spi-bcm-qspi.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-)
--- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1334,7 +1334,7 @@ int bcm_qspi_probe(struct platform_devic
data = of_id->data;
- master = spi_alloc_master(dev, sizeof(struct bcm_qspi)); + master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi)); if (!master) { dev_err(dev, "error allocating spi_master\n"); return -ENOMEM; @@ -1374,21 +1374,17 @@ int bcm_qspi_probe(struct platform_devic
if (res) { qspi->base[MSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[MSPI])) { - ret = PTR_ERR(qspi->base[MSPI]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[MSPI])) + return PTR_ERR(qspi->base[MSPI]); } else { - goto qspi_resource_err; + return 0; }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); if (res) { qspi->base[BSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[BSPI])) { - ret = PTR_ERR(qspi->base[BSPI]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[BSPI])) + return PTR_ERR(qspi->base[BSPI]); qspi->bspi_mode = true; } else { qspi->bspi_mode = false; @@ -1399,18 +1395,14 @@ int bcm_qspi_probe(struct platform_devic res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg"); if (res) { qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[CHIP_SELECT])) { - ret = PTR_ERR(qspi->base[CHIP_SELECT]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[CHIP_SELECT])) + return PTR_ERR(qspi->base[CHIP_SELECT]); }
qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id), GFP_KERNEL); - if (!qspi->dev_ids) { - ret = -ENOMEM; - goto qspi_resource_err; - } + if (!qspi->dev_ids) + return -ENOMEM;
for (val = 0; val < num_irqs; val++) { irq = -1; @@ -1491,7 +1483,7 @@ int bcm_qspi_probe(struct platform_devic qspi->xfer_mode.addrlen = -1; qspi->xfer_mode.hp = -1;
- ret = devm_spi_register_master(&pdev->dev, master); + ret = spi_register_master(master); if (ret < 0) { dev_err(dev, "can't register master\n"); goto qspi_reg_err; @@ -1504,8 +1496,6 @@ qspi_reg_err: clk_disable_unprepare(qspi->clk); qspi_probe_err: kfree(qspi->dev_ids); -qspi_resource_err: - spi_master_put(master); return ret; } /* probe function to be called by SoC specific platform driver probe */ @@ -1515,10 +1505,10 @@ int bcm_qspi_remove(struct platform_devi { struct bcm_qspi *qspi = platform_get_drvdata(pdev);
+ spi_unregister_master(qspi->master); bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); kfree(qspi->dev_ids); - spi_unregister_master(qspi->master);
return 0; }
From: Lukas Wunner lukas@wunner.de
commit e1483ac030fb4c57734289742f1c1d38dca61e22 upstream
bcm2835_spi_remove() accesses the driver's private data after calling spi_unregister_controller() even though that function releases the last reference on the spi_controller and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound.
Fixes: f8043872e796 ("spi: add driver for BCM2835") Reported-by: Sascha Hauer s.hauer@pengutronix.de Reported-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Lukas Wunner lukas@wunner.de Cc: stable@vger.kernel.org # v3.10+: 123456789abc: spi: Introduce device-managed SPI controller allocation Cc: stable@vger.kernel.org # v3.10+ Cc: Vladimir Oltean olteanv@gmail.com Tested-by: Florian Fainelli f.fainelli@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/ad66e0a0ad96feb848814842ecf5b6a4539ef35c.160512103... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/spi/spi-bcm2835.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-)
--- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -1278,7 +1278,7 @@ static int bcm2835_spi_probe(struct plat struct bcm2835_spi *bs; int err;
- ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), + ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), dma_get_cache_alignment())); if (!ctlr) return -ENOMEM; @@ -1299,26 +1299,17 @@ static int bcm2835_spi_probe(struct plat bs->ctlr = ctlr;
bs->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(bs->regs)) { - err = PTR_ERR(bs->regs); - goto out_controller_put; - } + if (IS_ERR(bs->regs)) + return PTR_ERR(bs->regs);
bs->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(bs->clk)) { - err = PTR_ERR(bs->clk); - if (err == -EPROBE_DEFER) - dev_dbg(&pdev->dev, "could not get clk: %d\n", err); - else - dev_err(&pdev->dev, "could not get clk: %d\n", err); - goto out_controller_put; - } + if (IS_ERR(bs->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk), + "could not get clk\n");
bs->irq = platform_get_irq(pdev, 0); - if (bs->irq <= 0) { - err = bs->irq ? bs->irq : -ENODEV; - goto out_controller_put; - } + if (bs->irq <= 0) + return bs->irq ? bs->irq : -ENODEV;
clk_prepare_enable(bs->clk);
@@ -1352,8 +1343,6 @@ out_dma_release: bcm2835_dma_release(ctlr, bs); out_clk_disable: clk_disable_unprepare(bs->clk); -out_controller_put: - spi_controller_put(ctlr); return err; }
From: Florian Klink flokli@flokli.de
commit c09c8a27b9baa417864b9adc3228b10ae5eeec93 upstream.
Checking for ifdef CONFIG_x fails if CONFIG_x=m.
Use IS_ENABLED instead, which is true for both built-ins and modules.
Otherwise, a
ip -4 route add 1.2.3.4/32 via inet6 fe80::2 dev eth1
fails with the message "Error: IPv6 support not enabled in kernel." if CONFIG_IPV6 is `m`.
In the spirit of b8127113d01e53adba15b41aefd37b90ed83d631.
Fixes: d15662682db2 ("ipv4: Allow ipv6 gateway with ipv4 routes") Cc: Kim Phillips kim.phillips@arm.com Signed-off-by: Florian Klink flokli@flokli.de Reviewed-by: David Ahern dsahern@kernel.org Link: https://lore.kernel.org/r/20201115224509.2020651-1-flokli@flokli.de Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- net/ipv4/fib_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -696,7 +696,7 @@ int fib_gw_from_via(struct fib_config *c cfg->fc_gw4 = *((__be32 *)via->rtvia_addr); break; case AF_INET6: -#ifdef CONFIG_IPV6 +#if IS_ENABLED(CONFIG_IPV6) if (alen != sizeof(struct in6_addr)) { NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_VIA"); return -EINVAL;
From: Dennis Dalessandro dennis.dalessandro@cornelisnetworks.com
commit 3d2a9d642512c21a12d19b9250e7a835dcb41a79 upstream.
Two earlier bug fixes have created a security problem in the hfi1 driver. One fix aimed to solve an issue where current->mm was not valid when closing the hfi1 cdev. It attempted to do this by saving a cached value of the current->mm pointer at file open time. This is a problem if another process with access to the FD calls in via write() or ioctl() to pin pages via the hfi driver. The other fix tried to solve a use after free by taking a reference on the mm.
To fix this correctly we use the existing cached value of the mm in the mmu notifier. Now we can check in the insert, evict, etc. routines that current->mm matched what the notifier was registered for. If not, then don't allow access. The register of the mmu notifier will save the mm pointer.
Since in do_exit() the exit_mm() is called before exit_files(), which would call our close routine a reference is needed on the mm. We rely on the mmgrab done by the registration of the notifier, whereas before it was explicit. The mmu notifier deregistration happens when the user context is torn down, the creation of which triggered the registration.
Also of note is we do not do any explicit work to protect the interval tree notifier. It doesn't seem that this is going to be needed since we aren't actually doing anything with current->mm. The interval tree notifier stuff still has a FIXME noted from a previous commit that will be addressed in a follow on patch.
Cc: stable@vger.kernel.org Fixes: e0cf75deab81 ("IB/hfi1: Fix mm_struct use after free") Fixes: 3faa3d9a308e ("IB/hfi1: Make use of mm consistent") Link: https://lore.kernel.org/r/20201125210112.104301.51331.stgit@awfm-01.aw.intel... Suggested-by: Jann Horn jannh@google.com Reported-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Ira Weiny ira.weiny@intel.com Reviewed-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: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/infiniband/hw/hfi1/file_ops.c | 4 - drivers/infiniband/hw/hfi1/hfi.h | 2 drivers/infiniband/hw/hfi1/mmu_rb.c | 66 +++++++++++++++--------------- drivers/infiniband/hw/hfi1/mmu_rb.h | 16 ++++++- drivers/infiniband/hw/hfi1/user_exp_rcv.c | 12 +++-- drivers/infiniband/hw/hfi1/user_exp_rcv.h | 6 ++ drivers/infiniband/hw/hfi1/user_sdma.c | 13 +++-- drivers/infiniband/hw/hfi1/user_sdma.h | 7 ++- 8 files changed, 78 insertions(+), 48 deletions(-)
--- a/drivers/infiniband/hw/hfi1/file_ops.c +++ b/drivers/infiniband/hw/hfi1/file_ops.c @@ -1,4 +1,5 @@ /* + * Copyright(c) 2020 Cornelis Networks, Inc. * Copyright(c) 2015-2020 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -206,8 +207,6 @@ static int hfi1_file_open(struct inode * spin_lock_init(&fd->tid_lock); spin_lock_init(&fd->invalid_lock); fd->rec_cpu_num = -1; /* no cpu affinity by default */ - fd->mm = current->mm; - mmgrab(fd->mm); fd->dd = dd; fp->private_data = fd; return 0; @@ -711,7 +710,6 @@ static int hfi1_file_close(struct inode
deallocate_ctxt(uctxt); done: - mmdrop(fdata->mm);
if (atomic_dec_and_test(&dd->user_refcount)) complete(&dd->user_comp); --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -1,6 +1,7 @@ #ifndef _HFI1_KERNEL_H #define _HFI1_KERNEL_H /* + * Copyright(c) 2020 Cornelis Networks, Inc. * Copyright(c) 2015-2020 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -1451,7 +1452,6 @@ struct hfi1_filedata { u32 invalid_tid_idx; /* protect invalid_tids array and invalid_tid_idx */ spinlock_t invalid_lock; - struct mm_struct *mm; };
extern struct xarray hfi1_dev_table; --- a/drivers/infiniband/hw/hfi1/mmu_rb.c +++ b/drivers/infiniband/hw/hfi1/mmu_rb.c @@ -1,4 +1,5 @@ /* + * Copyright(c) 2020 Cornelis Networks, Inc. * Copyright(c) 2016 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -48,23 +49,11 @@ #include <linux/rculist.h> #include <linux/mmu_notifier.h> #include <linux/interval_tree_generic.h> +#include <linux/sched/mm.h>
#include "mmu_rb.h" #include "trace.h"
-struct mmu_rb_handler { - struct mmu_notifier mn; - struct rb_root_cached root; - void *ops_arg; - spinlock_t lock; /* protect the RB tree */ - struct mmu_rb_ops *ops; - struct mm_struct *mm; - struct list_head lru_list; - struct work_struct del_work; - struct list_head del_list; - struct workqueue_struct *wq; -}; - static unsigned long mmu_node_start(struct mmu_rb_node *); static unsigned long mmu_node_last(struct mmu_rb_node *); static int mmu_notifier_range_start(struct mmu_notifier *, @@ -92,37 +81,36 @@ static unsigned long mmu_node_last(struc return PAGE_ALIGN(node->addr + node->len) - 1; }
-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm, +int hfi1_mmu_rb_register(void *ops_arg, struct mmu_rb_ops *ops, struct workqueue_struct *wq, struct mmu_rb_handler **handler) { - struct mmu_rb_handler *handlr; + struct mmu_rb_handler *h; int ret;
- handlr = kmalloc(sizeof(*handlr), GFP_KERNEL); - if (!handlr) + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (!h) return -ENOMEM;
- handlr->root = RB_ROOT_CACHED; - handlr->ops = ops; - handlr->ops_arg = ops_arg; - INIT_HLIST_NODE(&handlr->mn.hlist); - spin_lock_init(&handlr->lock); - handlr->mn.ops = &mn_opts; - handlr->mm = mm; - INIT_WORK(&handlr->del_work, handle_remove); - INIT_LIST_HEAD(&handlr->del_list); - INIT_LIST_HEAD(&handlr->lru_list); - handlr->wq = wq; + h->root = RB_ROOT_CACHED; + h->ops = ops; + h->ops_arg = ops_arg; + INIT_HLIST_NODE(&h->mn.hlist); + spin_lock_init(&h->lock); + h->mn.ops = &mn_opts; + INIT_WORK(&h->del_work, handle_remove); + INIT_LIST_HEAD(&h->del_list); + INIT_LIST_HEAD(&h->lru_list); + h->wq = wq;
- ret = mmu_notifier_register(&handlr->mn, handlr->mm); + ret = mmu_notifier_register(&h->mn, current->mm); if (ret) { - kfree(handlr); + kfree(h); return ret; }
- *handler = handlr; + *handler = h; return 0; }
@@ -134,7 +122,7 @@ void hfi1_mmu_rb_unregister(struct mmu_r struct list_head del_list;
/* Unregister first so we don't get any more notifications. */ - mmu_notifier_unregister(&handler->mn, handler->mm); + mmu_notifier_unregister(&handler->mn, handler->mn.mm);
/* * Make sure the wq delete handler is finished running. It will not @@ -166,6 +154,10 @@ int hfi1_mmu_rb_insert(struct mmu_rb_han int ret = 0;
trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len); + + if (current->mm != handler->mn.mm) + return -EPERM; + spin_lock_irqsave(&handler->lock, flags); node = __mmu_rb_search(handler, mnode->addr, mnode->len); if (node) { @@ -180,6 +172,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_han __mmu_int_rb_remove(mnode, &handler->root); list_del(&mnode->list); /* remove from LRU list */ } + mnode->handler = handler; unlock: spin_unlock_irqrestore(&handler->lock, flags); return ret; @@ -217,6 +210,9 @@ bool hfi1_mmu_rb_remove_unless_exact(str unsigned long flags; bool ret = false;
+ if (current->mm != handler->mn.mm) + return ret; + spin_lock_irqsave(&handler->lock, flags); node = __mmu_rb_search(handler, addr, len); if (node) { @@ -239,6 +235,9 @@ void hfi1_mmu_rb_evict(struct mmu_rb_han unsigned long flags; bool stop = false;
+ if (current->mm != handler->mn.mm) + return; + INIT_LIST_HEAD(&del_list);
spin_lock_irqsave(&handler->lock, flags); @@ -272,6 +271,9 @@ void hfi1_mmu_rb_remove(struct mmu_rb_ha { unsigned long flags;
+ if (current->mm != handler->mn.mm) + return; + /* Validity of handler and node pointers has been checked by caller. */ trace_hfi1_mmu_rb_remove(node->addr, node->len); spin_lock_irqsave(&handler->lock, flags); --- a/drivers/infiniband/hw/hfi1/mmu_rb.h +++ b/drivers/infiniband/hw/hfi1/mmu_rb.h @@ -1,4 +1,5 @@ /* + * Copyright(c) 2020 Cornelis Networks, Inc. * Copyright(c) 2016 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -54,6 +55,7 @@ struct mmu_rb_node { unsigned long len; unsigned long __last; struct rb_node node; + struct mmu_rb_handler *handler; struct list_head list; };
@@ -71,7 +73,19 @@ struct mmu_rb_ops { void *evict_arg, bool *stop); };
-int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm, +struct mmu_rb_handler { + struct mmu_notifier mn; + struct rb_root_cached root; + void *ops_arg; + spinlock_t lock; /* protect the RB tree */ + struct mmu_rb_ops *ops; + struct list_head lru_list; + struct work_struct del_work; + struct list_head del_list; + struct workqueue_struct *wq; +}; + +int hfi1_mmu_rb_register(void *ops_arg, struct mmu_rb_ops *ops, struct workqueue_struct *wq, struct mmu_rb_handler **handler); --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c @@ -1,4 +1,5 @@ /* + * Copyright(c) 2020 Cornelis Networks, Inc. * Copyright(c) 2015-2018 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -173,15 +174,18 @@ static void unpin_rcv_pages(struct hfi1_ { struct page **pages; struct hfi1_devdata *dd = fd->uctxt->dd; + struct mm_struct *mm;
if (mapped) { pci_unmap_single(dd->pcidev, node->dma_addr, node->npages * PAGE_SIZE, PCI_DMA_FROMDEVICE); pages = &node->pages[idx]; + mm = mm_from_tid_node(node); } else { pages = &tidbuf->pages[idx]; + mm = current->mm; } - hfi1_release_user_pages(fd->mm, pages, npages, mapped); + hfi1_release_user_pages(mm, pages, npages, mapped); fd->tid_n_pinned -= npages; }
@@ -216,12 +220,12 @@ static int pin_rcv_pages(struct hfi1_fil * pages, accept the amount pinned so far and program only that. * User space knows how to deal with partially programmed buffers. */ - if (!hfi1_can_pin_pages(dd, fd->mm, fd->tid_n_pinned, npages)) { + if (!hfi1_can_pin_pages(dd, current->mm, fd->tid_n_pinned, npages)) { kfree(pages); return -ENOMEM; }
- pinned = hfi1_acquire_user_pages(fd->mm, vaddr, npages, true, pages); + pinned = hfi1_acquire_user_pages(current->mm, vaddr, npages, true, pages); if (pinned <= 0) { kfree(pages); return pinned; @@ -756,7 +760,7 @@ static int set_rcvarray_entry(struct hfi
if (fd->use_mn) { ret = mmu_interval_notifier_insert( - &node->notifier, fd->mm, + &node->notifier, current->mm, tbuf->vaddr + (pageidx * PAGE_SIZE), npages * PAGE_SIZE, &tid_mn_ops); if (ret) --- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h +++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h @@ -1,6 +1,7 @@ #ifndef _HFI1_USER_EXP_RCV_H #define _HFI1_USER_EXP_RCV_H /* + * Copyright(c) 2020 - Cornelis Networks, Inc. * Copyright(c) 2015 - 2017 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -95,4 +96,9 @@ int hfi1_user_exp_rcv_clear(struct hfi1_ int hfi1_user_exp_rcv_invalid(struct hfi1_filedata *fd, struct hfi1_tid_info *tinfo);
+static inline struct mm_struct *mm_from_tid_node(struct tid_rb_node *node) +{ + return node->notifier.mm; +} + #endif /* _HFI1_USER_EXP_RCV_H */ --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -1,4 +1,5 @@ /* + * Copyright(c) 2020 - Cornelis Networks, Inc. * Copyright(c) 2015 - 2018 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -188,7 +189,6 @@ int hfi1_user_sdma_alloc_queues(struct h atomic_set(&pq->n_reqs, 0); init_waitqueue_head(&pq->wait); atomic_set(&pq->n_locked, 0); - pq->mm = fd->mm;
iowait_init(&pq->busy, 0, NULL, NULL, defer_packet_queue, activate_packet_queue, NULL, NULL); @@ -230,7 +230,7 @@ int hfi1_user_sdma_alloc_queues(struct h
cq->nentries = hfi1_sdma_comp_ring_size;
- ret = hfi1_mmu_rb_register(pq, pq->mm, &sdma_rb_ops, dd->pport->hfi1_wq, + ret = hfi1_mmu_rb_register(pq, &sdma_rb_ops, dd->pport->hfi1_wq, &pq->handler); if (ret) { dd_dev_err(dd, "Failed to register with MMU %d", ret); @@ -980,13 +980,13 @@ static int pin_sdma_pages(struct user_sd
npages -= node->npages; retry: - if (!hfi1_can_pin_pages(pq->dd, pq->mm, + if (!hfi1_can_pin_pages(pq->dd, current->mm, atomic_read(&pq->n_locked), npages)) { cleared = sdma_cache_evict(pq, npages); if (cleared >= npages) goto retry; } - pinned = hfi1_acquire_user_pages(pq->mm, + pinned = hfi1_acquire_user_pages(current->mm, ((unsigned long)iovec->iov.iov_base + (node->npages * PAGE_SIZE)), npages, 0, pages + node->npages); @@ -995,7 +995,7 @@ retry: return pinned; } if (pinned != npages) { - unpin_vector_pages(pq->mm, pages, node->npages, pinned); + unpin_vector_pages(current->mm, pages, node->npages, pinned); return -EFAULT; } kfree(node->pages); @@ -1008,7 +1008,8 @@ retry: static void unpin_sdma_pages(struct sdma_mmu_node *node) { if (node->npages) { - unpin_vector_pages(node->pq->mm, node->pages, 0, node->npages); + unpin_vector_pages(mm_from_sdma_node(node), node->pages, 0, + node->npages); atomic_sub(node->npages, &node->pq->n_locked); } } --- a/drivers/infiniband/hw/hfi1/user_sdma.h +++ b/drivers/infiniband/hw/hfi1/user_sdma.h @@ -1,6 +1,7 @@ #ifndef _HFI1_USER_SDMA_H #define _HFI1_USER_SDMA_H /* + * Copyright(c) 2020 - Cornelis Networks, Inc. * Copyright(c) 2015 - 2018 Intel Corporation. * * This file is provided under a dual BSD/GPLv2 license. When using or @@ -133,7 +134,6 @@ struct hfi1_user_sdma_pkt_q { unsigned long unpinned; struct mmu_rb_handler *handler; atomic_t n_locked; - struct mm_struct *mm; };
struct hfi1_user_sdma_comp_q { @@ -250,4 +250,9 @@ int hfi1_user_sdma_process_request(struc struct iovec *iovec, unsigned long dim, unsigned long *count);
+static inline struct mm_struct *mm_from_sdma_node(struct sdma_mmu_node *node) +{ + return node->rb.handler->mn.mm; +} + #endif /* _HFI1_USER_SDMA_H */
From: Shiraz Saleem shiraz.saleem@intel.com
commit 2ed381439e89fa6d1a0839ef45ccd45d99d8e915 upstream.
i40iw_mmap manipulates the vma->vm_pgoff to differentiate a push page mmap vs a doorbell mmap, and uses it to compute the pfn in remap_pfn_range without any validation. This is vulnerable to an mmap exploit as described in: https://lore.kernel.org/r/20201119093523.7588-1-zhudi21@huawei.com
The push feature is disabled in the driver currently and therefore no push mmaps are issued from user-space. The feature does not work as expected in the x722 product.
Remove the push module parameter and all VMA attribute manipulations for this feature in i40iw_mmap. Update i40iw_mmap to only allow DB user mmapings at offset = 0. Check vm_pgoff for zero and if the mmaps are bound to a single page.
Cc: stable@kernel.org Fixes: d37498417947 ("i40iw: add files for iwarp interface") Link: https://lore.kernel.org/r/20201125005616.1800-2-shiraz.saleem@intel.com Reported-by: Di Zhu zhudi21@huawei.com Signed-off-by: Shiraz Saleem shiraz.saleem@intel.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/infiniband/hw/i40iw/i40iw_main.c | 5 ---- drivers/infiniband/hw/i40iw/i40iw_verbs.c | 37 +++++------------------------- 2 files changed, 7 insertions(+), 35 deletions(-)
--- a/drivers/infiniband/hw/i40iw/i40iw_main.c +++ b/drivers/infiniband/hw/i40iw/i40iw_main.c @@ -54,10 +54,6 @@ #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD)
-static int push_mode; -module_param(push_mode, int, 0644); -MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)"); - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all"); @@ -1580,7 +1576,6 @@ static enum i40iw_status_code i40iw_setu if (status) goto exit; iwdev->obj_next = iwdev->obj_mem; - iwdev->push_mode = push_mode;
init_waitqueue_head(&iwdev->vchnl_waitq); init_waitqueue_head(&dev->vf_reqs); --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -167,39 +167,16 @@ static void i40iw_dealloc_ucontext(struc */ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) { - struct i40iw_ucontext *ucontext; - u64 db_addr_offset, push_offset, pfn; + struct i40iw_ucontext *ucontext = to_ucontext(context); + u64 dbaddr;
- ucontext = to_ucontext(context); - if (ucontext->iwdev->sc_dev.is_pf) { - db_addr_offset = I40IW_DB_ADDR_OFFSET; - push_offset = I40IW_PUSH_OFFSET; - if (vma->vm_pgoff) - vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1; - } else { - db_addr_offset = I40IW_VF_DB_ADDR_OFFSET; - push_offset = I40IW_VF_PUSH_OFFSET; - if (vma->vm_pgoff) - vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1; - } + if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL;
- vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT; + dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0);
- if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) { - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - } else { - if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2) - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - else - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - } - - pfn = vma->vm_pgoff + - (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> - PAGE_SHIFT); - - return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE, - vma->vm_page_prot, NULL); + return rdma_user_mmap_io(context, vma, dbaddr >> PAGE_SHIFT, PAGE_SIZE, + pgprot_noncached(vma->vm_page_prot), NULL); }
/**
From: Filipe Manana fdmanana@suse.com
commit c334730988ee07908ba4eb816ce78d3fe06fecaa upstream.
When doing a buffered write, through one of the write family syscalls, we look for ranges which currently don't have allocated extents and set the 'delalloc new' bit on them, so that we can report a correct number of used blocks to the stat(2) syscall until delalloc is flushed and ordered extents complete.
However there are a few other places where we can do a buffered write against a range that is mapped to a hole (no extent allocated) and where we do not set the 'new delalloc' bit. Those places are:
- Doing a memory mapped write against a hole;
- Cloning an inline extent into a hole starting at file offset 0;
- Calling btrfs_cont_expand() when the i_size of the file is not aligned to the sector size and is located in a hole. For example when cloning to a destination offset beyond EOF.
So after such cases, until the corresponding delalloc range is flushed and the respective ordered extents complete, we can report an incorrect number of blocks used through the stat(2) syscall.
In some cases we can end up reporting 0 used blocks to stat(2), which is a particular bad value to report as it may mislead tools to think a file is completely sparse when its i_size is not zero, making them skip reading any data, an undesired consequence for tools such as archivers and other backup tools, as reported a long time ago in the following thread (and other past threads):
https://lists.gnu.org/archive/html/bug-tar/2016-07/msg00001.html
Example reproducer:
$ cat reproducer.sh #!/bin/bash
MNT=/mnt/sdi DEV=/dev/sdi
mkfs.btrfs -f $DEV > /dev/null # mkfs.xfs -f $DEV > /dev/null # mkfs.ext4 -F $DEV > /dev/null # mkfs.f2fs -f $DEV > /dev/null mount $DEV $MNT
xfs_io -f -c "truncate 64K" \ -c "mmap -w 0 64K" \ -c "mwrite -S 0xab 0 64K" \ -c "munmap" \ $MNT/foo
blocks_used=$(stat -c %b $MNT/foo) echo "blocks used: $blocks_used"
if [ $blocks_used -eq 0 ]; then echo "ERROR: blocks used is 0" fi
umount $DEV
$ ./reproducer.sh blocks used: 0 ERROR: blocks used is 0
So move the logic that decides to set the 'delalloc bit' bit into the function btrfs_set_extent_delalloc(), since that is what we use for all those missing cases as well as for the cases that currently work well.
This change is also preparatory work for an upcoming patch that fixes other problems related to tracking and reporting the number of bytes used by an inode.
CC: stable@vger.kernel.org # 4.19+ Reviewed-by: Josef Bacik josef@toxicpanda.com 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 | 57 ------------------------------------------ fs/btrfs/inode.c | 58 +++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/tests/inode-tests.c | 12 +++++--- 3 files changed, 66 insertions(+), 61 deletions(-)
--- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -452,46 +452,6 @@ static void btrfs_drop_pages(struct page } }
-static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode, - const u64 start, - const u64 len, - struct extent_state **cached_state) -{ - u64 search_start = start; - const u64 end = start + len - 1; - - while (search_start < end) { - const u64 search_len = end - search_start + 1; - struct extent_map *em; - u64 em_len; - int ret = 0; - - em = btrfs_get_extent(inode, NULL, 0, search_start, search_len); - if (IS_ERR(em)) - return PTR_ERR(em); - - if (em->block_start != EXTENT_MAP_HOLE) - goto next; - - em_len = em->len; - if (em->start < search_start) - em_len -= search_start - em->start; - if (em_len > search_len) - em_len = search_len; - - ret = set_extent_bit(&inode->io_tree, search_start, - search_start + em_len - 1, - EXTENT_DELALLOC_NEW, - NULL, cached_state, GFP_NOFS); -next: - search_start = extent_map_end(em); - free_extent_map(em); - if (ret) - return ret; - } - return 0; -} - /* * after copy_from_user, pages need to be dirtied and we need to make * sure holes are created between the current EOF and the start of @@ -528,23 +488,6 @@ int btrfs_dirty_pages(struct btrfs_inode EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, cached);
- if (!btrfs_is_free_space_inode(inode)) { - if (start_pos >= isize && - !(inode->flags & BTRFS_INODE_PREALLOC)) { - /* - * There can't be any extents following eof in this case - * so just set the delalloc new bit for the range - * directly. - */ - extra_bits |= EXTENT_DELALLOC_NEW; - } else { - err = btrfs_find_new_delalloc_bytes(inode, start_pos, - num_bytes, cached); - if (err) - return err; - } - } - err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, extra_bits, cached); if (err) --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2262,11 +2262,69 @@ static noinline int add_pending_csums(st return 0; }
+static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode, + const u64 start, + const u64 len, + struct extent_state **cached_state) +{ + u64 search_start = start; + const u64 end = start + len - 1; + + while (search_start < end) { + const u64 search_len = end - search_start + 1; + struct extent_map *em; + u64 em_len; + int ret = 0; + + em = btrfs_get_extent(inode, NULL, 0, search_start, search_len); + if (IS_ERR(em)) + return PTR_ERR(em); + + if (em->block_start != EXTENT_MAP_HOLE) + goto next; + + em_len = em->len; + if (em->start < search_start) + em_len -= search_start - em->start; + if (em_len > search_len) + em_len = search_len; + + ret = set_extent_bit(&inode->io_tree, search_start, + search_start + em_len - 1, + EXTENT_DELALLOC_NEW, + NULL, cached_state, GFP_NOFS); +next: + search_start = extent_map_end(em); + free_extent_map(em); + if (ret) + return ret; + } + return 0; +} + int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end, unsigned int extra_bits, struct extent_state **cached_state) { WARN_ON(PAGE_ALIGNED(end)); + + if (start >= i_size_read(&inode->vfs_inode) && + !(inode->flags & BTRFS_INODE_PREALLOC)) { + /* + * There can't be any extents following eof in this case so just + * set the delalloc new bit for the range directly. + */ + extra_bits |= EXTENT_DELALLOC_NEW; + } else { + int ret; + + ret = btrfs_find_new_delalloc_bytes(inode, start, + end + 1 - start, + cached_state); + if (ret) + return ret; + } + return set_extent_delalloc(&inode->io_tree, start, end, extra_bits, cached_state); } --- a/fs/btrfs/tests/inode-tests.c +++ b/fs/btrfs/tests/inode-tests.c @@ -986,7 +986,8 @@ static int test_extent_accounting(u32 se ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, BTRFS_MAX_EXTENT_SIZE >> 1, (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1, - EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_UPTODATE, 0, 0, NULL); if (ret) { test_err("clear_extent_bit returned %d", ret); goto out; @@ -1053,7 +1054,8 @@ static int test_extent_accounting(u32 se ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, BTRFS_MAX_EXTENT_SIZE + sectorsize, BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, - EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_UPTODATE, 0, 0, NULL); if (ret) { test_err("clear_extent_bit returned %d", ret); goto out; @@ -1085,7 +1087,8 @@ static int test_extent_accounting(u32 se
/* Empty */ ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, - EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_UPTODATE, 0, 0, NULL); if (ret) { test_err("clear_extent_bit returned %d", ret); goto out; @@ -1100,7 +1103,8 @@ static int test_extent_accounting(u32 se out: if (ret) clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, - EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | + EXTENT_UPTODATE, 0, 0, NULL); iput(inode); btrfs_free_dummy_root(root); btrfs_free_dummy_fs_info(fs_info);
From: Daniel Xu dxu@dxuuu.xyz
commit 1a49a97df657c63a4e8ffcd1ea9b6ed95581789b upstream.
There's a missing return statement after an error is found in the root_item, this can cause further problems when a crafted image triggers the error.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=210181 Fixes: 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check") CC: stable@vger.kernel.org # 5.4+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Daniel Xu dxu@dxuuu.xyz 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/tree-checker.c | 1 + 1 file changed, 1 insertion(+)
--- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -1068,6 +1068,7 @@ static int check_root_item(struct extent "invalid root item size, have %u expect %zu or %u", btrfs_item_size_nr(leaf, slot), sizeof(ri), btrfs_legacy_root_item_size()); + return -EUCLEAN; }
/*
From: David Sterba dsterba@suse.com
commit 6d06b0ad94d3dd7e3503d8ad39c39c4634884611 upstream.
There are sectorsize alignment checks that are reported but then check_extent_data_ref continues. This was not intended, wrong alignment is not a minor problem and we should return with error.
CC: stable@vger.kernel.org # 5.4+ Fixes: 0785a9aacf9d ("btrfs: tree-checker: Add EXTENT_DATA_REF check") Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/btrfs/tree-checker.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -1424,6 +1424,7 @@ static int check_extent_data_ref(struct "invalid item size, have %u expect aligned to %zu for key type %u", btrfs_item_size_nr(leaf, slot), sizeof(*dref), key->type); + return -EUCLEAN; } if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { generic_err(leaf, slot, @@ -1452,6 +1453,7 @@ static int check_extent_data_ref(struct extent_err(leaf, slot, "invalid extent data backref offset, have %llu expect aligned to %u", offset, leaf->fs_info->sectorsize); + return -EUCLEAN; } } return 0;
From: Johannes Thumshirn johannes.thumshirn@wdc.com
commit 0697d9a610998b8bdee6b2390836cb2391d8fd1a upstream.
Syzbot reported a possible use-after-free when printing a duplicate device warning device_list_add().
At this point it can happen that a btrfs_device::fs_info is not correctly setup yet, so we're accessing stale data, when printing the warning message using the btrfs_printk() wrappers.
================================================================== BUG: KASAN: use-after-free in btrfs_printk+0x3eb/0x435 fs/btrfs/super.c:245 Read of size 8 at addr ffff8880878e06a8 by task syz-executor225/7068
CPU: 1 PID: 7068 Comm: syz-executor225 Not tainted 5.9.0-rc5-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d6/0x29e lib/dump_stack.c:118 print_address_description+0x66/0x620 mm/kasan/report.c:383 __kasan_report mm/kasan/report.c:513 [inline] kasan_report+0x132/0x1d0 mm/kasan/report.c:530 btrfs_printk+0x3eb/0x435 fs/btrfs/super.c:245 device_list_add+0x1a88/0x1d60 fs/btrfs/volumes.c:943 btrfs_scan_one_device+0x196/0x490 fs/btrfs/volumes.c:1359 btrfs_mount_root+0x48f/0xb60 fs/btrfs/super.c:1634 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 fc_mount fs/namespace.c:978 [inline] vfs_kern_mount+0xc9/0x160 fs/namespace.c:1008 btrfs_mount+0x33c/0xae0 fs/btrfs/super.c:1732 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 do_new_mount fs/namespace.c:2875 [inline] path_mount+0x179d/0x29e0 fs/namespace.c:3192 do_mount fs/namespace.c:3205 [inline] __do_sys_mount fs/namespace.c:3413 [inline] __se_sys_mount+0x126/0x180 fs/namespace.c:3390 do_syscall_64+0x31/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x44840a RSP: 002b:00007ffedfffd608 EFLAGS: 00000293 ORIG_RAX: 00000000000000a5 RAX: ffffffffffffffda RBX: 00007ffedfffd670 RCX: 000000000044840a RDX: 0000000020000000 RSI: 0000000020000100 RDI: 00007ffedfffd630 RBP: 00007ffedfffd630 R08: 00007ffedfffd670 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000293 R12: 000000000000001a R13: 0000000000000004 R14: 0000000000000003 R15: 0000000000000003
Allocated by task 6945: kasan_save_stack mm/kasan/common.c:48 [inline] kasan_set_track mm/kasan/common.c:56 [inline] __kasan_kmalloc+0x100/0x130 mm/kasan/common.c:461 kmalloc_node include/linux/slab.h:577 [inline] kvmalloc_node+0x81/0x110 mm/util.c:574 kvmalloc include/linux/mm.h:757 [inline] kvzalloc include/linux/mm.h:765 [inline] btrfs_mount_root+0xd0/0xb60 fs/btrfs/super.c:1613 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 fc_mount fs/namespace.c:978 [inline] vfs_kern_mount+0xc9/0x160 fs/namespace.c:1008 btrfs_mount+0x33c/0xae0 fs/btrfs/super.c:1732 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 do_new_mount fs/namespace.c:2875 [inline] path_mount+0x179d/0x29e0 fs/namespace.c:3192 do_mount fs/namespace.c:3205 [inline] __do_sys_mount fs/namespace.c:3413 [inline] __se_sys_mount+0x126/0x180 fs/namespace.c:3390 do_syscall_64+0x31/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 6945: kasan_save_stack mm/kasan/common.c:48 [inline] kasan_set_track+0x3d/0x70 mm/kasan/common.c:56 kasan_set_free_info+0x17/0x30 mm/kasan/generic.c:355 __kasan_slab_free+0xdd/0x110 mm/kasan/common.c:422 __cache_free mm/slab.c:3418 [inline] kfree+0x113/0x200 mm/slab.c:3756 deactivate_locked_super+0xa7/0xf0 fs/super.c:335 btrfs_mount_root+0x72b/0xb60 fs/btrfs/super.c:1678 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 fc_mount fs/namespace.c:978 [inline] vfs_kern_mount+0xc9/0x160 fs/namespace.c:1008 btrfs_mount+0x33c/0xae0 fs/btrfs/super.c:1732 legacy_get_tree+0xea/0x180 fs/fs_context.c:592 vfs_get_tree+0x88/0x270 fs/super.c:1547 do_new_mount fs/namespace.c:2875 [inline] path_mount+0x179d/0x29e0 fs/namespace.c:3192 do_mount fs/namespace.c:3205 [inline] __do_sys_mount fs/namespace.c:3413 [inline] __se_sys_mount+0x126/0x180 fs/namespace.c:3390 do_syscall_64+0x31/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
The buggy address belongs to the object at ffff8880878e0000 which belongs to the cache kmalloc-16k of size 16384 The buggy address is located 1704 bytes inside of 16384-byte region [ffff8880878e0000, ffff8880878e4000) The buggy address belongs to the page: page:0000000060704f30 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x878e0 head:0000000060704f30 order:3 compound_mapcount:0 compound_pincount:0 flags: 0xfffe0000010200(slab|head) raw: 00fffe0000010200 ffffea00028e9a08 ffffea00021e3608 ffff8880aa440b00 raw: 0000000000000000 ffff8880878e0000 0000000100000001 0000000000000000 page dumped because: kasan: bad access detected
Memory state around the buggy address: ffff8880878e0580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8880878e0600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8880878e0680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^ ffff8880878e0700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8880878e0780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ==================================================================
The syzkaller reproducer for this use-after-free crafts a filesystem image and loop mounts it twice in a loop. The mount will fail as the crafted image has an invalid chunk tree. When this happens btrfs_mount_root() will call deactivate_locked_super(), which then cleans up fs_info and fs_info::sb. If a second thread now adds the same block-device to the filesystem, it will get detected as a duplicate device and device_list_add() will reject the duplicate and print a warning. But as the fs_info pointer passed in is non-NULL this will result in a use-after-free.
Instead of printing possibly uninitialized or already freed memory in btrfs_printk(), explicitly pass in a NULL fs_info so the printing of the device name will be skipped altogether.
There was a slightly different approach discussed in https://lore.kernel.org/linux-btrfs/20200114060920.4527-1-anand.jain@oracle....
Link: https://lore.kernel.org/linux-btrfs/000000000000c9e14b05afcc41ba@google.com Reported-by: syzbot+582e66e5edf36a22c7b0@syzkaller.appspotmail.com CC: stable@vger.kernel.org # 4.19+ Reviewed-by: Nikolay Borisov nborisov@suse.com Reviewed-by: Anand Jain anand.jain@oracle.com Signed-off-by: Johannes Thumshirn johannes.thumshirn@wdc.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/volumes.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -941,7 +941,13 @@ static noinline struct btrfs_device *dev if (device->bdev != path_bdev) { bdput(path_bdev); mutex_unlock(&fs_devices->device_list_mutex); - btrfs_warn_in_rcu(device->fs_info, + /* + * device->fs_info may not be reliable here, so + * pass in a NULL instead. This avoids a + * possible use-after-free when the fs_info and + * fs_info->sb are already torn down. + */ + btrfs_warn_in_rcu(NULL, "duplicate device %s devid %llu generation %llu scanned by %s (%d)", path, devid, found_transid, current->comm,
From: Filipe Manana fdmanana@suse.com
commit 3d05cad3c357a2b749912914356072b38435edfa upstream.
Lockdep reported the following splat when running test btrfs/190 from fstests:
[ 9482.126098] ====================================================== [ 9482.126184] WARNING: possible circular locking dependency detected [ 9482.126281] 5.10.0-rc4-btrfs-next-73 #1 Not tainted [ 9482.126365] ------------------------------------------------------ [ 9482.126456] mount/24187 is trying to acquire lock: [ 9482.126534] ffffa0c869a7dac0 (&fs_info->qgroup_rescan_lock){+.+.}-{3:3}, at: qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.126647] but task is already holding lock: [ 9482.126777] ffffa0c892ebd3a0 (btrfs-quota-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x27/0x120 [btrfs] [ 9482.126886] which lock already depends on the new lock.
[ 9482.127078] the existing dependency chain (in reverse order) is: [ 9482.127213] -> #1 (btrfs-quota-00){++++}-{3:3}: [ 9482.127366] lock_acquire+0xd8/0x490 [ 9482.127436] down_read_nested+0x45/0x220 [ 9482.127528] __btrfs_tree_read_lock+0x27/0x120 [btrfs] [ 9482.127613] btrfs_read_lock_root_node+0x41/0x130 [btrfs] [ 9482.127702] btrfs_search_slot+0x514/0xc30 [btrfs] [ 9482.127788] update_qgroup_status_item+0x72/0x140 [btrfs] [ 9482.127877] btrfs_qgroup_rescan_worker+0xde/0x680 [btrfs] [ 9482.127964] btrfs_work_helper+0xf1/0x600 [btrfs] [ 9482.128039] process_one_work+0x24e/0x5e0 [ 9482.128110] worker_thread+0x50/0x3b0 [ 9482.128181] kthread+0x153/0x170 [ 9482.128256] ret_from_fork+0x22/0x30 [ 9482.128327] -> #0 (&fs_info->qgroup_rescan_lock){+.+.}-{3:3}: [ 9482.128464] check_prev_add+0x91/0xc60 [ 9482.128551] __lock_acquire+0x1740/0x3110 [ 9482.128623] lock_acquire+0xd8/0x490 [ 9482.130029] __mutex_lock+0xa3/0xb30 [ 9482.130590] qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.131577] btrfs_read_qgroup_config+0x43a/0x550 [btrfs] [ 9482.132175] open_ctree+0x1228/0x18a0 [btrfs] [ 9482.132756] btrfs_mount_root.cold+0x13/0xed [btrfs] [ 9482.133325] legacy_get_tree+0x30/0x60 [ 9482.133866] vfs_get_tree+0x28/0xe0 [ 9482.134392] fc_mount+0xe/0x40 [ 9482.134908] vfs_kern_mount.part.0+0x71/0x90 [ 9482.135428] btrfs_mount+0x13b/0x3e0 [btrfs] [ 9482.135942] legacy_get_tree+0x30/0x60 [ 9482.136444] vfs_get_tree+0x28/0xe0 [ 9482.136949] path_mount+0x2d7/0xa70 [ 9482.137438] do_mount+0x75/0x90 [ 9482.137923] __x64_sys_mount+0x8e/0xd0 [ 9482.138400] do_syscall_64+0x33/0x80 [ 9482.138873] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 9482.139346] other info that might help us debug this:
[ 9482.140735] Possible unsafe locking scenario:
[ 9482.141594] CPU0 CPU1 [ 9482.142011] ---- ---- [ 9482.142411] lock(btrfs-quota-00); [ 9482.142806] lock(&fs_info->qgroup_rescan_lock); [ 9482.143216] lock(btrfs-quota-00); [ 9482.143629] lock(&fs_info->qgroup_rescan_lock); [ 9482.144056] *** DEADLOCK ***
[ 9482.145242] 2 locks held by mount/24187: [ 9482.145637] #0: ffffa0c8411c40e8 (&type->s_umount_key#44/1){+.+.}-{3:3}, at: alloc_super+0xb9/0x400 [ 9482.146061] #1: ffffa0c892ebd3a0 (btrfs-quota-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x27/0x120 [btrfs] [ 9482.146509] stack backtrace: [ 9482.147350] CPU: 1 PID: 24187 Comm: mount Not tainted 5.10.0-rc4-btrfs-next-73 #1 [ 9482.147788] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 9482.148709] Call Trace: [ 9482.149169] dump_stack+0x8d/0xb5 [ 9482.149628] check_noncircular+0xff/0x110 [ 9482.150090] check_prev_add+0x91/0xc60 [ 9482.150561] ? kvm_clock_read+0x14/0x30 [ 9482.151017] ? kvm_sched_clock_read+0x5/0x10 [ 9482.151470] __lock_acquire+0x1740/0x3110 [ 9482.151941] ? __btrfs_tree_read_lock+0x27/0x120 [btrfs] [ 9482.152402] lock_acquire+0xd8/0x490 [ 9482.152887] ? qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.153354] __mutex_lock+0xa3/0xb30 [ 9482.153826] ? qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.154301] ? qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.154768] ? qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.155226] qgroup_rescan_init+0x43/0xf0 [btrfs] [ 9482.155690] btrfs_read_qgroup_config+0x43a/0x550 [btrfs] [ 9482.156160] open_ctree+0x1228/0x18a0 [btrfs] [ 9482.156643] btrfs_mount_root.cold+0x13/0xed [btrfs] [ 9482.157108] ? rcu_read_lock_sched_held+0x5d/0x90 [ 9482.157567] ? kfree+0x31f/0x3e0 [ 9482.158030] legacy_get_tree+0x30/0x60 [ 9482.158489] vfs_get_tree+0x28/0xe0 [ 9482.158947] fc_mount+0xe/0x40 [ 9482.159403] vfs_kern_mount.part.0+0x71/0x90 [ 9482.159875] btrfs_mount+0x13b/0x3e0 [btrfs] [ 9482.160335] ? rcu_read_lock_sched_held+0x5d/0x90 [ 9482.160805] ? kfree+0x31f/0x3e0 [ 9482.161260] ? legacy_get_tree+0x30/0x60 [ 9482.161714] legacy_get_tree+0x30/0x60 [ 9482.162166] vfs_get_tree+0x28/0xe0 [ 9482.162616] path_mount+0x2d7/0xa70 [ 9482.163070] do_mount+0x75/0x90 [ 9482.163525] __x64_sys_mount+0x8e/0xd0 [ 9482.163986] do_syscall_64+0x33/0x80 [ 9482.164437] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 9482.164902] RIP: 0033:0x7f51e907caaa
This happens because at btrfs_read_qgroup_config() we can call qgroup_rescan_init() while holding a read lock on a quota btree leaf, acquired by the previous call to btrfs_search_slot_for_read(), and qgroup_rescan_init() acquires the mutex qgroup_rescan_lock.
A qgroup rescan worker does the opposite: it acquires the mutex qgroup_rescan_lock, at btrfs_qgroup_rescan_worker(), and then tries to update the qgroup status item in the quota btree through the call to update_qgroup_status_item(). This inversion of locking order between the qgroup_rescan_lock mutex and quota btree locks causes the splat.
Fix this simply by releasing and freeing the path before calling qgroup_rescan_init() at btrfs_read_qgroup_config().
CC: stable@vger.kernel.org # 4.4+ 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/qgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -497,13 +497,13 @@ next2: break; } out: + btrfs_free_path(path); fs_info->qgroup_flags |= flags; if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN && ret >= 0) ret = qgroup_rescan_init(fs_info, rescan_progress, 0); - btrfs_free_path(path);
if (ret < 0) { ulist_free(fs_info->qgroup_ulist);
From: Biwen Li biwen.li@nxp.com
commit 35425bafc772ee189e3c3790d7c672b80ba65909 upstream.
Fix a bug when not specify interrupts property in dts as follows, rtc-pcf2127-i2c 1-0051: failed to request alarm irq rtc-pcf2127-i2c: probe of 1-0051 failed with error -22
Signed-off-by: Biwen Li biwen.li@nxp.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20200915073213.12779-1-biwen.li@oss.nxp.com Cc: Rasmus Villemoes rasmus.villemoes@prevas.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/rtc/rtc-pcf2127.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -559,7 +559,7 @@ static int pcf2127_probe(struct device * pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */ pcf2127->rtc->uie_unsupported = 1;
- if (alarm_irq >= 0) { + if (alarm_irq > 0) { ret = devm_request_threaded_irq(dev, alarm_irq, NULL, pcf2127_rtc_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, @@ -570,7 +570,7 @@ static int pcf2127_probe(struct device * } }
- if (alarm_irq >= 0 || device_property_read_bool(dev, "wakeup-source")) { + if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) { device_init_wakeup(dev, true); pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops; }
From: Sven Schnelle svens@linux.ibm.com
commit 1179f170b6f0af7bb0b3b7628136eaac450ddf31 upstream.
We need to disable interrupts in load_fpu_regs(). Otherwise an interrupt might come in after the registers are loaded, but before CIF_FPU is cleared in load_fpu_regs(). When the interrupt returns, CIF_FPU will be cleared and the registers will never be restored.
The entry.S code usually saves the interrupt state in __SF_EMPTY on the stack when disabling/restoring interrupts. sie64a however saves the pointer to the sie control block in __SF_SIE_CONTROL, which references the same location. This is non-obvious to the reader. To avoid thrashing the sie control block pointer in load_fpu_regs(), move the __SIE_* offsets eight bytes after __SF_EMPTY on the stack.
Cc: stable@vger.kernel.org # 5.8 Fixes: 0b0ed657fe00 ("s390: remove critical section cleanup from entry.S") Reported-by: Pierre Morel pmorel@linux.ibm.com Signed-off-by: Sven Schnelle svens@linux.ibm.com Acked-by: Christian Borntraeger borntraeger@de.ibm.com Reviewed-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/s390/kernel/asm-offsets.c | 10 +++++----- arch/s390/kernel/entry.S | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-)
--- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -53,11 +53,11 @@ int main(void) /* stack_frame offsets */ OFFSET(__SF_BACKCHAIN, stack_frame, back_chain); OFFSET(__SF_GPRS, stack_frame, gprs); - OFFSET(__SF_EMPTY, stack_frame, empty1); - OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]); - OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]); - OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]); - OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[3]); + OFFSET(__SF_EMPTY, stack_frame, empty1[0]); + OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]); + OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]); + OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]); + OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]); BLANK(); /* timeval/timezone offsets for use by vdso */ OFFSET(__VDSO_UPD_COUNT, vdso_data, tb_update_count); --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -1072,6 +1072,7 @@ EXPORT_SYMBOL(save_fpu_regs) * %r4 */ load_fpu_regs: + stnsm __SF_EMPTY(%r15),0xfc lg %r4,__LC_CURRENT aghi %r4,__TASK_thread TSTMSK __LC_CPU_FLAGS,_CIF_FPU @@ -1103,6 +1104,7 @@ load_fpu_regs: .Lload_fpu_regs_done: ni __LC_CPU_FLAGS+7,255-_CIF_FPU .Lload_fpu_regs_exit: + ssm __SF_EMPTY(%r15) BR_EX %r14 .Lload_fpu_regs_end: ENDPROC(load_fpu_regs)
From: Hugh Dickins hughd@google.com
commit 073861ed77b6b957c3c8d54a11dc503f7d986ceb upstream.
Twice now, when exercising ext4 looped on shmem huge pages, I have crashed on the PF_ONLY_HEAD check inside PageWaiters(): ext4_finish_bio() calling end_page_writeback() calling wake_up_page() on tail of a shmem huge page, no longer an ext4 page at all.
The problem is that PageWriteback is not accompanied by a page reference (as the NOTE at the end of test_clear_page_writeback() acknowledges): as soon as TestClearPageWriteback has been done, that page could be removed from page cache, freed, and reused for something else by the time that wake_up_page() is reached.
https://lore.kernel.org/linux-mm/20200827122019.GC14765@casper.infradead.org... Matthew Wilcox suggested avoiding or weakening the PageWaiters() tail check; but I'm paranoid about even looking at an unreferenced struct page, lest its memory might itself have already been reused or hotremoved (and wake_up_page_bit() may modify that memory with its ClearPageWaiters()).
Then on crashing a second time, realized there's a stronger reason against that approach. If my testing just occasionally crashes on that check, when the page is reused for part of a compound page, wouldn't it be much more common for the page to get reused as an order-0 page before reaching wake_up_page()? And on rare occasions, might that reused page already be marked PageWriteback by its new user, and already be waited upon? What would that look like?
It would look like BUG_ON(PageWriteback) after wait_on_page_writeback() in write_cache_pages() (though I have never seen that crash myself).
Matthew Wilcox explaining this to himself: "page is allocated, added to page cache, dirtied, writeback starts,
--- thread A --- filesystem calls end_page_writeback() test_clear_page_writeback() --- context switch to thread B --- truncate_inode_pages_range() finds the page, it doesn't have writeback set, we delete it from the page cache. Page gets reallocated, dirtied, writeback starts again. Then we call write_cache_pages(), see PageWriteback() set, call wait_on_page_writeback() --- context switch back to thread A --- wake_up_page(page, PG_writeback); ... thread B is woken, but because the wakeup was for the old use of the page, PageWriteback is still set.
Devious"
And prior to 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic") this would have been much less likely: before that, wake_page_function()'s non-exclusive case would stop walking and not wake if it found Writeback already set again; whereas now the non-exclusive case proceeds to wake.
I have not thought of a fix that does not add a little overhead: the simplest fix is for end_page_writeback() to get_page() before calling test_clear_page_writeback(), then put_page() after wake_up_page().
Was there a chance of missed wakeups before, since a page freed before reaching wake_up_page() would have PageWaiters cleared? I think not, because each waiter does hold a reference on the page. This bug comes when the old use of the page, the one we do TestClearPageWriteback on, had *no* waiters, so no additional page reference beyond the page cache (and whoever racily freed it). The reuse of the page has a waiter holding a reference, and its own PageWriteback set; but the belated wake_up_page() has woken the reuse to hit that BUG_ON(PageWriteback).
Reported-by: syzbot+3622cea378100f45d59f@syzkaller.appspotmail.com Reported-by: Qian Cai cai@lca.pw Fixes: 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic") Signed-off-by: Hugh Dickins hughd@google.com Cc: stable@vger.kernel.org # v5.8+ Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- mm/filemap.c | 8 ++++++++ mm/page-writeback.c | 6 ------ 2 files changed, 8 insertions(+), 6 deletions(-)
--- a/mm/filemap.c +++ b/mm/filemap.c @@ -1464,11 +1464,19 @@ void end_page_writeback(struct page *pag rotate_reclaimable_page(page); }
+ /* + * Writeback does not hold a page reference of its own, relying + * on truncation to wait for the clearing of PG_writeback. + * But here we must make sure that the page is not freed and + * reused before the wake_up_page(). + */ + get_page(page); if (!test_clear_page_writeback(page)) BUG();
smp_mb__after_atomic(); wake_up_page(page, PG_writeback); + put_page(page); } EXPORT_SYMBOL(end_page_writeback);
--- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -2754,12 +2754,6 @@ int test_clear_page_writeback(struct pag } else { ret = TestClearPageWriteback(page); } - /* - * NOTE: Page might be free now! Writeback doesn't hold a page - * reference on its own, it relies on truncation to wait for - * the clearing of PG_writeback. The below can only access - * page state that is static across allocation cycles. - */ if (ret) { dec_lruvec_state(lruvec, NR_WRITEBACK); dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
From: Rohith Surabattula rohiths@microsoft.com
commit de9ac0a6e9efdffc8cde18781f48fb56ca4157b7 upstream.
cifs_reconnect needs to be called only from demultiplex thread. skip cifs_reconnect in offload thread. So, cifs_reconnect will be called by demultiplex thread in subsequent request.
These patches address a problem found during decryption offload: CIFS: VFS: trying to dequeue a deleted mid that can cause a refcount use after free:
[ 1271.389453] Workqueue: smb3decryptd smb2_decrypt_offload [cifs] [ 1271.389456] RIP: 0010:refcount_warn_saturate+0xae/0xf0 [ 1271.389457] Code: fa 1d 6a 01 01 e8 c7 44 b1 ff 0f 0b 5d c3 80 3d e7 1d 6a 01 00 75 91 48 c7 c7 d8 be 1d a2 c6 05 d7 1d 6a 01 01 e8 a7 44 b1 ff <0f> 0b 5d c3 80 3d c5 1d 6a 01 00 0f 85 6d ff ff ff 48 c7 c7 30 bf [ 1271.389458] RSP: 0018:ffffa4cdc1f87e30 EFLAGS: 00010286 [ 1271.389458] RAX: 0000000000000000 RBX: ffff9974d2809f00 RCX: ffff9974df898cc8 [ 1271.389459] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9974df898cc0 [ 1271.389460] RBP: ffffa4cdc1f87e30 R08: 0000000000000004 R09: 00000000000002c0 [ 1271.389460] R10: 0000000000000000 R11: 0000000000000001 R12: ffff9974b7fdb5c0 [ 1271.389461] R13: ffff9974d2809f00 R14: ffff9974ccea0a80 R15: ffff99748e60db80 [ 1271.389462] FS: 0000000000000000(0000) GS:ffff9974df880000(0000) knlGS:0000000000000000 [ 1271.389462] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1271.389463] CR2: 000055c60f344fe4 CR3: 0000001031a3c002 CR4: 00000000003706e0 [ 1271.389465] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1271.389465] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1271.389466] Call Trace: [ 1271.389483] cifs_mid_q_entry_release+0xce/0x110 [cifs] [ 1271.389499] smb2_decrypt_offload+0xa9/0x1c0 [cifs] [ 1271.389501] process_one_work+0x1e8/0x3b0 [ 1271.389503] worker_thread+0x50/0x370 [ 1271.389504] kthread+0x12f/0x150 [ 1271.389506] ? process_one_work+0x3b0/0x3b0 [ 1271.389507] ? __kthread_bind_mask+0x70/0x70 [ 1271.389509] ret_from_fork+0x22/0x30
Signed-off-by: Rohith Surabattula rohiths@microsoft.com Reviewed-by: Pavel Shilovsky pshilov@microsoft.com CC: Stable stable@vger.kernel.org #5.4+ Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/smb2ops.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
--- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -4212,7 +4212,8 @@ init_read_bvec(struct page **pages, unsi static int handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, char *buf, unsigned int buf_len, struct page **pages, - unsigned int npages, unsigned int page_data_size) + unsigned int npages, unsigned int page_data_size, + bool is_offloaded) { unsigned int data_offset; unsigned int data_len; @@ -4234,7 +4235,8 @@ handle_read_data(struct TCP_Server_Info
if (server->ops->is_session_expired && server->ops->is_session_expired(buf)) { - cifs_reconnect(server); + if (!is_offloaded) + cifs_reconnect(server); return -1; }
@@ -4374,7 +4376,8 @@ static void smb2_decrypt_offload(struct mid->decrypted = true; rc = handle_read_data(dw->server, mid, dw->buf, dw->server->vals->read_rsp_size, - dw->ppages, dw->npages, dw->len); + dw->ppages, dw->npages, dw->len, + true); mid->callback(mid); cifs_mid_q_entry_release(mid); } @@ -4478,7 +4481,7 @@ non_offloaded_decrypt: (*mid)->decrypted = true; rc = handle_read_data(server, *mid, buf, server->vals->read_rsp_size, - pages, npages, len); + pages, npages, len, false); }
free_pages: @@ -4621,7 +4624,7 @@ smb3_handle_read_data(struct TCP_Server_ char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
return handle_read_data(server, mid, buf, server->pdu_size, - NULL, 0, 0); + NULL, 0, 0, false); }
static int
From: Rohith Surabattula rohiths@microsoft.com
commit ac873aa3dc21707c47db5db6608b38981c731afe upstream.
When reconnect happens Mid queue can be corrupted when both demultiplex and offload thread try to dequeue the MID from the pending list.
These patches address a problem found during decryption offload: CIFS: VFS: trying to dequeue a deleted mid that could cause a refcount use after free: Workqueue: smb3decryptd smb2_decrypt_offload [cifs]
Signed-off-by: Rohith Surabattula rohiths@microsoft.com Reviewed-by: Pavel Shilovsky pshilov@microsoft.com CC: Stable stable@vger.kernel.org #5.4+ Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/smb2ops.c | 55 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-)
--- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -262,7 +262,7 @@ smb2_revert_current_mid(struct TCP_Serve }
static struct mid_q_entry * -smb2_find_mid(struct TCP_Server_Info *server, char *buf) +__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) { struct mid_q_entry *mid; struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; @@ -279,6 +279,10 @@ smb2_find_mid(struct TCP_Server_Info *se (mid->mid_state == MID_REQUEST_SUBMITTED) && (mid->command == shdr->Command)) { kref_get(&mid->refcount); + if (dequeue) { + list_del_init(&mid->qhead); + mid->mid_flags |= MID_DELETED; + } spin_unlock(&GlobalMid_Lock); return mid; } @@ -287,6 +291,18 @@ smb2_find_mid(struct TCP_Server_Info *se return NULL; }
+static struct mid_q_entry * +smb2_find_mid(struct TCP_Server_Info *server, char *buf) +{ + return __smb2_find_mid(server, buf, false); +} + +static struct mid_q_entry * +smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf) +{ + return __smb2_find_mid(server, buf, true); +} + static void smb2_dump_detail(void *buf, struct TCP_Server_Info *server) { @@ -4260,7 +4276,10 @@ handle_read_data(struct TCP_Server_Info cifs_dbg(FYI, "%s: server returned error %d\n", __func__, rdata->result); /* normal error on read response */ - dequeue_mid(mid, false); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_RECEIVED; + else + dequeue_mid(mid, false); return 0; }
@@ -4284,7 +4303,10 @@ handle_read_data(struct TCP_Server_Info cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", __func__, data_offset); rdata->result = -EIO; - dequeue_mid(mid, rdata->result); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_MALFORMED; + else + dequeue_mid(mid, rdata->result); return 0; }
@@ -4300,21 +4322,30 @@ handle_read_data(struct TCP_Server_Info cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n", __func__, data_offset); rdata->result = -EIO; - dequeue_mid(mid, rdata->result); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_MALFORMED; + else + dequeue_mid(mid, rdata->result); return 0; }
if (data_len > page_data_size - pad_len) { /* data_len is corrupt -- discard frame */ rdata->result = -EIO; - dequeue_mid(mid, rdata->result); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_MALFORMED; + else + dequeue_mid(mid, rdata->result); return 0; }
rdata->result = init_read_bvec(pages, npages, page_data_size, cur_off, &bvec); if (rdata->result != 0) { - dequeue_mid(mid, rdata->result); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_MALFORMED; + else + dequeue_mid(mid, rdata->result); return 0; }
@@ -4329,7 +4360,10 @@ handle_read_data(struct TCP_Server_Info /* read response payload cannot be in both buf and pages */ WARN_ONCE(1, "buf can not contain only a part of read data"); rdata->result = -EIO; - dequeue_mid(mid, rdata->result); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_MALFORMED; + else + dequeue_mid(mid, rdata->result); return 0; }
@@ -4340,7 +4374,10 @@ handle_read_data(struct TCP_Server_Info if (length < 0) return length;
- dequeue_mid(mid, false); + if (is_offloaded) + mid->mid_state = MID_RESPONSE_RECEIVED; + else + dequeue_mid(mid, false); return length; }
@@ -4369,7 +4406,7 @@ static void smb2_decrypt_offload(struct }
dw->server->lstrp = jiffies; - mid = smb2_find_mid(dw->server, dw->buf); + mid = smb2_find_dequeue_mid(dw->server, dw->buf); if (mid == NULL) cifs_dbg(FYI, "mid not found\n"); else {
From: Rohith Surabattula rohiths@microsoft.com
commit 1254100030b3377e8302f9c75090ab191d73ee7c upstream.
Mid callback needs to be called only when valid data is read into pages.
These patches address a problem found during decryption offload: CIFS: VFS: trying to dequeue a deleted mid that could cause a refcount use after free: Workqueue: smb3decryptd smb2_decrypt_offload [cifs]
Signed-off-by: Rohith Surabattula rohiths@microsoft.com Reviewed-by: Pavel Shilovsky pshilov@microsoft.com CC: Stable stable@vger.kernel.org #5.4+ Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/smb2ops.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
--- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -4415,7 +4415,25 @@ static void smb2_decrypt_offload(struct dw->server->vals->read_rsp_size, dw->ppages, dw->npages, dw->len, true); - mid->callback(mid); + if (rc >= 0) { +#ifdef CONFIG_CIFS_STATS2 + mid->when_received = jiffies; +#endif + mid->callback(mid); + } else { + spin_lock(&GlobalMid_Lock); + if (dw->server->tcpStatus == CifsNeedReconnect) { + mid->mid_state = MID_RETRY_NEEDED; + spin_unlock(&GlobalMid_Lock); + mid->callback(mid); + } else { + mid->mid_state = MID_REQUEST_SUBMITTED; + mid->mid_flags &= ~(MID_DELETED); + list_add_tail(&mid->qhead, + &dw->server->pending_mid_q); + spin_unlock(&GlobalMid_Lock); + } + } cifs_mid_q_entry_release(mid); }
From: Namjae Jeon namjae.jeon@samsung.com
commit 98128572084c3dd8067f48bb588aa3733d1355b5 upstream.
kmemleak reported a memory leak allocated in query_info() when cifs is working with modefromsid.
backtrace: [<00000000aeef6a1e>] slab_post_alloc_hook+0x58/0x510 [<00000000b2f7a440>] __kmalloc+0x1a0/0x390 [<000000006d470ebc>] query_info+0x5b5/0x700 [cifs] [<00000000bad76ce0>] SMB2_query_acl+0x2b/0x30 [cifs] [<000000001fa09606>] get_smb2_acl_by_path+0x2f3/0x720 [cifs] [<000000001b6ebab7>] get_smb2_acl+0x75/0x90 [cifs] [<00000000abf43904>] cifs_acl_to_fattr+0x13b/0x1d0 [cifs] [<00000000a5372ec3>] cifs_get_inode_info+0x4cd/0x9a0 [cifs] [<00000000388e0a04>] cifs_revalidate_dentry_attr+0x1cd/0x510 [cifs] [<0000000046b6b352>] cifs_getattr+0x8a/0x260 [cifs] [<000000007692c95e>] vfs_getattr_nosec+0xa1/0xc0 [<00000000cbc7d742>] vfs_getattr+0x36/0x40 [<00000000de8acf67>] vfs_statx_fd+0x4a/0x80 [<00000000a58c6adb>] __do_sys_newfstat+0x31/0x70 [<00000000300b3b4e>] __x64_sys_newfstat+0x16/0x20 [<000000006d8e9c48>] do_syscall_64+0x37/0x80
This patch add missing kfree for pntsd when mounting modefromsid option.
Cc: Stable stable@vger.kernel.org # v5.4+ Signed-off-by: Namjae Jeon namjae.jeon@samsung.com Reviewed-by: Aurelien Aptel aaptel@suse.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/cifs/cifsacl.c | 1 + 1 file changed, 1 insertion(+)
--- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *c cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); } else if (mode_from_special_sid) { rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); + kfree(pntsd); } else { /* get approximated mode from ACL */ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
From: Nicholas Piggin npiggin@gmail.com
commit 575cba20c421ecb6b563ae352e4e0468e4ca8b3c upstream.
pseries guest kernels have a FWNMI handler for SRESET and MCE NMIs, which is basically the same as the regular handlers for those interrupts.
The system reset FWNMI handler did not have a KVM guest test in it, although it probably should have because the guest can itself run guests.
Commit 4f50541f6703b ("powerpc/64s/exception: Move all interrupt handlers to new style code gen macros") convert the handler faithfully to avoid a KVM test with a "clever" trick to modify the IKVM_REAL setting to 0 when the fwnmi handler is to be generated (PPC_PSERIES=y). This worked when the KVM test was generated in the interrupt entry handlers, but a later patch moved the KVM test to the common handler, and the common handler macro is expanded below the fwnmi entry. This prevents the KVM test from being generated even for the 0x100 entry point as well.
The result is NMI IPIs in the host kernel when a guest is running will use gest registers. This goes particularly badly when an HPT guest is running and the MMU is set to guest mode.
Remove this trickery and just generate the test always.
Fixes: 9600f261acaa ("powerpc/64s/exception: Move KVM test to common code") Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Nicholas Piggin npiggin@gmail.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20201114114743.3306283-1-npiggin@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/powerpc/kernel/exceptions-64s.S | 2 -- 1 file changed, 2 deletions(-)
--- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1000,8 +1000,6 @@ TRAMP_REAL_BEGIN(system_reset_idle_wake) * Vectors for the FWNMI option. Share common code. */ TRAMP_REAL_BEGIN(system_reset_fwnmi) - /* XXX: fwnmi guest could run a nested/PR guest, so why no test? */ - __IKVM_REAL(system_reset)=0 GEN_INT_ENTRY system_reset, virt=0
#endif /* CONFIG_PPC_PSERIES */
From: Nicholas Piggin npiggin@gmail.com
commit cd81acc600a9684ea4b4d25a47900d38a3890eab upstream.
Commit 2284ffea8f0c ("powerpc/64s/exception: Only test KVM in SRR interrupts when PR KVM is supported") removed KVM guest tests from interrupts that do not set HV=1, when PR-KVM is not configured.
This is wrong for HV-KVM HPT guest MMIO emulation case which attempts to load the faulting instruction word with MSR[DR]=1 and MSR[HV]=1 with the guest MMU context loaded. This can cause host DSI, DSLB interrupts which must test for KVM guest. Restore this and add a comment.
Fixes: 2284ffea8f0c ("powerpc/64s/exception: Only test KVM in SRR interrupts when PR KVM is supported") Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Nicholas Piggin npiggin@gmail.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20201117135617.3521127-1-npiggin@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/powerpc/kernel/exceptions-64s.S | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
--- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1410,6 +1410,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) * If none is found, do a Linux page fault. Linux page faults can happen in * kernel mode due to user copy operations of course. * + * KVM: The KVM HDSI handler may perform a load with MSR[DR]=1 in guest + * MMU context, which may cause a DSI in the host, which must go to the + * KVM handler. MSR[IR] is not enabled, so the real-mode handler will + * always be used regardless of AIL setting. + * * - Radix MMU * The hardware loads from the Linux page table directly, so a fault goes * immediately to Linux page fault. @@ -1420,10 +1425,8 @@ INT_DEFINE_BEGIN(data_access) IVEC=0x300 IDAR=1 IDSISR=1 -#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_SKIP=1 IKVM_REAL=1 -#endif INT_DEFINE_END(data_access)
EXC_REAL_BEGIN(data_access, 0x300, 0x80) @@ -1462,6 +1465,8 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TY * ppc64_bolted_size (first segment). The kernel handler must avoid stomping * on user-handler data structures. * + * KVM: Same as 0x300, DSLB must test for KVM guest. + * * A dedicated save area EXSLB is used (XXX: but it actually need not be * these days, we could use EXGEN). */ @@ -1470,10 +1475,8 @@ INT_DEFINE_BEGIN(data_access_slb) IAREA=PACA_EXSLB IRECONCILE=0 IDAR=1 -#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_SKIP=1 IKVM_REAL=1 -#endif INT_DEFINE_END(data_access_slb)
EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
From: Cédric Le Goater clg@kaod.org
commit 75b49620267c700f0a07fec7f27f69852db70e46 upstream.
When accessing the ESB page of a source interrupt, the fault handler will retrieve the page address from the XIVE interrupt 'xive_irq_data' structure. If the associated KVM XIVE interrupt is not valid, that is not allocated at the HW level for some reason, the fault handler will dereference a NULL pointer leading to the oops below :
WARNING: CPU: 40 PID: 59101 at arch/powerpc/kvm/book3s_xive_native.c:259 xive_native_esb_fault+0xe4/0x240 [kvm] CPU: 40 PID: 59101 Comm: qemu-system-ppc Kdump: loaded Tainted: G W --------- - - 4.18.0-240.el8.ppc64le #1 NIP: c00800000e949fac LR: c00000000044b164 CTR: c00800000e949ec8 REGS: c000001f69617840 TRAP: 0700 Tainted: G W --------- - - (4.18.0-240.el8.ppc64le) MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 44044282 XER: 00000000 CFAR: c00000000044b160 IRQMASK: 0 GPR00: c00000000044b164 c000001f69617ac0 c00800000e96e000 c000001f69617c10 GPR04: 05faa2b21e000080 0000000000000000 0000000000000005 ffffffffffffffff GPR08: 0000000000000000 0000000000000001 0000000000000000 0000000000000001 GPR12: c00800000e949ec8 c000001ffffd3400 0000000000000000 0000000000000000 GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 GPR20: 0000000000000000 0000000000000000 c000001f5c065160 c000000001c76f90 GPR24: c000001f06f20000 c000001f5c065100 0000000000000008 c000001f0eb98c78 GPR28: c000001dcab40000 c000001dcab403d8 c000001f69617c10 0000000000000011 NIP [c00800000e949fac] xive_native_esb_fault+0xe4/0x240 [kvm] LR [c00000000044b164] __do_fault+0x64/0x220 Call Trace: [c000001f69617ac0] [0000000137a5dc20] 0x137a5dc20 (unreliable) [c000001f69617b50] [c00000000044b164] __do_fault+0x64/0x220 [c000001f69617b90] [c000000000453838] do_fault+0x218/0x930 [c000001f69617bf0] [c000000000456f50] __handle_mm_fault+0x350/0xdf0 [c000001f69617cd0] [c000000000457b1c] handle_mm_fault+0x12c/0x310 [c000001f69617d10] [c00000000007ef44] __do_page_fault+0x264/0xbb0 [c000001f69617df0] [c00000000007f8c8] do_page_fault+0x38/0xd0 [c000001f69617e30] [c00000000000a714] handle_page_fault+0x18/0x38 Instruction dump: 40c2fff0 7c2004ac 2fa90000 409e0118 73e90001 41820080 e8bd0008 7c2004ac 7ca90074 39400000 915c0000 7929d182 <0b090000> 2fa50000 419e0080 e89e0018 ---[ end trace 66c6ff034c53f64f ]--- xive-kvm: xive_native_esb_fault: accessing invalid ESB page for source 8 !
Fix that by checking the validity of the KVM XIVE interrupt structure.
Fixes: 6520ca64cde7 ("KVM: PPC: Book3S HV: XIVE: Add a mapping for the source ESB pages") Cc: stable@vger.kernel.org # v5.2+ Reported-by: Greg Kurz groug@kaod.org Signed-off-by: Cédric Le Goater clg@kaod.org Tested-by: Greg Kurz groug@kaod.org Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20201105134713.656160-1-clg@kaod.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/powerpc/kvm/book3s_xive_native.c | 7 +++++++ 1 file changed, 7 insertions(+)
--- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -251,6 +251,13 @@ static vm_fault_t xive_native_esb_fault( }
state = &sb->irq_state[src]; + + /* Some sanity checking */ + if (!state->valid) { + pr_devel("%s: source %lx invalid !\n", __func__, irq); + return VM_FAULT_SIGBUS; + } + kvmppc_xive_select_irq(state, &hw_num, &xd);
arch_spin_lock(&sb->lock);
From: Zenghui Yu yuzenghui@huawei.com
commit 23bde34771f1ea92fb5e6682c0d8c04304d34b3b upstream.
It was recently reported that if GICR_TYPER is accessed before the RD base address is set, we'll suffer from the unset @rdreg dereferencing. Oops...
gpa_t last_rdist_typer = rdreg->base + GICR_TYPER + (rdreg->free_index - 1) * KVM_VGIC_V3_REDIST_SIZE;
It's "expected" that users will access registers in the redistributor if the RD has been properly configured (e.g., the RD base address is set). But it hasn't yet been covered by the existing documentation.
Per discussion on the list [1], the reporting of the GICR_TYPER.Last bit for userspace never actually worked. And it's difficult for us to emulate it correctly given that userspace has the flexibility to access it any time. Let's just drop the reporting of the Last bit for userspace for now (userspace should have full knowledge about it anyway) and it at least prevents kernel from panic ;-)
[1] https://lore.kernel.org/kvmarm/c20865a267e44d1e2c0d52ce4e012263@kernel.org/
Fixes: ba7b3f1275fd ("KVM: arm/arm64: Revisit Redistributor TYPER last bit computation") Reported-by: Keqian Zhu zhukeqian1@huawei.com Signed-off-by: Zenghui Yu yuzenghui@huawei.com Signed-off-by: Marc Zyngier maz@kernel.org Reviewed-by: Eric Auger eric.auger@redhat.com Link: https://lore.kernel.org/r/20201117151629.1738-1-yuzenghui@huawei.com Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -273,6 +273,23 @@ static unsigned long vgic_mmio_read_v3r_ return extract_bytes(value, addr & 7, len); }
+static unsigned long vgic_uaccess_read_v3r_typer(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len) +{ + unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu); + int target_vcpu_id = vcpu->vcpu_id; + u64 value; + + value = (u64)(mpidr & GENMASK(23, 0)) << 32; + value |= ((target_vcpu_id & 0xffff) << 8); + + if (vgic_has_its(vcpu->kvm)) + value |= GICR_TYPER_PLPIS; + + /* reporting of the Last bit is not supported for userspace */ + return extract_bytes(value, addr & 7, len); +} + static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len) { @@ -593,8 +610,9 @@ static const struct vgic_register_region REGISTER_DESC_WITH_LENGTH(GICR_IIDR, vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_TYPER, - vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8, + REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_TYPER, + vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, + vgic_uaccess_read_v3r_typer, vgic_mmio_uaccess_write_wi, 8, VGIC_ACCESS_64bit | VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH(GICR_WAKER, vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
From: Paolo Bonzini pbonzini@redhat.com
commit 72c3bcdcda494cbd600712a32e67702cdee60c07 upstream.
Centralize handling of interrupts from the userspace APIC in kvm_cpu_has_extint and kvm_cpu_get_extint, since userspace APIC interrupts are handled more or less the same as ExtINTs are with split irqchip. This removes duplicated code from kvm_cpu_has_injectable_intr and kvm_cpu_has_interrupt, and makes the code more similar between kvm_cpu_has_{extint,interrupt} on one side and kvm_cpu_get_{extint,interrupt} on the other.
Cc: stable@vger.kernel.org Reviewed-by: Filippo Sironi sironi@amazon.de Reviewed-by: David Woodhouse dwmw@amazon.co.uk Tested-by: David Woodhouse dwmw@amazon.co.uk Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kvm/irq.c | 83 ++++++++++++++++++++------------------------------- arch/x86/kvm/lapic.c | 2 - 2 files changed, 34 insertions(+), 51 deletions(-)
--- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -42,27 +42,8 @@ static int pending_userspace_extint(stru */ static int kvm_cpu_has_extint(struct kvm_vcpu *v) { - u8 accept = kvm_apic_accept_pic_intr(v); - - if (accept) { - if (irqchip_split(v->kvm)) - return pending_userspace_extint(v); - else - return v->kvm->arch.vpic->output; - } else - return 0; -} - -/* - * check if there is injectable interrupt: - * when virtual interrupt delivery enabled, - * interrupt from apic will handled by hardware, - * we don't need to check it here. - */ -int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) -{ /* - * FIXME: interrupt.injected represents an interrupt that it's + * FIXME: interrupt.injected represents an interrupt whose * side-effects have already been applied (e.g. bit from IRR * already moved to ISR). Therefore, it is incorrect to rely * on interrupt.injected to know if there is a pending @@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct k if (!lapic_in_kernel(v)) return v->arch.interrupt.injected;
+ if (!kvm_apic_accept_pic_intr(v)) + return 0; + + if (irqchip_split(v->kvm)) + return pending_userspace_extint(v); + else + return v->kvm->arch.vpic->output; +} + +/* + * check if there is injectable interrupt: + * when virtual interrupt delivery enabled, + * interrupt from apic will handled by hardware, + * we don't need to check it here. + */ +int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) +{ if (kvm_cpu_has_extint(v)) return 1;
@@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable */ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { - /* - * FIXME: interrupt.injected represents an interrupt that it's - * side-effects have already been applied (e.g. bit from IRR - * already moved to ISR). Therefore, it is incorrect to rely - * on interrupt.injected to know if there is a pending - * interrupt in the user-mode LAPIC. - * This leads to nVMX/nSVM not be able to distinguish - * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on - * pending interrupt or should re-inject an injected - * interrupt. - */ - if (!lapic_in_kernel(v)) - return v->arch.interrupt.injected; - if (kvm_cpu_has_extint(v)) return 1;
@@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt) */ static int kvm_cpu_get_extint(struct kvm_vcpu *v) { - if (kvm_cpu_has_extint(v)) { - if (irqchip_split(v->kvm)) { - int vector = v->arch.pending_external_vector; - - v->arch.pending_external_vector = -1; - return vector; - } else - return kvm_pic_read_irq(v->kvm); /* PIC */ - } else + if (!kvm_cpu_has_extint(v)) { + WARN_ON(!lapic_in_kernel(v)); return -1; + } + + if (!lapic_in_kernel(v)) + return v->arch.interrupt.nr; + + if (irqchip_split(v->kvm)) { + int vector = v->arch.pending_external_vector; + + v->arch.pending_external_vector = -1; + return vector; + } else + return kvm_pic_read_irq(v->kvm); /* PIC */ }
/* @@ -135,13 +124,7 @@ static int kvm_cpu_get_extint(struct kvm */ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) { - int vector; - - if (!lapic_in_kernel(v)) - return v->arch.interrupt.nr; - - vector = kvm_cpu_get_extint(v); - + int vector = kvm_cpu_get_extint(v); if (vector != -1) return vector; /* PIC */
--- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2461,7 +2461,7 @@ int kvm_apic_has_interrupt(struct kvm_vc struct kvm_lapic *apic = vcpu->arch.apic; u32 ppr;
- if (!kvm_apic_hw_enabled(apic)) + if (!kvm_apic_present(vcpu)) return -1;
__apic_update_ppr(apic, &ppr);
From: Paolo Bonzini pbonzini@redhat.com
commit 71cc849b7093bb83af966c0e60cb11b7f35cd746 upstream.
kvm_cpu_accept_dm_intr and kvm_vcpu_ready_for_interrupt_injection are a hodge-podge of conditions, hacked together to get something that more or less works. But what is actually needed is much simpler; in both cases the fundamental question is, do we have a place to stash an interrupt if userspace does KVM_INTERRUPT?
In userspace irqchip mode, that is !vcpu->arch.interrupt.injected. Currently kvm_event_needs_reinjection(vcpu) covers it, but it is unnecessarily restrictive.
In split irqchip mode it's a bit more complicated, we need to check kvm_apic_accept_pic_intr(vcpu) (the IRQ window exit is basically an INTACK cycle and thus requires ExtINTs not to be masked) as well as !pending_userspace_extint(vcpu). However, there is no need to check kvm_event_needs_reinjection(vcpu), since split irqchip keeps pending ExtINT state separate from event injection state, and checking kvm_cpu_has_interrupt(vcpu) is wrong too since ExtINT has higher priority than APIC interrupts. In fact the latter fixes a bug: when userspace requests an IRQ window vmexit, an interrupt in the local APIC can cause kvm_cpu_has_interrupt() to be true and thus kvm_vcpu_ready_for_interrupt_injection() to return false. When this happens, vcpu_run does not exit to userspace but the interrupt window vmexits keep occurring. The VM loops without any hope of making progress.
Once we try to fix these with something like
return kvm_arch_interrupt_allowed(vcpu) && - !kvm_cpu_has_interrupt(vcpu) && - !kvm_event_needs_reinjection(vcpu) && - kvm_cpu_accept_dm_intr(vcpu); + (!lapic_in_kernel(vcpu) + ? !vcpu->arch.interrupt.injected + : (kvm_apic_accept_pic_intr(vcpu) + && !pending_userspace_extint(v)));
we realize two things. First, thanks to the previous patch the complex conditional can reuse !kvm_cpu_has_extint(vcpu). Second, the interrupt window request in vcpu_enter_guest()
bool req_int_win = dm_request_for_irq_injection(vcpu) && kvm_cpu_accept_dm_intr(vcpu);
should be kept in sync with kvm_vcpu_ready_for_interrupt_injection(): it is unnecessary to ask the processor for an interrupt window if we would not be able to return to userspace. Therefore, kvm_cpu_accept_dm_intr(vcpu) is basically !kvm_cpu_has_extint(vcpu) ANDed with the existing check for masked ExtINT. It all makes sense:
- we can accept an interrupt from userspace if there is a place to stash it (and, for irqchip split, ExtINTs are not masked). Interrupts from userspace _can_ be accepted even if right now EFLAGS.IF=0.
- in order to tell userspace we will inject its interrupt ("IRQ window open" i.e. kvm_vcpu_ready_for_interrupt_injection), both KVM and the vCPU need to be ready to accept the interrupt.
... and this is what the patch implements.
Reported-by: David Woodhouse dwmw@amazon.co.uk Analyzed-by: David Woodhouse dwmw@amazon.co.uk Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Reviewed-by: Nikos Tsironis ntsironis@arrikto.com Reviewed-by: David Woodhouse dwmw@amazon.co.uk Tested-by: David Woodhouse dwmw@amazon.co.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/irq.c | 2 +- arch/x86/kvm/x86.c | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-)
--- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1603,6 +1603,7 @@ int kvm_test_age_hva(struct kvm *kvm, un int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v); int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); +int kvm_cpu_has_extint(struct kvm_vcpu *v); int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); int kvm_cpu_get_interrupt(struct kvm_vcpu *v); void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -40,7 +40,7 @@ static int pending_userspace_extint(stru * check if there is pending interrupt from * non-APIC source without intack. */ -static int kvm_cpu_has_extint(struct kvm_vcpu *v) +int kvm_cpu_has_extint(struct kvm_vcpu *v) { /* * FIXME: interrupt.injected represents an interrupt whose --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3839,21 +3839,23 @@ static int kvm_vcpu_ioctl_set_lapic(stru
static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu) { + /* + * We can accept userspace's request for interrupt injection + * as long as we have a place to store the interrupt number. + * The actual injection will happen when the CPU is able to + * deliver the interrupt. + */ + if (kvm_cpu_has_extint(vcpu)) + return false; + + /* Acknowledging ExtINT does not happen if LINT0 is masked. */ return (!lapic_in_kernel(vcpu) || kvm_apic_accept_pic_intr(vcpu)); }
-/* - * if userspace requested an interrupt window, check that the - * interrupt window is open. - * - * No need to exit to userspace if we already have an interrupt queued. - */ static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu) { return kvm_arch_interrupt_allowed(vcpu) && - !kvm_cpu_has_interrupt(vcpu) && - !kvm_event_needs_reinjection(vcpu) && kvm_cpu_accept_dm_intr(vcpu); }
From: David Woodhouse dwmw@amazon.co.uk
commit d76b42e92780c3587c1a998a3a943b501c137553 upstream.
My virtual IOMMU implementation is whining that the guest is reading a register that doesn't exist. Only read the VCCAP_REG if the corresponding capability is set in ECAP_REG to indicate that it actually exists.
Fixes: 3375303e8287 ("iommu/vt-d: Add custom allocator for IOASID") Signed-off-by: David Woodhouse dwmw@amazon.co.uk Reviewed-by: Liu Yi L yi.l.liu@intel.com Cc: stable@vger.kernel.org # v5.7+ Acked-by: Lu Baolu baolu.lu@linux.intel.com Link: https://lore.kernel.org/r/de32b150ffaa752e0cff8571b17dfb1213fbe71c.camel@inf... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/iommu/intel/dmar.c | 3 ++- drivers/iommu/intel/iommu.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -964,7 +964,8 @@ static int map_iommu(struct intel_iommu warn_invalid_dmar(phys_addr, " returns all ones"); goto unmap; } - iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); + if (ecap_vcs(iommu->ecap)) + iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG);
/* the registers might be more than one page */ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1798,7 +1798,7 @@ static void free_dmar_iommu(struct intel if (ecap_prs(iommu->ecap)) intel_svm_finish_prq(iommu); } - if (ecap_vcs(iommu->ecap) && vccap_pasid(iommu->vccap)) + if (vccap_pasid(iommu->vccap)) ioasid_unregister_allocator(&iommu->pasid_allocator);
#endif @@ -3177,7 +3177,7 @@ static void register_pasid_allocator(str * is active. All vIOMMU allocators will eventually be calling the same * host allocator. */ - if (!ecap_vcs(iommu->ecap) || !vccap_pasid(iommu->vccap)) + if (!vccap_pasid(iommu->vccap)) return;
pr_info("Register custom PASID allocator\n");
From: Amit Sunil Dhamne amit.sunil.dhamne@xilinx.com
commit acfdd18591eaac25446e976a0c0d190f8b3dbfb1 upstream.
Currently array of fix length PM_API_MAX is used to cache the pm_api version (valid or invalid). However ATF based PM APIs values are much higher then PM_API_MAX. So to include ATF based PM APIs also, use hash-table to store the pm_api version status.
Signed-off-by: Amit Sunil Dhamne amit.sunil.dhamne@xilinx.com Reported-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Ravi Patel ravi.patel@xilinx.com Signed-off-by: Rajan Vaja rajan.vaja@xilinx.com Reviewed-by: Arnd Bergmann arnd@arndb.de Tested-by: Michal Simek michal.simek@xilinx.com Fixes: f3217d6f2f7a ("firmware: xilinx: fix out-of-bounds access") Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/1606197161-25976-1-git-send-email-rajan.vaja@xilin... Signed-off-by: Michal Simek michal.simek@xilinx.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/firmware/xilinx/zynqmp.c | 63 +++++++++++++++++++++++++++-------- include/linux/firmware/xlnx-zynqmp.h | 4 -- 2 files changed, 49 insertions(+), 18 deletions(-)
--- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -20,12 +20,28 @@ #include <linux/of_platform.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/hashtable.h>
#include <linux/firmware/xlnx-zynqmp.h> #include "zynqmp-debug.h"
+/* Max HashMap Order for PM API feature check (1<<7 = 128) */ +#define PM_API_FEATURE_CHECK_MAX_ORDER 7 + static bool feature_check_enabled; -static u32 zynqmp_pm_features[PM_API_MAX]; +DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER); + +/** + * struct pm_api_feature_data - PM API Feature data + * @pm_api_id: PM API Id, used as key to index into hashmap + * @feature_status: status of PM API feature: valid, invalid + * @hentry: hlist_node that hooks this entry into hashtable + */ +struct pm_api_feature_data { + u32 pm_api_id; + int feature_status; + struct hlist_node hentry; +};
static const struct mfd_cell firmware_devs[] = { { @@ -142,29 +158,37 @@ static int zynqmp_pm_feature(u32 api_id) int ret; u32 ret_payload[PAYLOAD_ARG_CNT]; u64 smc_arg[2]; + struct pm_api_feature_data *feature_data;
if (!feature_check_enabled) return 0;
- /* Return value if feature is already checked */ - if (api_id > ARRAY_SIZE(zynqmp_pm_features)) - return PM_FEATURE_INVALID; + /* Check for existing entry in hash table for given api */ + hash_for_each_possible(pm_api_features_map, feature_data, hentry, + api_id) { + if (feature_data->pm_api_id == api_id) + return feature_data->feature_status; + }
- if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED) - return zynqmp_pm_features[api_id]; + /* Add new entry if not present */ + feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL); + if (!feature_data) + return -ENOMEM;
+ feature_data->pm_api_id = api_id; smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK; smc_arg[1] = api_id;
ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload); - if (ret) { - zynqmp_pm_features[api_id] = PM_FEATURE_INVALID; - return PM_FEATURE_INVALID; - } + if (ret) + ret = -EOPNOTSUPP; + else + ret = ret_payload[1];
- zynqmp_pm_features[api_id] = ret_payload[1]; + feature_data->feature_status = ret; + hash_add(pm_api_features_map, &feature_data->hentry, api_id);
- return zynqmp_pm_features[api_id]; + return ret; }
/** @@ -200,9 +224,12 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u * Make sure to stay in x0 register */ u64 smc_arg[4]; + int ret;
- if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID) - return -ENOTSUPP; + /* Check if feature is supported or not */ + ret = zynqmp_pm_feature(pm_api_id); + if (ret < 0) + return ret;
smc_arg[0] = PM_SIP_SVC | pm_api_id; smc_arg[1] = ((u64)arg1 << 32) | arg0; @@ -1252,9 +1279,17 @@ static int zynqmp_firmware_probe(struct
static int zynqmp_firmware_remove(struct platform_device *pdev) { + struct pm_api_feature_data *feature_data; + int i; + mfd_remove_devices(&pdev->dev); zynqmp_pm_api_debugfs_exit();
+ hash_for_each(pm_api_features_map, i, feature_data, hentry) { + hash_del(&feature_data->hentry); + kfree(feature_data); + } + return 0; }
--- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -50,10 +50,6 @@ #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U #define ZYNQMP_PM_CAPABILITY_UNUSABLE 0x8U
-/* Feature check status */ -#define PM_FEATURE_INVALID -1 -#define PM_FEATURE_UNCHECKED 0 - /* * Firmware FPGA Manager flags * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
From: Sonny Jiang sonny.jiang@amd.com
commit 4d6a95366117b241bb3298e1c318a36ebb7544d0 upstream.
The SI UVD firmware validate key is stored at the end of firmware, which is changed during resume while playing video. So get the key at sw_init and store it for fw validate using.
Signed-off-by: Sonny Jiang sonny.jiang@amd.com Reviewed-by: Leo Liu leo.liu@amd.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/amd/amdgpu/amdgpu_uvd.h | 1 + drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h @@ -67,6 +67,7 @@ struct amdgpu_uvd { unsigned harvest_config; /* store image width to adjust nb memory state */ unsigned decode_image_width; + uint32_t keyselect; };
int amdgpu_uvd_sw_init(struct amdgpu_device *adev); --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -277,15 +277,8 @@ static void uvd_v3_1_mc_resume(struct am */ static int uvd_v3_1_fw_validate(struct amdgpu_device *adev) { - void *ptr; - uint32_t ucode_len, i; - uint32_t keysel; - - ptr = adev->uvd.inst[0].cpu_addr; - ptr += 192 + 16; - memcpy(&ucode_len, ptr, 4); - ptr += ucode_len; - memcpy(&keysel, ptr, 4); + int i; + uint32_t keysel = adev->uvd.keyselect;
WREG32(mmUVD_FW_START, keysel);
@@ -550,6 +543,8 @@ static int uvd_v3_1_sw_init(void *handle struct amdgpu_ring *ring; struct amdgpu_device *adev = (struct amdgpu_device *)handle; int r; + void *ptr; + uint32_t ucode_len;
/* UVD TRAP */ r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 124, &adev->uvd.inst->irq); @@ -560,6 +555,13 @@ static int uvd_v3_1_sw_init(void *handle if (r) return r;
+ /* Retrieval firmware validate key */ + ptr = adev->uvd.inst[0].cpu_addr; + ptr += 192 + 16; + memcpy(&ucode_len, ptr, 4); + ptr += ucode_len; + memcpy(&adev->uvd.keyselect, ptr, 4); + ring = &adev->uvd.inst->ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0,
From: Pavel Begunkov asml.silence@gmail.com
commit 9c3a205c5ffa36e96903c2e37eb5f41c0f03c43e upstream.
iov_iter::type is a bitmask that also keeps direction etc., so it shouldn't be directly compared against ITER_*. Use proper helper.
Fixes: ff6165b2d7f6 ("io_uring: retain iov_iter state over io_read/io_write calls") Reported-by: David Howells dhowells@redhat.com Signed-off-by: Pavel Begunkov asml.silence@gmail.com Cc: stable@vger.kernel.org # 5.9 Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/io_uring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2991,7 +2991,7 @@ static void io_req_map_rw(struct io_kioc rw->free_iovec = NULL; rw->bytes_done = 0; /* can only be fixed buffers, no need to do anything */ - if (iter->type == ITER_BVEC) + if (iov_iter_is_bvec(iter)) return; if (!iovec) { unsigned iov_off = 0;
From: Hui Su sh_def@163.com
commit fdeb17c70c9ecae655378761accf5a26a55a33cf upstream.
The bdi_dev_name() returns a char [64], and the __entry->name is a char [32].
It maybe dangerous to TP_printk("%s", __entry->name) after the strncpy().
CC: stable@vger.kernel.org Link: https://lore.kernel.org/r/20201124165205.GA23937@rlk Acked-by: Steven Rostedt (VMware) rostedt@goodmis.org Acked-by: Tejun Heo tj@kernel.org Signed-off-by: Hui Su sh_def@163.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- include/trace/events/writeback.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -190,7 +190,7 @@ TRACE_EVENT(inode_foreign_history, ),
TP_fast_assign( - strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); + strscpy_pad(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); __entry->ino = inode->i_ino; __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); __entry->history = history; @@ -219,7 +219,7 @@ TRACE_EVENT(inode_switch_wbs, ),
TP_fast_assign( - strncpy(__entry->name, bdi_dev_name(old_wb->bdi), 32); + strscpy_pad(__entry->name, bdi_dev_name(old_wb->bdi), 32); __entry->ino = inode->i_ino; __entry->old_cgroup_ino = __trace_wb_assign_cgroup(old_wb); __entry->new_cgroup_ino = __trace_wb_assign_cgroup(new_wb); @@ -252,7 +252,7 @@ TRACE_EVENT(track_foreign_dirty, struct address_space *mapping = page_mapping(page); struct inode *inode = mapping ? mapping->host : NULL;
- strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); __entry->bdi_id = wb->bdi->id; __entry->ino = inode ? inode->i_ino : 0; __entry->memcg_id = wb->memcg_css->id; @@ -285,7 +285,7 @@ TRACE_EVENT(flush_foreign, ),
TP_fast_assign( - strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); __entry->frn_bdi_id = frn_bdi_id; __entry->frn_memcg_id = frn_memcg_id;
From: Jon Hunter jonathanh@nvidia.com
commit 476e23f4c540949ac5ea4fad4f6f6fa0e2d41f42 upstream.
The Jetson Xavier NX board routes UARTA to the 40-pin header and UARTC to a 12-pin debug header. The UARTs can be used by either the Tegra Combined UART (TCU) driver or the Tegra 8250 driver. By default, the TCU will use UARTC on Jetson Xavier NX. Currently, device-tree for Xavier NX enables the TCU and the Tegra 8250 node for UARTC. Fix this by disabling the Tegra 8250 node for UARTC and enabling the Tegra 8250 node for UARTA.
Fixes: 3f9efbbe57bc ("arm64: tegra: Add support for Jetson Xavier NX") Cc: stable@vger.kernel.org Signed-off-by: Jon Hunter jonathanh@nvidia.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/boot/dts/nvidia/tegra194-p3668-0000.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm64/boot/dts/nvidia/tegra194-p3668-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194-p3668-0000.dtsi @@ -54,7 +54,7 @@ status = "okay"; };
- serial@c280000 { + serial@3100000 { status = "okay"; };
From: JC Kuo jckuo@nvidia.com
commit f24a2acc15bcc7bbd295f9759efc873b88fbe429 upstream.
USB host mode is broken on the OTG port of Jetson TX1 platform because the USB_VBUS_EN0 regulator (regulator@11) is being overwritten by the vdd-cam-1v2 regulator. This commit rearranges USB_VBUS_EN0 to be regulator@14.
Fixes: 257c8047be44 ("arm64: tegra: jetson-tx1: Add camera supplies") Cc: stable@vger.kernel.org Signed-off-by: JC Kuo jckuo@nvidia.com Reviewed-by: Jon Hunter jonathanh@nvidia.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi @@ -1663,16 +1663,6 @@ vin-supply = <&vdd_5v0_sys>; };
- vdd_usb_vbus_otg: regulator@11 { - compatible = "regulator-fixed"; - regulator-name = "USB_VBUS_EN0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>; - enable-active-high; - vin-supply = <&vdd_5v0_sys>; - }; - vdd_hdmi: regulator@10 { compatible = "regulator-fixed"; regulator-name = "VDD_HDMI_5V0"; @@ -1712,4 +1702,14 @@ enable-active-high; vin-supply = <&vdd_3v3_sys>; }; + + vdd_usb_vbus_otg: regulator@14 { + compatible = "regulator-fixed"; + regulator-name = "USB_VBUS_EN0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&vdd_5v0_sys>; + }; };
From: Will Deacon will@kernel.org
commit 07509e10dcc77627f8b6a57381e878fe269958d3 upstream.
pte_accessible() is used by ptep_clear_flush() to figure out whether TLB invalidation is necessary when unmapping pages for reclaim. Although our implementation is correct according to the architecture, returning true only for valid, young ptes in the absence of racing page-table modifications, this is in fact flawed due to lazy invalidation of old ptes in ptep_clear_flush_young() where we elide the expensive DSB instruction for completing the TLB invalidation.
Rather than penalise the aging path, adjust pte_accessible() to return true for any valid pte, even if the access flag is cleared.
Cc: stable@vger.kernel.org Fixes: 76c714be0e5e ("arm64: pgtable: implement pte_accessible()") Reported-by: Yu Zhao yuzhao@google.com Acked-by: Yu Zhao yuzhao@google.com Reviewed-by: Minchan Kim minchan@kernel.org Reviewed-by: Catalin Marinas catalin.marinas@arm.com Link: https://lore.kernel.org/r/20201120143557.6715-2-will@kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/include/asm/pgtable.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
--- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -108,8 +108,6 @@ extern unsigned long empty_zero_page[PAG #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) #define pte_valid_not_user(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) -#define pte_valid_young(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF)) #define pte_valid_user(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
@@ -117,9 +115,12 @@ extern unsigned long empty_zero_page[PAG * Could the pte be present in the TLB? We must check mm_tlb_flush_pending * so that we don't erroneously return false for pages that have been * remapped as PROT_NONE but are yet to be flushed from the TLB. + * Note that we can't make any assumptions based on the state of the access + * flag, since ptep_clear_flush_young() elides a DSB when invalidating the + * TLB. */ #define pte_accessible(mm, pte) \ - (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte)) + (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
/* * p??_access_permitted() is true for valid user mappings (subject to the
From: Will Deacon will@kernel.org
commit ff1712f953e27f0b0718762ec17d0adb15c9fd0b upstream.
With hardware dirty bit management, calling pte_wrprotect() on a writable, dirty PTE will lose the dirty state and return a read-only, clean entry.
Move the logic from ptep_set_wrprotect() into pte_wrprotect() to ensure that the dirty bit is preserved for writable entries, as this is required for soft-dirty bit management if we enable it in the future.
Cc: stable@vger.kernel.org Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits") Reviewed-by: Catalin Marinas catalin.marinas@arm.com Link: https://lore.kernel.org/r/20201120143557.6715-3-will@kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/include/asm/pgtable.h | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
--- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -146,13 +146,6 @@ static inline pte_t set_pte_bit(pte_t pt return pte; }
-static inline pte_t pte_wrprotect(pte_t pte) -{ - pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); - pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); - return pte; -} - static inline pte_t pte_mkwrite(pte_t pte) { pte = set_pte_bit(pte, __pgprot(PTE_WRITE)); @@ -178,6 +171,20 @@ static inline pte_t pte_mkdirty(pte_t pt return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) +{ + /* + * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY + * clear), set the PTE_DIRTY bit. + */ + if (pte_hw_dirty(pte)) + pte = pte_mkdirty(pte); + + pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); + pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); + return pte; +} + static inline pte_t pte_mkold(pte_t pte) { return clear_pte_bit(pte, __pgprot(PTE_AF)); @@ -799,12 +806,6 @@ static inline void ptep_set_wrprotect(st pte = READ_ONCE(*ptep); do { old_pte = pte; - /* - * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY - * clear), set the PTE_DIRTY bit. - */ - if (pte_hw_dirty(pte)) - pte = pte_mkdirty(pte); pte = pte_wrprotect(pte); pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), pte_val(old_pte), pte_val(pte));
From: Sonny Jiang sonny.jiang@amd.com
commit dbbf2728d50343b7947001a81f4c8cc98e4b44e5 upstream.
The UVD firmware is copied to cpu addr in uvd_resume, so it should be used after that. This is to fix a bug introduced by patch drm/amdgpu: fix SI UVD firmware validate resume fail.
Signed-off-by: Sonny Jiang sonny.jiang@amd.com Reviewed-by: Leo Liu leo.liu@amd.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/amd/amdgpu/uvd_v3_1.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -555,13 +555,6 @@ static int uvd_v3_1_sw_init(void *handle if (r) return r;
- /* Retrieval firmware validate key */ - ptr = adev->uvd.inst[0].cpu_addr; - ptr += 192 + 16; - memcpy(&ucode_len, ptr, 4); - ptr += ucode_len; - memcpy(&adev->uvd.keyselect, ptr, 4); - ring = &adev->uvd.inst->ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0, @@ -573,6 +566,13 @@ static int uvd_v3_1_sw_init(void *handle if (r) return r;
+ /* Retrieval firmware validate key */ + ptr = adev->uvd.inst[0].cpu_addr; + ptr += 192 + 16; + memcpy(&ucode_len, ptr, 4); + ptr += ucode_len; + memcpy(&adev->uvd.keyselect, ptr, 4); + r = amdgpu_uvd_entity_init(adev);
return r;
From: Likun Gao Likun.Gao@amd.com
commit 60734bd54679d7998a24a257b0403f7644005572 upstream.
Update golden setting for sienna_cichlid.
Signed-off-by: Likun Gao Likun.Gao@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org # 5.9.x Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3105,6 +3105,8 @@ static const struct soc15_reg_golden gol SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000), + SOC15_REG_GOLDEN_VALUE(GC, 0 ,mmGCEA_SDP_TAG_RESERVE0, 0xffffffff, 0x10100100), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCEA_SDP_TAG_RESERVE1, 0xffffffff, 0x17000088), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_PC_CNTL, 0x003fffff, 0x00280400), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf),
From: Kenneth Feng kenneth.feng@amd.com
commit 7acc79eb5f78d3d1aa5dd21fc0a0329f1b7f2be5 upstream.
fix the null pointer issue when runtime pm is triggered.
Signed-off-by: Kenneth Feng kenneth.feng@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.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/amd/amdgpu/amdgpu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4593,7 +4593,7 @@ int amdgpu_device_baco_enter(struct drm_ if (!amdgpu_device_supports_baco(adev->ddev)) return -ENOTSUPP;
- if (ras && ras->supported) + if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt) adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
return amdgpu_dpm_baco_enter(adev); @@ -4612,7 +4612,7 @@ int amdgpu_device_baco_exit(struct drm_d if (ret) return ret;
- if (ras && ras->supported) + if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt) adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
return 0;
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
commit d661155bfca329851a27bb5120fab027db43bd23 upstream.
The HDCP feature requires at least one connector attached to the device; however, some GPUs do not have a physical output, making the HDCP initialization irrelevant. This patch disables HDCP initialization when the graphic card does not have output.
Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.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/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -960,7 +960,7 @@ static int amdgpu_dm_init(struct amdgpu_ amdgpu_dm_init_color_mod();
#ifdef CONFIG_DRM_AMD_DC_HDCP - if (adev->asic_type >= CHIP_RAVEN) { + if (adev->dm.dc->caps.max_links > 0 && adev->asic_type >= CHIP_RAVEN) { adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc);
if (!adev->dm.hdcp_workqueue)
From: Martijn van de Streek martijn@zeewinde.xyz
[ Upstream commit 022fc5315b7aff69d3df2c953b892a6232642d50 ]
The Trust Flex Design Tablet has an UGTizer USB ID and requires the same initialization as the UGTizer GP0610 to be detected as a graphics tablet instead of a mouse.
Signed-off-by: Martijn van de Streek martijn@zeewinde.xyz Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 ++ drivers/hid/hid-uclogic-params.c | 2 ++ 3 files changed, 5 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 79495e218b7fc..6b7f90a4721f0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1297,6 +1297,7 @@
#define USB_VENDOR_ID_UGTIZER 0x2179 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 +#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
#define USB_VENDOR_ID_VIEWSONIC 0x0543 #define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 86b568037cb8a..8e9c9e646cb7d 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, + USB_DEVICE_ID_UGTIZER_TABLET_GT5040) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_G5) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 7d20d1fcf8d20..d26d8cd98efcf 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params, break; case VID_PID(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610): + case VID_PID(USB_VENDOR_ID_UGTIZER, + USB_DEVICE_ID_UGTIZER_TABLET_GT5040): case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): case VID_PID(USB_VENDOR_ID_UGEE,
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit 3c785a06dee99501a17f8e8cf29b2b7e3f1e94ea ]
The usb-hid keyboard-dock for the Acer Switch 10 SW5-012 model declares an application and hid-usage page of 0x0088 for the INPUT(4) report which it sends. This reports contains 2 8-bit fields which are declared as HID_MAIN_ITEM_VARIABLE.
The keyboard-touchpad combo never actually generates this report, except when the touchpad is toggled on/off with the Fn + F7 hotkey combo. The toggle on/off is handled inside the keyboard-dock, when the touchpad is toggled off it simply stops sending events.
When the touchpad is toggled on/off an INPUT(4) report is generated with the first content byte set to 120/121, before this commit the kernel would report this as ABS_MISC 120/121 events.
Patch the descriptor to replace the HID_MAIN_ITEM_VARIABLE with HID_MAIN_ITEM_RELATIVE (because no key-presss release events are send) and add mappings for the 0x00880078 and 0x00880079 usages to generate touchpad on/off key events when the touchpad is toggled on/off.
Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ite.c | 61 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c index 044a93f3c1178..742c052b0110a 100644 --- a/drivers/hid/hid-ite.c +++ b/drivers/hid/hid-ite.c @@ -11,6 +11,48 @@
#include "hid-ids.h"
+#define QUIRK_TOUCHPAD_ON_OFF_REPORT BIT(0) + +static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) +{ + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + + if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) { + if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) { + hid_info(hdev, "Fixing up ITE keyboard report descriptor\n"); + rdesc[163] = HID_MAIN_ITEM_RELATIVE; + } + } + + return rdesc; +} + +static int ite_input_mapping(struct hid_device *hdev, + struct hid_input *hi, struct hid_field *field, + struct hid_usage *usage, unsigned long **bit, + int *max) +{ + + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + + if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) && + (usage->hid & HID_USAGE_PAGE) == 0x00880000) { + if (usage->hid == 0x00880078) { + /* Touchpad on, userspace expects F22 for this */ + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22); + return 1; + } + if (usage->hid == 0x00880079) { + /* Touchpad off, userspace expects F23 for this */ + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23); + return 1; + } + return -1; + } + + return 0; +} + static int ite_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { @@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field, return 0; }
+static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + + hid_set_drvdata(hdev, (void *)id->driver_data); + + ret = hid_open_report(hdev); + if (ret) + return ret; + + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); +} + static const struct hid_device_id ite_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) }, /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_SYNAPTICS, - USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) }, + USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012), + .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_SYNAPTICS, @@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices); static struct hid_driver ite_driver = { .name = "itetech", .id_table = ite_devices, + .probe = ite_probe, + .report_fixup = ite_report_fixup, + .input_mapping = ite_input_mapping, .event = ite_event, }; module_hid_driver(ite_driver);
From: Frank Yang puilp0502@gmail.com
[ Upstream commit 652f3d00de523a17b0cebe7b90debccf13aa8c31 ]
The Varmilo VA104M Keyboard (04b4:07b1, reported as Varmilo Z104M) exposes media control hotkeys as a USB HID consumer control device, but these keys do not work in the current (5.8-rc1) kernel due to the incorrect HID report descriptor. Fix the problem by modifying the internal HID report descriptor.
More specifically, the keyboard report descriptor specifies the logical boundary as 572~10754 (0x023c ~ 0x2a02) while the usage boundary is specified as 0~10754 (0x00 ~ 0x2a02). This results in an incorrect interpretation of input reports, causing inputs to be ignored. By setting the Logical Minimum to zero, we align the logical boundary with the Usage ID boundary.
Some notes:
* There seem to be multiple variants of the VA104M keyboard. This patch specifically targets 04b4:07b1 variant.
* The device works out-of-the-box on Windows platform with the generic consumer control device driver (hidserv.inf). This suggests that Windows either ignores the Logical Minimum/Logical Maximum or interprets the Usage ID assignment differently from the linux implementation; Maybe there are other devices out there that only works on Windows due to this problem?
Signed-off-by: Frank Yang puilp0502@gmail.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-cypress.c | 44 ++++++++++++++++++++++++++++++++++----- drivers/hid/hid-ids.h | 2 ++ 2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index a50ba4a4a1d71..b88f889b3932e 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -23,19 +23,17 @@ #define CP_2WHEEL_MOUSE_HACK 0x02 #define CP_2WHEEL_MOUSE_HACK_ON 0x04
+#define VA_INVAL_LOGICAL_BOUNDARY 0x08 + /* * Some USB barcode readers from cypress have usage min and usage max in * the wrong order */ -static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); unsigned int i;
- if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) - return rdesc; - if (*rsize < 4) return rdesc;
@@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; }
+static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + /* + * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly + * reports Logical Minimum of its Consumer Control device as 572 + * (0x02 0x3c). Fix this by setting its Logical Minimum to zero. + */ + if (*rsize == 25 && + rdesc[0] == 0x05 && rdesc[1] == 0x0c && + rdesc[2] == 0x09 && rdesc[3] == 0x01 && + rdesc[6] == 0x19 && rdesc[7] == 0x00 && + rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) { + hid_info(hdev, + "fixing up varmilo VA104M consumer control report descriptor\n"); + rdesc[12] = 0x00; + rdesc[13] = 0x00; + } + return rdesc; +} + +static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + + if (quirks & CP_RDESC_SWAPPED_MIN_MAX) + rdesc = cp_rdesc_fixup(hdev, rdesc, rsize); + if (quirks & VA_INVAL_LOGICAL_BOUNDARY) + rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize); + + return rdesc; +} + static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = { .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), .driver_data = CP_2WHEEL_MOUSE_HACK }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1), + .driver_data = VA_INVAL_LOGICAL_BOUNDARY }, { } }; MODULE_DEVICE_TABLE(hid, cp_devices); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6b7f90a4721f0..8e7bd9f1b029c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -331,6 +331,8 @@ #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001
+#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1 0X07b1 + #define USB_VENDOR_ID_DATA_MODUL 0x7374 #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201
From: Jiri Kosina jkosina@suse.cz
[ Upstream commit 1811977cb11354aef8cbd13e35ff50db716728a4 ]
This device needs HID_QUIRK_MULTI_INPUT in order to be presented to userspace in a consistent way.
Reported-and-tested-by: David Gámiz Jiménez david.gamiz@gmail.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 8e7bd9f1b029c..6d6c961f8fee7 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -487,6 +487,7 @@ #define USB_DEVICE_ID_PENPOWER 0x00f4
#define USB_VENDOR_ID_GREENASIA 0x0e8f +#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010 #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013
#define USB_VENDOR_ID_GRETAGMACBETH 0x0971 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 7a2be0205dfd1..b154e11d43bfa 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -83,6 +83,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit b1884583fcd17d6a1b1bba94bbb5826e6b5c6e17 ]
The i8042 module exports several symbols which may be used by other modules.
Before this commit it would refuse to load (when built as a module itself) on systems without an i8042 controller.
This is a problem specifically for the asus-nb-wmi module. Many Asus laptops support the Asus WMI interface. Some of them have an i8042 controller and need to use i8042_install_filter() to filter some kbd events. Other models do not have an i8042 controller (e.g. they use an USB attached kbd).
Before this commit the asus-nb-wmi driver could not be loaded on Asus models without an i8042 controller, when the i8042 code was built as a module (as Arch Linux does) because the module_init function of the i8042 module would fail with -ENODEV and thus the i8042_install_filter symbol could not be loaded.
This commit fixes this by exiting from module_init with a return code of 0 if no controller is found. It also adds a i8042_present bool to make the module_exit function a no-op in this case and also adds a check for i8042_present to the exported i8042_command function.
The latter i8042_present check should not really be necessary because when builtin that function can already be used on systems without an i8042 controller, but better safe then sorry.
Reported-and-tested-by: Marius Iacob themariusus@gmail.com Signed-off-by: Hans de Goede hdegoede@redhat.com Link: https://lore.kernel.org/r/20201008112628.3979-2-hdegoede@redhat.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/serio/i8042.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index d3eda48032e39..944cbb519c6d7 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -122,6 +122,7 @@ module_param_named(unmask_kbd_data, i8042_unmask_kbd_data, bool, 0600); MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]"); #endif
+static bool i8042_present; static bool i8042_bypass_aux_irq_test; static char i8042_kbd_firmware_id[128]; static char i8042_aux_firmware_id[128]; @@ -343,6 +344,9 @@ int i8042_command(unsigned char *param, int command) unsigned long flags; int retval;
+ if (!i8042_present) + return -1; + spin_lock_irqsave(&i8042_lock, flags); retval = __i8042_command(param, command); spin_unlock_irqrestore(&i8042_lock, flags); @@ -1612,12 +1616,15 @@ static int __init i8042_init(void)
err = i8042_platform_init(); if (err) - return err; + return (err == -ENODEV) ? 0 : err;
err = i8042_controller_check(); if (err) goto err_platform_exit;
+ /* Set this before creating the dev to allow i8042_command to work right away */ + i8042_present = true; + pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); if (IS_ERR(pdev)) { err = PTR_ERR(pdev); @@ -1636,6 +1643,9 @@ static int __init i8042_init(void)
static void __exit i8042_exit(void) { + if (!i8042_present) + return; + platform_device_unregister(i8042_platform_device); platform_driver_unregister(&i8042_driver); i8042_platform_exit();
From: Pablo Ceballos pceballos@google.com
[ Upstream commit 34a9fa2025d9d3177c99351c7aaf256c5f50691f ]
Some HID devices don't use a report ID because they only have a single report. In those cases, the report ID in struct hid_report will be zero and the data for the report will start at the first byte, so don't skip over the first byte.
Signed-off-by: Pablo Ceballos pceballos@google.com Acked-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-sensor-hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 94c7398b5c279..3dd7d32467378 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev, return 1;
ptr = raw_data; - ptr++; /* Skip report id */ + if (report->id) + ptr++; /* Skip report id */
spin_lock_irqsave(&pdata->lock, flags);
From: Necip Fazil Yildiran fazilyildiran@gmail.com
[ Upstream commit 06ea594051707c6b8834ef5b24e9b0730edd391b ]
When DMA_RALINK is enabled and DMADEVICES is disabled, it results in the following Kbuild warnings:
WARNING: unmet direct dependencies detected for DMA_ENGINE Depends on [n]: DMADEVICES [=n] Selected by [y]: - DMA_RALINK [=y] && STAGING [=y] && RALINK [=y] && !SOC_RT288X [=n]
WARNING: unmet direct dependencies detected for DMA_VIRTUAL_CHANNELS Depends on [n]: DMADEVICES [=n] Selected by [y]: - DMA_RALINK [=y] && STAGING [=y] && RALINK [=y] && !SOC_RT288X [=n]
The reason is that DMA_RALINK selects DMA_ENGINE and DMA_VIRTUAL_CHANNELS without depending on or selecting DMADEVICES while DMA_ENGINE and DMA_VIRTUAL_CHANNELS are subordinate to DMADEVICES. This can also fail building the kernel as demonstrated in a bug report.
Honor the kconfig dependency to remove unmet direct dependency warnings and avoid any potential build failures.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=210055 Signed-off-by: Necip Fazil Yildiran fazilyildiran@gmail.com Link: https://lore.kernel.org/r/20201104181522.43567-1-fazilyildiran@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/ralink-gdma/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/staging/ralink-gdma/Kconfig b/drivers/staging/ralink-gdma/Kconfig index 54e8029e6b1af..0017376234e28 100644 --- a/drivers/staging/ralink-gdma/Kconfig +++ b/drivers/staging/ralink-gdma/Kconfig @@ -2,6 +2,7 @@ config DMA_RALINK tristate "RALINK DMA support" depends on RALINK && !SOC_RT288X + depends on DMADEVICES select DMA_ENGINE select DMA_VIRTUAL_CHANNELS
From: Chris Ye lzye@google.com
[ Upstream commit f59ee399de4a8ca4d7d19cdcabb4b63e94867f09 ]
Kernel 5.4 introduces HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE, devices need to be set explicitly with this flag.
Signed-off-by: Chris Ye lzye@google.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 4 ++++ drivers/hid/hid-quirks.c | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 6d6c961f8fee7..96e84a51f6b2c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -445,6 +445,10 @@ #define USB_VENDOR_ID_FRUCTEL 0x25B6 #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002
+#define USB_VENDOR_ID_GAMEVICE 0x27F8 +#define USB_DEVICE_ID_GAMEVICE_GV186 0x0BBE +#define USB_DEVICE_ID_GAMEVICE_KISHI 0x0BBF + #define USB_VENDOR_ID_GAMERON 0x0810 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index b154e11d43bfa..bf7ecab5d9e5e 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -85,6 +85,10 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186), + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI), + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
From: Marc Ferland ferlandm@amotus.ca
[ Upstream commit 0ba2df09f1500d3f27398a3382b86d39c3e6abe2 ]
The xilinx_dma_poll_timeout macro is sometimes called while holding a spinlock (see xilinx_dma_issue_pending() for an example) this means we shouldn't sleep when polling the dma channel registers. To address it in xilinx poll timeout macro use readl_poll_timeout_atomic instead of readl_poll_timeout variant.
Signed-off-by: Marc Ferland ferlandm@amotus.ca Signed-off-by: Radhey Shyam Pandey radhey.shyam.pandey@xilinx.com Link: https://lore.kernel.org/r/1604473206-32573-2-git-send-email-radhey.shyam.pan... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/xilinx/xilinx_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 0fc432567b857..993297d585c01 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -517,8 +517,8 @@ struct xilinx_dma_device { #define to_dma_tx_descriptor(tx) \ container_of(tx, struct xilinx_dma_tx_descriptor, async_tx) #define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \ - readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \ - cond, delay_us, timeout_us) + readl_poll_timeout_atomic(chan->xdev->regs + chan->ctrl_offset + reg, \ + val, cond, delay_us, timeout_us)
/* IO accessors */ static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
From: Brian Masney bmasney@redhat.com
[ Upstream commit 65cae18882f943215d0505ddc7e70495877308e6 ]
When booting a hyperthreaded system with the kernel parameter 'mitigations=auto,nosmt', the following warning occurs:
WARNING: CPU: 0 PID: 1 at drivers/xen/events/events_base.c:1112 unbind_from_irqhandler+0x4e/0x60 ... Hardware name: Xen HVM domU, BIOS 4.2.amazon 08/24/2006 ... Call Trace: xen_uninit_lock_cpu+0x28/0x62 xen_hvm_cpu_die+0x21/0x30 takedown_cpu+0x9c/0xe0 ? trace_suspend_resume+0x60/0x60 cpuhp_invoke_callback+0x9a/0x530 _cpu_up+0x11a/0x130 cpu_up+0x7e/0xc0 bringup_nonboot_cpus+0x48/0x50 smp_init+0x26/0x79 kernel_init_freeable+0xea/0x229 ? rest_init+0xaa/0xaa kernel_init+0xa/0x106 ret_from_fork+0x35/0x40
The secondary CPUs are not activated with the nosmt mitigations and only the primary thread on each CPU core is used. In this situation, xen_hvm_smp_prepare_cpus(), and more importantly xen_init_lock_cpu(), is not called, so the lock_kicker_irq is not initialized for the secondary CPUs. Let's fix this by exiting early in xen_uninit_lock_cpu() if the irq is not set to avoid the warning from above for each secondary CPU.
Signed-off-by: Brian Masney bmasney@redhat.com Link: https://lore.kernel.org/r/20201107011119.631442-1-bmasney@redhat.com Reviewed-by: Juergen Gross jgross@suse.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/xen/spinlock.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 799f4eba0a621..043c73dfd2c98 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -93,10 +93,20 @@ void xen_init_lock_cpu(int cpu)
void xen_uninit_lock_cpu(int cpu) { + int irq; + if (!xen_pvspin) return;
- unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); + /* + * When booting the kernel with 'mitigations=auto,nosmt', the secondary + * CPUs are not activated, and lock_kicker_irq is not initialized. + */ + irq = per_cpu(lock_kicker_irq, cpu); + if (irq == -1) + return; + + unbind_from_irqhandler(irq, NULL); per_cpu(lock_kicker_irq, cpu) = -1; kfree(per_cpu(irq_name, cpu)); per_cpu(irq_name, cpu) = NULL;
From: Daniel Latypov dlatypov@google.com
[ Upstream commit 3084db0e0d5076cd48408274ab0911cd3ccdae88 ]
Currently the following expectation KUNIT_EXPECT_STREQ(test, "hi", "bye"); will produce: Expected "hi" == "bye", but "hi" == 1625079497 "bye" == 1625079500
After this patch: Expected "hi" == "bye", but "hi" == hi "bye" == bye
KUNIT_INIT_BINARY_STR_ASSERT_STRUCT() was written but just mistakenly not actually used by KUNIT_EXPECT_STREQ() and friends.
Signed-off-by: Daniel Latypov dlatypov@google.com Reviewed-by: Brendan Higgins brendanhiggins@google.com Tested-by: Brendan Higgins brendanhiggins@google.com Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/kunit/test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/kunit/test.h b/include/kunit/test.h index 59f3144f009a5..b68ba33c16937 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -1064,7 +1064,7 @@ do { \ KUNIT_ASSERTION(test, \ strcmp(__left, __right) op 0, \ kunit_binary_str_assert, \ - KUNIT_INIT_BINARY_ASSERT_STRUCT(test, \ + KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ assert_type, \ #op, \ #left, \
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit c27168a04a438a457c100253b1aaf0c779218aae ]
Like the MX5000 and MX5500 quad/bluetooth keyboards the Dinovo Edge also needs the HIDPP_CONSUMER_VENDOR_KEYS quirk for some special keys to work. Specifically without this the "Phone" and the 'A' - 'D' Smart Keys do not send any events.
In addition to fixing these keys not sending any events, adding the Bluetooth match, so that hid-logitech-hidpp is used instead of the generic HID driver, also adds battery monitoring support when the keyboard is connected over Bluetooth.
Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Benjamin Tissoires benjamin.tissoires@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-logitech-hidpp.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index a2991622702ae..0ca7231195473 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3997,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = { { /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */ LDJ_DEVICE(0xb305), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, + { /* Dinovo Edge (Bluetooth-receiver in HID proxy mode) */ + LDJ_DEVICE(0xb309), + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, { /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */ LDJ_DEVICE(0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, @@ -4039,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX5000 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, + { /* Dinovo Edge keyboard over Bluetooth */ + HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb309), + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, { /* MX5500 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit 7940fb035abd88040d56be209962feffa33b03d0 ]
The battery status is also being reported by the logitech-hidpp driver, so ignore the standard HID battery status to avoid reporting the same info twice.
Note the logitech-hidpp battery driver provides more info, such as properly differentiating between charging and discharging. Also the standard HID battery info seems to be wrong, reporting a capacity of just 26% after fully charging the device.
Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Benjamin Tissoires benjamin.tissoires@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-input.c | 3 +++ 2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 96e84a51f6b2c..a6d63a7590434 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -749,6 +749,7 @@ #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_T651 0xb00c +#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309 #define USB_DEVICE_ID_LOGITECH_C007 0xc007 #define USB_DEVICE_ID_LOGITECH_C077 0xc077 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 9770db624bfaf..4dca113924593 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), HID_BATTERY_QUIRK_IGNORE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), + HID_BATTERY_QUIRK_IGNORE }, {} };
From: Jens Axboe axboe@kernel.dk
[ Upstream commit 8d4c3e76e3be11a64df95ddee52e99092d42fc19 ]
If this is attempted by a kthread, then return -EOPNOTSUPP as we don't currently support that. Once we can get task_pid_ptr() doing the right thing, then this can go away again.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/proc/self.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/fs/proc/self.c b/fs/proc/self.c index 72cd69bcaf4ad..cc71ce3466dc0 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry, pid_t tgid = task_tgid_nr_ns(current, ns); char *name;
+ /* + * Not currently supported. Once we can inherit all of struct pid, + * we can allow this. + */ + if (current->flags & PF_KTHREAD) + return ERR_PTR(-EOPNOTSUPP); + if (!tgid) return ERR_PTR(-ENOENT); /* max length of unsigned int in decimal + NULL term */
From: Minwoo Im minwoo.im.dev@gmail.com
[ Upstream commit 0f0d2c876c96d4908a9ef40959a44bec21bdd6cf ]
If Doorbell Buffer Config command fails even 'dev->dbbuf_dbs != NULL' which means OACS indicates that NVME_CTRL_OACS_DBBUF_SUPP is set, nvme_dbbuf_update_and_check_event() will check event even it's not been successfully set.
This patch fixes mismatch among dbbuf for sq/cqs in case that dbbuf command fails.
Signed-off-by: Minwoo Im minwoo.im.dev@gmail.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index a6af96aaa0eb7..3448f7ac209a0 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -292,9 +292,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev, nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)]; }
+static void nvme_dbbuf_free(struct nvme_queue *nvmeq) +{ + if (!nvmeq->qid) + return; + + nvmeq->dbbuf_sq_db = NULL; + nvmeq->dbbuf_cq_db = NULL; + nvmeq->dbbuf_sq_ei = NULL; + nvmeq->dbbuf_cq_ei = NULL; +} + static void nvme_dbbuf_set(struct nvme_dev *dev) { struct nvme_command c; + unsigned int i;
if (!dev->dbbuf_dbs) return; @@ -308,6 +320,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) dev_warn(dev->ctrl.device, "unable to set dbbuf\n"); /* Free memory and continue on */ nvme_dbbuf_dma_free(dev); + + for (i = 1; i <= dev->online_queues; i++) + nvme_dbbuf_free(&dev->queues[i]); } }
From: Jens Axboe axboe@kernel.dk
[ Upstream commit 944d1444d53f5a213457e5096db370cfd06923d4 ]
Any attempt to do path resolution on /proc/self from an async worker will yield -EOPNOTSUPP. We can safely do that resolution from the task itself, and without blocking, so retry it from there.
Ideally io_uring would know this upfront and not have to go through the worker thread to find out, but that doesn't currently seem feasible.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/io_uring.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c index 185c206e5683f..5d9f8e40b93d3 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -436,6 +436,7 @@ struct io_sr_msg { struct io_open { struct file *file; int dfd; + bool ignore_nonblock; struct filename *filename; struct open_how how; unsigned long nofile; @@ -3591,6 +3592,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe return ret; } req->open.nofile = rlimit(RLIMIT_NOFILE); + req->open.ignore_nonblock = false; req->flags |= REQ_F_NEED_CLEANUP; return 0; } @@ -3638,7 +3640,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock) struct file *file; int ret;
- if (force_nonblock) + if (force_nonblock && !req->open.ignore_nonblock) return -EAGAIN;
ret = build_open_flags(&req->open.how, &op); @@ -3653,6 +3655,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock) if (IS_ERR(file)) { put_unused_fd(ret); ret = PTR_ERR(file); + /* + * A work-around to ensure that /proc/self works that way + * that it should - if we get -EOPNOTSUPP back, then assume + * that proc_self_get_link() failed us because we're in async + * context. We should be safe to retry this from the task + * itself with force_nonblock == false set, as it should not + * block on lookup. Would be nice to know this upfront and + * avoid the async dance, but doesn't seem feasible. + */ + if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) { + req->open.ignore_nonblock = true; + refcount_inc(&req->refs); + io_req_task_queue(req); + return 0; + } } else { fsnotify_open(file); fd_install(ret, file);
From: Jisheng Zhang Jisheng.Zhang@synaptics.com
[ Upstream commit 56311a315da7ebc668dbcc2f1c99689cc10796c4 ]
If the phy enables power saving technology, the dwmac's software reset needs more time to complete, enlarge dma reset timeout to 200000us.
Signed-off-by: Jisheng Zhang Jisheng.Zhang@synaptics.com Link: https://lore.kernel.org/r/20201113090902.5c7aab1a@xhacker.debian Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index cb87d31a99dfb..57a53a600aa55 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -23,7 +23,7 @@ int dwmac_dma_reset(void __iomem *ioaddr)
return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value, !(value & DMA_BUS_MODE_SFT_RESET), - 10000, 100000); + 10000, 200000); }
/* CSR1 enables the transmit DMA to check for new descriptor */
From: Laurent Vivier lvivier@redhat.com
[ Upstream commit a312db697cb05dfa781848afe8585a1e1f2a5a99 ]
ERROR: modpost: "mac_pton" [drivers/vdpa/vdpa_sim/vdpa_sim.ko] undefined!
mac_pton() is defined in lib/net_utils.c and is not built if NET is not set.
Select GENERIC_NET_UTILS as vdpasim doesn't depend on NET.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Laurent Vivier lvivier@redhat.com Link: https://lore.kernel.org/r/20201113155706.599434-1-lvivier@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Acked-by: Randy Dunlap rdunlap@infradead.org # build-tested Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vdpa/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig index d7d32b6561021..358f6048dd3ce 100644 --- a/drivers/vdpa/Kconfig +++ b/drivers/vdpa/Kconfig @@ -13,6 +13,7 @@ config VDPA_SIM depends on RUNTIME_TESTING_MENU && HAS_DMA select DMA_OPS select VHOST_RING + select GENERIC_NET_UTILS default n help vDPA networking device simulator which loop TX traffic back
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 6bcf34224ac1e94103797fd68b9836061762f2b2 ]
This adds a helper check if a vq has been setup. The next patches will use this when we move the vhost scsi cmd preallocation from per session to per vq. In the per vq case, we only want to allocate cmds for vqs that have actually been setup and not for all the possible vqs.
Signed-off-by: Mike Christie michael.christie@oracle.com Link: https://lore.kernel.org/r/1604986403-4931-2-git-send-email-michael.christie@... Signed-off-by: Michael S. Tsirkin mst@redhat.com Acked-by: Jason Wang jasowang@redhat.com Acked-by: Stefan Hajnoczi stefanha@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vhost/vhost.c | 6 ++++++ drivers/vhost/vhost.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 9ad45e1d27f0f..23e7b2d624511 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -305,6 +305,12 @@ static void vhost_vring_call_reset(struct vhost_vring_call *call_ctx) spin_lock_init(&call_ctx->ctx_lock); }
+bool vhost_vq_is_setup(struct vhost_virtqueue *vq) +{ + return vq->avail && vq->desc && vq->used && vhost_vq_access_ok(vq); +} +EXPORT_SYMBOL_GPL(vhost_vq_is_setup); + static void vhost_vq_reset(struct vhost_dev *dev, struct vhost_virtqueue *vq) { diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 9032d3c2a9f48..3d30b3da7bcf5 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -190,6 +190,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *, struct vhost_log *log, unsigned int *log_num); void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
+bool vhost_vq_is_setup(struct vhost_virtqueue *vq); int vhost_vq_init_access(struct vhost_virtqueue *); int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 25b98b64e28423b0769313dcaf96423836b1f93d ]
We currently are limited to 256 cmds per session. This leads to problems where if the user has increased virtqueue_size to more than 2 or cmd_per_lun to more than 256 vhost_scsi_get_tag can fail and the guest will get IO errors.
This patch moves the cmd allocation to per vq so we can easily match whatever the user has specified for num_queues and virtqueue_size/cmd_per_lun. It also makes it easier to control how much memory we preallocate. For cases, where perf is not as important and we can use the current defaults (1 vq and 128 cmds per vq) memory use from preallocate cmds is cut in half. For cases, where we are willing to use more memory for higher perf, cmd mem use will now increase as the num queues and queue depth increases.
Signed-off-by: Mike Christie michael.christie@oracle.com Link: https://lore.kernel.org/r/1604986403-4931-3-git-send-email-michael.christie@... Signed-off-by: Michael S. Tsirkin mst@redhat.com Reviewed-by: Maurizio Lombardi mlombard@redhat.com Acked-by: Stefan Hajnoczi stefanha@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vhost/scsi.c | 207 ++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 79 deletions(-)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index b22adf03f5842..e31339be7dd78 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -52,7 +52,6 @@ #define VHOST_SCSI_VERSION "v0.1" #define VHOST_SCSI_NAMELEN 256 #define VHOST_SCSI_MAX_CDB_SIZE 32 -#define VHOST_SCSI_DEFAULT_TAGS 256 #define VHOST_SCSI_PREALLOC_SGLS 2048 #define VHOST_SCSI_PREALLOC_UPAGES 2048 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048 @@ -189,6 +188,9 @@ struct vhost_scsi_virtqueue { * Writers must also take dev mutex and flush under it. */ int inflight_idx; + struct vhost_scsi_cmd *scsi_cmds; + struct sbitmap scsi_tags; + int max_cmds; };
struct vhost_scsi { @@ -324,7 +326,9 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) { struct vhost_scsi_cmd *tv_cmd = container_of(se_cmd, struct vhost_scsi_cmd, tvc_se_cmd); - struct se_session *se_sess = tv_cmd->tvc_nexus->tvn_se_sess; + struct vhost_scsi_virtqueue *svq = container_of(tv_cmd->tvc_vq, + struct vhost_scsi_virtqueue, vq); + struct vhost_scsi_inflight *inflight = tv_cmd->inflight; int i;
if (tv_cmd->tvc_sgl_count) { @@ -336,8 +340,8 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) put_page(sg_page(&tv_cmd->tvc_prot_sgl[i])); }
- vhost_scsi_put_inflight(tv_cmd->inflight); - target_free_tag(se_sess, se_cmd); + sbitmap_clear_bit(&svq->scsi_tags, se_cmd->map_tag); + vhost_scsi_put_inflight(inflight); }
static u32 vhost_scsi_sess_get_index(struct se_session *se_sess) @@ -566,31 +570,31 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) }
static struct vhost_scsi_cmd * -vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, +vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr, u32 exp_data_len, int data_direction) { + struct vhost_scsi_virtqueue *svq = container_of(vq, + struct vhost_scsi_virtqueue, vq); struct vhost_scsi_cmd *cmd; struct vhost_scsi_nexus *tv_nexus; - struct se_session *se_sess; struct scatterlist *sg, *prot_sg; struct page **pages; - int tag, cpu; + int tag;
tv_nexus = tpg->tpg_nexus; if (!tv_nexus) { pr_err("Unable to locate active struct vhost_scsi_nexus\n"); return ERR_PTR(-EIO); } - se_sess = tv_nexus->tvn_se_sess;
- tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); + tag = sbitmap_get(&svq->scsi_tags, 0, false); if (tag < 0) { pr_err("Unable to obtain tag for vhost_scsi_cmd\n"); return ERR_PTR(-ENOMEM); }
- cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[tag]; + cmd = &svq->scsi_cmds[tag]; sg = cmd->tvc_sgl; prot_sg = cmd->tvc_prot_sgl; pages = cmd->tvc_upages; @@ -599,7 +603,6 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, cmd->tvc_prot_sgl = prot_sg; cmd->tvc_upages = pages; cmd->tvc_se_cmd.map_tag = tag; - cmd->tvc_se_cmd.map_cpu = cpu; cmd->tvc_tag = scsi_tag; cmd->tvc_lun = lun; cmd->tvc_task_attr = task_attr; @@ -1065,11 +1068,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) scsi_command_size(cdb), VHOST_SCSI_MAX_CDB_SIZE); goto err; } - cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr, + cmd = vhost_scsi_get_cmd(vq, tpg, cdb, tag, lun, task_attr, exp_data_len + prot_bytes, data_direction); if (IS_ERR(cmd)) { - vq_err(vq, "vhost_scsi_get_tag failed %ld\n", + vq_err(vq, "vhost_scsi_get_cmd failed %ld\n", PTR_ERR(cmd)); goto err; } @@ -1373,6 +1376,83 @@ static void vhost_scsi_flush(struct vhost_scsi *vs) wait_for_completion(&old_inflight[i]->comp); }
+static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq) +{ + struct vhost_scsi_virtqueue *svq = container_of(vq, + struct vhost_scsi_virtqueue, vq); + struct vhost_scsi_cmd *tv_cmd; + unsigned int i; + + if (!svq->scsi_cmds) + return; + + for (i = 0; i < svq->max_cmds; i++) { + tv_cmd = &svq->scsi_cmds[i]; + + kfree(tv_cmd->tvc_sgl); + kfree(tv_cmd->tvc_prot_sgl); + kfree(tv_cmd->tvc_upages); + } + + sbitmap_free(&svq->scsi_tags); + kfree(svq->scsi_cmds); + svq->scsi_cmds = NULL; +} + +static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds) +{ + struct vhost_scsi_virtqueue *svq = container_of(vq, + struct vhost_scsi_virtqueue, vq); + struct vhost_scsi_cmd *tv_cmd; + unsigned int i; + + if (svq->scsi_cmds) + return 0; + + if (sbitmap_init_node(&svq->scsi_tags, max_cmds, -1, GFP_KERNEL, + NUMA_NO_NODE)) + return -ENOMEM; + svq->max_cmds = max_cmds; + + svq->scsi_cmds = kcalloc(max_cmds, sizeof(*tv_cmd), GFP_KERNEL); + if (!svq->scsi_cmds) { + sbitmap_free(&svq->scsi_tags); + return -ENOMEM; + } + + for (i = 0; i < max_cmds; i++) { + tv_cmd = &svq->scsi_cmds[i]; + + tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS, + sizeof(struct scatterlist), + GFP_KERNEL); + if (!tv_cmd->tvc_sgl) { + pr_err("Unable to allocate tv_cmd->tvc_sgl\n"); + goto out; + } + + tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES, + sizeof(struct page *), + GFP_KERNEL); + if (!tv_cmd->tvc_upages) { + pr_err("Unable to allocate tv_cmd->tvc_upages\n"); + goto out; + } + + tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS, + sizeof(struct scatterlist), + GFP_KERNEL); + if (!tv_cmd->tvc_prot_sgl) { + pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n"); + goto out; + } + } + return 0; +out: + vhost_scsi_destroy_vq_cmds(vq); + return -ENOMEM; +} + /* * Called from vhost_scsi_ioctl() context to walk the list of available * vhost_scsi_tpg with an active struct vhost_scsi_nexus @@ -1427,10 +1507,9 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) { if (vs->vs_tpg && vs->vs_tpg[tpg->tport_tpgt]) { - kfree(vs_tpg); mutex_unlock(&tpg->tv_tpg_mutex); ret = -EEXIST; - goto out; + goto undepend; } /* * In order to ensure individual vhost-scsi configfs @@ -1442,9 +1521,8 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, ret = target_depend_item(&se_tpg->tpg_group.cg_item); if (ret) { pr_warn("target_depend_item() failed: %d\n", ret); - kfree(vs_tpg); mutex_unlock(&tpg->tv_tpg_mutex); - goto out; + goto undepend; } tpg->tv_tpg_vhost_count++; tpg->vhost_scsi = vs; @@ -1457,6 +1535,16 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, if (match) { memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn, sizeof(vs->vs_vhost_wwpn)); + + for (i = VHOST_SCSI_VQ_IO; i < VHOST_SCSI_MAX_VQ; i++) { + vq = &vs->vqs[i].vq; + if (!vhost_vq_is_setup(vq)) + continue; + + if (vhost_scsi_setup_vq_cmds(vq, vq->num)) + goto destroy_vq_cmds; + } + for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) { vq = &vs->vqs[i].vq; mutex_lock(&vq->mutex); @@ -1476,7 +1564,22 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, vhost_scsi_flush(vs); kfree(vs->vs_tpg); vs->vs_tpg = vs_tpg; + goto out;
+destroy_vq_cmds: + for (i--; i >= VHOST_SCSI_VQ_IO; i--) { + if (!vhost_vq_get_backend(&vs->vqs[i].vq)) + vhost_scsi_destroy_vq_cmds(&vs->vqs[i].vq); + } +undepend: + for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) { + tpg = vs_tpg[i]; + if (tpg) { + tpg->tv_tpg_vhost_count--; + target_undepend_item(&tpg->se_tpg.tpg_group.cg_item); + } + } + kfree(vs_tpg); out: mutex_unlock(&vs->dev.mutex); mutex_unlock(&vhost_scsi_mutex); @@ -1549,6 +1652,12 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, mutex_lock(&vq->mutex); vhost_vq_set_backend(vq, NULL); mutex_unlock(&vq->mutex); + /* + * Make sure cmds are not running before tearing them + * down. + */ + vhost_scsi_flush(vs); + vhost_scsi_destroy_vq_cmds(vq); } } /* @@ -1842,23 +1951,6 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg, mutex_unlock(&vhost_scsi_mutex); }
-static void vhost_scsi_free_cmd_map_res(struct se_session *se_sess) -{ - struct vhost_scsi_cmd *tv_cmd; - unsigned int i; - - if (!se_sess->sess_cmd_map) - return; - - for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) { - tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i]; - - kfree(tv_cmd->tvc_sgl); - kfree(tv_cmd->tvc_prot_sgl); - kfree(tv_cmd->tvc_upages); - } -} - static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_store( struct config_item *item, const char *page, size_t count) { @@ -1898,45 +1990,6 @@ static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = { NULL, };
-static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg, - struct se_session *se_sess, void *p) -{ - struct vhost_scsi_cmd *tv_cmd; - unsigned int i; - - for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) { - tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i]; - - tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS, - sizeof(struct scatterlist), - GFP_KERNEL); - if (!tv_cmd->tvc_sgl) { - pr_err("Unable to allocate tv_cmd->tvc_sgl\n"); - goto out; - } - - tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES, - sizeof(struct page *), - GFP_KERNEL); - if (!tv_cmd->tvc_upages) { - pr_err("Unable to allocate tv_cmd->tvc_upages\n"); - goto out; - } - - tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS, - sizeof(struct scatterlist), - GFP_KERNEL); - if (!tv_cmd->tvc_prot_sgl) { - pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n"); - goto out; - } - } - return 0; -out: - vhost_scsi_free_cmd_map_res(se_sess); - return -ENOMEM; -} - static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg, const char *name) { @@ -1960,12 +2013,9 @@ static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg, * struct se_node_acl for the vhost_scsi struct se_portal_group with * the SCSI Initiator port name of the passed configfs group 'name'. */ - tv_nexus->tvn_se_sess = target_setup_session(&tpg->se_tpg, - VHOST_SCSI_DEFAULT_TAGS, - sizeof(struct vhost_scsi_cmd), + tv_nexus->tvn_se_sess = target_setup_session(&tpg->se_tpg, 0, 0, TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS, - (unsigned char *)name, tv_nexus, - vhost_scsi_nexus_cb); + (unsigned char *)name, tv_nexus, NULL); if (IS_ERR(tv_nexus->tvn_se_sess)) { mutex_unlock(&tpg->tv_tpg_mutex); kfree(tv_nexus); @@ -2015,7 +2065,6 @@ static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg) " %s Initiator Port: %s\n", vhost_scsi_dump_proto_id(tpg->tport), tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
- vhost_scsi_free_cmd_map_res(se_sess); /* * Release the SCSI I_T Nexus to the emulated vhost Target Port */
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 47a3565e8bb14ec48a75b48daf57aa830e2691f8 ]
We might not do the final se_cmd put from vhost_scsi_complete_cmd_work. When the last put happens a little later then we could race where vhost_scsi_complete_cmd_work does vhost_signal, the guest runs and sends more IO, and vhost_scsi_handle_vq runs but does not find any free cmds.
This patch has us delay completing the cmd until the last lio core ref is dropped. We then know that once we signal to the guest that the cmd is completed that if it queues a new command it will find a free cmd.
Signed-off-by: Mike Christie michael.christie@oracle.com Reviewed-by: Maurizio Lombardi mlombard@redhat.com Link: https://lore.kernel.org/r/1604986403-4931-4-git-send-email-michael.christie@... Signed-off-by: Michael S. Tsirkin mst@redhat.com Acked-by: Stefan Hajnoczi stefanha@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vhost/scsi.c | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index e31339be7dd78..5d8850f5aef16 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -322,7 +322,7 @@ static u32 vhost_scsi_tpg_get_inst_index(struct se_portal_group *se_tpg) return 1; }
-static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) +static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd) { struct vhost_scsi_cmd *tv_cmd = container_of(se_cmd, struct vhost_scsi_cmd, tvc_se_cmd); @@ -344,6 +344,16 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) vhost_scsi_put_inflight(inflight); }
+static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) +{ + struct vhost_scsi_cmd *cmd = container_of(se_cmd, + struct vhost_scsi_cmd, tvc_se_cmd); + struct vhost_scsi *vs = cmd->tvc_vhost; + + llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list); + vhost_work_queue(&vs->dev, &vs->vs_completion_work); +} + static u32 vhost_scsi_sess_get_index(struct se_session *se_sess) { return 0; @@ -366,28 +376,15 @@ static int vhost_scsi_get_cmd_state(struct se_cmd *se_cmd) return 0; }
-static void vhost_scsi_complete_cmd(struct vhost_scsi_cmd *cmd) -{ - struct vhost_scsi *vs = cmd->tvc_vhost; - - llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list); - - vhost_work_queue(&vs->dev, &vs->vs_completion_work); -} - static int vhost_scsi_queue_data_in(struct se_cmd *se_cmd) { - struct vhost_scsi_cmd *cmd = container_of(se_cmd, - struct vhost_scsi_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(cmd); + transport_generic_free_cmd(se_cmd, 0); return 0; }
static int vhost_scsi_queue_status(struct se_cmd *se_cmd) { - struct vhost_scsi_cmd *cmd = container_of(se_cmd, - struct vhost_scsi_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(cmd); + transport_generic_free_cmd(se_cmd, 0); return 0; }
@@ -433,15 +430,6 @@ vhost_scsi_allocate_evt(struct vhost_scsi *vs, return evt; }
-static void vhost_scsi_free_cmd(struct vhost_scsi_cmd *cmd) -{ - struct se_cmd *se_cmd = &cmd->tvc_se_cmd; - - /* TODO locking against target/backend threads? */ - transport_generic_free_cmd(se_cmd, 0); - -} - static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd) { return target_put_sess_cmd(se_cmd); @@ -560,7 +548,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) } else pr_err("Faulted on virtio_scsi_cmd_resp\n");
- vhost_scsi_free_cmd(cmd); + vhost_scsi_release_cmd_res(se_cmd); }
vq = -1; @@ -1091,7 +1079,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) &prot_iter, exp_data_len, &data_iter))) { vq_err(vq, "Failed to map iov to sgl\n"); - vhost_scsi_release_cmd(&cmd->tvc_se_cmd); + vhost_scsi_release_cmd_res(&cmd->tvc_se_cmd); goto err; } }
From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit c39de538a06e76d89b7e598a71e16688009cd56c ]
Annotate tegra_pm_set[clear]_cpu_in_lp2() with RCU_NONIDLE in order to fix lockdep warning about suspicious RCU usage of a spinlock during late idling phase.
WARNING: suspicious RCU usage ... include/trace/events/lock.h:13 suspicious rcu_dereference_check() usage! ... (dump_stack) from (lock_acquire) (lock_acquire) from (_raw_spin_lock) (_raw_spin_lock) from (tegra_pm_set_cpu_in_lp2) (tegra_pm_set_cpu_in_lp2) from (tegra_cpuidle_enter) (tegra_cpuidle_enter) from (cpuidle_enter_state) (cpuidle_enter_state) from (cpuidle_enter_state_coupled) (cpuidle_enter_state_coupled) from (cpuidle_enter) (cpuidle_enter) from (do_idle) ...
Tested-by: Peter Geis pgwipeout@gmail.com Reported-by: Peter Geis pgwipeout@gmail.com Signed-off-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/cpuidle/cpuidle-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c index e8956706a2917..191966dc8d023 100644 --- a/drivers/cpuidle/cpuidle-tegra.c +++ b/drivers/cpuidle/cpuidle-tegra.c @@ -189,7 +189,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, }
local_fiq_disable(); - tegra_pm_set_cpu_in_lp2(); + RCU_NONIDLE(tegra_pm_set_cpu_in_lp2()); cpu_pm_enter();
switch (index) { @@ -207,7 +207,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, }
cpu_pm_exit(); - tegra_pm_clear_cpu_in_lp2(); + RCU_NONIDLE(tegra_pm_clear_cpu_in_lp2()); local_fiq_enable();
return err ?: index;
From: Sugar Zhang sugar.zhang@rock-chips.com
[ Upstream commit e773ca7da8beeca7f17fe4c9d1284a2b66839cc1 ]
Actually, burst size is equal to '1 << desc->rqcfg.brst_size'. we should use burst size, not desc->rqcfg.brst_size.
dma memcpy performance on Rockchip RV1126 @ 1512MHz A7, 1056MHz LPDDR3, 200MHz DMA:
dmatest:
/# echo dma0chan0 > /sys/module/dmatest/parameters/channel /# echo 4194304 > /sys/module/dmatest/parameters/test_buf_size /# echo 8 > /sys/module/dmatest/parameters/iterations /# echo y > /sys/module/dmatest/parameters/norandom /# echo y > /sys/module/dmatest/parameters/verbose /# echo 1 > /sys/module/dmatest/parameters/run
dmatest: dma0chan0-copy0: result #1: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #2: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #3: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #4: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #5: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #6: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #7: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000 dmatest: dma0chan0-copy0: result #8: 'test passed' with src_off=0x0 dst_off=0x0 len=0x400000
Before:
dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 48 iops 200338 KB/s (0)
After this patch:
dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 179 iops 734873 KB/s (0)
After this patch and increase dma clk to 400MHz:
dmatest: dma0chan0-copy0: summary 8 tests, 0 failures 259 iops 1062929 KB/s (0)
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com Link: https://lore.kernel.org/r/1605326106-55681-1-git-send-email-sugar.zhang@rock... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/pl330.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 5274a0704d960..2c3c47e4f7770 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2802,7 +2802,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, * If burst size is smaller than bus width then make sure we only * transfer one at a time to avoid a burst stradling an MFIFO entry. */ - if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width) + if (burst * 8 < pl330->pcfg.data_bus_width) desc->rqcfg.brst_len = 1;
desc->bytes_requested = len;
From: Lee Duncan lduncan@suse.com
[ Upstream commit fe0a8a95e7134d0b44cd407bc0085b9ba8d8fe31 ]
iSCSI NOPs are sometimes "lost", mistakenly sent to the user-land iscsid daemon instead of handled in the kernel, as they should be, resulting in a message from the daemon like:
iscsid: Got nop in, but kernel supports nop handling.
This can occur because of the new forward- and back-locks, and the fact that an iSCSI NOP response can occur before processing of the NOP send is complete. This can result in "conn->ping_task" being NULL in iscsi_nop_out_rsp(), when the pointer is actually in the process of being set.
To work around this, we add a new state to the "ping_task" pointer. In addition to NULL (not assigned) and a pointer (assigned), we add the state "being set", which is signaled with an INVALID pointer (using "-1").
Link: https://lore.kernel.org/r/20201106193317.16993-1-leeman.duncan@gmail.com Reviewed-by: Mike Christie michael.christie@oracle.com Signed-off-by: Lee Duncan lduncan@suse.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/libiscsi.c | 23 +++++++++++++++-------- include/scsi/libiscsi.h | 3 +++ 2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1e9c3171fa9f4..f9314f1393fbd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -533,8 +533,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) if (conn->task == task) conn->task = NULL;
- if (conn->ping_task == task) - conn->ping_task = NULL; + if (READ_ONCE(conn->ping_task) == task) + WRITE_ONCE(conn->ping_task, NULL);
/* release get from queueing */ __iscsi_put_task(task); @@ -738,6 +738,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, task->conn->session->age); }
+ if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) + WRITE_ONCE(conn->ping_task, task); + if (!ihost->workq) { if (iscsi_prep_mgmt_task(conn, task)) goto free_task; @@ -941,8 +944,11 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) struct iscsi_nopout hdr; struct iscsi_task *task;
- if (!rhdr && conn->ping_task) - return -EINVAL; + if (!rhdr) { + if (READ_ONCE(conn->ping_task)) + return -EINVAL; + WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); + }
memset(&hdr, 0, sizeof(struct iscsi_nopout)); hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; @@ -957,11 +963,12 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); if (!task) { + if (!rhdr) + WRITE_ONCE(conn->ping_task, NULL); iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); return -EIO; } else if (!rhdr) { /* only track our nops */ - conn->ping_task = task; conn->last_ping = jiffies; }
@@ -984,7 +991,7 @@ static int iscsi_nop_out_rsp(struct iscsi_task *task, struct iscsi_conn *conn = task->conn; int rc = 0;
- if (conn->ping_task != task) { + if (READ_ONCE(conn->ping_task) != task) { /* * If this is not in response to one of our * nops then it must be from userspace. @@ -1923,7 +1930,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) */ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) { - if (conn->ping_task && + if (READ_ONCE(conn->ping_task) && time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) return 1; @@ -2058,7 +2065,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) * Checking the transport already or nop from a cmd timeout still * running */ - if (conn->ping_task) { + if (READ_ONCE(conn->ping_task)) { task->have_checked_conn = true; rc = BLK_EH_RESET_TIMER; goto done; diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index c25fb86ffae95..b3bbd10eb3f07 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -132,6 +132,9 @@ struct iscsi_task { void *dd_data; /* driver/transport data */ };
+/* invalid scsi_task pointer */ +#define INVALID_SCSI_TASK (struct iscsi_task *)-1l + static inline int iscsi_task_has_unsol_data(struct iscsi_task *task) { return task->unsol_r2t.data_length > task->unsol_r2t.sent;
From: Mike Christie michael.christie@oracle.com
[ Upstream commit f36199355c64a39fe82cfddc7623d827c7e050da ]
Maurizio found a race where the abort and cmd stop paths can race as follows:
1. thread1 runs iscsit_release_commands_from_conn and sets CMD_T_FABRIC_STOP.
2. thread2 runs iscsit_aborted_task and then does __iscsit_free_cmd. It then returns from the aborted_task callout and we finish target_handle_abort and do:
target_handle_abort -> transport_cmd_check_stop_to_fabric -> lio_check_stop_free -> target_put_sess_cmd
The cmd is now freed.
3. thread1 now finishes iscsit_release_commands_from_conn and runs iscsit_free_cmd while accessing a command we just released.
In __target_check_io_state we check for CMD_T_FABRIC_STOP and set the CMD_T_ABORTED if the driver is not cleaning up the cmd because of a session shutdown. However, iscsit_release_commands_from_conn only sets the CMD_T_FABRIC_STOP and does not check to see if the abort path has claimed completion ownership of the command.
This adds a check in iscsit_release_commands_from_conn so only the abort or fabric stop path cleanup the command.
Link: https://lore.kernel.org/r/1605318378-9269-1-git-send-email-michael.christie@... Reported-by: Maurizio Lombardi mlombard@redhat.com Reviewed-by: Maurizio Lombardi mlombard@redhat.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/target/iscsi/iscsi_target.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 7b56fe9f10628..2e18ec42c7045 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -483,8 +483,7 @@ EXPORT_SYMBOL(iscsit_queue_rsp); void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) { spin_lock_bh(&conn->cmd_lock); - if (!list_empty(&cmd->i_conn_node) && - !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) + if (!list_empty(&cmd->i_conn_node)) list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock);
@@ -4083,12 +4082,22 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) spin_lock_bh(&conn->cmd_lock); list_splice_init(&conn->conn_cmd_list, &tmp_list);
- list_for_each_entry(cmd, &tmp_list, i_conn_node) { + list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { struct se_cmd *se_cmd = &cmd->se_cmd;
if (se_cmd->se_tfo != NULL) { spin_lock_irq(&se_cmd->t_state_lock); - se_cmd->transport_state |= CMD_T_FABRIC_STOP; + if (se_cmd->transport_state & CMD_T_ABORTED) { + /* + * LIO's abort path owns the cleanup for this, + * so put it back on the list and let + * aborted_task handle it. + */ + list_move_tail(&cmd->i_conn_node, + &conn->conn_cmd_list); + } else { + se_cmd->transport_state |= CMD_T_FABRIC_STOP; + } spin_unlock_irq(&se_cmd->t_state_lock); } }
From: Boqun Feng boqun.feng@gmail.com
[ Upstream commit 43be4388e94b915799a24f0eaf664bf95b85231f ]
A warning was hit when running xfstests/generic/068 in a Hyper-V guest:
[...] ------------[ cut here ]------------ [...] DEBUG_LOCKS_WARN_ON(lockdep_hardirqs_enabled()) [...] WARNING: CPU: 2 PID: 1350 at kernel/locking/lockdep.c:5280 check_flags.part.0+0x165/0x170 [...] ... [...] Workqueue: events pwq_unbound_release_workfn [...] RIP: 0010:check_flags.part.0+0x165/0x170 [...] ... [...] Call Trace: [...] lock_is_held_type+0x72/0x150 [...] ? lock_acquire+0x16e/0x4a0 [...] rcu_read_lock_sched_held+0x3f/0x80 [...] __send_ipi_one+0x14d/0x1b0 [...] hv_send_ipi+0x12/0x30 [...] __pv_queued_spin_unlock_slowpath+0xd1/0x110 [...] __raw_callee_save___pv_queued_spin_unlock_slowpath+0x11/0x20 [...] .slowpath+0x9/0xe [...] lockdep_unregister_key+0x128/0x180 [...] pwq_unbound_release_workfn+0xbb/0xf0 [...] process_one_work+0x227/0x5c0 [...] worker_thread+0x55/0x3c0 [...] ? process_one_work+0x5c0/0x5c0 [...] kthread+0x153/0x170 [...] ? __kthread_bind_mask+0x60/0x60 [...] ret_from_fork+0x1f/0x30
The cause of the problem is we have call chain lockdep_unregister_key() -> <irq disabled by raw_local_irq_save()> lockdep_unlock() -> arch_spin_unlock() -> __pv_queued_spin_unlock_slowpath() -> pv_kick() -> __send_ipi_one() -> trace_hyperv_send_ipi_one().
Although this particular warning is triggered because Hyper-V has a trace point in ipi sending, but in general arch_spin_unlock() may call another function having a trace point in it, so put the arch_spin_lock() and arch_spin_unlock() after lock_recursion protection to fix this problem and avoid similiar problems.
Signed-off-by: Boqun Feng boqun.feng@gmail.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Link: https://lkml.kernel.org/r/20201113110512.1056501-1-boqun.feng@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/locking/lockdep.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 3eb35ad1b5241..04134a242f3d5 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -108,19 +108,21 @@ static inline void lockdep_lock(void) { DEBUG_LOCKS_WARN_ON(!irqs_disabled());
+ __this_cpu_inc(lockdep_recursion); arch_spin_lock(&__lock); __owner = current; - __this_cpu_inc(lockdep_recursion); }
static inline void lockdep_unlock(void) { + DEBUG_LOCKS_WARN_ON(!irqs_disabled()); + if (debug_locks && DEBUG_LOCKS_WARN_ON(__owner != current)) return;
- __this_cpu_dec(lockdep_recursion); __owner = NULL; arch_spin_unlock(&__lock); + __this_cpu_dec(lockdep_recursion); }
static inline bool lockdep_assert_locked(void)
From: Sami Tolvanen samitolvanen@google.com
[ Upstream commit ebd19fc372e3e78bf165f230e7c084e304441c08 ]
This change switches rapl to use PMU_FORMAT_ATTR, and fixes two other macros to use device_attribute instead of kobj_attribute to avoid callback type mismatches that trip indirect call checking with Clang's Control-Flow Integrity (CFI).
Reported-by: Sedat Dilek sedat.dilek@gmail.com Signed-off-by: Sami Tolvanen samitolvanen@google.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Kees Cook keescook@chromium.org Link: https://lkml.kernel.org/r/20201113183126.1239404-1-samitolvanen@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/events/intel/cstate.c | 6 +++--- arch/x86/events/intel/uncore.c | 4 ++-- arch/x86/events/intel/uncore.h | 12 ++++++------ arch/x86/events/rapl.c | 14 +------------- 4 files changed, 12 insertions(+), 24 deletions(-)
diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 442e1ed4acd49..4eb7ee5fed72d 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -107,14 +107,14 @@ MODULE_LICENSE("GPL");
#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __cstate_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ +static ssize_t __cstate_##_var##_show(struct device *dev, \ + struct device_attribute *attr, \ char *page) \ { \ BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ return sprintf(page, _format "\n"); \ } \ -static struct kobj_attribute format_attr_##_var = \ +static struct device_attribute format_attr_##_var = \ __ATTR(_name, 0444, __cstate_##_var##_show, NULL)
static ssize_t cstate_get_attr_cpumask(struct device *dev, diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index d5c6d3b340c50..803601baa753d 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -92,8 +92,8 @@ end: return map; }
-ssize_t uncore_event_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +ssize_t uncore_event_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct uncore_event_desc *event = container_of(attr, struct uncore_event_desc, attr); diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index 105fdc69825eb..c5744783e05d0 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h @@ -157,7 +157,7 @@ struct intel_uncore_box { #define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS 2
struct uncore_event_desc { - struct kobj_attribute attr; + struct device_attribute attr; const char *config; };
@@ -179,8 +179,8 @@ struct pci2phy_map { struct pci2phy_map *__find_pci2phy_map(int segment); int uncore_pcibus_to_physid(struct pci_bus *bus);
-ssize_t uncore_event_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf); +ssize_t uncore_event_show(struct device *dev, + struct device_attribute *attr, char *buf);
static inline struct intel_uncore_pmu *dev_to_uncore_pmu(struct device *dev) { @@ -201,14 +201,14 @@ extern int __uncore_max_dies; }
#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __uncore_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ +static ssize_t __uncore_##_var##_show(struct device *dev, \ + struct device_attribute *attr, \ char *page) \ { \ BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ return sprintf(page, _format "\n"); \ } \ -static struct kobj_attribute format_attr_##_var = \ +static struct device_attribute format_attr_##_var = \ __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
static inline bool uncore_pmc_fixed(int idx) diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c index 67b411f7e8c41..abaed36212250 100644 --- a/arch/x86/events/rapl.c +++ b/arch/x86/events/rapl.c @@ -93,18 +93,6 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { * any other bit is reserved */ #define RAPL_EVENT_MASK 0xFFULL - -#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __rapl_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ - char *page) \ -{ \ - BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ - return sprintf(page, _format "\n"); \ -} \ -static struct kobj_attribute format_attr_##_var = \ - __ATTR(_name, 0444, __rapl_##_var##_show, NULL) - #define RAPL_CNTR_WIDTH 32
#define RAPL_EVENT_ATTR_STR(_name, v, str) \ @@ -441,7 +429,7 @@ static struct attribute_group rapl_pmu_events_group = { .attrs = attrs_empty, };
-DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7"); +PMU_FORMAT_ATTR(event, "config:0-7"); static struct attribute *rapl_formats_attr[] = { &format_attr_event.attr, NULL,
From: Laurent Pinchart laurent.pinchart@ideasonboard.com
[ Upstream commit dc293f2106903ab9c24e9cea18c276e32c394c33 ]
When adding __user annotations in commit 2adf5352a34a, the strncpy_from_user() function declaration for the CONFIG_GENERIC_STRNCPY_FROM_USER case was missed. Fix it.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Message-Id: 20200831210937.17938-1-laurent.pinchart@ideasonboard.com Signed-off-by: Max Filippov jcmvbkbc@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/xtensa/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index b9758119feca1..5c9fb8005aa89 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -302,7 +302,7 @@ strncpy_from_user(char *dst, const char __user *src, long count) return -EFAULT; } #else -long strncpy_from_user(char *dst, const char *src, long count); +long strncpy_from_user(char *dst, const char __user *src, long count); #endif
/*
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit 860aaabac8235cfde10fe556aa82abbbe3117888 ]
sysrq-t ends up invoking show_opcodes() for each task which tries to access the user space code of other processes, which is obviously bogus.
It either manages to dump where the foreign task's regs->ip points to in a valid mapping of the current task or triggers a pagefault and prints "Code: Bad RIP value.". Both is just wrong.
Add a safeguard in copy_code() and check whether the @regs pointer matches currents pt_regs. If not, do not even try to access it.
While at it, add commentary why using copy_from_user_nmi() is safe in copy_code() even if the function name suggests otherwise.
Reported-by: Oleg Nesterov oleg@redhat.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Borislav Petkov bp@suse.de Acked-by: Oleg Nesterov oleg@redhat.com Tested-by: Borislav Petkov bp@suse.de Link: https://lkml.kernel.org/r/20201117202753.667274723@linutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kernel/dumpstack.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index ea8d51ec251bb..4da8345d34bb0 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -77,6 +77,9 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src, if (!user_mode(regs)) return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
+ /* The user space code from other tasks cannot be accessed. */ + if (regs != task_pt_regs(current)) + return -EPERM; /* * Make sure userspace isn't trying to trick us into dumping kernel * memory by pointing the userspace instruction pointer at it. @@ -84,6 +87,12 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src, if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX)) return -EINVAL;
+ /* + * Even if named copy_from_user_nmi() this can be invoked from + * other contexts and will not try to resolve a pagefault, which is + * the correct thing to do here as this code can be called from any + * context. + */ return copy_from_user_nmi(buf, (void __user *)src, nbytes); }
@@ -114,13 +123,19 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl) u8 opcodes[OPCODE_BUFSIZE]; unsigned long prologue = regs->ip - PROLOGUE_SIZE;
- if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { - printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", - loglvl, prologue); - } else { + switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { + case 0: printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %" __stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes, opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1); + break; + case -EPERM: + /* No access to the user space stack of other tasks. Ignore. */ + break; + default: + printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", + loglvl, prologue); + break; } }
From: Andrew Lunn andrew@lunn.ch
[ Upstream commit a3dcb3e7e70c72a68a79b30fc3a3adad5612731c ]
When the switch is hardware reset, it reads the contents of the EEPROM. This can contain instructions for programming values into registers and to perform waits between such programming. Reading the EEPROM can take longer than the 100ms mv88e6xxx_hardware_reset() waits after deasserting the reset GPIO. So poll the EEPROM done bit to ensure it is complete.
Signed-off-by: Andrew Lunn andrew@lunn.ch Signed-off-by: Ruslan Sushko rus@sushko.dev Link: https://lore.kernel.org/r/20201116164301.977661-1-rus@sushko.dev Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ drivers/net/dsa/mv88e6xxx/global1.c | 31 +++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 1 + 3 files changed, 34 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index f0dbc05e30a4d..16040b13579ef 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2299,6 +2299,8 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) usleep_range(10000, 20000); gpiod_set_value_cansleep(gpiod, 0); usleep_range(10000, 20000); + + mv88e6xxx_g1_wait_eeprom_done(chip); } }
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index f62aa83ca08d4..33d443a37efc4 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -75,6 +75,37 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); }
+void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) +{ + const unsigned long timeout = jiffies + 1 * HZ; + u16 val; + int err; + + /* Wait up to 1 second for the switch to finish reading the + * EEPROM. + */ + while (time_before(jiffies, timeout)) { + err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); + if (err) { + dev_err(chip->dev, "Error reading status"); + return; + } + + /* If the switch is still resetting, it may not + * respond on the bus, and so MDIO read returns + * 0xffff. Differentiate between that, and waiting for + * the EEPROM to be done by bit 0 being set. + */ + if (val != 0xffff && + val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)) + return; + + usleep_range(1000, 2000); + } + + dev_err(chip->dev, "Timeout waiting for EEPROM done"); +} + /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index 1e3546f8b0727..e05abe61fa114 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -278,6 +278,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); +void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
From: Tony Lindgren tony@atomide.com
[ Upstream commit e275d2109cdaea8b4554b9eb8a828bdb8f8ba068 ]
Commit d46f9fbec719 ("bus: ti-sysc: Use optional clocks on for enable and wait for softreset bit") started showing a "OCP softreset timed out" warning on enable if the interconnect target module is not out of reset. This caused the warning to be often triggered for i2c and hdq while the devices are working properly.
Turns out that some interconnect target modules seem to have an unusable reset status bits unless the module specific reset quirks are activated.
Let's just skip the reset status check for those modules as we only want to activate the reset quirks when doing a reset, and not on enable. This way we don't see the bogus "OCP softreset timed out" warnings during boot.
Fixes: d46f9fbec719 ("bus: ti-sysc: Use optional clocks on for enable and wait for softreset bit") Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/ti-sysc.c | 24 +++++++++++++++--------- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index efb088df12766..88a751c11677b 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -970,9 +970,15 @@ static int sysc_enable_module(struct device *dev) return error; } } - error = sysc_wait_softreset(ddata); - if (error) - dev_warn(ddata->dev, "OCP softreset timed out\n"); + /* + * Some modules like i2c and hdq1w have unusable reset status unless + * the module reset quirk is enabled. Skip status check on enable. + */ + if (!(ddata->cfg.quirks & SYSC_MODULE_QUIRK_ENA_RESETDONE)) { + error = sysc_wait_softreset(ddata); + if (error) + dev_warn(ddata->dev, "OCP softreset timed out\n"); + } if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET) sysc_disable_opt_clocks(ddata);
@@ -1373,17 +1379,17 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff, SYSC_QUIRK_OPT_CLKS_NEEDED), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, - SYSC_MODULE_QUIRK_HDQ1W), + SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, - SYSC_MODULE_QUIRK_HDQ1W), + SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff, - SYSC_MODULE_QUIRK_I2C), + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff, - SYSC_MODULE_QUIRK_I2C), + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff, - SYSC_MODULE_QUIRK_I2C), + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, - SYSC_MODULE_QUIRK_I2C), + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0), SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, SYSC_MODULE_QUIRK_SGX), diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index c59999ce044e5..240dce553a0bd 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -50,6 +50,7 @@ struct sysc_regbits { s8 emufree_shift; };
+#define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) #define SYSC_MODULE_QUIRK_PRUSS BIT(24) #define SYSC_MODULE_QUIRK_DSS_RESET BIT(23) #define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22)
From: Tony Lindgren tony@atomide.com
[ Upstream commit e7ae08d398e094e1305dee823435b1f996d39106 ]
Bail out early from sysc_wait_softreset() just like we do in sysc_reset() if there's no sysstatus srst_shift to fix a bogus resetdone warning on enable as suggested by Grygorii Strashko grygorii.strashko@ti.com.
We do not currently handle resets for modules that need writing to the sysstatus register. If we at some point add that, we also need to add SYSS_QUIRK_RESETDONE_INVERTED flag for cpsw as the sysstatus bit is low when reset is done as described in the am335x TRM "Table 14-202 SOFT_RESET Register Field Descriptions"
Fixes: d46f9fbec719 ("bus: ti-sysc: Use optional clocks on for enable and wait for softreset bit") Suggested-by: Grygorii Strashko grygorii.strashko@ti.com Acked-by: Grygorii Strashko grygorii.strashko@ti.com Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/ti-sysc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 88a751c11677b..16132e6e91f8d 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -227,6 +227,9 @@ static int sysc_wait_softreset(struct sysc *ddata) u32 sysc_mask, syss_done, rstval; int syss_offset, error = 0;
+ if (ddata->cap->regbits->srst_shift < 0) + return 0; + syss_offset = ddata->offsets[SYSC_SYSSTATUS]; sysc_mask = BIT(ddata->cap->regbits->srst_shift);
From: Tony Lindgren tony@atomide.com
[ Upstream commit 294a3317bef52b189139c813b50dd14d344fa9ec ]
Based on more testing, commit 8ca5ee624b4c ("ARM: OMAP2+: Restore MPU power domain if cpu_cluster_pm_enter() fails") is a poor fix for handling cpu_cluster_pm_enter() returned errors.
We should not override the cpuidle states with a hardcoded PWRDM_POWER_ON value. Instead, we should use a configured idle state that does not cause the context to be lost. Otherwise we end up configuring a potentially improper state for the MPUSS. We also want to update the returned state index for the selected state.
Let's just select the highest power idle state C1 to ensure no context loss is allowed on cpu_cluster_pm_enter() errors. With these changes we can now unconditionally call omap4_enter_lowpower() for WFI like we did earlier before commit 55be2f50336f ("ARM: OMAP2+: Handle errors for cpu_pm"). And we can return the selected state index.
Fixes: 8f04aea048d5 ("ARM: OMAP2+: Restore MPU power domain if cpu_cluster_pm_enter() fails") Fixes: 55be2f50336f ("ARM: OMAP2+: Handle errors for cpu_pm") Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/mach-omap2/cpuidle44xx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index a92d277f81a08..c8d317fafe2ea 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -175,8 +175,11 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, if (mpuss_can_lose_context) { error = cpu_cluster_pm_enter(); if (error) { - omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); - goto cpu_cluster_pm_out; + index = 0; + cx = state_ptr + index; + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); + omap_set_pwrdm_state(mpu_pd, cx->mpu_state); + mpuss_can_lose_context = 0; } } } @@ -184,7 +187,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, omap4_enter_lowpower(dev->cpu, cx->cpu_state); cpu_done[dev->cpu] = true;
-cpu_cluster_pm_out: /* Wakeup CPU1 only if it is not offlined */ if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
From: Marc Zyngier maz@kernel.org
[ Upstream commit eb9c4dd9bdfdebaa13846c16a8c79b5b336066b6 ]
If, for some reason, the xusb PHY fails to probe, it leaves a dangling pointer attached to the platform device structure.
This would normally be harmless, but the Tegra XHCI driver then goes and extract that pointer from the PHY device. Things go downhill from there:
8.752082] [004d554e5145533c] address between user and kernel address ranges [ 8.752085] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 8.752088] Modules linked in: max77620_regulator(E+) xhci_tegra(E+) sdhci_tegra(E+) xhci_hcd(E) sdhci_pltfm(E) cqhci(E) fixed(E) usbcore(E) scsi_mod(E) sdhci(E) host1x(E+) [ 8.752103] CPU: 4 PID: 158 Comm: systemd-udevd Tainted: G S W E 5.9.0-rc7-00298-gf6337624c4fe #1980 [ 8.752105] Hardware name: NVIDIA Jetson TX2 Developer Kit (DT) [ 8.752108] pstate: 20000005 (nzCv daif -PAN -UAO BTYPE=--) [ 8.752115] pc : kobject_put+0x1c/0x21c [ 8.752120] lr : put_device+0x20/0x30 [ 8.752121] sp : ffffffc012eb3840 [ 8.752122] x29: ffffffc012eb3840 x28: ffffffc010e82638 [ 8.752125] x27: ffffffc008d56440 x26: 0000000000000000 [ 8.752128] x25: ffffff81eb508200 x24: 0000000000000000 [ 8.752130] x23: ffffff81eb538800 x22: 0000000000000000 [ 8.752132] x21: 00000000fffffdfb x20: ffffff81eb538810 [ 8.752134] x19: 3d4d554e51455300 x18: 0000000000000020 [ 8.752136] x17: ffffffc008d00270 x16: ffffffc008d00c94 [ 8.752138] x15: 0000000000000004 x14: ffffff81ebd4ae90 [ 8.752140] x13: 0000000000000000 x12: ffffff81eb86a4e8 [ 8.752142] x11: ffffff81eb86a480 x10: ffffff81eb862fea [ 8.752144] x9 : ffffffc01055fb28 x8 : ffffff81eb86a4a8 [ 8.752146] x7 : 0000000000000001 x6 : 0000000000000001 [ 8.752148] x5 : ffffff81dff8bc38 x4 : 0000000000000000 [ 8.752150] x3 : 0000000000000001 x2 : 0000000000000001 [ 8.752152] x1 : 0000000000000002 x0 : 3d4d554e51455300 [ 8.752155] Call trace: [ 8.752157] kobject_put+0x1c/0x21c [ 8.752160] put_device+0x20/0x30 [ 8.752164] tegra_xusb_padctl_put+0x24/0x3c [ 8.752170] tegra_xusb_probe+0x8b0/0xd10 [xhci_tegra] [ 8.752174] platform_drv_probe+0x60/0xb4 [ 8.752176] really_probe+0xf0/0x504 [ 8.752179] driver_probe_device+0x100/0x170 [ 8.752181] device_driver_attach+0xcc/0xd4 [ 8.752183] __driver_attach+0xb0/0x17c [ 8.752185] bus_for_each_dev+0x7c/0xd4 [ 8.752187] driver_attach+0x30/0x3c [ 8.752189] bus_add_driver+0x154/0x250 [ 8.752191] driver_register+0x84/0x140 [ 8.752193] __platform_driver_register+0x54/0x60 [ 8.752197] tegra_xusb_init+0x40/0x1000 [xhci_tegra] [ 8.752201] do_one_initcall+0x54/0x2d0 [ 8.752205] do_init_module+0x68/0x29c [ 8.752207] load_module+0x2178/0x26c0 [ 8.752209] __do_sys_finit_module+0xb0/0x120 [ 8.752211] __arm64_sys_finit_module+0x2c/0x40 [ 8.752215] el0_svc_common.constprop.0+0x80/0x240 [ 8.752218] do_el0_svc+0x30/0xa0 [ 8.752220] el0_svc+0x18/0x50 [ 8.752223] el0_sync_handler+0x90/0x318 [ 8.752225] el0_sync+0x158/0x180 [ 8.752230] Code: a9bd7bfd 910003fd a90153f3 aa0003f3 (3940f000) [ 8.752232] ---[ end trace 90f6c89d62d85ff5 ]---
Reset the pointer on probe failure fixes the issue.
Fixes: 53d2a715c2403 ("phy: Add Tegra XUSB pad controller support") Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20201013095820.311376-1-maz@kernel.org Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/tegra/xusb.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index de4a46fe17630..ad88d74c18842 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -1242,6 +1242,7 @@ power_down: reset: reset_control_assert(padctl->rst); remove: + platform_set_drvdata(pdev, NULL); soc->ops->remove(padctl); return err; }
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit fb8d1b6e97980057b7ebed444b8950e57f268a67 ]
The ROC that runs on the AUX ROC (meaning an ROC on the STA vif), was added with the HOT_SPOT_CMD firmware command and must be cancelled with that same command.
Signed-off-by: Emmanuel Grumbach emmanuel.grumbach@intel.com Fixes: fe959c7b2049 ("iwlwifi: mvm: use the new session protection command") Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/iwlwifi.20201107104557.a317376154da.I44fa3637373ba... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 1babc4bb5194b..da52c1e433a29 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -985,10 +985,13 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { mvmvif = iwl_mvm_vif_from_mac80211(vif);
- iwl_mvm_cancel_session_protection(mvm, mvmvif); - - if (vif->type == NL80211_IFTYPE_P2P_DEVICE) + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { + iwl_mvm_cancel_session_protection(mvm, mvmvif); set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); + } else { + iwl_mvm_remove_aux_roc_te(mvm, mvmvif, + &mvmvif->time_event_data); + }
iwl_mvm_roc_finished(mvm);
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit 1cf260e3a75b87726ec609ad1b6b88f515749786 ]
We need to feed the configuration id to remove session protection properly. Remember the conf_id when we add the session protection so that we can give it back when we want to remove the session protection. While at it, slightly improve the kernel doc for the conf_id of the notification.
Signed-off-by: Emmanuel Grumbach emmanuel.grumbach@intel.com Fixes: fe959c7b2049 ("iwlwifi: mvm: use the new session protection command") Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/iwlwifi.20201107104557.3642f730333d.I01a98ecde6209... Signed-off-by: Sasha Levin sashal@kernel.org --- .../intel/iwlwifi/fw/api/time-event.h | 8 +- .../wireless/intel/iwlwifi/mvm/time-event.c | 94 +++++++++++++------ 2 files changed, 68 insertions(+), 34 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index a731f28e101a6..53b438d709dbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -421,12 +421,14 @@ struct iwl_hs20_roc_res { * able to run the GO Negotiation. Will not be fragmented and not * repetitive. Valid only on the P2P Device MAC. Only the duration will * be taken into account. + * @SESSION_PROTECT_CONF_MAX_ID: not used */ enum iwl_mvm_session_prot_conf_id { SESSION_PROTECT_CONF_ASSOC, SESSION_PROTECT_CONF_GO_CLIENT_ASSOC, SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV, SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION, + SESSION_PROTECT_CONF_MAX_ID, }; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */
/** @@ -459,7 +461,7 @@ struct iwl_mvm_session_prot_cmd { * @mac_id: the mac id for which the session protection started / ended * @status: 1 means success, 0 means failure * @start: 1 means the session protection started, 0 means it ended - * @conf_id: the configuration id of the session that started / eneded + * @conf_id: see &enum iwl_mvm_session_prot_conf_id * * Note that any session protection will always get two notifications: start * and end even the firmware could not schedule it. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index da52c1e433a29..6ca45e89a820c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -638,11 +638,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, } }
+static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm, + struct iwl_mvm_vif *mvmvif) +{ + struct iwl_mvm_session_prot_cmd cmd = { + .id_and_color = + cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)), + .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), + .conf_id = cpu_to_le32(mvmvif->time_event_data.id), + }; + int ret; + + ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, + MAC_CONF_GROUP, 0), + 0, sizeof(cmd), &cmd); + if (ret) + IWL_ERR(mvm, + "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret); +} + static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, struct iwl_mvm_time_event_data *te_data, u32 *uid) { u32 id; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
/* * It is possible that by the time we got to this point the time @@ -660,14 +681,29 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, iwl_mvm_te_clear_data(mvm, te_data); spin_unlock_bh(&mvm->time_event_lock);
- /* - * It is possible that by the time we try to remove it, the time event - * has already ended and removed. In such a case there is no need to - * send a removal command. + /* When session protection is supported, the te_data->id field + * is reused to save session protection's configuration. */ - if (id == TE_MAX) { - IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { + if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) { + /* Session protection is still ongoing. Cancel it */ + iwl_mvm_cancel_session_protection(mvm, mvmvif); + if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { + set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); + iwl_mvm_roc_finished(mvm); + } + } return false; + } else { + /* It is possible that by the time we try to remove it, the + * time event has already ended and removed. In such a case + * there is no need to send a removal command. + */ + if (id == TE_MAX) { + IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); + return false; + } }
return true; @@ -768,6 +804,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data; struct ieee80211_vif *vif; + struct iwl_mvm_vif *mvmvif;
rcu_read_lock(); vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id), @@ -776,9 +813,10 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, if (!vif) goto out_unlock;
+ mvmvif = iwl_mvm_vif_from_mac80211(vif); + /* The vif is not a P2P_DEVICE, maintain its time_event_data */ if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
@@ -813,10 +851,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) { /* End TE, notify mac80211 */ + mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID; ieee80211_remain_on_channel_expired(mvm->hw); set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); iwl_mvm_roc_finished(mvm); } else if (le32_to_cpu(notif->start)) { + if (WARN_ON(mvmvif->time_event_data.id != + le32_to_cpu(notif->conf_id))) + goto out_unlock; set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); ieee80211_ready_on_channel(mvm->hw); /* Start TE */ } @@ -842,20 +884,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
+ /* The time_event_data.id field is reused to save session + * protection's configuration. + */ switch (type) { case IEEE80211_ROC_TYPE_NORMAL: - cmd.conf_id = - cpu_to_le32(SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV); + mvmvif->time_event_data.id = + SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV; break; case IEEE80211_ROC_TYPE_MGMT_TX: - cmd.conf_id = - cpu_to_le32(SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION); + mvmvif->time_event_data.id = + SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION; break; default: WARN_ONCE(1, "Got an invalid ROC type\n"); return -EINVAL; }
+ cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, MAC_CONF_GROUP, 0), 0, sizeof(cmd), &cmd); @@ -957,25 +1003,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm) __iwl_mvm_remove_time_event(mvm, te_data, &uid); }
-static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvmvif) -{ - struct iwl_mvm_session_prot_cmd cmd = { - .id_and_color = - cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, - mvmvif->color)), - .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), - }; - int ret; - - ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, - MAC_CONF_GROUP, 0), - 0, sizeof(cmd), &cmd); - if (ret) - IWL_ERR(mvm, - "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret); -} - void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif; @@ -1104,10 +1131,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)), .action = cpu_to_le32(FW_CTXT_ACTION_ADD), - .conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC), .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), };
+ /* The time_event_data.id field is reused to save session + * protection's configuration. + */ + mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC; + cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); + lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock);
From: Avraham Stern avraham.stern@intel.com
[ Upstream commit 97cc16943f23078535fdbce4f6391b948b4ccc08 ]
We use mvm->queue_sync_state to wait for synchronous queue sync messages, but if an async one happens inbetween we shouldn't clear mvm->queue_sync_state after sending the async one, that can run concurrently (at least from the CPU POV) with another synchronous queue sync.
Signed-off-by: Johannes Berg johannes.berg@intel.com Fixes: 3c514bf831ac ("iwlwifi: mvm: add a loose synchronization of the NSSN across Rx queues") Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/iwlwifi.20201107104557.51a3148f2c14.I0772171dbaec8... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index c918c0887ed01..34362dc0d4612 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3104,6 +3104,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, goto out_unlock; }
+ if (vif->type == NL80211_IFTYPE_STATION) + vif->bss_conf.he_support = sta->he_cap.has_he; + if (sta->tdls && (vif->p2p || iwl_mvm_tdls_sta_count(mvm, NULL) ==
From: Janosch Frank frankja@linux.ibm.com
[ Upstream commit 1ed576a20cd5c93295f57d6b7400357bd8d01b21 ]
We can only have protected guest pages after a successful set secure parameters call as only then the UV allows imports and unpacks.
By moving the test we can now also check for it in s390_reset_acc() and do an early return if it is 0.
Signed-off-by: Janosch Frank frankja@linux.ibm.com Fixes: 29b40f105ec8 ("KVM: s390: protvirt: Add initial vm and cpu lifecycle handling") Reviewed-by: Cornelia Huck cohuck@redhat.com Signed-off-by: Christian Borntraeger borntraeger@de.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/kvm/kvm-s390.c | 2 +- arch/s390/kvm/pv.c | 3 ++- arch/s390/mm/gmap.c | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 6b74b92c1a586..08ea6c4735cdc 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2312,7 +2312,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) struct kvm_s390_pv_unp unp = {};
r = -EINVAL; - if (!kvm_s390_pv_is_protected(kvm)) + if (!kvm_s390_pv_is_protected(kvm) || !mm_is_protected(kvm->mm)) break;
r = -EFAULT; diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c index eb99e2f95ebed..f5847f9dec7c9 100644 --- a/arch/s390/kvm/pv.c +++ b/arch/s390/kvm/pv.c @@ -208,7 +208,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) return -EIO; } kvm->arch.gmap->guest_handle = uvcb.guest_handle; - atomic_set(&kvm->mm->context.is_protected, 1); return 0; }
@@ -228,6 +227,8 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc, *rrc = uvcb.header.rrc; KVM_UV_EVENT(kvm, 3, "PROTVIRT VM SET PARMS: rc %x rrc %x", *rc, *rrc); + if (!cc) + atomic_set(&kvm->mm->context.is_protected, 1); return cc ? -EINVAL : 0; }
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 373542ca1113e..78dbba6a4500c 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -2690,6 +2690,8 @@ static const struct mm_walk_ops reset_acc_walk_ops = { #include <linux/sched/mm.h> void s390_reset_acc(struct mm_struct *mm) { + if (!mm_is_protected(mm)) + return; /* * we might be called during * reset: we walk the pages and clear
From: Collin Walling walling@linux.ibm.com
[ Upstream commit 6cbf1e960fa52e4c63a6dfa4cda8736375b34ccc ]
The diag318 data must be set to 0 by VM-wide reset events triggered by diag308. As such, KVM should not handle resetting this data via the VCPU ioctls.
Fixes: 23a60f834406 ("s390/kvm: diagnose 0x318 sync and reset") Signed-off-by: Collin Walling walling@linux.ibm.com Reviewed-by: Christian Borntraeger borntraeger@de.ibm.com Reviewed-by: Janosch Frank frankja@linux.ibm.com Acked-by: Cornelia Huck cohuck@redhat.com Signed-off-by: Christian Borntraeger borntraeger@de.ibm.com Link: https://lore.kernel.org/r/20201104181032.109800-1-walling@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/kvm/kvm-s390.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 08ea6c4735cdc..425d3d75320bf 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -3564,7 +3564,6 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->pp = 0; vcpu->arch.sie_block->fpf &= ~FPF_BPBC; vcpu->arch.sie_block->todpr = 0; - vcpu->arch.sie_block->cpnc = 0; } }
@@ -3582,7 +3581,6 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
regs->etoken = 0; regs->etoken_extension = 0; - regs->diag318 = 0; }
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
From: Qu Wenruo wqu@suse.com
[ Upstream commit 6f23277a49e68f8a9355385c846939ad0b1261e7 ]
[BUG] When running the following script, btrfs will trigger an ASSERT():
#/bin/bash mkfs.btrfs -f $dev mount $dev $mnt xfs_io -f -c "pwrite 0 1G" $mnt/file sync btrfs quota enable $mnt btrfs quota rescan -w $mnt
# Manually set the limit below current usage btrfs qgroup limit 512M $mnt $mnt
# Crash happens touch $mnt/file
The dmesg looks like this:
assertion failed: refcount_read(&trans->use_count) == 1, in fs/btrfs/transaction.c:2022 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ctree.h:3230! invalid opcode: 0000 [#1] SMP PTI RIP: 0010:assertfail.constprop.0+0x18/0x1a [btrfs] btrfs_commit_transaction.cold+0x11/0x5d [btrfs] try_flush_qgroup+0x67/0x100 [btrfs] __btrfs_qgroup_reserve_meta+0x3a/0x60 [btrfs] btrfs_delayed_update_inode+0xaa/0x350 [btrfs] btrfs_update_inode+0x9d/0x110 [btrfs] btrfs_dirty_inode+0x5d/0xd0 [btrfs] touch_atime+0xb5/0x100 iterate_dir+0xf1/0x1b0 __x64_sys_getdents64+0x78/0x110 do_syscall_64+0x33/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fb5afe588db
[CAUSE] In try_flush_qgroup(), we assume we don't hold a transaction handle at all. This is true for data reservation and mostly true for metadata. Since data space reservation always happens before we start a transaction, and for most metadata operation we reserve space in start_transaction().
But there is an exception, btrfs_delayed_inode_reserve_metadata(). It holds a transaction handle, while still trying to reserve extra metadata space.
When we hit EDQUOT inside btrfs_delayed_inode_reserve_metadata(), we will join current transaction and commit, while we still have transaction handle from qgroup code.
[FIX] Let's check current->journal before we join the transaction.
If current->journal is unset or BTRFS_SEND_TRANS_STUB, it means we are not holding a transaction, thus are able to join and then commit transaction.
If current->journal is a valid transaction handle, we avoid committing transaction and just end it
This is less effective than committing current transaction, as it won't free metadata reserved space, but we may still free some data space before new data writes.
Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1178634 Fixes: c53e9653605d ("btrfs: qgroup: try to flush qgroup space when we get -EDQUOT") Reviewed-by: Filipe Manana fdmanana@suse.com Signed-off-by: Qu Wenruo wqu@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/btrfs/qgroup.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 9af010131d589..9205a88f2a881 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -3516,6 +3516,7 @@ static int try_flush_qgroup(struct btrfs_root *root) { struct btrfs_trans_handle *trans; int ret; + bool can_commit = true;
/* * We don't want to run flush again and again, so if there is a running @@ -3527,6 +3528,20 @@ static int try_flush_qgroup(struct btrfs_root *root) return 0; }
+ /* + * If current process holds a transaction, we shouldn't flush, as we + * assume all space reservation happens before a transaction handle is + * held. + * + * But there are cases like btrfs_delayed_item_reserve_metadata() where + * we try to reserve space with one transction handle already held. + * In that case we can't commit transaction, but at least try to end it + * and hope the started data writes can free some space. + */ + if (current->journal_info && + current->journal_info != BTRFS_SEND_TRANS_STUB) + can_commit = false; + ret = btrfs_start_delalloc_snapshot(root); if (ret < 0) goto out; @@ -3538,7 +3553,10 @@ static int try_flush_qgroup(struct btrfs_root *root) goto out; }
- ret = btrfs_commit_transaction(trans); + if (can_commit) + ret = btrfs_commit_transaction(trans); + else + ret = btrfs_end_transaction(trans); out: clear_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state); wake_up(&root->qgroup_flush_wait);
From: Taehee Yoo ap420073@gmail.com
[ Upstream commit 14a2e551faea53d45bc11629a9dac88f88950ca7 ]
If THIS_MODULE is not set, the module would be removed while debugfs is being used. It eventually makes kernel panic.
Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol") Signed-off-by: Taehee Yoo ap420073@gmail.com Signed-off-by: Sven Eckelmann sven@narfation.org Signed-off-by: Simon Wunderlich sw@simonwunderlich.de Signed-off-by: Sasha Levin sashal@kernel.org --- net/batman-adv/log.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c index a67b2b0914478..c0ca5fbe5b081 100644 --- a/net/batman-adv/log.c +++ b/net/batman-adv/log.c @@ -180,6 +180,7 @@ static const struct file_operations batadv_log_fops = { .read = batadv_log_read, .poll = batadv_log_poll, .llseek = no_llseek, + .owner = THIS_MODULE, };
/**
From: Peter Chen peter.chen@nxp.com
[ Upstream commit 8dafb3c04df3b3b5a3ee2c7f5d8285a8b2f0aa78 ]
It is found by sparse.
Reported-by: kbuild test robot lkp@intel.com Signed-off-by: Peter Chen peter.chen@nxp.com Signed-off-by: Felipe Balbi balbi@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/cdns3/gadget.c | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-)
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index e0e1cb907ffd8..dc5e6be3fd45a 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -261,8 +261,8 @@ int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) */ link_trb->control = 0; } else { - link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma); - link_trb->control = TRB_CYCLE | TRB_TYPE(TRB_LINK) | TRB_TOGGLE; + link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma)); + link_trb->control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_LINK) | TRB_TOGGLE); } return 0; } @@ -853,10 +853,10 @@ static void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) priv_ep->wa1_trb_index = 0xFFFF; if (priv_ep->wa1_cycle_bit) { priv_ep->wa1_trb->control = - priv_ep->wa1_trb->control | 0x1; + priv_ep->wa1_trb->control | cpu_to_le32(0x1); } else { priv_ep->wa1_trb->control = - priv_ep->wa1_trb->control & ~0x1; + priv_ep->wa1_trb->control & cpu_to_le32(~0x1); } } } @@ -1014,17 +1014,16 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, TRB_STREAM_ID(priv_req->request.stream_id) | TRB_ISP;
if (!request->num_sgs) { - trb->buffer = TRB_BUFFER(trb_dma); + trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma)); length = request->length; } else { - trb->buffer = TRB_BUFFER(request->sg[sg_idx].dma_address); + trb->buffer = cpu_to_le32(TRB_BUFFER(request->sg[sg_idx].dma_address)); length = request->sg[sg_idx].length; }
tdl = DIV_ROUND_UP(length, priv_ep->endpoint.maxpacket);
- trb->length = TRB_BURST_LEN(16 /*priv_ep->trb_burst_size*/) | - TRB_LEN(length); + trb->length = cpu_to_le32(TRB_BURST_LEN(16) | TRB_LEN(length));
/* * For DEV_VER_V2 controller version we have enabled @@ -1033,11 +1032,11 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, */ if (priv_dev->dev_ver >= DEV_VER_V2) { if (priv_dev->gadget.speed == USB_SPEED_SUPER) - trb->length |= TRB_TDL_SS_SIZE(tdl); + trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(tdl)); } priv_req->flags |= REQUEST_PENDING;
- trb->control = control; + trb->control = cpu_to_le32(control);
trace_cdns3_prepare_trb(priv_ep, priv_req->trb);
@@ -1162,8 +1161,8 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, TRBS_PER_SEGMENT > 2) ch_bit = TRB_CHAIN;
- link_trb->control = ((priv_ep->pcs) ? TRB_CYCLE : 0) | - TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit; + link_trb->control = cpu_to_le32(((priv_ep->pcs) ? TRB_CYCLE : 0) | + TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit); }
if (priv_dev->dev_ver <= DEV_VER_V2) @@ -1178,8 +1177,8 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
/* fill TRB */ control |= TRB_TYPE(TRB_NORMAL); - trb->buffer = TRB_BUFFER(request->num_sgs == 0 - ? trb_dma : request->sg[sg_iter].dma_address); + trb->buffer = cpu_to_le32(TRB_BUFFER(request->num_sgs == 0 + ? trb_dma : request->sg[sg_iter].dma_address));
if (likely(!request->num_sgs)) length = request->length; @@ -1193,10 +1192,10 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, total_tdl += DIV_ROUND_UP(length, priv_ep->endpoint.maxpacket);
- trb->length = TRB_BURST_LEN(priv_ep->trb_burst_size) | - TRB_LEN(length); + trb->length = cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) | + TRB_LEN(length)); if (priv_dev->gadget.speed == USB_SPEED_SUPER) - trb->length |= TRB_TDL_SS_SIZE(td_size); + trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(td_size)); else control |= TRB_TDL_HS_SIZE(td_size);
@@ -1218,9 +1217,9 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, }
if (sg_iter) - trb->control = control; + trb->control = cpu_to_le32(control); else - priv_req->trb->control = control; + priv_req->trb->control = cpu_to_le32(control);
control = 0; ++sg_iter; @@ -1234,7 +1233,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, priv_req->flags |= REQUEST_PENDING;
if (sg_iter == 1) - trb->control |= TRB_IOC | TRB_ISP; + trb->control |= cpu_to_le32(TRB_IOC | TRB_ISP);
if (priv_dev->dev_ver < DEV_VER_V2 && (priv_ep->flags & EP_TDLCHK_EN)) { @@ -1260,7 +1259,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
/* give the TD to the consumer*/ if (togle_pcs) - trb->control = trb->control ^ 1; + trb->control = trb->control ^ cpu_to_le32(1);
if (priv_dev->dev_ver <= DEV_VER_V2) cdns3_wa1_tray_restore_cycle_bit(priv_dev, priv_ep); @@ -1399,7 +1398,7 @@ static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep,
trb = &priv_ep->trb_pool[priv_req->start_trb];
- if ((trb->control & TRB_CYCLE) != priv_ep->ccs) + if ((le32_to_cpu(trb->control) & TRB_CYCLE) != priv_ep->ccs) goto finish;
if (doorbell == 1 && current_index == priv_ep->dequeue) @@ -1448,7 +1447,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, trb = priv_ep->trb_pool + priv_ep->dequeue;
/* Request was dequeued and TRB was changed to TRB_LINK. */ - if (TRB_FIELD_TO_TYPE(trb->control) == TRB_LINK) { + if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { trace_cdns3_complete_trb(priv_ep, trb); cdns3_move_deq_to_next_trb(priv_req); } @@ -1580,7 +1579,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) * that host ignore the ERDY packet and driver has to send it * again. */ - if (tdl && (dbusy | !EP_STS_BUFFEMPTY(ep_sts_reg) | + if (tdl && (dbusy || !EP_STS_BUFFEMPTY(ep_sts_reg) || EP_STS_HOSTPP(ep_sts_reg))) { writel(EP_CMD_ERDY | EP_CMD_ERDY_SID(priv_ep->last_stream_id), @@ -2564,10 +2563,10 @@ found:
/* Update ring only if removed request is on pending_req_list list */ if (req_on_hw_ring && link_trb) { - link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + - ((priv_req->end_trb + 1) * TRB_SIZE)); - link_trb->control = (link_trb->control & TRB_CYCLE) | - TRB_TYPE(TRB_LINK) | TRB_CHAIN; + link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma + + ((priv_req->end_trb + 1) * TRB_SIZE))); + link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) & TRB_CYCLE) | + TRB_TYPE(TRB_LINK) | TRB_CHAIN);
if (priv_ep->wa1_trb == priv_req->trb) cdns3_wa1_restore_cycle_bit(priv_ep); @@ -2622,7 +2621,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) priv_req = to_cdns3_request(request); trb = priv_req->trb; if (trb) - trb->control = trb->control ^ TRB_CYCLE; + trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); }
writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); @@ -2637,7 +2636,8 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
if (request) { if (trb) - trb->control = trb->control ^ TRB_CYCLE; + trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); + cdns3_rearm_transfer(priv_ep, 1); }
From: Peter Chen peter.chen@nxp.com
[ Upstream commit 40252dd7cf7cad81c784c695c36bc475b518f0ea ]
The TRB entry TD_SIZE is the packet number for the TD (request) but not the each TRB, so it only needs to be assigned for the first TRB during the TD, and the value of it is for TD too.
Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Signed-off-by: Peter Chen peter.chen@nxp.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/cdns3/gadget.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index dc5e6be3fd45a..6af6343c7c65a 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -1170,10 +1170,20 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
/* set incorrect Cycle Bit for first trb*/ control = priv_ep->pcs ? 0 : TRB_CYCLE; + trb->length = 0; + if (priv_dev->dev_ver >= DEV_VER_V2) { + u16 td_size; + + td_size = DIV_ROUND_UP(request->length, + priv_ep->endpoint.maxpacket); + if (priv_dev->gadget.speed == USB_SPEED_SUPER) + trb->length = TRB_TDL_SS_SIZE(td_size); + else + control |= TRB_TDL_HS_SIZE(td_size); + }
do { u32 length; - u16 td_size = 0;
/* fill TRB */ control |= TRB_TYPE(TRB_NORMAL); @@ -1185,20 +1195,12 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, else length = request->sg[sg_iter].length;
- if (likely(priv_dev->dev_ver >= DEV_VER_V2)) - td_size = DIV_ROUND_UP(length, - priv_ep->endpoint.maxpacket); - else if (priv_ep->flags & EP_TDLCHK_EN) + if (priv_ep->flags & EP_TDLCHK_EN) total_tdl += DIV_ROUND_UP(length, priv_ep->endpoint.maxpacket);
- trb->length = cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) | + trb->length |= cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) | TRB_LEN(length)); - if (priv_dev->gadget.speed == USB_SPEED_SUPER) - trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(td_size)); - else - control |= TRB_TDL_HS_SIZE(td_size); - pcs = priv_ep->pcs ? TRB_CYCLE : 0;
/*
From: Bryan O'Donoghue bryan.odonoghue@linaro.org
[ Upstream commit 44786a26a7485e12a1d2aaad2adfb3c82f6ad171 ]
This Kconfig entry should declare a dependency on OF
Fixes: 6076967a500c ("phy: qualcomm: usb: Add SuperSpeed PHY driver") Reported-by: kernel test robot lkp@intel.com Link: https://lkml.org/lkml/2020/11/13/414 Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Link: https://lore.kernel.org/r/20201113151225.1657600-2-bryan.odonoghue@linaro.or... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/qualcomm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 928db510b86c6..9129c4b8bb9b1 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -98,7 +98,7 @@ config PHY_QCOM_USB_HS_28NM
config PHY_QCOM_USB_SS tristate "Qualcomm USB Super-Speed PHY driver" - depends on ARCH_QCOM || COMPILE_TEST + depends on OF && (ARCH_QCOM || COMPILE_TEST) depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in select GENERIC_PHY help
From: Bryan O'Donoghue bryan.odonoghue@linaro.org
[ Upstream commit 14839107b51cc0db19579039b1f72cba7a0c8049 ]
This Kconfig entry should declare a dependency on OF
Fixes: 67b27dbeac4d ("phy: qualcomm: Add Synopsys 28nm Hi-Speed USB PHY driver") Signed-off-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Link: https://lore.kernel.org/r/20201113151225.1657600-3-bryan.odonoghue@linaro.or... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/qualcomm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 9129c4b8bb9b1..7f6fcb8ec5bab 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -87,7 +87,7 @@ config PHY_QCOM_USB_HSIC
config PHY_QCOM_USB_HS_28NM tristate "Qualcomm 28nm High-Speed PHY" - depends on ARCH_QCOM || COMPILE_TEST + depends on OF && (ARCH_QCOM || COMPILE_TEST) depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in select GENERIC_PHY help
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit cef397038167ac15d085914493d6c86385773709 ]
Stefan Agner reported a bug when using zsram on 32-bit Arm machines with RAM above the 4GB address boundary:
Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = a27bd01c [00000000] *pgd=236a0003, *pmd=1ffa64003 Internal error: Oops: 207 [#1] SMP ARM Modules linked in: mdio_bcm_unimac(+) brcmfmac cfg80211 brcmutil raspberrypi_hwmon hci_uart crc32_arm_ce bcm2711_thermal phy_generic genet CPU: 0 PID: 123 Comm: mkfs.ext4 Not tainted 5.9.6 #1 Hardware name: BCM2711 PC is at zs_map_object+0x94/0x338 LR is at zram_bvec_rw.constprop.0+0x330/0xa64 pc : [<c0602b38>] lr : [<c0bda6a0>] psr: 60000013 sp : e376bbe0 ip : 00000000 fp : c1e2921c r10: 00000002 r9 : c1dda730 r8 : 00000000 r7 : e8ff7a00 r6 : 00000000 r5 : 02f9ffa0 r4 : e3710000 r3 : 000fdffe r2 : c1e0ce80 r1 : ebf979a0 r0 : 00000000 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 30c5383d Table: 235c2a80 DAC: fffffffd Process mkfs.ext4 (pid: 123, stack limit = 0x495a22e6) Stack: (0xe376bbe0 to 0xe376c000)
As it turns out, zsram needs to know the maximum memory size, which is defined in MAX_PHYSMEM_BITS when CONFIG_SPARSEMEM is set, or in MAX_POSSIBLE_PHYSMEM_BITS on the x86 architecture.
The same problem will be hit on all 32-bit architectures that have a physical address space larger than 4GB and happen to not enable sparsemem and include asm/sparsemem.h from asm/pgtable.h.
After the initial discussion, I suggested just always defining MAX_POSSIBLE_PHYSMEM_BITS whenever CONFIG_PHYS_ADDR_T_64BIT is set, or provoking a build error otherwise. This addresses all configurations that can currently have this runtime bug, but leaves all other configurations unchanged.
I looked up the possible number of bits in source code and datasheets, here is what I found:
- on ARC, CONFIG_ARC_HAS_PAE40 controls whether 32 or 40 bits are used - on ARM, CONFIG_LPAE enables 40 bit addressing, without it we never support more than 32 bits, even though supersections in theory allow up to 40 bits as well. - on MIPS, some MIPS32r1 or later chips support 36 bits, and MIPS32r5 XPA supports up to 60 bits in theory, but 40 bits are more than anyone will ever ship - On PowerPC, there are three different implementations of 36 bit addressing, but 32-bit is used without CONFIG_PTE_64BIT - On RISC-V, the normal page table format can support 34 bit addressing. There is no highmem support on RISC-V, so anything above 2GB is unused, but it might be useful to eventually support CONFIG_ZRAM for high pages.
Fixes: 61989a80fb3a ("staging: zsmalloc: zsmalloc memory allocation library") Fixes: 02390b87a945 ("mm/zsmalloc: Prepare to variable MAX_PHYSMEM_BITS") Acked-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Reviewed-by: Stefan Agner stefan@agner.ch Tested-by: Stefan Agner stefan@agner.ch Acked-by: Mike Rapoport rppt@linux.ibm.com Link: https://lore.kernel.org/linux-mm/bdfa44bf1c570b05d6c70898e2bbb0acf234ecdf.16... Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arc/include/asm/pgtable.h | 2 ++ arch/arm/include/asm/pgtable-2level.h | 2 ++ arch/arm/include/asm/pgtable-3level.h | 2 ++ arch/mips/include/asm/pgtable-32.h | 3 +++ arch/powerpc/include/asm/book3s/32/pgtable.h | 2 ++ arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++ arch/riscv/include/asm/pgtable-32.h | 2 ++ include/linux/pgtable.h | 13 +++++++++++++ 8 files changed, 28 insertions(+)
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index f1ed17edb085b..163641726a2b9 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -134,8 +134,10 @@
#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
/************************************************************************** diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index 3502c2f746ca7..baf7d0204eb5a 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -75,6 +75,8 @@ #define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32))
+#define MAX_POSSIBLE_PHYSMEM_BITS 32 + /* * PMD_SHIFT determines the size of the area a second-level page table can map * PGDIR_SHIFT determines what a third-level page table entry can map diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index fbb6693c33528..2b85d175e9996 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -25,6 +25,8 @@ #define PTE_HWTABLE_OFF (0) #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64))
+#define MAX_POSSIBLE_PHYSMEM_BITS 40 + /* * PGDIR_SHIFT determines the size a top-level page table entry can map. */ diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index a950fc1ddb4da..6c0532d7b2119 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h @@ -154,6 +154,7 @@ static inline void pmd_clear(pmd_t *pmdp)
#if defined(CONFIG_XPA)
+#define MAX_POSSIBLE_PHYSMEM_BITS 40 #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) @@ -169,6 +170,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#define MAX_POSSIBLE_PHYSMEM_BITS 36 #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6))
static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) @@ -183,6 +185,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
#else
+#define MAX_POSSIBLE_PHYSMEM_BITS 32 #ifdef CONFIG_CPU_VR41XX #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 36443cda8dcf2..1376be95e975f 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -36,8 +36,10 @@ static inline bool pte_user(pte_t pte) */ #ifdef CONFIG_PTE_64BIT #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) +#define MAX_POSSIBLE_PHYSMEM_BITS 36 #else #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) +#define MAX_POSSIBLE_PHYSMEM_BITS 32 #endif
/* diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index b9e134d0f03ad..5f5049c1ddb7f 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -153,8 +153,10 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); */ #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) +#define MAX_POSSIBLE_PHYSMEM_BITS 36 #else #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) +#define MAX_POSSIBLE_PHYSMEM_BITS 32 #endif
/* diff --git a/arch/riscv/include/asm/pgtable-32.h b/arch/riscv/include/asm/pgtable-32.h index b0ab66e5fdb1d..5b2e79e5bfa5b 100644 --- a/arch/riscv/include/asm/pgtable-32.h +++ b/arch/riscv/include/asm/pgtable-32.h @@ -14,4 +14,6 @@ #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 34 + #endif /* _ASM_RISCV_PGTABLE_32_H */ diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 0cb5fe3afd164..cd5aa875245b4 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -1399,6 +1399,19 @@ typedef unsigned int pgtbl_mod_mask;
#endif /* !__ASSEMBLY__ */
+#if !defined(MAX_POSSIBLE_PHYSMEM_BITS) && !defined(CONFIG_64BIT) +#ifdef CONFIG_PHYS_ADDR_T_64BIT +/* + * ZSMALLOC needs to know the highest PFN on 32-bit architectures + * with physical address space extension, but falls back to + * BITS_PER_LONG otherwise. + */ +#error Missing MAX_POSSIBLE_PHYSMEM_BITS definition +#else +#define MAX_POSSIBLE_PHYSMEM_BITS 32 +#endif +#endif + #ifndef has_transparent_hugepage #ifdef CONFIG_TRANSPARENT_HUGEPAGE #define has_transparent_hugepage() 1
From: Grygorii Strashko grygorii.strashko@ti.com
[ Upstream commit 65fb73676112f6fd107c5e542b2cbcfb206fe881 ]
GP Timers used as clockevent/source are not available for ti-sysc bus and handled by Kernel timekeeping core. Now ti-sysc produces error message every time such timer is detected:
"ti-sysc: probe of 48040000.target-module failed with error -16"
Such messages are not necessary, so suppress them by returning -ENXIO instead of -EBUSY.
Fixes: 6cfcd5563b4f ("clocksource/drivers/timer-ti-dm: Fix suspend and resume for am3 and am4") Signed-off-by: Grygorii Strashko grygorii.strashko@ti.com Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/ti-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 16132e6e91f8d..92ecf1a78ec73 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -2889,7 +2889,7 @@ static int sysc_check_active_timer(struct sysc *ddata)
if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) - return -EBUSY; + return -ENXIO;
return 0; }
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 05d5de6ba7dbe490dd413b5ca11d0875bd2bc006 ]
According to the bosch,m_can.yaml bindings the first clock shall be the "hclk", while the second clock "cclk".
This patch fixes the order accordingly.
Fixes: 0adbe832f21a ("ARM: dts: dra76x: Add MCAN node") Cc: Faiz Abbas faiz_abbas@ti.com Cc: Tony Lindgren tony@atomide.com Cc: linux-omap@vger.kernel.org Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/dra76x.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/dra76x.dtsi index b69c7d40f5d82..2f326151116b7 100644 --- a/arch/arm/boot/dts/dra76x.dtsi +++ b/arch/arm/boot/dts/dra76x.dtsi @@ -32,8 +32,8 @@ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "int0", "int1"; - clocks = <&mcan_clk>, <&l3_iclk_div>; - clock-names = "cclk", "hclk"; + clocks = <&l3_iclk_div>, <&mcan_clk>; + clock-names = "hclk", "cclk"; bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; }; };
From: Stanley Chu stanley.chu@mediatek.com
[ Upstream commit e92643db514803c2c87d72caf5950b4c0a8faf4a ]
If UFS host device is in runtime-suspended state while UFS shutdown callback is invoked, UFS device shall be resumed for register accesses. Currently only UFS local runtime resume function will be invoked to wake up the host. This is not enough because if someone triggers runtime resume from block layer, then race may happen between shutdown and runtime resume flow, and finally lead to unlocked register access.
To fix this, in ufshcd_shutdown(), use pm_runtime_get_sync() instead of resuming UFS device by ufshcd_runtime_resume() "internally" to let runtime PM framework manage the whole resume flow.
Link: https://lore.kernel.org/r/20201119062916.12931-1-stanley.chu@mediatek.com Fixes: 57d104c153d3 ("ufs: add UFS power management support") Reviewed-by: Can Guo cang@codeaurora.org Signed-off-by: Stanley Chu stanley.chu@mediatek.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 54928a837dad0..9dd32bb0ff2be 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8677,11 +8677,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) goto out;
- if (pm_runtime_suspended(hba->dev)) { - ret = ufshcd_runtime_resume(hba); - if (ret) - goto out; - } + pm_runtime_get_sync(hba->dev);
ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM); out:
From: Zhang Changzhong zhangchangzhong@huawei.com
[ Upstream commit b5f796b62c98cd8c219c4b788ecb6e1218e648cb ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: c213eae8d3cd ("bnxt_en: Improve VF/PF link change logic.") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Reviewed-by: Edwin Peer edwin.peer@broadcom.com Link: https://lore.kernel.org/r/1605701851-20270-1-git-send-email-zhangchangzhong@... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 2326571e8c84a..cb57e8ce368ac 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -12353,6 +12353,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) create_singlethread_workqueue("bnxt_pf_wq"); if (!bnxt_pf_wq) { dev_err(&pdev->dev, "Unable to create workqueue.\n"); + rc = -ENOMEM; goto init_err_pci_clean; } }
From: Zhang Changzhong zhangchangzhong@huawei.com
[ Upstream commit 3383176efc0fb0c0900a191026468a58668b4214 ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Reviewed-by: Edwin Peer edwin.peer@broadcom.com Link: https://lore.kernel.org/r/1605792621-6268-1-git-send-email-zhangchangzhong@h... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index cb57e8ce368ac..f726c91a9b3bc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -11273,6 +11273,7 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 && dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { dev_err(&pdev->dev, "System does not support DMA, aborting\n"); + rc = -EIO; goto init_err_disable; }
From: Dexuan Cui decui@microsoft.com
[ Upstream commit 5f1251a48c17b54939d7477305e39679a565382c ]
x86 Hyper-V used to essentially always overwrite the effective cache type of guest memory accesses to WB. This was problematic in cases where there is a physical device assigned to the VM, since that often requires that the VM should have control over cache types. Thus, on newer Hyper-V since 2018, Hyper-V always honors the VM's cache type, but unexpectedly Linux VM users start to complain that Linux VM's VRAM becomes very slow, and it turns out that Linux VM should not map the VRAM uncacheable by ioremap(). Fix this slowness issue by using ioremap_cache().
On ARM64, ioremap_cache() is also required as the host also maps the VRAM cacheable, otherwise VM Connect can't display properly with ioremap() or ioremap_wc().
With this change, the VRAM on new Hyper-V is as fast as regular RAM, so it's no longer necessary to use the hacks we added to mitigate the slowness, i.e. we no longer need to allocate physical memory and use it to back up the VRAM in Generation-1 VM, and we also no longer need to allocate physical memory to back up the framebuffer in a Generation-2 VM and copy the framebuffer to the real VRAM. A further big change will address these for v5.11.
Fixes: 68a2d20b79b1 ("drivers/video: add Hyper-V Synthetic Video Frame Buffer Driver") Tested-by: Boqun Feng boqun.feng@gmail.com Signed-off-by: Dexuan Cui decui@microsoft.com Reviewed-by: Michael Kelley mikelley@microsoft.com Reviewed-by: Haiyang Zhang haiyangz@microsoft.com Link: https://lore.kernel.org/r/20201118000305.24797-1-decui@microsoft.com Signed-off-by: Wei Liu wei.liu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/video/fbdev/hyperv_fb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index e36fb1a0ecdbd..19b3f3416d31c 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -1092,7 +1092,12 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) goto err1; }
- fb_virt = ioremap(par->mem->start, screen_fb_size); + /* + * Map the VRAM cacheable for performance. This is also required for + * VM Connect to display properly for ARM64 Linux VM, as the host also + * maps the VRAM cacheable. + */ + fb_virt = ioremap_cache(par->mem->start, screen_fb_size); if (!fb_virt) goto err2;
From: Michael Chan michael.chan@broadcom.com
[ Upstream commit c54bc3ced5106663c2f2b44071800621f505b00e ]
Jump to init_err_release to cleanup. bnxt_unmap_bars() will also be called but it will do nothing if the BARs are not mapped yet.
Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Reported-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Michael Chan michael.chan@broadcom.com Link: https://lore.kernel.org/r/1605858271-8209-1-git-send-email-michael.chan@broa... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f726c91a9b3bc..50efdcf681083 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -11274,7 +11274,7 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { dev_err(&pdev->dev, "System does not support DMA, aborting\n"); rc = -EIO; - goto init_err_disable; + goto init_err_release; }
pci_set_master(pdev);
From: Eric Biggers ebiggers@google.com
[ Upstream commit 47a846536e1bf62626f1c0d8488f3718ce5f8296 ]
If there is only one keyslot, then blk_ksm_init() computes slot_hashtable_size=1 and log_slot_ht_size=0. This causes blk_ksm_find_keyslot() to crash later because it uses hash_ptr(key, log_slot_ht_size) to find the hash bucket containing the key, and hash_ptr() doesn't support the bits == 0 case.
Fix this by making the hash table always have at least 2 buckets.
Tested by running:
kvm-xfstests -c ext4 -g encrypt -m inlinecrypt \ -o blk-crypto-fallback.num_keyslots=1
Fixes: 1b2628397058 ("block: Keyslot Manager for Inline Encryption") Signed-off-by: Eric Biggers ebiggers@google.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/keyslot-manager.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c index 35abcb1ec051d..86f8195d8039e 100644 --- a/block/keyslot-manager.c +++ b/block/keyslot-manager.c @@ -103,6 +103,13 @@ int blk_ksm_init(struct blk_keyslot_manager *ksm, unsigned int num_slots) spin_lock_init(&ksm->idle_slots_lock);
slot_hashtable_size = roundup_pow_of_two(num_slots); + /* + * hash_ptr() assumes bits != 0, so ensure the hash table has at least 2 + * buckets. This only makes a difference when there is only 1 keyslot. + */ + if (slot_hashtable_size < 2) + slot_hashtable_size = 2; + ksm->log_slot_ht_size = ilog2(slot_hashtable_size); ksm->slot_hashtable = kvmalloc_array(slot_hashtable_size, sizeof(ksm->slot_hashtable[0]),
From: Raju Rangoju rajur@chelsio.com
[ Upstream commit bff453921ae105a8dbbad0ed7dd5f5ce424536e7 ]
SMT entry is allocated only when loopback Source MAC rewriting is requested. Accessing SMT entry for non smac rewrite cases results in kernel panic.
Fix the panic caused by non smac rewrite
Fixes: 937d84205884 ("cxgb4: set up filter action after rewrites") Signed-off-by: Raju Rangoju rajur@chelsio.com Link: https://lore.kernel.org/r/20201118143213.13319-1-rajur@chelsio.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c index 8eb976106d0c8..7e7537eabf000 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c @@ -883,7 +883,8 @@ int set_filter_wr(struct adapter *adapter, int fidx) FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) | FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) | FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld)); - fwr->smac_sel = f->smt->idx; + if (f->fs.newsmac) + fwr->smac_sel = f->smt->idx; fwr->rx_chan_rx_rpl_iq = htons(FW_FILTER_WR_RX_CHAN_V(0) | FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id));
From: Ioana Ciornei ioana.ciornei@nxp.com
[ Upstream commit d2624e70a2f53b6f402fdaeabe7db798148618c5 ]
Explicitly enable the FSL_XGMAC_MDIO Kconfig option in order to have MDIO access to internal and external PHYs.
Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") Signed-off-by: Ioana Ciornei ioana.ciornei@nxp.com Link: https://lore.kernel.org/r/20201119145106.712761-1-ciorneiioana@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/dpaa2/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig b/drivers/net/ethernet/freescale/dpaa2/Kconfig index feea797cde022..70aabd2343371 100644 --- a/drivers/net/ethernet/freescale/dpaa2/Kconfig +++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig @@ -3,6 +3,7 @@ config FSL_DPAA2_ETH tristate "Freescale DPAA2 Ethernet" depends on FSL_MC_BUS && FSL_MC_DPIO select PHYLINK + select FSL_XGMAC_MDIO help This is the DPAA2 Ethernet driver supporting Freescale SoCs with DPAA2 (DataPath Acceleration Architecture v2).
From: Julian Wiedmann jwi@linux.ibm.com
[ Upstream commit 34c7f50f7d0d36fa663c74aee39e25e912505320 ]
Calling into socket code is ugly already, at least check whether we are dealing with the expected sk_family. Only looking at skb->protocol is bound to cause troubles (consider eg. af_packet).
Fixes: b333293058aa ("qeth: add support for af_iucv HiperSockets transport") Signed-off-by: Julian Wiedmann jwi@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/s390/net/qeth_core_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6a73982514237..f22e3653da52d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -32,6 +32,7 @@
#include <net/iucv/af_iucv.h> #include <net/dsfield.h> +#include <net/sock.h>
#include <asm/ebcdic.h> #include <asm/chpid.h> @@ -1408,7 +1409,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, skb_queue_walk(&buf->skb_list, skb) { QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification); QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb); - if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk) + if (skb->sk && skb->sk->sk_family == PF_IUCV) iucv_sk(skb->sk)->sk_txnotify(skb, notification); } }
From: Julian Wiedmann jwi@linux.ibm.com
[ Upstream commit 8908f36d20d8ba610d3a7d110b3049b5853b9bb1 ]
The two expected notification sequences are 1. TX_NOTIFY_PENDING with a subsequent TX_NOTIFY_DELAYED_*, when our TX completion code first observed the pending TX and the QAOB then completes at a later time; or 2. TX_NOTIFY_OK, when qeth_qdio_handle_aob() picked up the QAOB completion before our TX completion code even noticed that the TX was pending.
But as qeth_iqd_tx_complete() and qeth_qdio_handle_aob() can run concurrently, we may end up with a race that results in a sequence of TX_NOTIFY_DELAYED_* followed by TX_NOTIFY_PENDING. Which would confuse the af_iucv code in its tracking of pending transmits.
Rework the notification code, so that qeth_qdio_handle_aob() defers its notification if the TX completion code is still active.
Fixes: b333293058aa ("qeth: add support for af_iucv HiperSockets transport") Signed-off-by: Julian Wiedmann jwi@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/s390/net/qeth_core.h | 9 ++-- drivers/s390/net/qeth_core_main.c | 73 ++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 24 deletions(-)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 6b5cf9ba03e5b..757d6ba817ee1 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -397,10 +397,13 @@ enum qeth_qdio_out_buffer_state { QETH_QDIO_BUF_EMPTY, /* Filled by driver; owned by hardware in order to be sent. */ QETH_QDIO_BUF_PRIMED, - /* Identified to be pending in TPQ. */ + /* Discovered by the TX completion code: */ QETH_QDIO_BUF_PENDING, - /* Found in completion queue. */ - QETH_QDIO_BUF_IN_CQ, + /* Finished by the TX completion code: */ + QETH_QDIO_BUF_NEED_QAOB, + /* Received QAOB notification on CQ: */ + QETH_QDIO_BUF_QAOB_OK, + QETH_QDIO_BUF_QAOB_ERROR, /* Handled via transfer pending / completion queue. */ QETH_QDIO_BUF_HANDLED_DELAYED, }; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f22e3653da52d..54a7eefe73d19 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -513,6 +513,7 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, static void qeth_qdio_handle_aob(struct qeth_card *card, unsigned long phys_aob_addr) { + enum qeth_qdio_out_buffer_state new_state = QETH_QDIO_BUF_QAOB_OK; struct qaob *aob; struct qeth_qdio_out_buffer *buffer; enum iucv_tx_notify notification; @@ -524,22 +525,6 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, buffer = (struct qeth_qdio_out_buffer *) aob->user1; QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
- if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, - QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) { - notification = TX_NOTIFY_OK; - } else { - WARN_ON_ONCE(atomic_read(&buffer->state) != - QETH_QDIO_BUF_PENDING); - atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ); - notification = TX_NOTIFY_DELAYED_OK; - } - - if (aob->aorc != 0) { - QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); - notification = qeth_compute_cq_notification(aob->aorc, 1); - } - qeth_notify_skbs(buffer->q, buffer, notification); - /* Free dangling allocations. The attached skbs are handled by * qeth_cleanup_handled_pending(). */ @@ -551,7 +536,33 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, if (data && buffer->is_header[i]) kmem_cache_free(qeth_core_header_cache, data); } - atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); + + if (aob->aorc) { + QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); + new_state = QETH_QDIO_BUF_QAOB_ERROR; + } + + switch (atomic_xchg(&buffer->state, new_state)) { + case QETH_QDIO_BUF_PRIMED: + /* Faster than TX completion code. */ + notification = qeth_compute_cq_notification(aob->aorc, 0); + qeth_notify_skbs(buffer->q, buffer, notification); + atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); + break; + case QETH_QDIO_BUF_PENDING: + /* TX completion code is active and will handle the async + * completion for us. + */ + break; + case QETH_QDIO_BUF_NEED_QAOB: + /* TX completion code is already finished. */ + notification = qeth_compute_cq_notification(aob->aorc, 1); + qeth_notify_skbs(buffer->q, buffer, notification); + atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); + break; + default: + WARN_ON_ONCE(1); + }
qdio_release_aob(aob); } @@ -1420,9 +1431,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, struct qeth_qdio_out_q *queue = buf->q; struct sk_buff *skb;
- /* release may never happen from within CQ tasklet scope */ - WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); - if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR);
@@ -5847,9 +5855,32 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, QETH_QDIO_BUF_PENDING) == - QETH_QDIO_BUF_PRIMED) + QETH_QDIO_BUF_PRIMED) { qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING);
+ /* Handle race with qeth_qdio_handle_aob(): */ + switch (atomic_xchg(&buffer->state, + QETH_QDIO_BUF_NEED_QAOB)) { + case QETH_QDIO_BUF_PENDING: + /* No concurrent QAOB notification. */ + break; + case QETH_QDIO_BUF_QAOB_OK: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_OK); + atomic_set(&buffer->state, + QETH_QDIO_BUF_HANDLED_DELAYED); + break; + case QETH_QDIO_BUF_QAOB_ERROR: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_GENERALERROR); + atomic_set(&buffer->state, + QETH_QDIO_BUF_HANDLED_DELAYED); + break; + default: + WARN_ON_ONCE(1); + } + } + QETH_CARD_TEXT_(card, 5, "pel%u", bidx);
/* prepare the queue slot for re-use: */
From: Julian Wiedmann jwi@linux.ibm.com
[ Upstream commit 7ed10e16e50daf74460f54bc922e27c6863c8d61 ]
When qeth_iqd_tx_complete() detects that a TX buffer requires additional async completion via QAOB, it might fail to replace the queue entry's metadata (and ends up triggering recovery).
Assume now that the device gets torn down, overruling the recovery. If the QAOB notification then arrives before the tear down has sufficiently progressed, the buffer state is changed to QETH_QDIO_BUF_HANDLED_DELAYED by qeth_qdio_handle_aob().
The tear down code calls qeth_drain_output_queue(), where qeth_cleanup_handled_pending() will then attempt to replace such a buffer _again_. If it succeeds this time, the buffer ends up dangling in its replacement's ->next_pending list ... where it will never be freed, since there's no further call to qeth_cleanup_handled_pending().
But the second attempt isn't actually needed, we can simply leave the buffer on the queue and re-use it after a potential recovery has completed. The qeth_clear_output_buffer() in qeth_drain_output_queue() will ensure that it's in a clean state again.
Fixes: 72861ae792c2 ("qeth: recovery through asynchronous delivery") Signed-off-by: Julian Wiedmann jwi@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/s390/net/qeth_core_main.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 54a7eefe73d19..e3666232a19a8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -501,12 +501,6 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx,
} } - if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) == - QETH_QDIO_BUF_HANDLED_DELAYED)) { - /* for recovery situations */ - qeth_init_qdio_out_buf(q, bidx); - QETH_CARD_TEXT(q->card, 2, "clprecov"); - } }
From: CK Hu ck.hu@mediatek.com
[ Upstream commit 487778f8d22fcdebb6436f0a5f96484ffa237b0b ]
In the patch to be fixed, horizontal_backporch_byte become too large for some panel, so roll back that patch. For small hfp or hbp panel, using vm->hfront_porch + vm->hback_porch to calculate horizontal_backporch_byte would make it negtive, so use horizontal_backporch_byte itself to make it positive.
Fixes: 35bf948f1edb ("drm/mediatek: dsi: Fix scrolling of panel with small hfp or hbp")
Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Chun-Kuang Hu chunkuang.hu@kernel.org Tested-by: Bilal Wasim bilal.wasim@imgtec.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/mediatek/mtk_dsi.c | 61 +++++++++++------------------- 1 file changed, 22 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 80b7a082e8740..d6e0a29ea6b28 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -444,7 +444,10 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) u32 horizontal_sync_active_byte; u32 horizontal_backporch_byte; u32 horizontal_frontporch_byte; + u32 horizontal_front_back_byte; + u32 data_phy_cycles_byte; u32 dsi_tmp_buf_bpp, data_phy_cycles; + u32 delta; struct mtk_phy_timing *timing = &dsi->phy_timing;
struct videomode *vm = &dsi->vm; @@ -466,50 +469,30 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) - horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp; + horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp - 10; else horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) * - dsi_tmp_buf_bpp; + dsi_tmp_buf_bpp - 10;
data_phy_cycles = timing->lpx + timing->da_hs_prepare + - timing->da_hs_zero + timing->da_hs_exit; - - if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { - if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp > - data_phy_cycles * dsi->lanes + 18) { - horizontal_frontporch_byte = - vm->hfront_porch * dsi_tmp_buf_bpp - - (data_phy_cycles * dsi->lanes + 18) * - vm->hfront_porch / - (vm->hfront_porch + vm->hback_porch); - - horizontal_backporch_byte = - horizontal_backporch_byte - - (data_phy_cycles * dsi->lanes + 18) * - vm->hback_porch / - (vm->hfront_porch + vm->hback_porch); - } else { - DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n"); - horizontal_frontporch_byte = vm->hfront_porch * - dsi_tmp_buf_bpp; - } + timing->da_hs_zero + timing->da_hs_exit + 3; + + delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12; + + horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp; + horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte; + data_phy_cycles_byte = data_phy_cycles * dsi->lanes + delta; + + if (horizontal_front_back_byte > data_phy_cycles_byte) { + horizontal_frontporch_byte -= data_phy_cycles_byte * + horizontal_frontporch_byte / + horizontal_front_back_byte; + + horizontal_backporch_byte -= data_phy_cycles_byte * + horizontal_backporch_byte / + horizontal_front_back_byte; } else { - if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp > - data_phy_cycles * dsi->lanes + 12) { - horizontal_frontporch_byte = - vm->hfront_porch * dsi_tmp_buf_bpp - - (data_phy_cycles * dsi->lanes + 12) * - vm->hfront_porch / - (vm->hfront_porch + vm->hback_porch); - horizontal_backporch_byte = horizontal_backporch_byte - - (data_phy_cycles * dsi->lanes + 12) * - vm->hback_porch / - (vm->hfront_porch + vm->hback_porch); - } else { - DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n"); - horizontal_frontporch_byte = vm->hfront_porch * - dsi_tmp_buf_bpp; - } + DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n"); }
writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
From: Jamie Iles jamie@nuviainc.com
[ Upstream commit b9ad3e9f5a7a760ab068e33e1f18d240ba32ce92 ]
syzkaller found that with CONFIG_DEBUG_KOBJECT_RELEASE=y, releasing a struct slave device could result in the following splat:
kobject: 'bonding_slave' (00000000cecdd4fe): kobject_release, parent 0000000074ceb2b2 (delayed 1000) bond0 (unregistering): (slave bond_slave_1): Releasing backup interface ------------[ cut here ]------------ ODEBUG: free active (active state 0) object type: timer_list hint: workqueue_select_cpu_near kernel/workqueue.c:1549 [inline] ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x98 kernel/workqueue.c:1600 WARNING: CPU: 1 PID: 842 at lib/debugobjects.c:485 debug_print_object+0x180/0x240 lib/debugobjects.c:485 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 842 Comm: kworker/u4:4 Tainted: G S 5.9.0-rc8+ #96 Hardware name: linux,dummy-virt (DT) Workqueue: netns cleanup_net Call trace: dump_backtrace+0x0/0x4d8 include/linux/bitmap.h:239 show_stack+0x34/0x48 arch/arm64/kernel/traps.c:142 __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x174/0x1f8 lib/dump_stack.c:118 panic+0x360/0x7a0 kernel/panic.c:231 __warn+0x244/0x2ec kernel/panic.c:600 report_bug+0x240/0x398 lib/bug.c:198 bug_handler+0x50/0xc0 arch/arm64/kernel/traps.c:974 call_break_hook+0x160/0x1d8 arch/arm64/kernel/debug-monitors.c:322 brk_handler+0x30/0xc0 arch/arm64/kernel/debug-monitors.c:329 do_debug_exception+0x184/0x340 arch/arm64/mm/fault.c:864 el1_dbg+0x48/0xb0 arch/arm64/kernel/entry-common.c:65 el1_sync_handler+0x170/0x1c8 arch/arm64/kernel/entry-common.c:93 el1_sync+0x80/0x100 arch/arm64/kernel/entry.S:594 debug_print_object+0x180/0x240 lib/debugobjects.c:485 __debug_check_no_obj_freed lib/debugobjects.c:967 [inline] debug_check_no_obj_freed+0x200/0x430 lib/debugobjects.c:998 slab_free_hook mm/slub.c:1536 [inline] slab_free_freelist_hook+0x190/0x210 mm/slub.c:1577 slab_free mm/slub.c:3138 [inline] kfree+0x13c/0x460 mm/slub.c:4119 bond_free_slave+0x8c/0xf8 drivers/net/bonding/bond_main.c:1492 __bond_release_one+0xe0c/0xec8 drivers/net/bonding/bond_main.c:2190 bond_slave_netdev_event drivers/net/bonding/bond_main.c:3309 [inline] bond_netdev_event+0x8f0/0xa70 drivers/net/bonding/bond_main.c:3420 notifier_call_chain+0xf0/0x200 kernel/notifier.c:83 __raw_notifier_call_chain kernel/notifier.c:361 [inline] raw_notifier_call_chain+0x44/0x58 kernel/notifier.c:368 call_netdevice_notifiers_info+0xbc/0x150 net/core/dev.c:2033 call_netdevice_notifiers_extack net/core/dev.c:2045 [inline] call_netdevice_notifiers net/core/dev.c:2059 [inline] rollback_registered_many+0x6a4/0xec0 net/core/dev.c:9347 unregister_netdevice_many.part.0+0x2c/0x1c0 net/core/dev.c:10509 unregister_netdevice_many net/core/dev.c:10508 [inline] default_device_exit_batch+0x294/0x338 net/core/dev.c:10992 ops_exit_list.isra.0+0xec/0x150 net/core/net_namespace.c:189 cleanup_net+0x44c/0x888 net/core/net_namespace.c:603 process_one_work+0x96c/0x18c0 kernel/workqueue.c:2269 worker_thread+0x3f0/0xc30 kernel/workqueue.c:2415 kthread+0x390/0x498 kernel/kthread.c:292 ret_from_fork+0x10/0x18 arch/arm64/kernel/entry.S:925
This is a potential use-after-free if the sysfs nodes are being accessed whilst removing the struct slave, so wait for the object destruction to complete before freeing the struct slave itself.
Fixes: 07699f9a7c8d ("bonding: add sysfs /slave dir for bond slave devices.") Fixes: a068aab42258 ("bonding: Fix reference count leak in bond_sysfs_slave_add.") Cc: Qiushi Wu wu000273@umn.edu Cc: Jay Vosburgh j.vosburgh@gmail.com Cc: Veaceslav Falico vfalico@gmail.com Cc: Andy Gospodarek andy@greyhouse.net Signed-off-by: Jamie Iles jamie@nuviainc.com Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/20201120142827.879226-1-jamie@nuviainc.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/bonding/bond_main.c | 61 ++++++++++++++++++-------- drivers/net/bonding/bond_sysfs_slave.c | 18 +------- include/net/bonding.h | 8 ++++ 3 files changed, 52 insertions(+), 35 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 84ecbc6fa0ff2..47afc5938c26b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1460,7 +1460,39 @@ static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave) slave->dev->flags &= ~IFF_SLAVE; }
-static struct slave *bond_alloc_slave(struct bonding *bond) +static void slave_kobj_release(struct kobject *kobj) +{ + struct slave *slave = to_slave(kobj); + struct bonding *bond = bond_get_bond_by_slave(slave); + + cancel_delayed_work_sync(&slave->notify_work); + if (BOND_MODE(bond) == BOND_MODE_8023AD) + kfree(SLAVE_AD_INFO(slave)); + + kfree(slave); +} + +static struct kobj_type slave_ktype = { + .release = slave_kobj_release, +#ifdef CONFIG_SYSFS + .sysfs_ops = &slave_sysfs_ops, +#endif +}; + +static int bond_kobj_init(struct slave *slave) +{ + int err; + + err = kobject_init_and_add(&slave->kobj, &slave_ktype, + &(slave->dev->dev.kobj), "bonding_slave"); + if (err) + kobject_put(&slave->kobj); + + return err; +} + +static struct slave *bond_alloc_slave(struct bonding *bond, + struct net_device *slave_dev) { struct slave *slave = NULL;
@@ -1468,11 +1500,17 @@ static struct slave *bond_alloc_slave(struct bonding *bond) if (!slave) return NULL;
+ slave->bond = bond; + slave->dev = slave_dev; + + if (bond_kobj_init(slave)) + return NULL; + if (BOND_MODE(bond) == BOND_MODE_8023AD) { SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info), GFP_KERNEL); if (!SLAVE_AD_INFO(slave)) { - kfree(slave); + kobject_put(&slave->kobj); return NULL; } } @@ -1481,17 +1519,6 @@ static struct slave *bond_alloc_slave(struct bonding *bond) return slave; }
-static void bond_free_slave(struct slave *slave) -{ - struct bonding *bond = bond_get_bond_by_slave(slave); - - cancel_delayed_work_sync(&slave->notify_work); - if (BOND_MODE(bond) == BOND_MODE_8023AD) - kfree(SLAVE_AD_INFO(slave)); - - kfree(slave); -} - static void bond_fill_ifbond(struct bonding *bond, struct ifbond *info) { info->bond_mode = BOND_MODE(bond); @@ -1678,14 +1705,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, goto err_undo_flags; }
- new_slave = bond_alloc_slave(bond); + new_slave = bond_alloc_slave(bond, slave_dev); if (!new_slave) { res = -ENOMEM; goto err_undo_flags; }
- new_slave->bond = bond; - new_slave->dev = slave_dev; /* Set the new_slave's queue_id to be zero. Queue ID mapping * is set via sysfs or module option if desired. */ @@ -2007,7 +2032,7 @@ err_restore_mtu: dev_set_mtu(slave_dev, new_slave->original_mtu);
err_free: - bond_free_slave(new_slave); + kobject_put(&new_slave->kobj);
err_undo_flags: /* Enslave of first slave has failed and we need to fix master's mac */ @@ -2187,7 +2212,7 @@ static int __bond_release_one(struct net_device *bond_dev, if (!netif_is_bond_master(slave_dev)) slave_dev->priv_flags &= ~IFF_BONDING;
- bond_free_slave(slave); + kobject_put(&slave->kobj);
return 0; } diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c index 9b8346638f697..fd07561da0348 100644 --- a/drivers/net/bonding/bond_sysfs_slave.c +++ b/drivers/net/bonding/bond_sysfs_slave.c @@ -121,7 +121,6 @@ static const struct slave_attribute *slave_attrs[] = { };
#define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) -#define to_slave(obj) container_of(obj, struct slave, kobj)
static ssize_t slave_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -132,28 +131,15 @@ static ssize_t slave_show(struct kobject *kobj, return slave_attr->show(slave, buf); }
-static const struct sysfs_ops slave_sysfs_ops = { +const struct sysfs_ops slave_sysfs_ops = { .show = slave_show, };
-static struct kobj_type slave_ktype = { -#ifdef CONFIG_SYSFS - .sysfs_ops = &slave_sysfs_ops, -#endif -}; - int bond_sysfs_slave_add(struct slave *slave) { const struct slave_attribute **a; int err;
- err = kobject_init_and_add(&slave->kobj, &slave_ktype, - &(slave->dev->dev.kobj), "bonding_slave"); - if (err) { - kobject_put(&slave->kobj); - return err; - } - for (a = slave_attrs; *a; ++a) { err = sysfs_create_file(&slave->kobj, &((*a)->attr)); if (err) { @@ -171,6 +157,4 @@ void bond_sysfs_slave_del(struct slave *slave)
for (a = slave_attrs; *a; ++a) sysfs_remove_file(&slave->kobj, &((*a)->attr)); - - kobject_put(&slave->kobj); } diff --git a/include/net/bonding.h b/include/net/bonding.h index 7d132cc1e5848..d9d0ff3b0ad32 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -185,6 +185,11 @@ struct slave { struct rtnl_link_stats64 slave_stats; };
+static inline struct slave *to_slave(struct kobject *kobj) +{ + return container_of(kobj, struct slave, kobj); +} + struct bond_up_slave { unsigned int count; struct rcu_head rcu; @@ -750,6 +755,9 @@ extern struct bond_parm_tbl ad_select_tbl[]; /* exported from bond_netlink.c */ extern struct rtnl_link_ops bond_link_ops;
+/* exported from bond_sysfs_slave.c */ +extern const struct sysfs_ops slave_sysfs_ops; + static inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *skb) { atomic_long_inc(&dev->tx_dropped);
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 8393597579f5250636f1cff157ea73f402b6501e ]
When netdev_notify_peers was substituted in commit 986103e7920c ("net/ibmvnic: Fix RTNL deadlock during device reset"), call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev) was missed. Fix it now.
Fixes: 986103e7920c ("net/ibmvnic: Fix RTNL deadlock during device reset") Signed-off-by: Lijun Pan ljp@linux.ibm.com Reviewed-by: Dany Madden drt@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index c6ee42278fdcf..723651b34f94d 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2087,8 +2087,10 @@ static int do_reset(struct ibmvnic_adapter *adapter, for (i = 0; i < adapter->req_rx_queues; i++) napi_schedule(&adapter->napi[i]);
- if (adapter->reset_reason != VNIC_RESET_FAILOVER) + if (adapter->reset_reason != VNIC_RESET_FAILOVER) { call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); + call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); + }
rc = 0;
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 98025bce3a6200a0c4637272a33b5913928ba5b8 ]
Commit 61d3e1d9bc2a ("ibmvnic: Remove netdev notify for failover resets") excluded the failover case for notify call because it said netdev_notify_peers() can cause network traffic to stall or halt. Current testing does not show network traffic stall or halt because of the notify call for failover event. netdev_notify_peers may be used when a device wants to inform the rest of the network about some sort of a reconfiguration such as failover or migration.
It is unnecessary to call that in other events like FATAL, NON_FATAL, CHANGE_PARAM, and TIMEOUT resets since in those scenarios the hardware does not change. If the driver must do a hard reset, it is necessary to notify peers.
Fixes: 61d3e1d9bc2a ("ibmvnic: Remove netdev notify for failover resets") Suggested-by: Brian King brking@linux.vnet.ibm.com Suggested-by: Pradeep Satyanarayana pradeeps@linux.vnet.ibm.com Signed-off-by: Dany Madden drt@linux.ibm.com Signed-off-by: Lijun Pan ljp@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 723651b34f94d..0341089743ff1 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2087,7 +2087,8 @@ static int do_reset(struct ibmvnic_adapter *adapter, for (i = 0; i < adapter->req_rx_queues; i++) napi_schedule(&adapter->napi[i]);
- if (adapter->reset_reason != VNIC_RESET_FAILOVER) { + if (adapter->reset_reason == VNIC_RESET_FAILOVER || + adapter->reset_reason == VNIC_RESET_MOBILITY) { call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); } @@ -2160,6 +2161,9 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter, if (rc) return IBMVNIC_OPEN_FAILED;
+ call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); + call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); + return 0; }
From: Stephen Rothwell sfr@canb.auug.org.au
[ Upstream commit b6b79dd53082db11070b4368d85dd6699ff0b063 ]
Using DECLARE_STATIC_KEY_FALSE needs linux/jump_table.h.
Otherwise the build fails with eg:
arch/powerpc/include/asm/book3s/64/kup-radix.h:66:1: warning: data definition has no type or storage class 66 | DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
Fixes: 9a32a7e78bd0 ("powerpc/64s: flush L1D after user accesses") Signed-off-by: Stephen Rothwell sfr@canb.auug.org.au [mpe: Massage change log] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20201123184016.693fe464@canb.auug.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/book3s/64/kup-radix.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h index 28716e2f13e31..a39e2d193fdc1 100644 --- a/arch/powerpc/include/asm/book3s/64/kup-radix.h +++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h @@ -63,6 +63,8 @@
#else /* !__ASSEMBLY__ */
+#include <linux/jump_label.h> + DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
#ifdef CONFIG_PPC_KUAP
From: Shameer Kolothum shameerali.kolothum.thodi@huawei.com
[ Upstream commit 77c38c8cf52ef715bfc5cab3d14222d4f3e776e2 ]
Currently iommu_create_device_direct_mappings() is called without checking the return of __iommu_attach_device(). This may result in failures in iommu driver if dev attach returns error.
Fixes: ce574c27ae27 ("iommu: Move iommu_group_create_direct_mappings() out of iommu_group_add_device()") Signed-off-by: Shameer Kolothum shameerali.kolothum.thodi@huawei.com Link: https://lore.kernel.org/r/20201119165846.34180-1-shameerali.kolothum.thodi@h... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/iommu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 609bd25bf154b..6a0a79e3f5641 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -264,16 +264,18 @@ int iommu_probe_device(struct device *dev) */ iommu_alloc_default_domain(group, dev);
- if (group->default_domain) + if (group->default_domain) { ret = __iommu_attach_device(group->default_domain, dev); + if (ret) { + iommu_group_put(group); + goto err_release; + } + }
iommu_create_device_direct_mappings(group, dev);
iommu_group_put(group);
- if (ret) - goto err_release; - if (ops->probe_finalize) ops->probe_finalize(dev);
From: Xiongfeng Wang wangxiongfeng2@huawei.com
[ Upstream commit 6830ff853a5764c75e56750d59d0bbb6b26f1835 ]
We return 'err' in the error branch, but this variable may be set as zero by the above code. Fix it by setting 'err' as a negative value before we goto the error label.
Fixes: 74c2174e7be5 ("IB uverbs: add mthca user CQ support") Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/r/1605837422-42724-1-git-send-email-wangxiongfeng2@h... Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mthca/mthca_cq.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index c3cfea243af8c..119b2573c9a08 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -803,8 +803,10 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, }
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); - if (IS_ERR(mailbox)) + if (IS_ERR(mailbox)) { + err = PTR_ERR(mailbox); goto err_out_arm; + }
cq_context = mailbox->buf;
@@ -846,9 +848,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, }
spin_lock_irq(&dev->cq_table.lock); - if (mthca_array_set(&dev->cq_table.cq, - cq->cqn & (dev->limits.num_cqs - 1), - cq)) { + err = mthca_array_set(&dev->cq_table.cq, + cq->cqn & (dev->limits.num_cqs - 1), cq); + if (err) { spin_unlock_irq(&dev->cq_table.lock); goto err_out_free_mr; }
From: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com
[ Upstream commit 2980cbd4dce7b1e9bf57df3ced43a7b184986f50 ]
Prevent VFs from resetting when PF driver is being unloaded: - introduce new pf state: __I40E_VF_RESETS_DISABLED; - check if pf state has __I40E_VF_RESETS_DISABLED state set, if so, disable any further VFLR event notifications; - when i40e_remove (rmmod i40e) is called, disable any resets on the VFs;
Previously if there were bare-metal VFs passing traffic and PF driver was removed, there was a possibility of VFs triggering a Tx timeout right before iavf_remove. This was causing iavf_close to not be called because there is a check in the beginning of iavf_remove that bails out early if adapter->state < IAVF_DOWN_PENDING. This makes it so some resources do not get cleaned up.
Fixes: 6a9ddb36eeb8 ("i40e: disable IOV before freeing resources") Signed-off-by: Slawomir Laba slawomirx.laba@intel.com Signed-off-by: Brett Creeley brett.creeley@intel.com Signed-off-by: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com Tested-by: Konrad Jankowski konrad0.jankowski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Link: https://lore.kernel.org/r/20201120180640.3654474-1-anthony.l.nguyen@intel.co... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 22 +++++++++++----- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 +++++++++++-------- 3 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index a7e212d1caa22..6c1290137cbba 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -140,6 +140,7 @@ enum i40e_state_t { __I40E_CLIENT_RESET, __I40E_VIRTCHNL_OP_PENDING, __I40E_RECOVERY_MODE, + __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ /* This must be last as it determines the size of the BITMAP */ __I40E_STATE_SIZE__, }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2e433fdbf2c36..da80dccad1dd3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4006,8 +4006,16 @@ static irqreturn_t i40e_intr(int irq, void *data) }
if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { - ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; - set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); + /* disable any further VFLR event notifications */ + if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) { + u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA); + + reg &= ~I40E_PFINT_ICR0_VFLR_MASK; + wr32(hw, I40E_PFINT_ICR0_ENA, reg); + } else { + ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; + set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); + } }
if (icr0 & I40E_PFINT_ICR0_GRST_MASK) { @@ -15466,6 +15474,11 @@ static void i40e_remove(struct pci_dev *pdev) while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) usleep_range(1000, 2000);
+ if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { + set_bit(__I40E_VF_RESETS_DISABLED, pf->state); + i40e_free_vfs(pf); + pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; + } /* no more scheduling of any task */ set_bit(__I40E_SUSPENDED, pf->state); set_bit(__I40E_DOWN, pf->state); @@ -15492,11 +15505,6 @@ static void i40e_remove(struct pci_dev *pdev) */ i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false);
- if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { - i40e_free_vfs(pf); - pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; - } - i40e_fdir_teardown(pf);
/* If there is a switch structure or any orphans, remove them. diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 343177d71f70a..0d76b8c79f4da 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1403,7 +1403,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) * @vf: pointer to the VF structure * @flr: VFLR was issued or not * - * Returns true if the VF is reset, false otherwise. + * Returns true if the VF is in reset, resets successfully, or resets + * are disabled and false otherwise. **/ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) { @@ -1413,11 +1414,14 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) u32 reg; int i;
+ if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) + return true; + /* If the VFs have been disabled, this means something else is * resetting the VF, so we shouldn't continue. */ if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) - return false; + return true;
i40e_trigger_vf_reset(vf, flr);
@@ -1581,6 +1585,15 @@ void i40e_free_vfs(struct i40e_pf *pf)
i40e_notify_client_of_vf_enable(pf, 0);
+ /* Disable IOV before freeing resources. This lets any VF drivers + * running in the host get themselves cleaned up before we yank + * the carpet out from underneath their feet. + */ + if (!pci_vfs_assigned(pf->pdev)) + pci_disable_sriov(pf->pdev); + else + dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); + /* Amortize wait time by stopping all VFs at the same time */ for (i = 0; i < pf->num_alloc_vfs; i++) { if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states)) @@ -1596,15 +1609,6 @@ void i40e_free_vfs(struct i40e_pf *pf) i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]); }
- /* Disable IOV before freeing resources. This lets any VF drivers - * running in the host get themselves cleaned up before we yank - * the carpet out from underneath their feet. - */ - if (!pci_vfs_assigned(pf->pdev)) - pci_disable_sriov(pf->pdev); - else - dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); - /* free up VF resources */ tmp = pf->num_alloc_vfs; pf->num_alloc_vfs = 0;
From: Manish Narani manish.narani@xilinx.com
[ Upstream commit f4426311f927b01776edf8a45f6fad90feae4e72 ]
Fix the SD DLL node reset issue where incorrect node is being referenced instead of SD DLL node.
Fixes: 426c8d85df7a ("firmware: xilinx: Use APIs instead of IOCTLs")
Signed-off-by: Manish Narani manish.narani@xilinx.com Link: https://lore.kernel.org/r/1605534744-15649-1-git-send-email-manish.narani@xi... Signed-off-by: Michal Simek michal.simek@xilinx.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/xilinx/zynqmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 349ab39480068..d08ac824c993c 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -642,7 +642,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); */ int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) { - return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET, type, 0, NULL); } EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
From: Clark Wang xiaoning.wang@nxp.com
[ Upstream commit 7cd71202961090d8f2d2b863ec66b25ae43e1d39 ]
If set active without increase the usage count of pm, the dont use autosuspend function will call the suspend callback to close the two clocks of spi because the usage count is reduced to -1. This will cause the warning dump below when the defer-probe occurs.
[ 129.379701] ecspi2_root_clk already disabled [ 129.384005] WARNING: CPU: 1 PID: 33 at drivers/clk/clk.c:952 clk_core_disable+0xa4/0xb0
So add the get noresume function before set active.
Fixes: 43b6bf406cd0 spi: imx: fix runtime pm support for !CONFIG_PM Signed-off-by: Clark Wang xiaoning.wang@nxp.com Link: https://lore.kernel.org/r/20201124085247.18025-1-xiaoning.wang@nxp.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-imx.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 9aac515b718c8..91578103a3ca9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1684,6 +1684,7 @@ static int spi_imx_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(spi_imx->dev, MXC_RPM_TIMEOUT); pm_runtime_use_autosuspend(spi_imx->dev); + pm_runtime_get_noresume(spi_imx->dev); pm_runtime_set_active(spi_imx->dev); pm_runtime_enable(spi_imx->dev);
From: Joseph Qi joseph.qi@linux.alibaba.com
[ Upstream commit eb2667b343361863da7b79be26de641e22844ba0 ]
Abaci Fuzz reported a shift-out-of-bounds BUG in io_uring_create():
[ 59.598207] UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 [ 59.599665] shift exponent 64 is too large for 64-bit type 'long unsigned int' [ 59.601230] CPU: 0 PID: 963 Comm: a.out Not tainted 5.10.0-rc4+ #3 [ 59.602502] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 [ 59.603673] Call Trace: [ 59.604286] dump_stack+0x107/0x163 [ 59.605237] ubsan_epilogue+0xb/0x5a [ 59.606094] __ubsan_handle_shift_out_of_bounds.cold+0xb2/0x20e [ 59.607335] ? lock_downgrade+0x6c0/0x6c0 [ 59.608182] ? rcu_read_lock_sched_held+0xaf/0xe0 [ 59.609166] io_uring_create.cold+0x99/0x149 [ 59.610114] io_uring_setup+0xd6/0x140 [ 59.610975] ? io_uring_create+0x2510/0x2510 [ 59.611945] ? lockdep_hardirqs_on_prepare+0x286/0x400 [ 59.613007] ? syscall_enter_from_user_mode+0x27/0x80 [ 59.614038] ? trace_hardirqs_on+0x5b/0x180 [ 59.615056] do_syscall_64+0x2d/0x40 [ 59.615940] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 59.617007] RIP: 0033:0x7f2bb8a0b239
This is caused by roundup_pow_of_two() if the input entries larger enough, e.g. 2^32-1. For sq_entries, it will check first and we allow at most IORING_MAX_ENTRIES, so it is okay. But for cq_entries, we do round up first, that may overflow and truncate it to 0, which is not the expected behavior. So check the cq size first and then do round up.
Fixes: 88ec3211e463 ("io_uring: round-up cq size before comparing with rounded sq size") Reported-by: Abaci Fuzz abaci@linux.alibaba.com Signed-off-by: Joseph Qi joseph.qi@linux.alibaba.com Reviewed-by: Stefano Garzarella sgarzare@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/io_uring.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c index 5d9f8e40b93d3..6d729a278535e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8907,14 +8907,16 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, * to a power-of-two, if it isn't already. We do NOT impose * any cq vs sq ring sizing. */ - p->cq_entries = roundup_pow_of_two(p->cq_entries); - if (p->cq_entries < p->sq_entries) + if (!p->cq_entries) return -EINVAL; if (p->cq_entries > IORING_MAX_CQ_ENTRIES) { if (!(p->flags & IORING_SETUP_CLAMP)) return -EINVAL; p->cq_entries = IORING_MAX_CQ_ENTRIES; } + p->cq_entries = roundup_pow_of_two(p->cq_entries); + if (p->cq_entries < p->sq_entries) + return -EINVAL; } else { p->cq_entries = 2 * p->sq_entries; }
From: Lincoln Ramsay lincoln.ramsay@opengear.com
[ Upstream commit 9bd2702d292cb7b565b09e949d30288ab7a26d51 ]
When performing IPv6 forwarding, there is an expectation that SKBs will have some headroom. When forwarding a packet from the aquantia driver, this does not always happen, triggering a kernel warning.
aq_ring.c has this code (edited slightly for brevity):
if (buff->is_eop && buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) { skb = build_skb(aq_buf_vaddr(&buff->rxdata), AQ_CFG_RX_FRAME_MAX); } else { skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE);
There is a significant difference between the SKB produced by these 2 code paths. When napi_alloc_skb creates an SKB, there is a certain amount of headroom reserved. However, this is not done in the build_skb codepath.
As the hardware buffer that build_skb is built around does not handle the presence of the SKB header, this code path is being removed and the napi_alloc_skb path will always be used. This code path does have to copy the packet header into the SKB, but it adds the packet data as a frag.
Fixes: 018423e90bee ("net: ethernet: aquantia: Add ring support code") Signed-off-by: Lincoln Ramsay lincoln.ramsay@opengear.com Link: https://lore.kernel.org/r/MWHPR1001MB23184F3EAFA413E0D1910EC9E8FC0@MWHPR1001... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/aquantia/atlantic/aq_ring.c | 126 ++++++++---------- 1 file changed, 52 insertions(+), 74 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 4f913658eea46..24122ccda614c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -413,85 +413,63 @@ int aq_ring_rx_clean(struct aq_ring_s *self, buff->rxdata.pg_off, buff->len, DMA_FROM_DEVICE);
- /* for single fragment packets use build_skb() */ - if (buff->is_eop && - buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) { - skb = build_skb(aq_buf_vaddr(&buff->rxdata), + skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); + if (unlikely(!skb)) { + u64_stats_update_begin(&self->stats.rx.syncp); + self->stats.rx.skb_alloc_fails++; + u64_stats_update_end(&self->stats.rx.syncp); + err = -ENOMEM; + goto err_exit; + } + if (is_ptp_ring) + buff->len -= + aq_ptp_extract_ts(self->aq_nic, skb, + aq_buf_vaddr(&buff->rxdata), + buff->len); + + hdr_len = buff->len; + if (hdr_len > AQ_CFG_RX_HDR_SIZE) + hdr_len = eth_get_headlen(skb->dev, + aq_buf_vaddr(&buff->rxdata), + AQ_CFG_RX_HDR_SIZE); + + memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata), + ALIGN(hdr_len, sizeof(long))); + + if (buff->len - hdr_len > 0) { + skb_add_rx_frag(skb, 0, buff->rxdata.page, + buff->rxdata.pg_off + hdr_len, + buff->len - hdr_len, AQ_CFG_RX_FRAME_MAX); - if (unlikely(!skb)) { - u64_stats_update_begin(&self->stats.rx.syncp); - self->stats.rx.skb_alloc_fails++; - u64_stats_update_end(&self->stats.rx.syncp); - err = -ENOMEM; - goto err_exit; - } - if (is_ptp_ring) - buff->len -= - aq_ptp_extract_ts(self->aq_nic, skb, - aq_buf_vaddr(&buff->rxdata), - buff->len); - skb_put(skb, buff->len); page_ref_inc(buff->rxdata.page); - } else { - skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); - if (unlikely(!skb)) { - u64_stats_update_begin(&self->stats.rx.syncp); - self->stats.rx.skb_alloc_fails++; - u64_stats_update_end(&self->stats.rx.syncp); - err = -ENOMEM; - goto err_exit; - } - if (is_ptp_ring) - buff->len -= - aq_ptp_extract_ts(self->aq_nic, skb, - aq_buf_vaddr(&buff->rxdata), - buff->len); - - hdr_len = buff->len; - if (hdr_len > AQ_CFG_RX_HDR_SIZE) - hdr_len = eth_get_headlen(skb->dev, - aq_buf_vaddr(&buff->rxdata), - AQ_CFG_RX_HDR_SIZE); - - memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata), - ALIGN(hdr_len, sizeof(long))); - - if (buff->len - hdr_len > 0) { - skb_add_rx_frag(skb, 0, buff->rxdata.page, - buff->rxdata.pg_off + hdr_len, - buff->len - hdr_len, - AQ_CFG_RX_FRAME_MAX); - page_ref_inc(buff->rxdata.page); - } + }
- if (!buff->is_eop) { - buff_ = buff; - i = 1U; - do { - next_ = buff_->next, - buff_ = &self->buff_ring[next_]; + if (!buff->is_eop) { + buff_ = buff; + i = 1U; + do { + next_ = buff_->next; + buff_ = &self->buff_ring[next_];
- dma_sync_single_range_for_cpu( - aq_nic_get_dev(self->aq_nic), - buff_->rxdata.daddr, - buff_->rxdata.pg_off, - buff_->len, - DMA_FROM_DEVICE); - skb_add_rx_frag(skb, i++, - buff_->rxdata.page, - buff_->rxdata.pg_off, - buff_->len, - AQ_CFG_RX_FRAME_MAX); - page_ref_inc(buff_->rxdata.page); - buff_->is_cleaned = 1; - - buff->is_ip_cso &= buff_->is_ip_cso; - buff->is_udp_cso &= buff_->is_udp_cso; - buff->is_tcp_cso &= buff_->is_tcp_cso; - buff->is_cso_err |= buff_->is_cso_err; + dma_sync_single_range_for_cpu(aq_nic_get_dev(self->aq_nic), + buff_->rxdata.daddr, + buff_->rxdata.pg_off, + buff_->len, + DMA_FROM_DEVICE); + skb_add_rx_frag(skb, i++, + buff_->rxdata.page, + buff_->rxdata.pg_off, + buff_->len, + AQ_CFG_RX_FRAME_MAX); + page_ref_inc(buff_->rxdata.page); + buff_->is_cleaned = 1;
- } while (!buff_->is_eop); - } + buff->is_ip_cso &= buff_->is_ip_cso; + buff->is_udp_cso &= buff_->is_udp_cso; + buff->is_tcp_cso &= buff_->is_tcp_cso; + buff->is_cso_err |= buff_->is_cso_err; + + } while (!buff_->is_eop); }
if (buff->is_vlan)
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit d8f0a86795c69f5b697f7d9e5274c124da93c92d ]
GPIOs - as returned by of_get_named_gpio() and used by the gpiolib - are signed integers, where negative number indicates error. The return value of of_get_named_gpio() should not be assigned to an unsigned int because in case of !CONFIG_GPIOLIB such number would be a valid GPIO.
Fixes: c04c674fadeb ("nfc: s3fwrn5: Add driver for Samsung S3FWRN5 NFC Chip") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20201123162351.209100-1-krzk@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nfc/s3fwrn5/i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c index b4eb926d220ac..d7ecff0b1c662 100644 --- a/drivers/nfc/s3fwrn5/i2c.c +++ b/drivers/nfc/s3fwrn5/i2c.c @@ -26,8 +26,8 @@ struct s3fwrn5_i2c_phy { struct i2c_client *i2c_dev; struct nci_dev *ndev;
- unsigned int gpio_en; - unsigned int gpio_fw_wake; + int gpio_en; + int gpio_fw_wake;
struct mutex mutex;
From: Shay Agroskin shayagr@amazon.com
[ Upstream commit 5b7022cf1dc0d721bd4b5f3bada05bd8ced82fe0 ]
After request id is checked in validate_rx_req_id() its value is still used in the line rx_ring->free_ids[next_to_clean] = rx_ring->ena_bufs[i].req_id; even if it was found to be out-of-bound for the array free_ids.
The patch moves the request id to an earlier stage in the napi routine and makes sure its value isn't used if it's found out-of-bounds.
Fixes: 30623e1ed116 ("net: ena: avoid memory access violation by validating req_id properly") Signed-off-by: Ido Segev idose@amazon.com Signed-off-by: Shay Agroskin shayagr@amazon.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amazon/ena/ena_eth_com.c | 3 ++ drivers/net/ethernet/amazon/ena/ena_netdev.c | 43 +++++-------------- 2 files changed, 14 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/amazon/ena/ena_eth_com.c b/drivers/net/ethernet/amazon/ena/ena_eth_com.c index ccd4405895651..336f115e8091f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_eth_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_eth_com.c @@ -538,6 +538,7 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq, { struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0]; struct ena_eth_io_rx_cdesc_base *cdesc = NULL; + u16 q_depth = io_cq->q_depth; u16 cdesc_idx = 0; u16 nb_hw_desc; u16 i = 0; @@ -565,6 +566,8 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq, do { ena_buf[i].len = cdesc->length; ena_buf[i].req_id = cdesc->req_id; + if (unlikely(ena_buf[i].req_id >= q_depth)) + return -EIO;
if (++i >= nb_hw_desc) break; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index a3a8edf9a734d..0a8520a2e4649 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -801,24 +801,6 @@ static void ena_free_all_io_tx_resources(struct ena_adapter *adapter) adapter->num_io_queues); }
-static int validate_rx_req_id(struct ena_ring *rx_ring, u16 req_id) -{ - if (likely(req_id < rx_ring->ring_size)) - return 0; - - netif_err(rx_ring->adapter, rx_err, rx_ring->netdev, - "Invalid rx req_id: %hu\n", req_id); - - u64_stats_update_begin(&rx_ring->syncp); - rx_ring->rx_stats.bad_req_id++; - u64_stats_update_end(&rx_ring->syncp); - - /* Trigger device reset */ - rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; - set_bit(ENA_FLAG_TRIGGER_RESET, &rx_ring->adapter->flags); - return -EFAULT; -} - /* ena_setup_rx_resources - allocate I/O Rx resources (Descriptors) * @adapter: network interface device structure * @qid: queue index @@ -1368,15 +1350,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, struct ena_rx_buffer *rx_info; u16 len, req_id, buf = 0; void *va; - int rc;
len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id;
- rc = validate_rx_req_id(rx_ring, req_id); - if (unlikely(rc < 0)) - return NULL; - rx_info = &rx_ring->rx_buffer_info[req_id];
if (unlikely(!rx_info->page)) { @@ -1452,10 +1429,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id;
- rc = validate_rx_req_id(rx_ring, req_id); - if (unlikely(rc < 0)) - return NULL; - rx_info = &rx_ring->rx_buffer_info[req_id]; } while (1);
@@ -1704,12 +1677,18 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, error: adapter = netdev_priv(rx_ring->netdev);
- u64_stats_update_begin(&rx_ring->syncp); - rx_ring->rx_stats.bad_desc_num++; - u64_stats_update_end(&rx_ring->syncp); + if (rc == -ENOSPC) { + u64_stats_update_begin(&rx_ring->syncp); + rx_ring->rx_stats.bad_desc_num++; + u64_stats_update_end(&rx_ring->syncp); + adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS; + } else { + u64_stats_update_begin(&rx_ring->syncp); + rx_ring->rx_stats.bad_req_id++; + u64_stats_update_end(&rx_ring->syncp); + adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; + }
- /* Too many desc from the device. Trigger reset */ - adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS; set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
return 0;
From: Shay Agroskin shayagr@amazon.com
[ Upstream commit 09323b3bca95181c0da79daebc8b0603e500f573 ]
The ENA driver uses the readless mechanism, which uses DMA, to find out what the DMA mask is supposed to be.
If DMA is used without setting the dma_mask first, it causes the Intel IOMMU driver to think that ENA is a 32-bit device and therefore disables IOMMU passthrough permanently.
This patch sets the dma_mask to be ENA_MAX_PHYS_ADDR_SIZE_BITS=48 before readless initialization in ena_device_init()->ena_com_mmio_reg_read_request_init(), which is large enough to workaround the intel_iommu issue.
DMA mask is set again to the correct value after it's received from the device after readless is initialized.
The patch also changes the driver to use dma_set_mask_and_coherent() function instead of the two pci_set_dma_mask() and pci_set_consistent_dma_mask() ones. Both methods achieve the same effect.
Fixes: 1738cd3ed342 ("net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Mike Cui mikecui@amazon.com Signed-off-by: Arthur Kiyanovski akiyano@amazon.com Signed-off-by: Shay Agroskin shayagr@amazon.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 0a8520a2e4649..1c978c7987adc 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3357,16 +3357,9 @@ static int ena_device_init(struct ena_com_dev *ena_dev, struct pci_dev *pdev, goto err_mmio_read_less; }
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_width)); + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_width)); if (rc) { - dev_err(dev, "pci_set_dma_mask failed 0x%x\n", rc); - goto err_mmio_read_less; - } - - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_width)); - if (rc) { - dev_err(dev, "err_pci_set_consistent_dma_mask failed 0x%x\n", - rc); + dev_err(dev, "dma_set_mask_and_coherent failed %d\n", rc); goto err_mmio_read_less; }
@@ -4136,6 +4129,12 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; }
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ENA_MAX_PHYS_ADDR_SIZE_BITS)); + if (rc) { + dev_err(&pdev->dev, "dma_set_mask_and_coherent failed %d\n", rc); + goto err_disable_device; + } + pci_set_master(pdev);
ena_dev = vzalloc(sizeof(*ena_dev));
From: Shay Agroskin shayagr@amazon.com
[ Upstream commit 1396d3148bd250db880573f9ed0abe5d6fba1fce ]
This patch fixes two lines in which the rx_offset received by the device wasn't taken into account:
- prefetch function: In our driver the copied data would reside in rx_info->page + rx_headroom + rx_offset
so the prefetch function is changed accordingly.
- setting page_offset to zero for descriptors > 1: for every descriptor but the first, the rx_offset is zero. Hence the page_offset value should be set to rx_headroom.
The previous implementation changed the value of rx_info after the descriptor was added to the SKB (essentially providing wrong page offset).
Fixes: 68f236df93a9 ("net: ena: add support for the rx offset feature") Signed-off-by: Shay Agroskin shayagr@amazon.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 1c978c7987adc..36134fc3e9197 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -920,10 +920,14 @@ static void ena_free_all_io_rx_resources(struct ena_adapter *adapter) static int ena_alloc_rx_page(struct ena_ring *rx_ring, struct ena_rx_buffer *rx_info, gfp_t gfp) { + int headroom = rx_ring->rx_headroom; struct ena_com_buf *ena_buf; struct page *page; dma_addr_t dma;
+ /* restore page offset value in case it has been changed by device */ + rx_info->page_offset = headroom; + /* if previous allocated page is not used */ if (unlikely(rx_info->page)) return 0; @@ -953,10 +957,9 @@ static int ena_alloc_rx_page(struct ena_ring *rx_ring, "alloc page %p, rx_info %p\n", page, rx_info);
rx_info->page = page; - rx_info->page_offset = 0; ena_buf = &rx_info->ena_buf; - ena_buf->paddr = dma + rx_ring->rx_headroom; - ena_buf->len = ENA_PAGE_SIZE - rx_ring->rx_headroom; + ena_buf->paddr = dma + headroom; + ena_buf->len = ENA_PAGE_SIZE - headroom;
return 0; } @@ -1368,7 +1371,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
/* save virt address of first buffer */ va = page_address(rx_info->page) + rx_info->page_offset; - prefetch(va + NET_IP_ALIGN); + + prefetch(va);
if (len <= rx_ring->rx_copybreak) { skb = ena_alloc_skb(rx_ring, false); @@ -1409,8 +1413,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page, rx_info->page_offset, len, ENA_PAGE_SIZE); - /* The offset is non zero only for the first buffer */ - rx_info->page_offset = 0;
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, "rx skb updated. len %d. data_len %d\n", @@ -1529,8 +1531,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) int ret;
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; - xdp->data = page_address(rx_info->page) + - rx_info->page_offset + rx_ring->rx_headroom; + xdp->data = page_address(rx_info->page) + rx_info->page_offset; xdp_set_data_meta_invalid(xdp); xdp->data_hard_start = page_address(rx_info->page); xdp->data_end = xdp->data + rx_ring->ena_bufs[0].len; @@ -1597,8 +1598,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, if (unlikely(ena_rx_ctx.descs == 0)) break;
+ /* First descriptor might have an offset set by the device */ rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; - rx_info->page_offset = ena_rx_ctx.pkt_offset; + rx_info->page_offset += ena_rx_ctx.pkt_offset;
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit a0faaa27c71608799e0dd765c5af38a089091802 ]
adapter->tx_scrq and adapter->rx_scrq could be NULL if the previous reset did not complete after freeing sub crqs. Check for NULL before dereferencing them.
Snippet of call trace: ibmvnic 30000006 env6: Releasing sub-CRQ ibmvnic 30000006 env6: Releasing CRQ ... ibmvnic 30000006 env6: Got Control IP offload Response ibmvnic 30000006 env6: Re-setting tx_scrq[0] BUG: Kernel NULL pointer dereference on read at 0x00000000 Faulting instruction address: 0xc008000003dea7cc Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries Modules linked in: rpadlpar_io rpaphp xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_counter nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables xsk_diag tcp_diag udp_diag raw_diag inet_diag unix_diag af_packet_diag netlink_diag tun bridge stp llc rfkill sunrpc pseries_rng xts vmx_crypto uio_pdrv_genirq uio binfmt_misc ip_tables xfs libcrc32c sd_mod t10_pi sg ibmvscsi ibmvnic ibmveth scsi_transport_srp dm_mirror dm_region_hash dm_log dm_mod CPU: 80 PID: 1856 Comm: kworker/80:2 Tainted: G W 5.8.0+ #4 Workqueue: events __ibmvnic_reset [ibmvnic] NIP: c008000003dea7cc LR: c008000003dea7bc CTR: 0000000000000000 REGS: c0000007ef7db860 TRAP: 0380 Tainted: G W (5.8.0+) MSR: 800000000280b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 28002422 XER: 0000000d CFAR: c000000000bd9520 IRQMASK: 0 GPR00: c008000003dea7bc c0000007ef7dbaf0 c008000003df7400 c0000007fa26ec00 GPR04: c0000007fcd0d008 c0000007fcd96350 0000000000000027 c0000007fcd0d010 GPR08: 0000000000000023 0000000000000000 0000000000000000 0000000000000000 GPR12: 0000000000002000 c00000001ec18e00 c0000000001982f8 c0000007bad6e840 GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 GPR20: 0000000000000000 0000000000000000 0000000000000000 fffffffffffffef7 GPR24: 0000000000000402 c0000007fa26f3a8 0000000000000003 c00000016f8ec048 GPR28: 0000000000000000 0000000000000000 0000000000000000 c0000007fa26ec00 NIP [c008000003dea7cc] ibmvnic_reset_init+0x15c/0x258 [ibmvnic] LR [c008000003dea7bc] ibmvnic_reset_init+0x14c/0x258 [ibmvnic] Call Trace: [c0000007ef7dbaf0] [c008000003dea7bc] ibmvnic_reset_init+0x14c/0x258 [ibmvnic] (unreliable) [c0000007ef7dbb80] [c008000003de8860] __ibmvnic_reset+0x408/0x970 [ibmvnic] [c0000007ef7dbc50] [c00000000018b7cc] process_one_work+0x2cc/0x800 [c0000007ef7dbd20] [c00000000018bd78] worker_thread+0x78/0x520 [c0000007ef7dbdb0] [c0000000001984c4] kthread+0x1d4/0x1e0 [c0000007ef7dbe20] [c00000000000cea8] ret_from_kernel_thread+0x5c/0x74
Fixes: 57a49436f4e8 ("ibmvnic: Reset sub-crqs during driver reset") Signed-off-by: Lijun Pan ljp@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 0341089743ff1..349d0b3d9edc3 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2887,6 +2887,9 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter) { int i, rc;
+ if (!adapter->tx_scrq || !adapter->rx_scrq) + return -EINVAL; + for (i = 0; i < adapter->req_tx_queues; i++) { netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i); rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]);
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 0e435befaea45f7ea58682eecab5e37e05b2ce65 ]
crq->msgs could be NULL if the previous reset did not complete after freeing crq->msgs. Check for NULL before dereferencing them.
Snippet of call trace: ... ibmvnic 30000003 env3 (unregistering): Releasing sub-CRQ ibmvnic 30000003 env3 (unregistering): Releasing CRQ BUG: Kernel NULL pointer dereference on read at 0x00000000 Faulting instruction address: 0xc0000000000c1a30 Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries Modules linked in: ibmvnic(E-) rpadlpar_io rpaphp xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_counter nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables xsk_diag tcp_diag udp_diag tun raw_diag inet_diag unix_diag bridge af_packet_diag netlink_diag stp llc rfkill sunrpc pseries_rng xts vmx_crypto uio_pdrv_genirq uio binfmt_misc ip_tables xfs libcrc32c sd_mod t10_pi sg ibmvscsi ibmveth scsi_transport_srp dm_mirror dm_region_hash dm_log dm_mod [last unloaded: ibmvnic] CPU: 20 PID: 8426 Comm: kworker/20:0 Tainted: G E 5.10.0-rc1+ #12 Workqueue: events __ibmvnic_reset [ibmvnic] NIP: c0000000000c1a30 LR: c008000001b00c18 CTR: 0000000000000400 REGS: c00000000d05b7a0 TRAP: 0380 Tainted: G E (5.10.0-rc1+) MSR: 800000000280b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 44002480 XER: 20040000 CFAR: c0000000000c19ec IRQMASK: 0 GPR00: 0000000000000400 c00000000d05ba30 c008000001b17c00 0000000000000000 GPR04: 0000000000000000 0000000000000000 0000000000000000 00000000000001e2 GPR08: 000000000001f400 ffffffffffffd950 0000000000000000 c008000001b0b280 GPR12: c0000000000c19c8 c00000001ec72e00 c00000000019a778 c00000002647b440 GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 GPR20: 0000000000000006 0000000000000001 0000000000000003 0000000000000002 GPR24: 0000000000001000 c008000001b0d570 0000000000000005 c00000007ab5d550 GPR28: c00000007ab5c000 c000000032fcf848 c00000007ab5cc00 c000000032fcf800 NIP [c0000000000c1a30] memset+0x68/0x104 LR [c008000001b00c18] ibmvnic_reset_crq+0x70/0x110 [ibmvnic] Call Trace: [c00000000d05ba30] [0000000000000800] 0x800 (unreliable) [c00000000d05bab0] [c008000001b0a930] do_reset.isra.40+0x224/0x634 [ibmvnic] [c00000000d05bb80] [c008000001b08574] __ibmvnic_reset+0x17c/0x3c0 [ibmvnic] [c00000000d05bc50] [c00000000018d9ac] process_one_work+0x2cc/0x800 [c00000000d05bd20] [c00000000018df58] worker_thread+0x78/0x520 [c00000000d05bdb0] [c00000000019a934] kthread+0x1c4/0x1d0 [c00000000d05be20] [c00000000000d5d0] ret_from_kernel_thread+0x5c/0x6c
Fixes: 032c5e82847a ("Driver for IBM System i/p VNIC protocol") Signed-off-by: Lijun Pan ljp@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 349d0b3d9edc3..af8c10e629f88 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -4919,6 +4919,9 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter) } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
/* Clean out the queue */ + if (!crq->msgs) + return -EINVAL; + memset(crq->msgs, 0, PAGE_SIZE); crq->cur = 0; crq->active = false;
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 3ada288150fb17ab3fcce2cf5fce20461f86b2ee ]
Based on the discussion with Sukadev Bhattiprolu and Dany Madden, we believe that checking adapter->resetting bit is preferred since RESETTING state flag is not as strict as resetting bit. RESETTING state flag is removed since it is verbose now.
Fixes: 7d7195a026ba ("ibmvnic: Do not process device remove during device reset") Signed-off-by: Lijun Pan ljp@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 3 +-- drivers/net/ethernet/ibm/ibmvnic.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index af8c10e629f88..81ec233926acb 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2228,7 +2228,6 @@ static void __ibmvnic_reset(struct work_struct *work)
if (!saved_state) { reset_state = adapter->state; - adapter->state = VNIC_RESETTING; saved_state = true; } spin_unlock_irqrestore(&adapter->state_lock, flags); @@ -5261,7 +5260,7 @@ static int ibmvnic_remove(struct vio_dev *dev) unsigned long flags;
spin_lock_irqsave(&adapter->state_lock, flags); - if (adapter->state == VNIC_RESETTING) { + if (test_bit(0, &adapter->resetting)) { spin_unlock_irqrestore(&adapter->state_lock, flags); return -EBUSY; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 43feb96b0a68a..31d604fc7bde7 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -941,8 +941,7 @@ enum vnic_state {VNIC_PROBING = 1, VNIC_CLOSING, VNIC_CLOSED, VNIC_REMOVING, - VNIC_REMOVED, - VNIC_RESETTING}; + VNIC_REMOVED};
enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1, VNIC_RESET_MOBILITY,
From: Rui Miguel Silva rui.silva@linaro.org
[ Upstream commit 853735e404244f5496cdb6188c5ed9a0f9627ee6 ]
Only in smp systems the cache policy is setup as write alloc, in single cpu systems the cache policy is set as writeback and it is normal memory, so, it should pass the is_normal_memory check in the share memory registration.
Add the right condition to make it work in no smp systems.
Fixes: cdbcf83d29c1 ("tee: optee: check type of registered shared memory") Signed-off-by: Rui Miguel Silva rui.silva@linaro.org Signed-off-by: Jens Wiklander jens.wiklander@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tee/optee/call.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 20b6fd7383c54..c981757ba0d40 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -534,7 +534,8 @@ void optee_free_pages_list(void *list, size_t num_entries) static bool is_normal_memory(pgprot_t p) { #if defined(CONFIG_ARM) - return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC; + return (((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC) || + ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEBACK)); #elif defined(CONFIG_ARM64) return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); #else
From: Lu Baolu baolu.lu@linux.intel.com
[ Upstream commit e2be2a833ab5338fa5b8b99ba622b911d96f1795 ]
After commit 327d5b2fee91c ("iommu/vt-d: Allow 32bit devices to uses DMA domain"), swiotlb could also be used for direct memory access if IOMMU is enabled but a device is configured to pass through the DMA translation. Keep swiotlb when IOMMU is forced on, otherwise, some devices won't work if "iommu=pt" kernel parameter is used.
Fixes: 327d5b2fee91 ("iommu/vt-d: Allow 32bit devices to uses DMA domain") Reported-and-tested-by: Adrian Huang ahuang12@lenovo.com Signed-off-by: Lu Baolu baolu.lu@linux.intel.com Link: https://lore.kernel.org/r/20201125014124.4070776-1-baolu.lu@linux.intel.com Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=210237 Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kernel/tboot.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 420be871d9d45..ae64f98ec2ab6 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -514,13 +514,10 @@ int tboot_force_iommu(void) if (!tboot_enabled()) return 0;
- if (no_iommu || swiotlb || dmar_disabled) + if (no_iommu || dmar_disabled) pr_warn("Forcing Intel-IOMMU to enabled\n");
dmar_disabled = 0; -#ifdef CONFIG_SWIOTLB - swiotlb = 0; -#endif no_iommu = 0;
return 1;
From: Dipen Patel dipenp@nvidia.com
[ Upstream commit 1741e18737948c140ccc4cc643e8126d95ee6e79 ]
The AON HSP node's "reg" property size 0xa0000 will overlap with other resources. This patch fixes that wrong value with correct size 0x90000.
Reviewed-by: Mikko Perttunen mperttunen@nvidia.com Signed-off-by: Dipen Patel dipenp@nvidia.com Fixes: a38570c22e9d ("arm64: tegra: Add nodes for TCU on Tegra194") Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi index ca5cb6aef5ee4..6f6d460c931aa 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi @@ -924,7 +924,7 @@
hsp_aon: hsp@c150000 { compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp"; - reg = <0x0c150000 0xa0000>; + reg = <0x0c150000 0x90000>; interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
From: Amadeusz Sławiński amadeuszx.slawinski@linux.intel.com
[ Upstream commit 50bdcf047503e30126327d0be4f0ad7337106d68 ]
Efivars allows for overriding of SSDT tables, however starting with commit
bf67fad19e493b ("efi: Use more granular check for availability for variable services")
this use case is broken. When loading SSDT generic ops should be set first, however mentioned commit reversed order of operations. Fix this by restoring original order of operations.
Fixes: bf67fad19e493b ("efi: Use more granular check for availability for variable services") Signed-off-by: Amadeusz Sławiński amadeuszx.slawinski@linux.intel.com Link: https://lore.kernel.org/r/20201123172817.124146-1-amadeuszx.slawinski@linux.... Tested-by: Cezary Rojewski cezary.rojewski@intel.com Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/efi/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3aa07c3b51369..8ead4379e6e85 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -387,10 +387,10 @@ static int __init efisubsys_init(void)
if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE | EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) { - efivar_ssdt_load(); error = generic_ops_register(); if (error) goto err_put; + efivar_ssdt_load(); platform_device_register_simple("efivars", 0, NULL, 0); }
From: Ard Biesheuvel ardb@kernel.org
[ Upstream commit ff04f3b6f2e27f8ae28a498416af2a8dd5072b43 ]
The memory leak addressed by commit fe5186cf12e3 is a false positive: all allocations are recorded in a linked list, and freed when the filesystem is unmounted. This leads to double frees, and as reported by David, leads to crashes if SLUB is configured to self destruct when double frees occur.
So drop the redundant kfree() again, and instead, mark the offending pointer variable so the allocation is ignored by kmemleak.
Cc: Vamshi K Sthambamkadi vamshi.k.sthambamkadi@gmail.com Fixes: fe5186cf12e3 ("efivarfs: fix memory leak in efivarfs_create()") Reported-by: David Laight David.Laight@aculab.com Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/efivarfs/inode.c | 2 ++ fs/efivarfs/super.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 96c0c86f3fffe..0297ad95eb5cc 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c @@ -7,6 +7,7 @@ #include <linux/efi.h> #include <linux/fs.h> #include <linux/ctype.h> +#include <linux/kmemleak.h> #include <linux/slab.h> #include <linux/uuid.h>
@@ -103,6 +104,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, var->var.VariableName[i] = '\0';
inode->i_private = var; + kmemleak_ignore(var);
err = efivar_entry_add(var, &efivarfs_list); if (err) diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c index f943fd0b0699c..15880a68faadc 100644 --- a/fs/efivarfs/super.c +++ b/fs/efivarfs/super.c @@ -21,7 +21,6 @@ LIST_HEAD(efivarfs_list); static void efivarfs_evict_inode(struct inode *inode) { clear_inode(inode); - kfree(inode->i_private); }
static const struct super_operations efivarfs_ops = {
From: Geert Uytterhoeven geert@linux-m68k.org
[ Upstream commit 36a237526cd81ff4b6829e6ebd60921c6f976e3b ]
CONFIG_EFI_EARLYCON defaults to yes, and thus is enabled on systems that do not support EFI, or do not have EFI support enabled, but do satisfy the symbol's other dependencies.
While drivers/firmware/efi/ won't be entered during the build phase if CONFIG_EFI=n, and drivers/firmware/efi/earlycon.c itself thus won't be built, enabling EFI_EARLYCON does force-enable CONFIG_FONT_SUPPORT and CONFIG_ARCH_USE_MEMREMAP_PROT, and CONFIG_FONT_8x16, which is undesirable.
Fix this by making CONFIG_EFI_EARLYCON depend on CONFIG_EFI.
This reduces kernel size on headless systems by more than 4 KiB.
Fixes: 69c1f396f25b805a ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation") Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Link: https://lore.kernel.org/r/20201124191646.3559757-1-geert@linux-m68k.org Reviewed-by: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/efi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 3939699e62fe0..929d6f05b6bb1 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -275,7 +275,7 @@ config EFI_DEV_PATH_PARSER
config EFI_EARLYCON def_bool y - depends on SERIAL_EARLYCON && !ARM && !IA64 + depends on EFI && SERIAL_EARLYCON && !ARM && !IA64 select FONT_SUPPORT select ARCH_USE_MEMREMAP_PROT
From: Nathan Chancellor natechancellor@gmail.com
[ Upstream commit e553fdc8105ac2ef3f321739da3908bb6673f7de ]
Commit a96843372331 ("kbuild: explicitly specify the build id style") explicitly set the build ID style to SHA1. Commit c2c81bb2f691 ("RISC-V: Fix the VDSO symbol generaton for binutils-2.35+") undid this change, likely unintentionally.
Restore it so that the build ID style stays consistent across the tree regardless of linker.
Fixes: c2c81bb2f691 ("RISC-V: Fix the VDSO symbol generaton for binutils-2.35+") Signed-off-by: Nathan Chancellor natechancellor@gmail.com Reviewed-by: Nick Desaulniers ndesaulniers@google.com Reviewed-by: Bill Wendling morbo@google.com Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/kernel/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile index cb8f9e4cfcbf8..0cfd6da784f84 100644 --- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile @@ -44,7 +44,7 @@ SYSCFLAGS_vdso.so.dbg = $(c_flags) $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE $(call if_changed,vdsold) SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \ - -Wl,--build-id -Wl,--hash-style=both + -Wl,--build-id=sha1 -Wl,--hash-style=both
# We also create a special relocatable object that should mirror the symbol # table and layout of the linked DSO. With ld --just-symbols we can then
From: Anup Patel anup.patel@wdc.com
[ Upstream commit 6134b110f97178d6919441a82dc91a7f3664b4e0 ]
The jump_label_init() should be called from setup_arch() very early for proper functioning of jump label support.
Fixes: ebc00dde8a97 ("riscv: Add jump-label implementation") 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/setup.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 2c6dd329312bd..3de5234b6de5b 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -69,6 +69,7 @@ void __init setup_arch(char **cmdline_p)
*cmdline_p = boot_command_line;
+ jump_label_init(); parse_early_param();
setup_bootmem();
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit 30aca1bacb398dec6c1ed5eeca33f355bd7b6203 ]
riscv's <vdso/processor.h> uses barrier() so it should include <asm/barrier.h>
Fixes this build error: CC [M] drivers/net/ethernet/emulex/benet/be_main.o In file included from ./include/vdso/processor.h:10, from ./arch/riscv/include/asm/processor.h:11, from ./include/linux/prefetch.h:15, from drivers/net/ethernet/emulex/benet/be_main.c:14: ./arch/riscv/include/asm/vdso/processor.h: In function 'cpu_relax': ./arch/riscv/include/asm/vdso/processor.h:14:2: error: implicit declaration of function 'barrier' [-Werror=implicit-function-declaration] 14 | barrier();
This happens with a total of 5 networking drivers -- they all use <linux/prefetch.h>.
rv64 allmodconfig now builds cleanly after this patch.
Fixes fallout from: 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive")
Fixes: ad5d1122b82f ("riscv: use vDSO common flow to reduce the latency of the time-related functions") Reported-by: Andreas Schwab schwab@linux-m68k.org Signed-off-by: Randy Dunlap rdunlap@infradead.org Acked-by: Arvind Sankar nivedita@alum.mit.edu Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Reviewed-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/riscv/include/asm/vdso/processor.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/riscv/include/asm/vdso/processor.h b/arch/riscv/include/asm/vdso/processor.h index 82a5693b18614..134388cbaaa1d 100644 --- a/arch/riscv/include/asm/vdso/processor.h +++ b/arch/riscv/include/asm/vdso/processor.h @@ -4,6 +4,8 @@
#ifndef __ASSEMBLY__
+#include <asm/barrier.h> + static inline void cpu_relax(void) { #ifdef __riscv_muldiv
From: Antonio Borneo antonio.borneo@st.com
[ Upstream commit 12a8fe56c0f06eaab1f9d89d246c3591bcc7a966 ]
Commit 757926247836 ("net: stmmac: add flexible PPS to dwmac 4.10a") was intended to modify the struct dwmac410_ops, but it got somehow badly merged and modified the struct dwmac4_ops.
Revert the modification in struct dwmac4_ops and re-apply it properly in struct dwmac410_ops.
Fixes: 757926247836 ("net: stmmac: add flexible PPS to dwmac 4.10a") Signed-off-by: Antonio Borneo antonio.borneo@st.com Reported-by: Ahmad Fatoum a.fatoum@pengutronix.de Link: https://lore.kernel.org/r/20201124223729.886992-1-antonio.borneo@st.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index ecd834e0e1216..72a5408a44d61 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -1160,7 +1160,6 @@ const struct stmmac_ops dwmac4_ops = { .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, - .flex_pps_config = dwmac5_flex_pps_config, .set_mac_loopback = dwmac4_set_mac_loopback, .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure, @@ -1202,6 +1201,7 @@ const struct stmmac_ops dwmac410_ops = { .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, + .flex_pps_config = dwmac5_flex_pps_config, .set_mac_loopback = dwmac4_set_mac_loopback, .update_vlan_hash = dwmac4_update_vlan_hash, .sarc_configure = dwmac4_sarc_configure,
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 90cf87d16bd566cff40c2bc8e32e6d4cd3af23f0 ]
The tc-taprio base time indicates the beginning of the tc-taprio schedule, which is cyclic by definition (where the length of the cycle in nanoseconds is called the cycle time). The base time is a 64-bit PTP time in the TAI domain.
Logically, the base-time should be a future time. But that imposes some restrictions to user space, which has to retrieve the current PTP time from the NIC first, then calculate a base time that will still be larger than the base time by the time the kernel driver programs this value into the hardware. Actually ensuring that the programmed base time is in the future is still a problem even if the kernel alone deals with this.
Luckily, the enetc hardware already advances a base-time that is in the past into a congruent time in the immediate future, according to the same formula that can be found in the software implementation of taprio (in taprio_get_start_time):
/* Schedule the start time for the beginning of the next * cycle. */ n = div64_s64(ktime_sub_ns(now, base), cycle); *start = ktime_add_ns(base, (n + 1) * cycle);
There's only one problem: the driver doesn't let the hardware do that. It interferes with the base-time passed from user space, by special-casing the situation when the base-time is zero, and replaces that with the current PTP time. This changes the intended effective base-time of the schedule, which will in the end have a different phase offset than if the base-time of 0.000000000 was to be advanced by an integer multiple of the cycle-time.
Fixes: 34c6adf1977b ("enetc: Configure the Time-Aware Scheduler via tc-taprio offload") Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Link: https://lore.kernel.org/r/20201124220259.3027991-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/enetc/enetc_qos.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c index 1c4a535890dac..9a91e3568adbf 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c @@ -95,18 +95,8 @@ static int enetc_setup_taprio(struct net_device *ndev, gcl_config->atc = 0xff; gcl_config->acl_len = cpu_to_le16(gcl_len);
- if (!admin_conf->base_time) { - gcl_data->btl = - cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR0)); - gcl_data->bth = - cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR1)); - } else { - gcl_data->btl = - cpu_to_le32(lower_32_bits(admin_conf->base_time)); - gcl_data->bth = - cpu_to_le32(upper_32_bits(admin_conf->base_time)); - } - + gcl_data->btl = cpu_to_le32(lower_32_bits(admin_conf->base_time)); + gcl_data->bth = cpu_to_le32(upper_32_bits(admin_conf->base_time)); gcl_data->ct = cpu_to_le32(admin_conf->cycle_time); gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension);
From: Min Li min.li.xe@renesas.com
[ Upstream commit 3cb2e6d92be637b79d6ba0746d610a8dfcc0400b ]
Feed kstrtou8 with NULL terminated string.
Changes since v1: -Use sscanf to get rid of adhoc string parse. Changes since v2: -Check if sscanf returns 3.
Fixes: 7ea5fda2b132 ("ptp: ptp_clockmatrix: update to support 4.8.7 firmware") Signed-off-by: Min Li min.li.xe@renesas.com Link: https://lore.kernel.org/r/1606273115-25792-1-git-send-email-min.li.xe@renesa... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ptp/ptp_clockmatrix.c | 49 ++++++++++++----------------------- 1 file changed, 16 insertions(+), 33 deletions(-)
diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c index e020faff7da53..663255774c0b0 100644 --- a/drivers/ptp/ptp_clockmatrix.c +++ b/drivers/ptp/ptp_clockmatrix.c @@ -103,43 +103,26 @@ static int timespec_to_char_array(struct timespec64 const *ts, return 0; }
-static int idtcm_strverscmp(const char *ver1, const char *ver2) +static int idtcm_strverscmp(const char *version1, const char *version2) { - u8 num1; - u8 num2; - int result = 0; - - /* loop through each level of the version string */ - while (result == 0) { - /* extract leading version numbers */ - if (kstrtou8(ver1, 10, &num1) < 0) - return -1; + u8 ver1[3], ver2[3]; + int i;
- if (kstrtou8(ver2, 10, &num2) < 0) - return -1; + if (sscanf(version1, "%hhu.%hhu.%hhu", + &ver1[0], &ver1[1], &ver1[2]) != 3) + return -1; + if (sscanf(version2, "%hhu.%hhu.%hhu", + &ver2[0], &ver2[1], &ver2[2]) != 3) + return -1;
- /* if numbers differ, then set the result */ - if (num1 < num2) - result = -1; - else if (num1 > num2) - result = 1; - else { - /* if numbers are the same, go to next level */ - ver1 = strchr(ver1, '.'); - ver2 = strchr(ver2, '.'); - if (!ver1 && !ver2) - break; - else if (!ver1) - result = -1; - else if (!ver2) - result = 1; - else { - ver1++; - ver2++; - } - } + for (i = 0; i < 3; i++) { + if (ver1[i] > ver2[i]) + return 1; + if (ver1[i] < ver2[i]) + return -1; } - return result; + + return 0; }
static int idtcm_xfer_read(struct idtcm *idtcm,
From: Matti Hamalainen ccr@tnsp.org
[ Upstream commit 2be65641642ef423f82162c3a5f28c754d1637d2 ]
Commit 03e0d26fcf79 ("drm/nouveau: slowpath for pushbuf ioctl") included a logic-bug which results in the relocations not actually getting applied at all as the call to nouveau_gem_pushbuf_reloc_apply() is never reached. This causes a regression with graphical corruption, triggered when relocations need to be done (for example after a suspend/resume cycle.)
Fix by setting *apply_relocs value only if there were more than 0 relocations.
Additionally, the never reached code had a leftover u_free() call, which, after fixing the logic, now got called and resulted in a double-free. Fix by removing one u_free(), moving the other and adding check for errors.
Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: Ben Skeggs bskeggs@redhat.com Cc: nouveau@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Matti Hamalainen ccr@tnsp.org Fixes: 03e0d26fcf79 ("drm/nouveau: slowpath for pushbuf ioctl") Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20201120152338.1203257-1-ccr@t... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nouveau/nouveau_gem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 124d3dcc5c590..98e99aa8a547e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -570,8 +570,10 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, NV_PRINTK(err, cli, "validating bo list\n"); validate_fini(op, chan, NULL, NULL); return ret; + } else if (ret > 0) { + *apply_relocs = true; } - *apply_relocs = ret; + return 0; }
@@ -674,7 +676,6 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); }
- u_free(reloc); return ret; }
@@ -884,9 +885,10 @@ out: break; } } - u_free(reloc); } out_prevalid: + if (!IS_ERR(reloc)) + u_free(reloc); u_free(bo); u_free(push);
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 4ba1cb39fce4464151517a37ce0ac0a1a3f580d6 ]
The firmware on the original USB2CAN by Geschwister Schneider Technologie Entwicklungs- und Vertriebs UG exchanges all data between the host and the device in host byte order. This is done with the struct gs_host_config::byte_order member, which is sent first to indicate the desired byte order.
The widely used open source firmware candleLight doesn't support this feature and exchanges the data in little endian byte order. This breaks if a device with candleLight firmware is used on big endianess systems.
To fix this problem, all u32 (but not the struct gs_host_frame::echo_id, which is a transparent cookie) are converted to __le32.
Cc: Maximilian Schneider max@schneidersoft.net Cc: Hubert Denkmair hubert@denkmair.de Reported-by: Michael Rausch mr@netadair.de Link: https://lore.kernel.org/r/b58aace7-61f3-6df7-c6df-69fee2c66906@netadair.de Tested-by: Oleksij Rempel o.rempel@pengutronix.de Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") Link: https://lore.kernel.org/r/20201120103818.3386964-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/usb/gs_usb.c | 131 +++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 61 deletions(-)
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index a4b4b742c80c3..0ad13d78815c5 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -63,21 +63,27 @@ enum gs_can_identify_mode { };
/* data types passed between host and device */ + +/* The firmware on the original USB2CAN by Geschwister Schneider + * Technologie Entwicklungs- und Vertriebs UG exchanges all data + * between the host and the device in host byte order. This is done + * with the struct gs_host_config::byte_order member, which is sent + * first to indicate the desired byte order. + * + * The widely used open source firmware candleLight doesn't support + * this feature and exchanges the data in little endian byte order. + */ struct gs_host_config { - u32 byte_order; + __le32 byte_order; } __packed; -/* All data exchanged between host and device is exchanged in host byte order, - * thanks to the struct gs_host_config byte_order member, which is sent first - * to indicate the desired byte order. - */
struct gs_device_config { u8 reserved1; u8 reserved2; u8 reserved3; u8 icount; - u32 sw_version; - u32 hw_version; + __le32 sw_version; + __le32 hw_version; } __packed;
#define GS_CAN_MODE_NORMAL 0 @@ -87,26 +93,26 @@ struct gs_device_config { #define GS_CAN_MODE_ONE_SHOT BIT(3)
struct gs_device_mode { - u32 mode; - u32 flags; + __le32 mode; + __le32 flags; } __packed;
struct gs_device_state { - u32 state; - u32 rxerr; - u32 txerr; + __le32 state; + __le32 rxerr; + __le32 txerr; } __packed;
struct gs_device_bittiming { - u32 prop_seg; - u32 phase_seg1; - u32 phase_seg2; - u32 sjw; - u32 brp; + __le32 prop_seg; + __le32 phase_seg1; + __le32 phase_seg2; + __le32 sjw; + __le32 brp; } __packed;
struct gs_identify_mode { - u32 mode; + __le32 mode; } __packed;
#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) @@ -117,23 +123,23 @@ struct gs_identify_mode { #define GS_CAN_FEATURE_IDENTIFY BIT(5)
struct gs_device_bt_const { - u32 feature; - u32 fclk_can; - u32 tseg1_min; - u32 tseg1_max; - u32 tseg2_min; - u32 tseg2_max; - u32 sjw_max; - u32 brp_min; - u32 brp_max; - u32 brp_inc; + __le32 feature; + __le32 fclk_can; + __le32 tseg1_min; + __le32 tseg1_max; + __le32 tseg2_min; + __le32 tseg2_max; + __le32 sjw_max; + __le32 brp_min; + __le32 brp_max; + __le32 brp_inc; } __packed;
#define GS_CAN_FLAG_OVERFLOW 1
struct gs_host_frame { u32 echo_id; - u32 can_id; + __le32 can_id;
u8 can_dlc; u8 channel; @@ -329,13 +335,13 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (!skb) return;
- cf->can_id = hf->can_id; + cf->can_id = le32_to_cpu(hf->can_id);
cf->can_dlc = get_can_dlc(hf->can_dlc); memcpy(cf->data, hf->data, 8);
/* ERROR frames tell us information about the controller */ - if (hf->can_id & CAN_ERR_FLAG) + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) gs_update_state(dev, cf);
netdev->stats.rx_packets++; @@ -418,11 +424,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev) if (!dbt) return -ENOMEM;
- dbt->prop_seg = bt->prop_seg; - dbt->phase_seg1 = bt->phase_seg1; - dbt->phase_seg2 = bt->phase_seg2; - dbt->sjw = bt->sjw; - dbt->brp = bt->brp; + dbt->prop_seg = cpu_to_le32(bt->prop_seg); + dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1); + dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2); + dbt->sjw = cpu_to_le32(bt->sjw); + dbt->brp = cpu_to_le32(bt->brp);
/* request bit timings */ rc = usb_control_msg(interface_to_usbdev(intf), @@ -503,7 +509,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
cf = (struct can_frame *)skb->data;
- hf->can_id = cf->can_id; + hf->can_id = cpu_to_le32(cf->can_id); hf->can_dlc = cf->can_dlc; memcpy(hf->data, cf->data, cf->can_dlc);
@@ -573,6 +579,7 @@ static int gs_can_open(struct net_device *netdev) int rc, i; struct gs_device_mode *dm; u32 ctrlmode; + u32 flags = 0;
rc = open_candev(netdev); if (rc) @@ -640,24 +647,24 @@ static int gs_can_open(struct net_device *netdev)
/* flags */ ctrlmode = dev->can.ctrlmode; - dm->flags = 0;
if (ctrlmode & CAN_CTRLMODE_LOOPBACK) - dm->flags |= GS_CAN_MODE_LOOP_BACK; + flags |= GS_CAN_MODE_LOOP_BACK; else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) - dm->flags |= GS_CAN_MODE_LISTEN_ONLY; + flags |= GS_CAN_MODE_LISTEN_ONLY;
/* Controller is not allowed to retry TX * this mode is unavailable on atmels uc3c hardware */ if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) - dm->flags |= GS_CAN_MODE_ONE_SHOT; + flags |= GS_CAN_MODE_ONE_SHOT;
if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) - dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE; + flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
/* finally start device */ - dm->mode = GS_CAN_MODE_START; + dm->mode = cpu_to_le32(GS_CAN_MODE_START); + dm->flags = cpu_to_le32(flags); rc = usb_control_msg(interface_to_usbdev(dev->iface), usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), GS_USB_BREQ_MODE, @@ -737,9 +744,9 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) return -ENOMEM;
if (do_identify) - imode->mode = GS_CAN_IDENTIFY_ON; + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON); else - imode->mode = GS_CAN_IDENTIFY_OFF; + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
rc = usb_control_msg(interface_to_usbdev(dev->iface), usb_sndctrlpipe(interface_to_usbdev(dev->iface), @@ -790,6 +797,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct net_device *netdev; int rc; struct gs_device_bt_const *bt_const; + u32 feature;
bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); if (!bt_const) @@ -830,14 +838,14 @@ static struct gs_can *gs_make_candev(unsigned int channel,
/* dev settup */ strcpy(dev->bt_const.name, "gs_usb"); - dev->bt_const.tseg1_min = bt_const->tseg1_min; - dev->bt_const.tseg1_max = bt_const->tseg1_max; - dev->bt_const.tseg2_min = bt_const->tseg2_min; - dev->bt_const.tseg2_max = bt_const->tseg2_max; - dev->bt_const.sjw_max = bt_const->sjw_max; - dev->bt_const.brp_min = bt_const->brp_min; - dev->bt_const.brp_max = bt_const->brp_max; - dev->bt_const.brp_inc = bt_const->brp_inc; + dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min); + dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max); + dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min); + dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max); + dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max); + dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min); + dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max); + dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);
dev->udev = interface_to_usbdev(intf); dev->iface = intf; @@ -854,28 +862,29 @@ static struct gs_can *gs_make_candev(unsigned int channel,
/* can settup */ dev->can.state = CAN_STATE_STOPPED; - dev->can.clock.freq = bt_const->fclk_can; + dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can); dev->can.bittiming_const = &dev->bt_const; dev->can.do_set_bittiming = gs_usb_set_bittiming;
dev->can.ctrlmode_supported = 0;
- if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) + feature = le32_to_cpu(bt_const->feature); + if (feature & GS_CAN_FEATURE_LISTEN_ONLY) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
- if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) + if (feature & GS_CAN_FEATURE_LOOP_BACK) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;
- if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) + if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
- if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) + if (feature & GS_CAN_FEATURE_ONE_SHOT) dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
SET_NETDEV_DEV(netdev, &intf->dev);
- if (dconf->sw_version > 1) - if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) + if (le32_to_cpu(dconf->sw_version) > 1) + if (feature & GS_CAN_FEATURE_IDENTIFY) netdev->ethtool_ops = &gs_usb_ethtool_ops;
kfree(bt_const); @@ -910,7 +919,7 @@ static int gs_usb_probe(struct usb_interface *intf, if (!hconf) return -ENOMEM;
- hconf->byte_order = 0x0000beef; + hconf->byte_order = cpu_to_le32(0x0000beef);
/* send host config */ rc = usb_control_msg(interface_to_usbdev(intf),
From: Benjamin Berg bberg@redhat.com
[ Upstream commit e40cc1b476d60f22628741e53cf3446a29e6e6b9 ]
The lid state may change while the machine is suspended. As such, we may need to re-check the state at wake-up time (at least when waking up from hibernation). Add the appropriate call to the resume handler in order to sync the SW_TABLET_MODE switch state with the hardware state.
Fixes: dda3ec0aa631 ("platform/x86: thinkpad_acpi: Implement tablet mode using GMMS method") BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=210269 Signed-off-by: Benjamin Berg bberg@redhat.com Acked-by: Henrique de Moraes Holschuh hnh@hmh.eng.br Link: https://lore.kernel.org/r/20201123132157.866303-1-benjamin@sipsolutions.net Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/thinkpad_acpi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index eae3579f106f3..017f090a90f68 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -4220,6 +4220,7 @@ static void hotkey_resume(void) pr_err("error while attempting to reset the event firmware interface\n");
tpacpi_send_radiosw_update(); + tpacpi_input_send_tabletsw(); hotkey_tablet_mode_notify_change(); hotkey_wakeup_reason_notify_change(); hotkey_wakeup_hotunplug_complete_notify_change();
From: Kaixu Xia kaixuxia@tencent.com
[ Upstream commit 2a72c46ac4d665614faa25e267c3fb27fb729ed7 ]
The commit 78429e55e4057 ("platform/x86: toshiba_acpi: Clean up variable declaration") cleans up variable declaration in video_proc_write(). Seems it does the variable assignment in the wrong place, this results in dead code and changes the source code logic. Fix it by doing the assignment at the beginning of the funciton.
Fixes: 78429e55e4057 ("platform/x86: toshiba_acpi: Clean up variable declaration") Reported-by: Tosk Robot tencent_os_robot@tencent.com Signed-off-by: Kaixu Xia kaixuxia@tencent.com Link: https://lore.kernel.org/r/1606024177-16481-1-git-send-email-kaixuxia@tencent... Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/toshiba_acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index e557d757c6470..fa7232ad8c395 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1478,7 +1478,7 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file)); char *buffer; char *cmd; - int lcd_out, crt_out, tv_out; + int lcd_out = -1, crt_out = -1, tv_out = -1; int remain = count; int value; int ret; @@ -1510,7 +1510,6 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
kfree(cmd);
- lcd_out = crt_out = tv_out = -1; ret = get_video_status(dev, &video_out); if (!ret) { unsigned int new_video_out = video_out;
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit ebed7b7ca47f3aa95ebf2185a526227744616ac1 ]
The SRQ capacity is got from the firmware, whose field should be ended at bit 19.
Fixes: ba6bb7e97421 ("RDMA/hns: Add interfaces to get pf capabilities from firmware") Link: https://lore.kernel.org/r/1606382812-23636-1-git-send-email-liweihang@huawei... Signed-off-by: Wenpeng Liang liangwenpeng@huawei.com Signed-off-by: Weihang Li liweihang@huawei.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index 17f35f91f4ad2..9d27dfe86821b 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -1639,7 +1639,7 @@ struct hns_roce_query_pf_caps_d { __le32 rsv_uars_rsv_qps; }; #define V2_QUERY_PF_CAPS_D_NUM_SRQS_S 0 -#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(20, 0) +#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(19, 0)
#define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S 20 #define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M GENMASK(21, 20)
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit ab6f7248cc446b85fe9e31091670ad7c4293d7fd ]
The maximum number of retransmission should be returned when querying QP, not the value of retransmission counter.
Fixes: 99fcf82521d9 ("RDMA/hns: Fix the wrong value of rnr_retry when querying qp") Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC") Link: https://lore.kernel.org/r/1606382977-21431-1-git-send-email-liweihang@huawei... Signed-off-by: Wenpeng Liang liangwenpeng@huawei.com Signed-off-by: Weihang Li liweihang@huawei.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index cee140920c579..ccbe12de8e59b 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -4771,11 +4771,11 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, V2_QPC_BYTE_28_AT_M, V2_QPC_BYTE_28_AT_S); qp_attr->retry_cnt = roce_get_field(context.byte_212_lsn, - V2_QPC_BYTE_212_RETRY_CNT_M, - V2_QPC_BYTE_212_RETRY_CNT_S); + V2_QPC_BYTE_212_RETRY_NUM_INIT_M, + V2_QPC_BYTE_212_RETRY_NUM_INIT_S); qp_attr->rnr_retry = roce_get_field(context.byte_244_rnr_rxack, - V2_QPC_BYTE_244_RNR_CNT_M, - V2_QPC_BYTE_244_RNR_CNT_S); + V2_QPC_BYTE_244_RNR_NUM_INIT_M, + V2_QPC_BYTE_244_RNR_NUM_INIT_S);
done: qp_attr->cur_qp_state = qp_attr->qp_state;
From: Yixian Liu liuyixian@huawei.com
[ Upstream commit 17475e104dcb74217c282781817f8f52b46130d3 ]
When a memory window is bound to a memory region, the local write access should be set for its mtpt table.
Fixes: c7c28191408b ("RDMA/hns: Add MW support for hip08") Link: https://lore.kernel.org/r/1606386372-21094-1-git-send-email-liweihang@huawei... Signed-off-by: Yixian Liu liuyixian@huawei.com Signed-off-by: Weihang Li liweihang@huawei.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index ccbe12de8e59b..4c02839b7b418 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -2738,6 +2738,7 @@ static int hns_roce_v2_mw_write_mtpt(void *mb_buf, struct hns_roce_mw *mw)
roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1); roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_L_INV_EN_S, 1); + roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S, 1);
roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S, 0); roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_MR_MW_S, 1);
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 865f5b671b48d0088ce981cff1e822d9f7da441f ]
The threaded IRQ handler is used for the tcan4x5x driver only. The IRQ pin of the tcan4x5x controller is active low, so better not use IRQF_TRIGGER_FALLING when requesting the IRQ. As this can result in missing interrupts.
Further, if the device tree specified the interrupt as "IRQ_TYPE_LEVEL_LOW", unloading and reloading of the driver results in the following error during ifup:
| irq: type mismatch, failed to map hwirq-31 for gpio@20a8000! | tcan4x5x spi1.1: m_can device registered (irq=0, version=32) | tcan4x5x spi1.1 can2: TCAN4X5X successfully initialized. | tcan4x5x spi1.1 can2: failed to request interrupt
This patch fixes the problem by removing the IRQF_TRIGGER_FALLING from the request_threaded_irq().
Fixes: f524f829b75a ("can: m_can: Create a m_can platform framework") Cc: Dan Murphy dmurphy@ti.com Cc: Sriram Dash sriram.dash@samsung.com Cc: Pankaj Sharma pankj.sharma@samsung.com Link: https://lore.kernel.org/r/20201127093548.509253-1-mkl@pengutronix.de 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index f3fc37e96b087..c62439bdee28c 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1653,7 +1653,7 @@ static int m_can_open(struct net_device *dev) INIT_WORK(&cdev->tx_work, m_can_tx_work_queue);
err = request_threaded_irq(dev->irq, NULL, m_can_isr, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + IRQF_ONESHOT, dev->name, dev); } else { err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit e3409e4192535fbcc86a84b7a65d9351f46039ec ]
At lest the revision 3.3.0 of the bosch m_can IP core specifies that valid register values for "Nominal Time segment after sample point (NTSEG2)" are from 1 to 127. As the hardware uses a value of one more than the programmed value, mean tseg2_min is 2.
This patch fixes the tseg2_min value accordingly.
Cc: Dan Murphy dmurphy@ti.com Cc: Mario Huettel mario.huettel@gmx.net Acked-by: Sriram Dash sriram.dash@samsung.com Link: https://lore.kernel.org/r/20201124190751.3972238-1-mkl@pengutronix.de Fixes: b03cfc5bb0e1 ("can: m_can: Enable M_CAN version dependent initialization") 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index c62439bdee28c..d4030abad935d 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -1033,7 +1033,7 @@ static const struct can_bittiming_const m_can_bittiming_const_31X = { .name = KBUILD_MODNAME, .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ .tseg1_max = 256, - .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ .tseg2_max = 128, .sjw_max = 128, .brp_min = 1,
From: Namhyung Kim namhyung@kernel.org
[ Upstream commit aa50d953c169e876413bf237319e728dd41d9fdd ]
It didn't check the tool->cgroup_events bit which is set when the --all-cgroups option is given. Without it, samples will not have cgroup info so no reason to synthesize.
We can check the PERF_RECORD_CGROUP records after running perf record *WITHOUT* the --all-cgroups option:
Before:
$ perf report -D | grep CGROUP 0 0 0x8430 [0x38]: PERF_RECORD_CGROUP cgroup: 1 / CGROUP events: 1 CGROUP events: 0 CGROUP events: 0
After:
$ perf report -D | grep CGROUP CGROUP events: 0 CGROUP events: 0 CGROUP events: 0
Committer testing:
Before:
# perf record -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 2.208 MB perf.data (10003 samples) ] # perf report -D | grep "CGROUP events" CGROUP events: 146 CGROUP events: 0 CGROUP events: 0 #
After:
# perf record -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 2.208 MB perf.data (10448 samples) ] # perf report -D | grep "CGROUP events" CGROUP events: 0 CGROUP events: 0 CGROUP events: 0 #
With all-cgroups:
# perf record --all-cgroups -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 2.374 MB perf.data (11526 samples) ] # perf report -D | grep "CGROUP events" CGROUP events: 146 CGROUP events: 0 CGROUP events: 0 #
Fixes: 8fb4b67939e16 ("perf record: Add --all-cgroups option") Signed-off-by: Namhyung Kim namhyung@kernel.org Tested-by: Arnaldo Carvalho de Melo acme@redhat.com Acked-by: Jiri Olsa jolsa@redhat.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Ian Rogers irogers@google.com Cc: Mark Rutland mark.rutland@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Link: http://lore.kernel.org/lkml/20201127054356.405481-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/synthetic-events.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 89b390623b63d..54ca751a2b3b3 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -563,6 +563,9 @@ int perf_event__synthesize_cgroups(struct perf_tool *tool, char cgrp_root[PATH_MAX]; size_t mount_len; /* length of mount point in the path */
+ if (!tool || !tool->cgroup_events) + return 0; + if (cgroupfs_find_mountpoint(cgrp_root, PATH_MAX, "perf_event") < 0) { pr_debug("cannot find cgroup mount point\n"); return -1;
From: Namhyung Kim namhyung@kernel.org
[ Upstream commit c0ee1d5ae8c8650031badcfca6483a28c0f94f38 ]
Currently perf stat shows some metrics (like IPC) for defined events. But when no aggregation mode is used (-A option), it shows incorrect values since it used a value from a different cpu.
Before:
$ perf stat -aA -e cycles,instructions sleep 1
Performance counter stats for 'system wide':
CPU0 116,057,380 cycles CPU1 86,084,722 cycles CPU2 99,423,125 cycles CPU3 98,272,994 cycles CPU0 53,369,217 instructions # 0.46 insn per cycle CPU1 33,378,058 instructions # 0.29 insn per cycle CPU2 58,150,086 instructions # 0.50 insn per cycle CPU3 40,029,703 instructions # 0.34 insn per cycle
1.001816971 seconds time elapsed
So the IPC for CPU1 should be 0.38 (= 33,378,058 / 86,084,722) but it was 0.29 (= 33,378,058 / 116,057,380) and so on.
After:
$ perf stat -aA -e cycles,instructions sleep 1
Performance counter stats for 'system wide':
CPU0 109,621,384 cycles CPU1 159,026,454 cycles CPU2 99,460,366 cycles CPU3 124,144,142 cycles CPU0 44,396,706 instructions # 0.41 insn per cycle CPU1 120,195,425 instructions # 0.76 insn per cycle CPU2 44,763,978 instructions # 0.45 insn per cycle CPU3 69,049,079 instructions # 0.56 insn per cycle
1.001910444 seconds time elapsed
Fixes: 44d49a600259 ("perf stat: Support metrics in --per-core/socket mode") Reported-by: Sam Xi xyzsam@google.com Signed-off-by: Namhyung Kim namhyung@kernel.org Reviewed-by: Andi Kleen ak@linux.intel.com Acked-by: Jiri Olsa jolsa@redhat.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Ian Rogers irogers@google.com Cc: Mark Rutland mark.rutland@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Link: http://lore.kernel.org/lkml/20201127041404.390276-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/stat-display.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 493ec372fdec4..f2709879bad96 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -324,13 +324,10 @@ static int first_shadow_cpu(struct perf_stat_config *config, struct evlist *evlist = evsel->evlist; int i;
- if (!config->aggr_get_id) - return 0; - if (config->aggr_mode == AGGR_NONE) return id;
- if (config->aggr_mode == AGGR_GLOBAL) + if (!config->aggr_get_id) return 0;
for (i = 0; i < evsel__nr_cpus(evsel); i++) {
From: Masami Hiramatsu mhiramat@kernel.org
[ Upstream commit ab4200c17ba6fe71d2da64317aae8a8aa684624c ]
Fix die_entrypc() to return error correctly if the DIE has no DW_AT_ranges attribute. Since dwarf_ranges() will treat the case as an empty ranges and return 0, we have to check it by ourselves.
Fixes: 91e2f539eeda ("perf probe: Fix to show function entry line as probe-able") Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Cc: Sumanth Korikkar sumanthk@linux.ibm.com Cc: Thomas Richter tmricht@linux.ibm.com Link: http://lore.kernel.org/lkml/160645612634.2824037.5284932731175079426.stgit@d... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/dwarf-aux.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index aa898014ad12f..03c1a39c312a8 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -373,6 +373,7 @@ bool die_is_func_def(Dwarf_Die *dw_die) int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) { Dwarf_Addr base, end; + Dwarf_Attribute attr;
if (!addr) return -EINVAL; @@ -380,6 +381,13 @@ int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) if (dwarf_entrypc(dw_die, addr) == 0) return 0;
+ /* + * Since the dwarf_ranges() will return 0 if there is no + * DW_AT_ranges attribute, we should check it first. + */ + if (!dwarf_attr(dw_die, DW_AT_ranges, &attr)) + return -ENOENT; + return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0; }
From: Nathan Chancellor natechancellor@gmail.com
commit d853b3406903a7dc5b14eb5bada3e8cd677f66a2 upstream.
Clang warns:
drivers/spi/spi-bcm2835aux.c:532:50: warning: variable 'err' is uninitialized when used here [-Wuninitialized] dev_err(&pdev->dev, "could not get clk: %d\n", err); ^~~ ./include/linux/dev_printk.h:112:32: note: expanded from macro 'dev_err' _dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~~~~~~~~~ drivers/spi/spi-bcm2835aux.c:495:9: note: initialize the variable 'err' to silence this warning int err; ^ = 0 1 warning generated.
Restore the assignment so that the error value can be used in the dev_err statement and there is no uninitialized memory being leaked.
Fixes: e13ee6cc4781 ("spi: bcm2835aux: Fix use-after-free on unbind") Link: https://github.com/ClangBuiltLinux/linux/issues/1199 Signed-off-by: Nathan Chancellor natechancellor@gmail.com Link: https://lore.kernel.org/r/20201113180701.455541-1-natechancellor@gmail.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/spi/spi-bcm2835aux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -529,8 +529,9 @@ static int bcm2835aux_spi_probe(struct p
bs->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(bs->clk)) { + err = PTR_ERR(bs->clk); dev_err(&pdev->dev, "could not get clk: %d\n", err); - return PTR_ERR(bs->clk); + return err; }
bs->irq = platform_get_irq(pdev, 0);
From: Alan Stern stern@rowland.harvard.edu
commit f3bc432aa8a7a2bfe9ebb432502be5c5d979d7fe upstream.
Commit 2f964780c03b ("USB: core: replace %p with %pK") used the %pK format specifier for a bunch of __user pointers. But as the 'K' in the specifier indicates, it is meant for kernel pointers. The reason for the %pK specifier is to avoid leaks of kernel addresses, but when the pointer is to an address in userspace the security implications are minimal. In particular, no kernel information is leaked.
This patch changes the __user %pK specifiers (used in a bunch of debugging output lines) to %px, which will always print the actual address with no mangling. (Notably, there is no printk format specifier particularly intended for __user pointers.)
Fixes: 2f964780c03b ("USB: core: replace %p with %pK") CC: Vamsi Krishna Samavedam vskrishn@codeaurora.org CC: stable@vger.kernel.org Signed-off-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20201119170228.GB576844@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/core/devio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
--- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -482,11 +482,11 @@ static void snoop_urb(struct usb_device
if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %px, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %px, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); @@ -1997,7 +1997,7 @@ static int proc_reapurb(struct usb_dev_s if (as) { int retval;
- snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); return retval; @@ -2014,7 +2014,7 @@ static int proc_reapurbnonblock(struct u
as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); } else { @@ -2142,7 +2142,7 @@ static int proc_reapurb_compat(struct us if (as) { int retval;
- snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); return retval; @@ -2159,7 +2159,7 @@ static int proc_reapurbnonblock_compat(s
as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); } else { @@ -2624,7 +2624,7 @@ static long usbdev_do_ioctl(struct file #endif
case USBDEVFS_DISCARDURB: - snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p); + snoop(&dev->dev, "%s: DISCARDURB %px\n", __func__, p); ret = proc_unlinkurb(ps, p); break;
From: Zhang Qilong zhangqilong3@huawei.com
commit e7694cb6998379341fd9bf3bd62b48c4e6a79385 upstream.
In the error path, if midi is not null, we should free the midi->id if necessary to prevent memleak.
Fixes: b85e9de9e818d ("usb: gadget: f_midi: convert to new function interface with backward compatibility") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhang Qilong zhangqilong3@huawei.com Link: https://lore.kernel.org/r/20201117021629.1470544-2-zhangqilong3@huawei.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/gadget/function/f_midi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1315,7 +1315,7 @@ static struct usb_function *f_midi_alloc midi->id = kstrdup(opts->id, GFP_KERNEL); if (opts->id && !midi->id) { status = -ENOMEM; - goto setup_fail; + goto midi_free; } midi->in_ports = opts->in_ports; midi->out_ports = opts->out_ports; @@ -1327,7 +1327,7 @@ static struct usb_function *f_midi_alloc
status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL); if (status) - goto setup_fail; + goto midi_free;
spin_lock_init(&midi->transmit_lock);
@@ -1343,9 +1343,13 @@ static struct usb_function *f_midi_alloc
return &midi->func;
+midi_free: + if (midi) + kfree(midi->id); + kfree(midi); setup_fail: mutex_unlock(&opts->lock); - kfree(midi); + return ERR_PTR(status); }
From: Alan Stern stern@rowland.harvard.edu
commit 184eead057cc7e803558269babc1f2cfb9113ad1 upstream.
Commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints") aimed to make the USB stack more reliable by detecting and skipping over endpoints that are duplicated between interfaces. This caused a regression for a Hercules audio card (reported as Bugzilla #208357), which contains such non-compliant duplications. Although the duplications are harmless, skipping the valid endpoints prevented the device from working.
This patch fixes the regression by adding ENDPOINT_IGNORE quirks for the Hercules card, telling the kernel to ignore the invalid duplicate endpoints and thereby allowing the valid endpoints to be used as intended.
Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints") CC: stable@vger.kernel.org Reported-by: Alexander Chalikiopoulos bugzilla.kernel.org@mrtoasted.com Signed-off-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20201119170040.GA576844@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/core/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -348,6 +348,10 @@ static const struct usb_device_id usb_qu /* Guillemot Webcam Hercules Dualpix Exchange*/ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Guillemot Hercules DJ Console audio card (BZ 208357) */ + { USB_DEVICE(0x06f8, 0xb000), .driver_info = + USB_QUIRK_ENDPOINT_IGNORE }, + /* Midiman M-Audio Keystation 88es */ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
@@ -521,6 +525,8 @@ static const struct usb_device_id usb_am * Matched for devices with USB_QUIRK_ENDPOINT_IGNORE. */ static const struct usb_device_id usb_endpoint_ignore[] = { + { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x01 }, + { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x81 }, { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 }, { }
From: penghao penghao@uniontech.com
commit 9ca57518361418ad5ae7dc38a2128fbf4855e1a2 upstream.
Add a USB_QUIRK_DISCONNECT_SUSPEND quirk for the Lenovo TIO built-in usb-audio. when A630Z going into S3,the system immediately wakeup 7-8 seconds later by usb-audio disconnect interrupt to avoids the issue. eg dmesg: .... [ 626.974091 ] usb 7-1.1: USB disconnect, device number 3 .... .... [ 1774.486691] usb 7-1.1: new full-speed USB device number 5 using xhci_hcd [ 1774.947742] usb 7-1.1: New USB device found, idVendor=17ef, idProduct=a012, bcdDevice= 0.55 [ 1774.956588] usb 7-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 1774.964339] usb 7-1.1: Product: Thinkcentre TIO24Gen3 for USB-audio [ 1774.970999] usb 7-1.1: Manufacturer: Lenovo [ 1774.975447] usb 7-1.1: SerialNumber: 000000000000 [ 1775.048590] usb 7-1.1: 2:1: cannot get freq at ep 0x1 ....... Seeking a better fix, we've tried a lot of things, including: - Check that the device's power/wakeup is disabled - Check that remote wakeup is off at the USB level - All the quirks in drivers/usb/core/quirks.c e.g. USB_QUIRK_RESET_RESUME, USB_QUIRK_RESET, USB_QUIRK_IGNORE_REMOTE_WAKEUP, USB_QUIRK_NO_LPM.
but none of that makes any difference.
There are no errors in the logs showing any suspend/resume-related issues. When the system wakes up due to the modem, log-wise it appears to be a normal resume.
Introduce a quirk to disable the port during suspend when the modem is detected.
Signed-off-by: penghao penghao@uniontech.com Link: https://lore.kernel.org/r/20201118123039.11696-1-penghao@uniontech.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -425,6 +425,10 @@ static const struct usb_device_id usb_qu { USB_DEVICE(0x1532, 0x0116), .driver_info = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
+ /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ + { USB_DEVICE(0x17ef, 0xa012), .driver_info = + USB_QUIRK_DISCONNECT_SUSPEND }, + /* BUILDWIN Photo Frame */ { USB_DEVICE(0x1908, 0x1315), .driver_info = USB_QUIRK_HONOR_BNUMINTERFACES },
From: Zhang Qilong zhangqilong3@huawei.com
commit 87bed3d7d26c974948a3d6e7176f304b2d41272b upstream.
usb_get_gadget_udc_name will alloc memory for CHIP in "Enomem" branch. we should free it before error returns to prevent memleak.
Fixes: 175f712119c57 ("usb: gadget: provide interface for legacy gadgets to get UDC name") Reported-by: Hulk Robot hulkci@huawei.com Acked-by: Alan Stern stern@rowland.harvard.edu Signed-off-by: Zhang Qilong zhangqilong3@huawei.com Link: https://lore.kernel.org/r/20201117021629.1470544-3-zhangqilong3@huawei.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/gadget/legacy/inode.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -2039,6 +2039,9 @@ gadgetfs_fill_super (struct super_block return 0;
Enomem: + kfree(CHIP); + CHIP = NULL; + return -ENOMEM; }
From: Chen Baozi chenbaozi@phytium.com.cn
commit d001e41e1b15716e9b759df5ef00510699f85282 upstream.
Since fwspec->param_count of ACPI node is two, the index of IRQ type in fwspec->param[] should be 1 rather than 2.
Fixes: 3d090a36c8c8 ("irqchip/exiu: Implement ACPI support") Signed-off-by: Chen Baozi chenbaozi@phytium.com.cn Signed-off-by: Marc Zyngier maz@kernel.org Acked-by: Ard Biesheuvel ardb@kernel.org Link: https://lore.kernel.org/r/20201117032015.11805-1-cbz@baozis.org Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/irqchip/irq-sni-exiu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/irqchip/irq-sni-exiu.c +++ b/drivers/irqchip/irq-sni-exiu.c @@ -136,7 +136,7 @@ static int exiu_domain_translate(struct if (fwspec->param_count != 2) return -EINVAL; *hwirq = fwspec->param[0]; - *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; } return 0; }
From: Gabriele Paoloni gabriele.paoloni@intel.com
commit 25bc65d8ddfc17cc1d7a45bd48e9bdc0e729ced3 upstream.
Currently, if mce_end() fails, no_way_out - the variable denoting whether the machine can recover from this MCE - is determined by whether the worst severity that was found across the MCA banks associated with the current CPU, is of panic severity.
However, at this point no_way_out could have been already set by mca_start() after looking at all severities of all CPUs that entered the MCE handler. If mce_end() fails, check first if no_way_out is already set and, if so, stick to it, otherwise use the local worst value.
[ bp: Massage. ]
Signed-off-by: Gabriele Paoloni gabriele.paoloni@intel.com Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Tony Luck tony.luck@intel.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20201127161819.3106432-2-gabriele.paoloni@intel.co... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/cpu/mce/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -1363,8 +1363,10 @@ noinstr void do_machine_check(struct pt_ * When there's any problem use only local no_way_out state. */ if (!lmce) { - if (mce_end(order) < 0) - no_way_out = worst >= MCE_PANIC_SEVERITY; + if (mce_end(order) < 0) { + if (!no_way_out) + no_way_out = worst >= MCE_PANIC_SEVERITY; + } } else { /* * If there was a fatal machine check we should have
From: Anand K Mistry amistry@google.com
commit 33fc379df76b4991e5ae312f07bcd6820811971e upstream.
When spectre_v2_user={seccomp,prctl},ibpb is specified on the command line, IBPB is force-enabled and STIPB is conditionally-enabled (or not available).
However, since
21998a351512 ("x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.")
the spectre_v2_user_ibpb variable is set to SPECTRE_V2_USER_{PRCTL,SECCOMP} instead of SPECTRE_V2_USER_STRICT, which is the actual behaviour. Because the issuing of IBPB relies on the switch_mm_*_ibpb static branches, the mitigations behave as expected.
Since
1978b3a53a74 ("x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP")
this discrepency caused the misreporting of IB speculation via prctl().
On CPUs with STIBP always-on and spectre_v2_user=seccomp,ibpb, prctl(PR_GET_SPECULATION_CTRL) would return PR_SPEC_PRCTL | PR_SPEC_ENABLE instead of PR_SPEC_DISABLE since both IBPB and STIPB are always on. It also allowed prctl(PR_SET_SPECULATION_CTRL) to set the IB speculation mode, even though the flag is ignored.
Similarly, for CPUs without SMT, prctl(PR_GET_SPECULATION_CTRL) should also return PR_SPEC_DISABLE since IBPB is always on and STIBP is not available.
[ bp: Massage commit message. ]
Fixes: 21998a351512 ("x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.") Fixes: 1978b3a53a74 ("x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP") Signed-off-by: Anand K Mistry amistry@google.com Signed-off-by: Borislav Petkov bp@suse.de Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20201110123349.1.Id0cbf996d2151f4c143c90f9028651a5... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/cpu/bugs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -739,11 +739,13 @@ spectre_v2_user_select_mitigation(enum s if (boot_cpu_has(X86_FEATURE_IBPB)) { setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
+ spectre_v2_user_ibpb = mode; switch (cmd) { case SPECTRE_V2_USER_CMD_FORCE: case SPECTRE_V2_USER_CMD_PRCTL_IBPB: case SPECTRE_V2_USER_CMD_SECCOMP_IBPB: static_branch_enable(&switch_mm_always_ibpb); + spectre_v2_user_ibpb = SPECTRE_V2_USER_STRICT; break; case SPECTRE_V2_USER_CMD_PRCTL: case SPECTRE_V2_USER_CMD_AUTO: @@ -757,8 +759,6 @@ spectre_v2_user_select_mitigation(enum s pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n", static_key_enabled(&switch_mm_always_ibpb) ? "always-on" : "conditional"); - - spectre_v2_user_ibpb = mode; }
/*
From: Xiaochen Shen xiaochen.shen@intel.com
commit fd8d9db3559a29fd737bcdb7c4fcbe1940caae34 upstream.
Willem reported growing of kernfs_node_cache entries in slabtop when repeatedly creating and removing resctrl subdirectories as well as when repeatedly mounting and unmounting the resctrl filesystem.
On resource group (control as well as monitoring) creation via a mkdir an extra kernfs_node reference is obtained to ensure that the rdtgroup structure remains accessible for the rdtgroup_kn_unlock() calls where it is removed on deletion. The kernfs_node reference count is dropped by kernfs_put() in rdtgroup_kn_unlock().
With the above explaining the need for one kernfs_get()/kernfs_put() pair in resctrl there are more places where a kernfs_node reference is obtained without a corresponding release. The excessive amount of reference count on kernfs nodes will never be dropped to 0 and the kernfs nodes will never be freed in the call paths of rmdir and umount. It leads to reference count leak and kernfs_node_cache memory leak.
Remove the superfluous kernfs_get() calls and expand the existing comments surrounding the remaining kernfs_get()/kernfs_put() pair that remains in use.
Superfluous kernfs_get() calls are removed from two areas:
(1) In call paths of mount and mkdir, when kernfs nodes for "info", "mon_groups" and "mon_data" directories and sub-directories are created, the reference count of newly created kernfs node is set to 1. But after kernfs_create_dir() returns, superfluous kernfs_get() are called to take an additional reference.
(2) kernfs_get() calls in rmdir call paths.
Fixes: 17eafd076291 ("x86/intel_rdt: Split resource group removal in two") Fixes: 4af4a88e0c92 ("x86/intel_rdt/cqm: Add mount,umount support") Fixes: f3cbeacaa06e ("x86/intel_rdt/cqm: Add rmdir support") Fixes: d89b7379015f ("x86/intel_rdt/cqm: Add mon_data") Fixes: c7d9aac61311 ("x86/intel_rdt/cqm: Add mkdir support for RDT monitoring") Fixes: 5dc1d5c6bac2 ("x86/intel_rdt: Simplify info and base file lists") Fixes: 60cf5e101fd4 ("x86/intel_rdt: Add mkdir to resctrl file system") Fixes: 4e978d06dedb ("x86/intel_rdt: Add "info" files to resctrl file system") Reported-by: Willem de Bruijn willemb@google.com Signed-off-by: Xiaochen Shen xiaochen.shen@intel.com Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Reinette Chatre reinette.chatre@intel.com Tested-by: Willem de Bruijn willemb@google.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1604085053-31639-1-git-send-email-xiaochen.shen@in... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 35 +-------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-)
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -1708,7 +1708,6 @@ static int rdtgroup_mkdir_info_resdir(st if (IS_ERR(kn_subdir)) return PTR_ERR(kn_subdir);
- kernfs_get(kn_subdir); ret = rdtgroup_kn_set_ugid(kn_subdir); if (ret) return ret; @@ -1731,7 +1730,6 @@ static int rdtgroup_create_info_dir(stru kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL); if (IS_ERR(kn_info)) return PTR_ERR(kn_info); - kernfs_get(kn_info);
ret = rdtgroup_add_files(kn_info, RF_TOP_INFO); if (ret) @@ -1752,12 +1750,6 @@ static int rdtgroup_create_info_dir(stru goto out_destroy; }
- /* - * This extra ref will be put in kernfs_remove() and guarantees - * that @rdtgrp->kn is always accessible. - */ - kernfs_get(kn_info); - ret = rdtgroup_kn_set_ugid(kn_info); if (ret) goto out_destroy; @@ -1786,12 +1778,6 @@ mongroup_create_dir(struct kernfs_node * if (dest_kn) *dest_kn = kn;
- /* - * This extra ref will be put in kernfs_remove() and guarantees - * that @rdtgrp->kn is always accessible. - */ - kernfs_get(kn); - ret = rdtgroup_kn_set_ugid(kn); if (ret) goto out_destroy; @@ -2078,13 +2064,11 @@ static int rdt_get_tree(struct fs_contex &kn_mongrp); if (ret < 0) goto out_info; - kernfs_get(kn_mongrp);
ret = mkdir_mondata_all(rdtgroup_default.kn, &rdtgroup_default, &kn_mondata); if (ret < 0) goto out_mongrp; - kernfs_get(kn_mondata); rdtgroup_default.mon.mon_data_kn = kn_mondata; }
@@ -2450,11 +2434,6 @@ static int mkdir_mondata_subdir(struct k if (IS_ERR(kn)) return PTR_ERR(kn);
- /* - * This extra ref will be put in kernfs_remove() and guarantees - * that kn is always accessible. - */ - kernfs_get(kn); ret = rdtgroup_kn_set_ugid(kn); if (ret) goto out_destroy; @@ -2789,8 +2768,8 @@ static int mkdir_rdt_prepare(struct kern /* * kernfs_remove() will drop the reference count on "kn" which * will free it. But we still need it to stick around for the - * rdtgroup_kn_unlock(kn} call below. Take one extra reference - * here, which will be dropped inside rdtgroup_kn_unlock(). + * rdtgroup_kn_unlock(kn) call. Take one extra reference here, + * which will be dropped inside rdtgroup_kn_unlock(). */ kernfs_get(kn);
@@ -3000,11 +2979,6 @@ static int rdtgroup_rmdir_mon(struct ker WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list)); list_del(&rdtgrp->mon.crdtgrp_list);
- /* - * one extra hold on this, will drop when we kfree(rdtgrp) - * in rdtgroup_kn_unlock() - */ - kernfs_get(kn); kernfs_remove(rdtgrp->kn);
return 0; @@ -3016,11 +2990,6 @@ static int rdtgroup_ctrl_remove(struct k rdtgrp->flags = RDT_DELETED; list_del(&rdtgrp->rdtgroup_list);
- /* - * one extra hold on this, will drop when we kfree(rdtgrp) - * in rdtgroup_kn_unlock() - */ - kernfs_get(kn); kernfs_remove(rdtgrp->kn); return 0; }
From: Xiaochen Shen xiaochen.shen@intel.com
commit 758999246965eeb8b253d47e72f7bfe508804b16 upstream.
On resource group creation via a mkdir an extra kernfs_node reference is obtained by kernfs_get() to ensure that the rdtgroup structure remains accessible for the rdtgroup_kn_unlock() calls where it is removed on deletion. Currently the extra kernfs_node reference count is only dropped by kernfs_put() in rdtgroup_kn_unlock() while the rdtgroup structure is removed in a few other locations that lack the matching reference drop.
In call paths of rmdir and umount, when a control group is removed, kernfs_remove() is called to remove the whole kernfs nodes tree of the control group (including the kernfs nodes trees of all child monitoring groups), and then rdtgroup structure is freed by kfree(). The rdtgroup structures of all child monitoring groups under the control group are freed by kfree() in free_all_child_rdtgrp().
Before calling kfree() to free the rdtgroup structures, the kernfs node of the control group itself as well as the kernfs nodes of all child monitoring groups still take the extra references which will never be dropped to 0 and the kernfs nodes will never be freed. It leads to reference count leak and kernfs_node_cache memory leak.
For example, reference count leak is observed in these two cases: (1) mount -t resctrl resctrl /sys/fs/resctrl mkdir /sys/fs/resctrl/c1 mkdir /sys/fs/resctrl/c1/mon_groups/m1 umount /sys/fs/resctrl
(2) mkdir /sys/fs/resctrl/c1 mkdir /sys/fs/resctrl/c1/mon_groups/m1 rmdir /sys/fs/resctrl/c1
The same reference count leak issue also exists in the error exit paths of mkdir in mkdir_rdt_prepare() and rdtgroup_mkdir_ctrl_mon().
Fix this issue by following changes to make sure the extra kernfs_node reference on rdtgroup is dropped before freeing the rdtgroup structure. (1) Introduce rdtgroup removal helper rdtgroup_remove() to wrap up kernfs_put() and kfree().
(2) Call rdtgroup_remove() in rdtgroup removal path where the rdtgroup structure is about to be freed by kfree().
(3) Call rdtgroup_remove() or kernfs_put() as appropriate in the error exit paths of mkdir where an extra reference is taken by kernfs_get().
Fixes: f3cbeacaa06e ("x86/intel_rdt/cqm: Add rmdir support") Fixes: e02737d5b826 ("x86/intel_rdt: Add tasks files") Fixes: 60cf5e101fd4 ("x86/intel_rdt: Add mkdir to resctrl file system") Reported-by: Willem de Bruijn willemb@google.com Signed-off-by: Xiaochen Shen xiaochen.shen@intel.com Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Reinette Chatre reinette.chatre@intel.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1604085088-31707-1-git-send-email-xiaochen.shen@in... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -507,6 +507,24 @@ unlock: return ret ?: nbytes; }
+/** + * rdtgroup_remove - the helper to remove resource group safely + * @rdtgrp: resource group to remove + * + * On resource group creation via a mkdir, an extra kernfs_node reference is + * taken to ensure that the rdtgroup structure remains accessible for the + * rdtgroup_kn_unlock() calls where it is removed. + * + * Drop the extra reference here, then free the rdtgroup structure. + * + * Return: void + */ +static void rdtgroup_remove(struct rdtgroup *rdtgrp) +{ + kernfs_put(rdtgrp->kn); + kfree(rdtgrp); +} + struct task_move_callback { struct callback_head work; struct rdtgroup *rdtgrp; @@ -529,7 +547,7 @@ static void move_myself(struct callback_ (rdtgrp->flags & RDT_DELETED)) { current->closid = 0; current->rmid = 0; - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); }
if (unlikely(current->flags & PF_EXITING)) @@ -2004,8 +2022,7 @@ void rdtgroup_kn_unlock(struct kernfs_no rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) rdtgroup_pseudo_lock_remove(rdtgrp); kernfs_unbreak_active_protection(kn); - kernfs_put(rdtgrp->kn); - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } else { kernfs_unbreak_active_protection(kn); } @@ -2292,7 +2309,7 @@ static void free_all_child_rdtgrp(struct if (atomic_read(&sentry->waitcount) != 0) sentry->flags = RDT_DELETED; else - kfree(sentry); + rdtgroup_remove(sentry); } }
@@ -2334,7 +2351,7 @@ static void rmdir_all_sub(void) if (atomic_read(&rdtgrp->waitcount) != 0) rdtgrp->flags = RDT_DELETED; else - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } /* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */ update_closid_rmid(cpu_online_mask, &rdtgroup_default); @@ -2769,7 +2786,7 @@ static int mkdir_rdt_prepare(struct kern * kernfs_remove() will drop the reference count on "kn" which * will free it. But we still need it to stick around for the * rdtgroup_kn_unlock(kn) call. Take one extra reference here, - * which will be dropped inside rdtgroup_kn_unlock(). + * which will be dropped by kernfs_put() in rdtgroup_remove(). */ kernfs_get(kn);
@@ -2810,6 +2827,7 @@ static int mkdir_rdt_prepare(struct kern out_idfree: free_rmid(rdtgrp->mon.rmid); out_destroy: + kernfs_put(rdtgrp->kn); kernfs_remove(rdtgrp->kn); out_free_rgrp: kfree(rdtgrp); @@ -2822,7 +2840,7 @@ static void mkdir_rdt_prepare_clean(stru { kernfs_remove(rgrp->kn); free_rmid(rgrp->mon.rmid); - kfree(rgrp); + rdtgroup_remove(rgrp); }
/*
From: Likun Gao Likun.Gao@amd.com
commit 843c7eb2f7571aa092a8ea010c80e8d94c197f67 upstream.
Support to load RLC iram and dram ucode when RLC firmware struct use v2.2
Signed-off-by: Likun Gao Likun.Gao@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h | 4 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 10 +++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 11 ++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 39 +++++++++++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h | 4 +-- 6 files changed, 66 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1571,6 +1571,12 @@ static int psp_get_fw_type(struct amdgpu case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; break; + case AMDGPU_UCODE_ID_RLC_IRAM: + *type = GFX_FW_TYPE_RLC_IRAM; + break; + case AMDGPU_UCODE_ID_RLC_DRAM: + *type = GFX_FW_TYPE_RLC_DRAM_BOOT; + break; case AMDGPU_UCODE_ID_SMC: *type = GFX_FW_TYPE_SMU; break; --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h @@ -168,12 +168,16 @@ struct amdgpu_rlc { u32 save_restore_list_cntl_size_bytes; u32 save_restore_list_gpm_size_bytes; u32 save_restore_list_srm_size_bytes; + u32 rlc_iram_ucode_size_bytes; + u32 rlc_dram_ucode_size_bytes;
u32 *register_list_format; u32 *register_restore; u8 *save_restore_list_cntl; u8 *save_restore_list_gpm; u8 *save_restore_list_srm; + u8 *rlc_iram_ucode; + u8 *rlc_dram_ucode;
bool is_rlc_v2_1;
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -500,6 +500,8 @@ static int amdgpu_ucode_init_single_fw(s ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL && ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM && ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM && + ucode->ucode_id != AMDGPU_UCODE_ID_RLC_IRAM && + ucode->ucode_id != AMDGPU_UCODE_ID_RLC_DRAM && ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM && ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV && ucode->ucode_id != AMDGPU_UCODE_ID_DMCUB)) { @@ -556,6 +558,14 @@ static int amdgpu_ucode_init_single_fw(s ucode->ucode_size = adev->gfx.rlc.save_restore_list_srm_size_bytes; memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_srm, ucode->ucode_size); + } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_IRAM) { + ucode->ucode_size = adev->gfx.rlc.rlc_iram_ucode_size_bytes; + memcpy(ucode->kaddr, adev->gfx.rlc.rlc_iram_ucode, + ucode->ucode_size); + } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_DRAM) { + ucode->ucode_size = adev->gfx.rlc.rlc_dram_ucode_size_bytes; + memcpy(ucode->kaddr, adev->gfx.rlc.rlc_dram_ucode, + ucode->ucode_size); } else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MES) { ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes); memcpy(ucode->kaddr, (void *)((uint8_t *)adev->mes.fw->data + --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -221,6 +221,15 @@ struct rlc_firmware_header_v2_1 { uint32_t save_restore_list_srm_offset_bytes; };
+/* version_major=2, version_minor=1 */ +struct rlc_firmware_header_v2_2 { + struct rlc_firmware_header_v2_1 v2_1; + uint32_t rlc_iram_ucode_size_bytes; + uint32_t rlc_iram_ucode_offset_bytes; + uint32_t rlc_dram_ucode_size_bytes; + uint32_t rlc_dram_ucode_offset_bytes; +}; + /* version_major=1, version_minor=0 */ struct sdma_firmware_header_v1_0 { struct common_firmware_header header; @@ -338,6 +347,8 @@ enum AMDGPU_UCODE_ID { AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL, AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM, AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM, + AMDGPU_UCODE_ID_RLC_IRAM, + AMDGPU_UCODE_ID_RLC_DRAM, AMDGPU_UCODE_ID_RLC_G, AMDGPU_UCODE_ID_STORAGE, AMDGPU_UCODE_ID_SMC, --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3596,6 +3596,17 @@ static void gfx_v10_0_init_rlc_ext_micro le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length); }
+static void gfx_v10_0_init_rlc_iram_dram_microcode(struct amdgpu_device *adev) +{ + const struct rlc_firmware_header_v2_2 *rlc_hdr; + + rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data; + adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes); + adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes); + adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes); + adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes); +} + static bool gfx_v10_0_navi10_gfxoff_should_enable(struct amdgpu_device *adev) { bool ret = false; @@ -3711,8 +3722,6 @@ static int gfx_v10_0_init_microcode(stru rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; version_major = le16_to_cpu(rlc_hdr->header.header_version_major); version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor); - if (version_major == 2 && version_minor == 1) - adev->gfx.rlc.is_rlc_v2_1 = true;
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version); adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version); @@ -3754,8 +3763,12 @@ static int gfx_v10_0_init_microcode(stru for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++) adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
- if (adev->gfx.rlc.is_rlc_v2_1) - gfx_v10_0_init_rlc_ext_microcode(adev); + if (version_major == 2) { + if (version_minor >= 1) + gfx_v10_0_init_rlc_ext_microcode(adev); + if (version_minor == 2) + gfx_v10_0_init_rlc_iram_dram_microcode(adev); + } }
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", chip_name, wks); @@ -3816,8 +3829,7 @@ static int gfx_v10_0_init_microcode(stru adev->firmware.fw_size += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); } - if (adev->gfx.rlc.is_rlc_v2_1 && - adev->gfx.rlc.save_restore_list_cntl_size_bytes && + if (adev->gfx.rlc.save_restore_list_cntl_size_bytes && adev->gfx.rlc.save_restore_list_gpm_size_bytes && adev->gfx.rlc.save_restore_list_srm_size_bytes) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL]; @@ -3837,6 +3849,21 @@ static int gfx_v10_0_init_microcode(stru info->fw = adev->gfx.rlc_fw; adev->firmware.fw_size += ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE); + + if (adev->gfx.rlc.rlc_iram_ucode_size_bytes && + adev->gfx.rlc.rlc_dram_ucode_size_bytes) { + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM]; + info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM; + info->fw = adev->gfx.rlc_fw; + adev->firmware.fw_size += + ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE); + + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM]; + info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM; + info->fw = adev->gfx.rlc_fw; + adev->firmware.fw_size += + ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE); + } }
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1]; --- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h @@ -214,7 +214,7 @@ enum psp_gfx_fw_type { GFX_FW_TYPE_UVD1 = 23, /* UVD1 VG-20 */ GFX_FW_TYPE_TOC = 24, /* TOC NV-10 */ GFX_FW_TYPE_RLC_P = 25, /* RLC P NV */ - GFX_FW_TYPE_RLX6 = 26, /* RLX6 NV */ + GFX_FW_TYPE_RLC_IRAM = 26, /* RLC_IRAM NV */ GFX_FW_TYPE_GLOBAL_TAP_DELAYS = 27, /* GLOBAL TAP DELAYS NV */ GFX_FW_TYPE_SE0_TAP_DELAYS = 28, /* SE0 TAP DELAYS NV */ GFX_FW_TYPE_SE1_TAP_DELAYS = 29, /* SE1 TAP DELAYS NV */ @@ -236,7 +236,7 @@ enum psp_gfx_fw_type { GFX_FW_TYPE_ACCUM_CTRL_RAM = 45, /* ACCUM CTRL RAM NV */ GFX_FW_TYPE_RLCP_CAM = 46, /* RLCP CAM NV */ GFX_FW_TYPE_RLC_SPP_CAM_EXT = 47, /* RLC SPP CAM EXT NV */ - GFX_FW_TYPE_RLX6_DRAM_BOOT = 48, /* RLX6 DRAM BOOT NV */ + GFX_FW_TYPE_RLC_DRAM_BOOT = 48, /* RLC DRAM BOOT NV */ GFX_FW_TYPE_VCN0_RAM = 49, /* VCN_RAM NV + RN */ GFX_FW_TYPE_VCN1_RAM = 50, /* VCN_RAM NV + RN */ GFX_FW_TYPE_DMUB = 51, /* DMUB RN */
On Tue, 01 Dec 2020 09:51:55 +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.9: 15 builds: 15 pass, 0 fail 26 boots: 26 pass, 0 fail 64 tests: 64 pass, 0 fail
Linux version: 5.9.12-rc1-gfb49ad2107f4 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter jonathanh@nvidia.com
Jon
On Tue, 2020-12-01 at 09:51 +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.y and the diffstat can be found below.
thanks,
greg k-h
hello,
Compiled and booted 5.9.12-rc1+. No typical dmesg regression or regressions.
Tested-by: Jeffrin Jose T jeffrin@rajagiritech.edu.in
On Tue, Dec 01, 2020 at 09:51:55AM +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +0000. Anything received after that time might be too late.
Build results: total: 154 pass: 154 fail: 0 Qemu test results: total: 426 pass: 426 fail: 0
Tested-by: Guenter Roeck linux@roeck-us.net
Guenter
On Tue, 1 Dec 2020 at 14:38, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.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
NOTE: BUG: Invalid wait context on arm64 db410c device. This is an intermittent issue seen while booting and while running kselftests. https://lore.kernel.org/stable/CA+G9fYupbQK02Yor=U-80JEdkwacZ7bi3RKt3+D=e+qZ... https://lore.kernel.org/stable/CA+G9fYsk54r9Re4E9BWpqsoxLjpCvxRKFWRgdiKVcPoY...
Summary ------------------------------------------------------------------------
kernel: 5.9.12-rc1 git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git git branch: linux-5.9.y git commit: fb49ad2107f4b740257c84ec2991fc6afb447f53 git describe: v5.9.11-153-gfb49ad2107f4 Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.9.y/build/v5.9.11...
No regressions (compared to build v5.9.11)
No fixes (compared to build v5.9.11)
Ran 53637 total tests in the following environments and test suites.
Environments -------------- - arc - arm - arm64 - dragonboard-410c - hi6220-hikey - i386 - juno-r2 - juno-r2-compat - juno-r2-kasan - mips - nxp-ls2088 - parisc - powerpc - qemu-arm-clang - qemu-arm64-clang - qemu-arm64-kasan - qemu-i386-clang - qemu-x86_64-clang - qemu-x86_64-kasan - qemu_arm - qemu_arm64 - qemu_arm64-compat - qemu_i386 - qemu_x86_64 - qemu_x86_64-compat - riscv - s390 - sh - sparc - x15 - x86 - x86-kasan
Test Suites ----------- * build * linux-log-parser * igt-gpu-tools * install-android-platform-tools-r2600 * libhugetlbfs * ltp-cap_bounds-tests * ltp-commands-tests * ltp-cpuhotplug-tests * ltp-crypto-tests * ltp-cve-tests * ltp-dio-tests * ltp-fcntl-locktests-tests * ltp-filecaps-tests * ltp-fs_bind-tests * ltp-fs_perms_simple-tests * ltp-fsx-tests * ltp-io-tests * ltp-ipc-tests * ltp-math-tests * ltp-nptl-tests * ltp-pty-tests * ltp-securebits-tests * ltp-syscalls-tests * ltp-tracing-tests * perf * v4l2-compliance * ltp-containers-tests * ltp-fs-tests * ltp-hugetlb-tests * ltp-mm-tests * ltp-sched-tests * network-basic-tests * kselftest * ltp-controllers-tests * ltp-open-posix-tests * kvm-unit-tests * kunit * kselftest-vsyscall-mode-native * kselftest-vsyscall-mode-none
On 12/1/20 1:51 AM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.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 Wed, Dec 02, 2020 at 09:57:10AM -0700, Shuah Khan wrote:
On 12/1/20 1:51 AM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.9.12 release. There are 152 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 Thu, 03 Dec 2020 08:46:29 +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.9.12-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.9.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 for testing all of these and letting me know.
greg k-h
linux-stable-mirror@lists.linaro.org