This is the start of the stable review cycle for the 5.11.3 release. There are 775 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 03 Mar 2021 16:09:49 +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.11.3-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.11.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.11.3-rc1
Cong Wang cong.wang@bytedance.com net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa jeliantsurux@gmail.com net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov vladbu@nvidia.com net: sched: fix police ext initialization
Jason A. Donenfeld Jason@zx2c4.com wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld Jason@zx2c4.com wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld Jason@zx2c4.com net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky leon@kernel.org ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg sumit.garg@linaro.org kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä ville.syrjala@linux.intel.com drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis ntsironis@arrikto.com dm era: only resize metadata in preresume
Nikos Tsironis ntsironis@arrikto.com dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis ntsironis@arrikto.com dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis ntsironis@arrikto.com dm era: Fix bitset memory leaks
Nikos Tsironis ntsironis@arrikto.com dm era: Verify the data block size hasn't changed
Nikos Tsironis ntsironis@arrikto.com dm era: Update in-core bitset after committing the metadata
Nikos Tsironis ntsironis@arrikto.com dm era: Recover committed writeset after crash
Mikulas Patocka mpatocka@redhat.com dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka mpatocka@redhat.com dm writecache: return the exact table values that were set
Mikulas Patocka mpatocka@redhat.com dm writecache: fix performance degradation in ssd mode
Jeffle Xu jefflexu@linux.alibaba.com dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu jefflexu@linux.alibaba.com dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu jefflexu@linux.alibaba.com dm table: fix iterate_devices based device capability checks
Mikulas Patocka mpatocka@redhat.com dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher agruenba@redhat.com gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher agruenba@redhat.com gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson rpeterso@redhat.com gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson rpeterso@redhat.com gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima masahisa.kojima@linaro.org spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes rasmus.villemoes@prevas.dk spi: fsl: invert spisel_boot signal on MPC8309
Paul Cercueil paul@crapouillou.net perf stat: Use nftw() instead of ftw()
Al Viro viro@zeniv.linux.org.uk sparc32: fix a user-triggerable oops in clear_user()
Ronnie Sahlberg lsahlber@redhat.com cifs: fix handling of escaped ',' in the password mount argument
Paulo Alcantara pc@cjr.nz cifs: fix nodfs mount option
Paulo Alcantara pc@cjr.nz cifs: introduce helper for finding referral server to improve DFS target resolution
Paulo Alcantara pc@cjr.nz cifs: check all path components in resolved dfs target
Paulo Alcantara pc@cjr.nz cifs: fix DFS failover
Jaegeuk Kim jaegeuk@kernel.org f2fs: flush data when enabling checkpoint back
Chao Yu chao@kernel.org f2fs: enforce the immutable flag on open files
Chao Yu chao@kernel.org f2fs: fix out-of-repair __setattr_copy()
Huacai Chen chenhuacai@kernel.org irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg johannes.berg@intel.com um: defer killing userspace on page table update failures
Johannes Berg johannes.berg@intel.com um: mm: check more comprehensively for stub changes
Cornelia Huck cohuck@redhat.com virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens hca@linux.ibm.com s390/vtime: fix inline assembly clobber list
Jens Axboe axboe@kernel.dk proc: don't allow async path resolution of /proc/thread-self components
Chen Yu yu.c.chen@intel.com cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki rafael.j.wysocki@intel.com cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo shawn.guo@linaro.org cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar viresh.kumar@linaro.org thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson chris@chris-wilson.co.uk kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki shinichiro.kawasaki@wdc.com zonefs: Fix file size of zones in full condition
Namjae Jeon namjae.jeon@samsung.com exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song songmuchun@bytedance.com printk: fix deadlock when kernel panic
Tim Harvey tharvey@gateworks.com mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev bigunclemax@gmail.com gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin alexander.usyskin@intel.com mei: me: add adler lake point LP DID
Alexander Usyskin alexander.usyskin@intel.com mei: me: add adler lake point S DID
Tomas Winkler tomas.winkler@intel.com mei: me: emmitsburg workstation DID
Alexander Usyskin alexander.usyskin@intel.com mei: fix transfer over dma with extended header
Alexander Usyskin alexander.usyskin@intel.com mei: bus: block send with vtag on non-conformat FW
Subbaraman Narayanamurthy subbaram@codeaurora.org spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy christophe.leroy@csgroup.eu powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini hbathini@linux.ibm.com powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy christophe.leroy@csgroup.eu powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her shirley.her@bayhubtech.com mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li Frank.Li@nxp.com mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song maskray@google.com module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy subbaram@codeaurora.org nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini pbonzini@redhat.com KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka vbabka@suse.cz mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen dave.hansen@linux.intel.com mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz mike.kravetz@oracle.com hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz mike.kravetz@oracle.com hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song songmuchun@bytedance.com mm: memcontrol: fix get_active_memcg return value
Muchun Song songmuchun@bytedance.com mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown neilb@suse.de x86: fix seq_file iteration for pat/memtype.c
NeilBrown neilb@suse.de seq_file: document how per-entry resources are managed.
Pan Bian bianpan2016@163.com fs/affs: release old buffer head on error path
Pan Bian bianpan2016@163.com mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano Takahiro.Kuwano@infineon.com mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano Takahiro.Kuwano@infineon.com mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano Takahiro.Kuwano@infineon.com mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano Takahiro.Kuwano@infineon.com mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose suzuki.poulose@arm.com coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin alexander.usyskin@intel.com watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser tklauser@distanz.ch riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon will@kernel.org arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu shaoyi@amazon.com arm64 module: set plt* section addresses to 0x0
He Zhe zhe.he@windriver.com arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 qiuguorui1@huawei.com arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Viresh Kumar viresh.kumar@linaro.org mailbox: arm_mhuv2: Skip calling kfree() with invalid pointer
Isaac J. Manjarres isaacm@codeaurora.org iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose suzuki.poulose@arm.com arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu mhiramat@kernel.org kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker frederic@kernel.org entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker frederic@kernel.org entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker frederic@kernel.org rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker frederic@kernel.org rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker frederic@kernel.org rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater clg@kaod.org powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner tglx@linutronix.de x86/entry: Fix instrumentation annotation
Andy Lutomirski luto@kernel.org x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson seanjc@google.com x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson seanjc@google.com x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young sean@mess.org media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel lkundrak@v3.sk media: marvell-ccic: power up the device on mclk enable
Pavel Machek pavel@denx.de media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young sean@mess.org media: ir_toy: add another IR Droid device
Sakari Ailus sakari.ailus@linux.intel.com media: v4l: ioctl: Fix memory leak in video_usercopy
Tomi Valkeinen tomi.valkeinen@ideasonboard.com media: i2c: max9286: fix access to unallocated memory
Jiri Kosina jkosina@suse.cz floppy: reintroduce O_NDELAY fix
Martin Kaiser martin@kaiser.cx staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede ameynarkhede03@gmail.com staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy ilya.lipnitskiy@gmail.com staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen dinguyen@kernel.org arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich frank-w@public-files.de dts64: mt7622: fix slow sd card access
Jiri Bohac jbohac@suse.cz pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov snovitoll@gmail.com drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu ricky_wu@realtek.com misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin T.E.Baldwin99@members.leeds.ac.uk arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil paul@crapouillou.net seccomp: Add missing return in non-void function
Krzysztof Kozlowski krzk@kernel.org soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski m.szyprowski@samsung.com soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - initialize need_fallback
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel ardb@kernel.org crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel ardb@kernel.org crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel ardb@kernel.org crypto: arm64/sha - add missing module aliases
Chris Wilson chris@chris-wilson.co.uk drm/i915/gt: Correct surface base address for renderclear
Chris Wilson chris@chris-wilson.co.uk drm/i915/gt: Flush before changing register state
Filipe Manana fdmanana@suse.com btrfs: fix extent buffer leak on failure to copy root
Josef Bacik josef@toxicpanda.com btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik josef@toxicpanda.com btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik josef@toxicpanda.com btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik josef@toxicpanda.com btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik josef@toxicpanda.com btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik josef@toxicpanda.com btrfs: add asserts for deleting backref cache nodes
Josef Bacik josef@toxicpanda.com btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik josef@toxicpanda.com btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen jarkko@kernel.org KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen jarkko@kernel.org KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen jarkko@kernel.org KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley James.Bottomley@HansenPartnership.com tpm_tis: Clean up locality release
James Bottomley James.Bottomley@HansenPartnership.com tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang hsiangkao@redhat.com erofs: initialized fields can only be observed after bit is set
Amir Goldstein amir73il@gmail.com selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai tiwai@suse.de ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig alyssa.rosenzweig@collabora.com drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner heiko@sntech.de drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky andrey.grodzovsky@amd.com drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä ville.syrjala@linux.intel.com drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst kherbst@redhat.com drm/nouveau/kms: handle mDP connectors
xinhui pan xinhui.pan@amd.com drm/ttm: Fix a memory leak
Prike Liang Prike.Liang@amd.com drm/amdgpu: fix shutdown and poweroff process failed with s0ix
Alex Deucher alexander.deucher@amd.com drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Marek Olšák marek.olsak@amd.com drm/amdgpu: fix CGTS_TCC_DISABLE register offset on gfx10.3
Felix Kuehling Felix.Kuehling@amd.com drm/amdkfd: Fix recursive lock warnings
Anson Jacob Anson.Jacob@amd.com Revert "drm/amd/display: reuse current context instead of recreating one"
Rodrigo Siqueira Rodrigo.Siqueira@amd.com drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein eric.bernstein@amd.com drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller jan.kokemueller@gmail.com drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher alexander.deucher@amd.com Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow kai@kaishome.de bcache: Move journal work to new flush wq
Kai Krakow kai@kaishome.de bcache: Give btree_io_wq correct semantics again
Kai Krakow kai@kaishome.de Revert "bcache: Kill btree_io_wq"
Alexander Lobakin alobakin@pm.me MIPS: compressed: fix build with enabled UBSAN
Kevin Hao haokexin@gmail.com Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor nathan@kernel.org MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno aurelien@aurel32.net MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil paul@crapouillou.net MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai tiwai@suse.de ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou pshou@realtek.com ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai tiwai@suse.de ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen kai.vehmanen@linux.intel.com ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto o-takashi@sakamocchi.jp ALSA: fireface: fix to parse sync status register of latter protocol
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Don't avoid stopping the stream at disconnection
Takashi Iwai tiwai@suse.de ALSA: usb-audio: More strict state change in EP
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Handle invalid running state at releasing EP
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all()
Mathias Kresin dev@kresin.me phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter dan.carpenter@oracle.com USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter dan.carpenter@oracle.com USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold johan@kernel.org USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold johan@kernel.org USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen Thinh.Nguyen@synopsys.com usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen Thinh.Nguyen@synopsys.com usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil paul@crapouillou.net usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak lech.perczak@gmail.com USB: serial: option: update interface mapping for ZTE P685M
James Reynolds jr@memlen.com media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza mpdesouza@suse.com Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter dan.carpenter@oracle.com Input: joydev - prevent potential read overflow in ioctl
Olivier Crête olivier.crete@ocrete.ca Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin jeffrey.lin@rad-ic.com Input: raydium_ts_i2c - do not send zero length
Jason Gerecke killertofu@gmail.com HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns lains@riseup.net HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki rafael.j.wysocki@intel.com cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao miaoqinglang@huawei.com ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki rafael.j.wysocki@intel.com ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz marcin.slusarz@intel.com soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka mpatocka@redhat.com blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche bvanassche@acm.org scsi: sd: Fix Opal support
Finn Thain fthain@telegraphics.com.au ide/falconide: Fix module unload
Ming Lei ming.lei@redhat.com block: fix logging on capacity change
Christoph Hellwig hch@lst.de block: reopen the device in blkdev_reread_part
Johannes Thumshirn johannes.thumshirn@wdc.com scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap rdunlap@infradead.org scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan zhenzhong.duan@gmail.com csky: Fix a size determination in gpr_get()
Josef Bacik josef@toxicpanda.com proc: use kvzalloc for our kernel buffer
Miaohe Lin linmiaohe@huawei.com mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams dan.j.williams@intel.com mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel riel@surriel.com mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl martenli@axis.com i2c: exynos5: Preserve high speed master code
Maxime Ripard maxime@cerno.tech i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier maz@kernel.org arm64: Add missing ISB after invalidating TLB in __primary_switch
YueHaibing yuehaibing@huawei.com cifs: Fix inconsistent IS_ERR and PTR_ERR
Sean Christopherson seanjc@google.com KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson seanjc@google.com KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust trond.myklebust@hammerspace.com NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit hkallweit1@gmail.com r8169: fix jumbo packet handling on RTL8168e
Christian Melki christian.melki@t2data.com net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
Wonhyuk Yang vvghjk1234@gmail.com mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun chenwandun@huawei.com mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin linmiaohe@huawei.com mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin linmiaohe@huawei.com mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song songmuchun@bytedance.com mm: memcontrol: fix slub memory accounting
Muchun Song songmuchun@bytedance.com mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter dan.carpenter@oracle.com ocfs2: fix a use after free on error
Jason A. Donenfeld Jason@zx2c4.com wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld Jason@zx2c4.com wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo ap420073@gmail.com vxlan: move debug check after netdev unregister
Chen-Yu Tsai wens@csie.org PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan hslester96@gmail.com net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang yoong.siang.song@intel.com net: stmmac: fix CBS idleslope and sendslope calculation
Camelia Groza camelia.groza@nxp.com dpaa_eth: fix the access method for the dpaa_napi_portal
Henry Tieman henry.w.tieman@intel.com ice: update the number of available RSS queues
Dave Ertman david.m.ertman@intel.com ice: Fix state bits on LLDP mode switch
Brett Creeley brett.creeley@intel.com ice: Account for port VLAN in VF max packet size calculation
Dave Ertman david.m.ertman@intel.com ice: report correct max number of TCs
Uwe Kleine-König u.kleine-koenig@pengutronix.de pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter dan.carpenter@oracle.com octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Norbert Ciosek norbertx.ciosek@intel.com i40e: Fix endianness conversions
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Fix add TC filter for IPv6
Andreas Oetken andreas.oetken@siemens.com nios2: fixed broken sys_clone syscall
Jann Horn jannh@google.com Take mmap lock in cacheflush syscall
Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com i40e: Fix VFs not created
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Add zero-initialization of AQ command structures
Slawomir Laba slawomirx.laba@intel.com i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński kw@linux.com PCI: cadence: Fix DMA range mapping early return error
Russell King rmk+kernel@armlinux.org.uk PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan ruansy.fnst@cn.fujitsu.com device-dax: Fix default return code of range_parse()
Magnum Shan magnum.shan@unisoc.com mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven geert@linux-m68k.org ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao yung-chuan.liao@linux.intel.com regmap: sdw: use _no_pm functions in regmap_read/write
Loic Poulain loic.poulain@linaro.org mhi: Fix double dma free
Tzung-Bi Shih tzungbi@google.com remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek jonathan@marek.ca misc: fastrpc: fix incorrect usage of dma_map_sgtable
Stephen Boyd swboyd@chromium.org drm/msm/dp: Add a missing semi-colon
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao yung-chuan.liao@linux.intel.com soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com soundwire: bus: use sdw_update_no_pm when initializing a device
Rob Clark robdclark@chromium.org drm/msm: Fix legacy relocs path
Ahmad Fatoum a.fatoum@pengutronix.de nvmem: core: skip child nodes not matching binding
Dan Carpenter dan.carpenter@oracle.com nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose suzuki.poulose@arm.com coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven geert+renesas@glider.be phy: USB_LGM_PHY should depend on X86
Theodore Ts'o tytso@mit.edu ext4: fix potential htree index checksum corruption
Max Gurtovoy mgurtovoy@nvidia.com vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu zhukeqian1@huawei.com vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu zhukeqian1@huawei.com vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao judyhsiao@google.com drm/msm/dp: trigger unplug event in msm_dp_display_disable
Stephen Boyd swboyd@chromium.org drm/msm/kms: Make a lock_class_key for each crtc mutex
Eric Anholt eric@anholt.net drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt eric@anholt.net drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev iskren.chernev@gmail.com drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio konrad.dybcio@somainline.org drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org drm/msm: Add proper checks for GPU LLCC support
Iskren Chernev iskren.chernev@gmail.com drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin alexander.usyskin@intel.com mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit hkallweit1@gmail.com PCI: Align checking of syscall user config accessors
Jorgen Hansen jhansen@vmware.com VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian bianpan2016@163.com PCI: xilinx-cpm: Fix reference count leak on error path
Simon South simon@simonsouth.net pwm: rockchip: Eliminate potential race condition when probing
Simon South simon@simonsouth.net pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South simon@simonsouth.net pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla srinivas.kandagatla@linaro.org soundwire: debugfs: use controller id instead of link_id
Marek Vasut marek.vasut+renesas@gmail.com PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju a-govindraju@ti.com misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter dan.carpenter@oracle.com phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl chris.ruehl@gtsys.com.hk phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju a-govindraju@ti.com misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Geert Uytterhoeven geert+renesas@glider.be Input: st1232 - fix NORMAL vs. IDLE state handling
Randy Dunlap rdunlap@infradead.org ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Michael Tretter m.tretter@pengutronix.de Input: st1232 - add IDLE state as ready condition
Dmitry Torokhov dmitry.torokhov@gmail.com Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap rdunlap@infradead.org sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap rdunlap@infradead.org sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter dan.carpenter@oracle.com Input: elo - fix an error code in elo_connect()
Namhyung Kim namhyung@kernel.org perf test: Fix unaligned access in sample parsing test
Adrian Hunter adrian.hunter@intel.com perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter adrian.hunter@intel.com perf intel-pt: Fix premature IPC
Adrian Hunter adrian.hunter@intel.com perf intel-pt: Fix missing CYC processing in PSB
Dave Rigby d.rigby@me.com perf unwind: Set userdata for all __report_module() paths
Yang Jihong yangjihong1@huawei.com perf record: Fix continue profiling after draining the buffer
Dan Carpenter dan.carpenter@oracle.com Input: sur40 - fix an error code in sur40_probe()
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim gi-oh.kim@cloud.ionos.com RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim gi-oh.kim@cloud.ionos.com RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal haris.iqbal@cloud.ionos.com RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon avihaih@nvidia.com RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng chenglang@huawei.com RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton jlayton@kernel.org ceph: fix flush_snap logic after putting caps
Chuck Lever chuck.lever@oracle.com svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields bfields@redhat.com nfsd: register pernet ops last, unregister first
Nicholas Fraser nfraser@codeweavers.com perf symbols: Fix return value when loading PE DSO
John Ogness john.ogness@linutronix.de printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne nsaenzjulienne@suse.de spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook keescook@chromium.org spi: dw: Avoid stack content exposure
Matti Vaittinen matti.vaittinen@fi.rohmeurope.com regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov 0x7f454c46@gmail.com perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi zanussi@kernel.org selftests/ftrace: Update synthetic event syntax errors
Ryan Chen ryan_chen@aspeedtech.com clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek jonathan@marek.ca regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy aik@ozlabs.ru powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy aik@ozlabs.ru powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko andriy.shevchenko@linux.intel.com spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter m.tretter@pengutronix.de clk: divider: fix initialization with parent_hw
Lijun Ou oulijun@huawei.com RDMA/hns: Disable RQ inline by default
Xi Wang wangxi11@huawei.com RDMA/hns: Add mapped page count checking for MTR
Weihang Li liweihang@huawei.com RDMA/hns: Fix type of sq_signal_bits
Weihang Li liweihang@huawei.com RDMA/hns: Avoid filling sgid index when modifying QP to RTR
Kamal Heib kamalheib1@gmail.com RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Remove the reserved WQE of SRQ
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Fixed wrong judgments in the goto branch
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Force srq_limit to 0 when creating SRQ
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Bugfix for checking whether the srq is full when post wr
Lang Cheng chenglang@huawei.com RDMA/hns: Allocate one more recv SGE for HIP08
John Stultz john.stultz@linaro.org kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov dlatypov@google.com kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Taniya Das tdas@codeaurora.org clk: qcom: gcc-sc7180: Mark the MM XO clocks to be always ON
Srinivas Kandagatla srinivas.kandagatla@linaro.org clk: qcom: gfm-mux: fix clk mask
Sandipan Das sandipan@linux.ibm.com powerpc/sstep: Fix darn emulation
Sandipan Das sandipan@linux.ibm.com powerpc/sstep: Fix load-store and update emulation
Christophe Leroy christophe.leroy@csgroup.eu powerpc/8xx: Fix software emulation interrupt
Nathan Lynch nathanl@linux.ibm.com powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter dan.carpenter@oracle.com mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann arnd@arndb.de mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat alain.volmat@foss.st.com spi: stm32: properly handle 0 byte transfer
Bob Pearson rpearsonhpe@gmail.com RDMA/rxe: Correct skb on loopback path
Bob Pearson rpearsonhpe@gmail.com RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson rpearsonhpe@gmail.com RDMA/rxe: Fix coding error in rxe_recv.c
John Garry john.garry@huawei.com perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo acme@redhat.com perf tools: Fix DSO filtering when not finding a map for a sampled address
David E. Box david.e.box@linux.intel.com platform/x86: intel_pmt_crashlog: Add dependency on MFD_INTEL_PMT
David E. Box david.e.box@linux.intel.com platform/x86: intel_pmt_telemetry: Add dependency on MFD_INTEL_PMT
David E. Box david.e.box@linux.intel.com platform/x86: intel_pmt: Make INTEL_PMT_CLASS non-user-selectable
David Gow davidgow@google.com rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) rostedt@goodmis.org tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit parav@nvidia.com IB/cm: Avoid a loop when device has 255 ports
Parav Pandit parav@nvidia.com IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson dianders@chromium.org iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu yong.wu@mediatek.com iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König u.kleine-koenig@pengutronix.de amba: Fix resource leak for drivers without .remove
David Gow davidgow@google.com i3c/master/mipi-i3c-hci: Specify HAS_IOMEM dependency
Roja Rani Yarubandi rojay@codeaurora.org i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi rojay@codeaurora.org i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin vladimir.murzin@arm.com ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito takeshi.saito.xv@renesas.com mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET christophe.jaillet@wanadoo.fr mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET christophe.jaillet@wanadoo.fr mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET christophe.jaillet@wanadoo.fr mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Michal Suchanek msuchanek@suse.de powerpc: Fix build error in paravirt.h
Pingfan Liu kernelfans@gmail.com powerpc/time: Enable sched clock for irqtime
Ananth N Mavinakayanahalli ananth@linux.ibm.com powerpc/sstep: Fix incorrect return from analyze_instr()
Ananth N Mavinakayanahalli ananth@linux.ibm.com powerpc/sstep: Check instruction validity against ISA version before emulation
Christophe Leroy christophe.leroy@csgroup.eu powerpc/47x: Disable 256k page size
Christophe Leroy christophe.leroy@csgroup.eu powerpc/kvm: Force selection of CONFIG_PPC_FPU
Cédric Le Goater clg@kaod.org KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory shayd@nvidia.com IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory shayd@nvidia.com IB/umad: Return EIO in case of when device disassociated
Mark Bloch mbloch@nvidia.com RDMA/mlx5: Allow creating all QPs even when non RDMA profile is used
Maor Gottlieb maorg@nvidia.com tools/testing/scatterlist: Fix overflow of max segment size
Yong Wu yong.wu@mediatek.com iommu: Switch gather->end to the inclusive end
Dan Carpenter dan.carpenter@oracle.com scsi: lpfc: Fix ancient double free
Josh Poimboeuf jpoimboe@redhat.com objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf jpoimboe@redhat.com objtool: Fix retpoline detection in asm code
Josh Poimboeuf jpoimboe@redhat.com objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven geert@linux-m68k.org auxdisplay: Fix duplicate CHARLCD config symbol
Geert Uytterhoeven geert@linux-m68k.org auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko andriy.shevchenko@linux.intel.com watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian bianpan2016@163.com isofs: release buffer head before return
Hans de Goede hdegoede@redhat.com regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko digetx@gmail.com power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland samuel@sholland.org power: supply: axp20x_usb_power: Init work before enabling IRQs
Ahmed S. Darwish a.darwish@linutronix.de scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()
Ahmed S. Darwish a.darwish@linutronix.de scsi: isci: Pass gfp_t flags in isci_port_link_up()
Ahmed S. Darwish a.darwish@linutronix.de scsi: isci: Pass gfp_t flags in isci_port_link_down()
Ahmed S. Darwish a.darwish@linutronix.de scsi: mvsas: Pass gfp_t flags to libsas event notifiers
Ahmed S. Darwish a.darwish@linutronix.de scsi: libsas: Introduce a _gfp() variant of event notifiers
John Garry john.garry@huawei.com scsi: libsas: Remove notifier indirection
Krzysztof Kozlowski krzk@kernel.org regulator: s5m8767: Drop regulators OF node reference
Pan Bian bianpan2016@163.com spi: atmel: Put allocated master before return
Pan Bian bianpan2016@163.com regulator: s5m8767: Fix reference count leak
David Howells dhowells@redhat.com certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi krisman@collabora.com watch_queue: Drop references to /dev/watch_queue
Pan Bian bianpan2016@163.com regulator: axp20x: Fix reference cout leak
Evan Benn evanbenn@chromium.org platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn evanbenn@chromium.org platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara andre.przywara@arm.com clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit parav@nvidia.com IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas yishaih@nvidia.com RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther agx@sigxcpu.org spi: imx: Don't print error on -EPROBEDEFER
Frank van der Linden fllinden@amazon.com module: harden ELF info handling
Tom Rix trix@redhat.com clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann arnd@arndb.de clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap rdunlap@infradead.org power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang dave.jiang@intel.com dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski bgolaszewski@baylibre.com rtc: s5m: select REGMAP_I2C
Claudiu Beznea claudiu.beznea@microchip.com power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs: Fix KASAN: stack-out-of-bounds bug
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang guoqing.jiang@cloud.ionos.com RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang guoqing.jiang@cloud.ionos.com RDMA/rtrs: Call kobject_put in the failure path
Guoqing Jiang guoqing.jiang@cloud.ionos.com RDMA/rtrs-srv: Jump to dereg_mr label if allocate iu fails
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang jinpu.wang@cloud.ionos.com RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat drinkcat@chromium.org of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed karahmed@amazon.de fdt: Properly handle "no-map" field in the memory region
Colin Ian King colin.king@canonical.com power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Can Guo cang@codeaurora.org scsi: ufs: Fix a possible NULL pointer issue
Tony Lindgren tony@atomide.com power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren tony@atomide.com power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth ftoth@exalondelft.nl dmaengine: hsu: disable spurious interrupt
Vignesh Raghavendra vigneshr@ti.com dmaengine: ti: k3-udma: Set rflow count for BCDMA split channels
Nathan Chancellor nathan@kernel.org dmaengine: qcom: Always inline gpi_update_reg
Arnd Bergmann arnd@arndb.de rtc: rx6110: fix build against modular I2C
Christophe JAILLET christophe.jaillet@wanadoo.fr dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET christophe.jaillet@wanadoo.fr dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET christophe.jaillet@wanadoo.fr dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler bmt@zurich.ibm.com RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap rdunlap@infradead.org HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven geert+renesas@glider.be clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven geert+renesas@glider.be clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara andre.przywara@arm.com clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav p.yadav@ti.com spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com i2c: iproc: handle master read request
Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com i2c: iproc: handle only slave interrupts which are enabled
Jan Kara jack@suse.cz quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov dmitry.baryshkov@linaro.org arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov dmitry.baryshkov@linaro.org regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin po-hsu.lin@canonical.com selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl martin.blumenstingl@googlemail.com clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl martin.blumenstingl@googlemail.com clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl martin.blumenstingl@googlemail.com clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren tony@atomide.com power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong zhangqilong3@huawei.com HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman ebiederm@xmission.com capabilities: Don't allow writing ambiguous v3 file capabilities
Dmitry Torokhov dmitry.torokhov@gmail.com Input: imx_keypad - add dependency on HAS_IOMEM
Dmitry Torokhov dmitry.torokhov@gmail.com Input: da7280 - protect OF match table with CONFIG_OF
Dmitry Torokhov dmitry.torokhov@gmail.com Input: da7280 - fix missing error test
Nirmoy Das nirmoy.das@amd.com drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior bigeasy@linutronix.de smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven geert+renesas@glider.be irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo bobo.shaobowang@huawei.com ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann arnd@arndb.de ubifs: replay: Fix high stack usage, again
Dinghao Liu dinghao.liu@zju.edu.cn ubifs: Fix memleak in ubifs_init_authentication
Tom Rix trix@redhat.com jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King colin.king@canonical.com fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar spujar@nvidia.com ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian nramas@linux.microsoft.com ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian nramas@linux.microsoft.com ima: Free IMA measurement buffer on error
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni chaitanya.kulkarni@wdc.com nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni chaitanya.kulkarni@wdc.com nvmet: remove extra variable in identify ns
Keith Busch kbusch@kernel.org nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg sagi@grimberg.me nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg sagi@grimberg.me nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu haoxu@linux.alibaba.com io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli daniele.alessandrelli@intel.com crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock jan.weinstock@rwth-aachen.de hwrng: timeriomem - Fix cooldown period calculation
Imre Deak imre.deak@intel.com drm/dp_mst: Don't cache EDIDs for physical ports
Dan Carpenter dan.carpenter@oracle.com drm/virtio: fix an error code in virtio_gpu_init()
Qinglang Miao miaoqinglang@huawei.com drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard maxime@cerno.tech drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard maxime@cerno.tech drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley popcornmix@gmail.com drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley popcornmix@gmail.com drm/vc4: hdmi: Fix up CEC registers
Dom Cobley popcornmix@gmail.com drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley popcornmix@gmail.com drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger freude@linux.ibm.com s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson seanjc@google.com KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Jinyang He hejinyang@loongson.cn MIPS: relocatable: Provide kaslr_offset() to get the kernel offset
Qu Wenruo wqu@suse.com btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng chengzhihao1@huawei.com btrfs: clarify error returns values in __load_free_space_cache
Hui Wang hui.wang@canonical.com ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella sathyanarayana.nujella@intel.com ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie jun.nie@linaro.org ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra peterz@infradead.org locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) parri.andrea@gmail.com Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin sashal@kernel.org drm/mediatek: Fix aal size config
Yongqiang Niu yongqiang.niu@mediatek.com drm/mediatek: Check if fb is null
Sean Christopherson seanjc@google.com KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu srivasam@codeaurora.org ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu gudehe@huawei.com f2fs: fix a wrong condition in __submit_bio
Dan Carpenter dan.carpenter@oracle.com drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen chenyi77@huawei.com f2fs: fix to avoid inconsistent quota data
Christophe JAILLET christophe.jaillet@wanadoo.fr mtd: rawnand: intel: Fix an error handling path in 'ebu_dma_start()'
Manivannan Sadhasivam mani@kernel.org mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla srinivas.kandagatla@linaro.org ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel sre@kernel.org ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli f.fainelli@gmail.com ata: ahci_brcm: Add back regulators management
Will Deacon will@kernel.org mm: proc: Invalidate TLB after clearing soft-dirty page state
Biwen Li biwen.li@nxp.com irqchip/ls-extirq: add IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Frantisek Hrbata frantisek@hrbata.com drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy christophe.leroy@csgroup.eu crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy christophe.leroy@csgroup.eu crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter dan.carpenter@oracle.com mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy robin.murphy@arm.com perf/arm-cmn: Move IRQs when migrating context
Robin Murphy robin.murphy@arm.com perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan ranjani.sridharan@linux.intel.com ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu srivasam@codeaurora.org ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu chao@kernel.org f2fs: compress: fix potential deadlock
Daeho Jeong daehojeong@google.com f2fs: fix null page reference in redirty_blocks
Qais Yousef qais.yousef@arm.com sched/eas: Don't update misfit status if the task is pinned
Judy Hsiao judyhsiao@google.com ASoC: max98373: Fixes a typo in max98373_feedback_get
Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com media: i2c/Kconfig: Select FWNODE for OV772x sensor
Laurent Pinchart laurent.pinchart@ideasonboard.com media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix trix@redhat.com media: pxa_camera: declare variable when DEBUG is defined
yangerkun yangerkun@huawei.com mtd: phram: use div_u64_rem to stop overwrite len in phram_setup
Tom Rix trix@redhat.com media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET christophe.jaillet@wanadoo.fr media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng luomeng12@huawei.com media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter dan.carpenter@oracle.com media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida dwlsalmeida@gmail.com media: vidtv: psi: fix missing crc for PMT
Joe Perches joe@perches.com media: lmedm04: Fix misuse of comma
Daniel Scally djrscally@gmail.com media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner mario.kleiner.de@gmail.com drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner mario.kleiner.de@gmail.com drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain fthain@telegraphics.com.au macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian bianpan2016@163.com bsg: free the request before return error code
Guchun Chen guchun.chen@amd.com drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao miaoqinglang@huawei.com drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor nathan@kernel.org MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin alobakin@pm.me MIPS: properly stop .eh_frame generation
Tomi Valkeinen tomi.valkeinen@ideasonboard.com media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva rmfrfs@gmail.com media: imx7: csi: Fix pad link validation
Fabio Estevam festevam@gmail.com media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti giulio.benetti@micronovasrl.com drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan xuewen.yan@unisoc.com sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa jolsa@kernel.org crypto: bcm - Rename struct device_private to bcm_device_private
Marco Chiappero marco.chiappero@intel.com crypto: qat - replace CRYPTO_AES with CRYPTO_LIB_AES in Kconfig
Dinghao Liu dinghao.liu@zju.edu.cn evm: Fix memleak in init_desc
Stephan Gerhold stephan@gerhold.net ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter dan.carpenter@oracle.com ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong zhangchangzhong@huawei.com media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu dinghao.liu@zju.edu.cn media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu dinghao.liu@zju.edu.cn media: media/pci: Fix memleak in empress_init
Dinghao Liu dinghao.liu@zju.edu.cn media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET christophe.jaillet@wanadoo.fr media: vsp1: Fix an error handling path in the probe function
Dan Carpenter dan.carpenter@oracle.com media: camss: missing error code in msm_video_register()
Dan Carpenter dan.carpenter@oracle.com media: camss: Fix signedness bug in video_enum_fmt()
Zhang Changzhong zhangchangzhong@huawei.com media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia ezequiel@collabora.com media: imx: Fix csc/scaler unregister
Ezequiel Garcia ezequiel@collabora.com media: imx: Unregister csc/scaler only if registered
Jacopo Mondi jacopo@jmondi.org media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko andriy.shevchenko@linux.intel.com media: ipu3-cio2: Build only for x86
Simon Ser contact@emersion.fr drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu olvaffe@gmail.com drm/virtio: make sure context is created in gem open
Nathan Chancellor nathan@kernel.org MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor nathan@kernel.org MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li lichenyang@loongson.cn drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com drm: rcar-du: Fix leak of CMM platform device reference
Wang Xiaojun wangxiaojun11@huawei.com drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao miaoqinglang@huawei.com drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver elver@google.com kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Arnd Bergmann arnd@arndb.de ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA
Dan Carpenter dan.carpenter@oracle.com media: allegro: Fix use after free on error
Christophe JAILLET christophe.jaillet@wanadoo.fr hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel ardb@kernel.org crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - fix kmap usage
Corentin Labbe clabbe@baylibre.com crypto: sun4i-ss - linearize buffers content must be kept
Linus Walleij linus.walleij@linaro.org drm/panel: s6e63m0: Support max-brightness
Maxime Ripard maxime@cerno.tech drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther agx@sigxcpu.org drm/panel: mantix: Tweak init sequence
Linus Walleij linus.walleij@linaro.org drm/panel: s6e63m0: Fix init sequence again
Chuhong Yuan hslester96@gmail.com drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter dan.carpenter@oracle.com gma500: clean up error handling in init
Simon Ser contact@emersion.fr drm: document that user-space should force-probe connectors
Jialin Zhang zhangjialin11@huawei.com drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap rdunlap@infradead.org fbdev: aty: SPARC64 requires FB_ATY_CT
Bjarni Jonasson bjarni.jonasson@microchip.com net: phy: mscc: coma mode disabled for VSC8514
Bjarni Jonasson bjarni.jonasson@microchip.com net: phy: mscc: improved serdes calibration applied to VSC8514
Alex Elder elder@linaro.org net: ipa: initialize all resources
Dany Madden drt@linux.ibm.com ibmvnic: change IBMVNIC_MAX_IND_DESCS to 16
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: Fix CQ params of ICOSQ and async ICOSQ
Raed Salem raeds@nvidia.com net/mlx5e: Enable striding RQ for Connect-X IPsec capable devices
Parav Pandit parav@nvidia.com net/mlx5e: E-switch, Fix rate calculation for overflow
Joel Stanley joel@jms.id.au soc: aspeed: socinfo: Add new systems
Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Bluetooth: hci_qca: Fixed issue during suspend
Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Bluetooth: hci_qca: check for SSR triggered flag while suspend
Matthias Brugger mbrugger@suse.com arm64: dts: mt8183: Fix GCE include path
Peter Geis pgwipeout@gmail.com ARM: tegra: ouya: Fix eMMC on specific bootloaders
Pali Rohár pali@kernel.org net: sfp: add workaround for Realtek RTL8672 and RTL9601C chips
Enric Balletbo i Serra enric.balletbo@collabora.com arm64: dts: mt8183: Add missing power-domain for pwm0 node
Yongqiang Niu yongqiang.niu@mediatek.com arm64: dts: mt8183: refine gamma compatible name
Yongqiang Niu yongqiang.niu@mediatek.com arm64: dts: mt8183: rename rdma fifo size
Andrii Nakryiko andrii@kernel.org selftests/bpf: Don't exit on failed bpf_testmod unload
Sami Tolvanen samitolvanen@google.com x86/sgx: Fix the return type of sgx_init()
Linus Torvalds torvalds@linux-foundation.org tty: implement read_iter
Linus Torvalds torvalds@linux-foundation.org tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Dmitry Baryshkov dmitry.baryshkov@linaro.org arm64: dts: qcom: qrb5165-rb5: fix uSD pins drive strength
Dmitry Baryshkov dmitry.baryshkov@linaro.org arm64: dts: qcom: sm8250: correct sdhc_2 xo clk
Andrii Nakryiko andrii@kernel.org selftests/bpf: Sync RCU before unloading bpf_testmod
Andrii Nakryiko andrii@kernel.org bpf: Declare __bpf_free_used_maps() unconditionally
Erwan Le Ray erwan.leray@foss.st.com serial: stm32: fix DMA initialization error handling
Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Bluetooth: hci_qca: Wait for SSR completion during suspend
Rafał Miłecki rafal@milecki.pl arm64: dts: broadcom: bcm4908: use proper NAND binding
Abhishek Pandit-Subedi abhishekpandit@chromium.org Bluetooth: Remove hci_req_le_suspend_config
Vladimir Oltean vladimir.oltean@nxp.com net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier maxime.chevallier@bootlin.com net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K Shyam-sundar.S-k@amd.com net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K Shyam-sundar.S-k@amd.com net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K Shyam-sundar.S-k@amd.com net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K Shyam-sundar.S-k@amd.com net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson bjarni.jonasson@microchip.com net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean vladimir.oltean@nxp.com net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean vladimir.oltean@nxp.com net: dsa: felix: perform teardown in reverse order of setup
Sukadev Bhattiprolu sukadev@linux.ibm.com ibmvnic: serialize access to work queue on remove
Lijun Pan ljp@linux.ibm.com ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan ljp@linux.ibm.com ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich iii@linux.ibm.com bpf: Clear subreg_def for global function return values
Colin Ian King colin.king@canonical.com b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal ayush.sawal@chelsio.com cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock robert.hancock@calian.com net: axienet: Handle deferred probe on clock properly
Eric Dumazet edumazet@google.com tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts matthieu.baerts@tessares.net selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer brouer@redhat.com bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura junichi.nomura@nec.com bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song yhs@fb.com bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau kafai@fb.com libbpf: Ignore non function pointer member in struct_ops
Colin Ian King colin.king@canonical.com mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh moshe@nvidia.com net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo ozsh@nvidia.com net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory shayd@nvidia.com net/mlx5: Disable devlink reload for lag devices
Shay Drory shayd@nvidia.com net/mlx5: Disallow RoCE on lag device
Shay Drory shayd@nvidia.com net/mlx5: Disallow RoCE on multi port slave device
Shay Drory shayd@nvidia.com net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory shayd@nvidia.com net/mlx5: Fix health error state handling
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy maximmi@mellanox.com net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Raed Salem raeds@nvidia.com net/mlx5e: Enable XDP for Connect-X IPsec capable devices
Heiner Kallweit hkallweit1@gmail.com net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei ioana.ciornei@nxp.com dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross jgross@suse.com xen/netback: fix spurious event detection for common event case
Vasundhara Volam vasundhara-v.volam@broadcom.com bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer edwin.peer@broadcom.com bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu sukadev@linux.ibm.com ibmvnic: Set to CLOSED state even on error
Björn Töpel bjorn@kernel.org selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing ll@simonwunderlich.de ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho luciano.coelho@intel.com iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho luciano.coelho@intel.com iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver elver@google.com bpf_lru_list: Read double-checked variable once without lock
Sara Sharon sara.sharon@intel.com iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho luciano.coelho@intel.com iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho luciano.coelho@intel.com iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho luciano.coelho@intel.com iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho luciano.coelho@intel.com iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo jae.hyun.yoo@intel.com soc: aspeed: snoop: Add clock control logic
Dan Carpenter dan.carpenter@oracle.com ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry amistry@google.com ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry amistry@google.com ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann arnd@arndb.de ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller jerome.pouiller@silabs.com staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann arnd@arndb.de optee: simplify i2c access
Arnd Bergmann arnd@arndb.de ARM: s3c: fix fiq for clang IAS
Luca Coelho luciano.coelho@intel.com iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin email2tema@gmail.com arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht vincent.knecht@mailoo.org arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss luca@z3ntu.xyz soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong zhongjupeng@yulong.com Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko digetx@gmail.com opp: Correct debug message in _opp_add_static_v2()
Marek Behún kabel@kernel.org arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev rosenp@gmail.com ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev rosenp@gmail.com ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde mkl@pengutronix.de can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven geert+renesas@glider.be arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro misono.tomohiro@jp.fujitsu.com x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai wens@csie.org staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck linux@roeck-us.net usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck linux@roeck-us.net usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck linux@roeck-us.net usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren tony@atomide.com ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian bianpan2016@163.com memory: ti-aemif: Drop child node when jumping out loop
Pan Bian bianpan2016@163.com Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian bianpan2016@163.com Bluetooth: drop HCI device reference before return
Borislav Petkov bp@suse.de staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET christophe.jaillet@wanadoo.fr soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter dan.carpenter@oracle.com soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss robert.foss@linaro.org arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham jackp@codeaurora.org usb: gadget: u_audio: Free requests only after callback
Maximilian Luz luzmaximilian@gmail.com ACPICA: Fix exception code class checks
Chen-Yu Tsai wens@csie.org arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET christophe.jaillet@wanadoo.fr cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET christophe.jaillet@wanadoo.fr cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold stephan@gerhold.net arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara andre.przywara@arm.com arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara andre.przywara@arm.com arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara andre.przywara@arm.com arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara andre.przywara@arm.com arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara andre.przywara@arm.com arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi cristian.marussi@arm.com firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko andrii@kernel.org bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko andrii@kernel.org bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl martin.blumenstingl@googlemail.com net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold stephan@gerhold.net arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell phil@raspberrypi.com staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell phil@raspberrypi.com staging: vchiq: Fix bulk userdata handling
Dinghao Liu dinghao.liu@zju.edu.cn Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong zhangqilong3@huawei.com memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski krzk@kernel.org arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski krzk@kernel.org arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski krzk@kernel.org ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford aford173@gmail.com arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford aford173@gmail.com arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill chris@kode54.net Bluetooth: Fix initializing response id after clearing struct
Claire Chang tientzu@chromium.org Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET christophe.jaillet@wanadoo.fr Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai pillair@codeaurora.org ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson chris@chris-wilson.co.uk drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai tiwai@suse.de ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai tiwai@suse.de ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai tiwai@suse.de ALSA: pcm: Call sync_stop at disconnection
Eric Biggers ebiggers@google.com random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor nathan@kernel.org vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin alobakin@pm.me MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Rokudo Yan wu-yan@tcl.com zsmalloc: account the number of compacted pages correctly
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara jack@suse.cz bfq: Avoid false bfq queue merging
Hans de Goede hdegoede@redhat.com virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel ardb@kernel.org PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith ansuelsmth@gmail.com PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev ivan.zaentsev@wirenboard.ru w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg sumit.garg@linaro.org kdb: Make memory allocations more robust
Quinn Tran qutran@marvell.com scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish a.darwish@linutronix.de scsi: libsas: docs: Remove notify_ha_event()
Dave Jiang dave.jiang@intel.com driver core: auxiliary bus: Fix calling stage for auxiliary bus init
Greg Kroah-Hartman gregkh@linuxfoundation.org debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman gregkh@linuxfoundation.org debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella sgarzare@redhat.com vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers ndesaulniers@google.com vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +- Documentation/admin-guide/sysctl/vm.rst | 10 +- Documentation/filesystems/seq_file.rst | 6 + Documentation/scsi/libsas.rst | 10 +- Documentation/security/keys/core.rst | 4 +- Makefile | 4 +- arch/arm/boot/compressed/head.S | 4 +- arch/arm/boot/dts/armada-388-helios4.dts | 28 +- arch/arm/boot/dts/exynos3250-artik5.dtsi | 2 +- arch/arm/boot/dts/exynos3250-monk.dts | 2 +- arch/arm/boot/dts/exynos3250-rinato.dts | 2 +- arch/arm/boot/dts/exynos5250-spring.dts | 2 +- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 2 +- arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 2 +- arch/arm/boot/dts/omap443x.dtsi | 2 + arch/arm/boot/dts/tegra30-ouya.dts | 4 +- arch/arm/kernel/sys_oabi-compat.c | 15 + arch/arm/mach-at91/pm_suspend.S | 2 +- arch/arm/mach-ixp4xx/Kconfig | 1 - arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +- arch/arm64/Kconfig | 2 +- .../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +- .../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 + .../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +- arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2 +- .../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +- arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +- arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +- .../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +- arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 + arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10 +- .../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 + .../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +- arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 15 +- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +- arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +- .../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +- .../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + arch/arm64/crypto/aes-glue.c | 4 +- arch/arm64/crypto/sha1-ce-glue.c | 1 + arch/arm64/crypto/sha2-ce-glue.c | 2 + arch/arm64/crypto/sha3-ce-glue.c | 4 + arch/arm64/crypto/sha512-ce-glue.c | 2 + arch/arm64/include/asm/module.lds.h | 6 +- arch/arm64/kernel/cpufeature.c | 2 +- arch/arm64/kernel/head.S | 1 + arch/arm64/kernel/machine_kexec_file.c | 4 +- arch/arm64/kernel/probes/uprobes.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/arm64/kernel/suspend.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/mips/Makefile | 19 + arch/mips/boot/compressed/Makefile | 1 + arch/mips/cavium-octeon/setup.c | 9 +- arch/mips/include/asm/asm.h | 18 + arch/mips/include/asm/atomic.h | 2 +- arch/mips/include/asm/cmpxchg.h | 6 +- arch/mips/include/asm/page.h | 6 + arch/mips/kernel/cpu-probe.c | 15 +- arch/mips/kernel/relocate.c | 10 + arch/mips/kernel/setup.c | 3 + arch/mips/kernel/vmlinux.lds.S | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/loongson64/Platform | 22 - arch/mips/mm/c-r4k.c | 2 +- arch/mips/vdso/Makefile | 5 +- arch/nios2/kernel/entry.S | 3 + arch/nios2/kernel/sys_nios2.c | 11 +- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/kexec.h | 1 + arch/powerpc/include/asm/paravirt.h | 1 + arch/powerpc/include/asm/uaccess.h | 13 +- arch/powerpc/kernel/entry_32.S | 3 + arch/powerpc/kernel/head_32.h | 2 +- arch/powerpc/kernel/head_8xx.S | 2 +- arch/powerpc/kernel/head_book3s_32.S | 6 - arch/powerpc/kernel/irq.c | 27 +- arch/powerpc/kernel/prom_init.c | 12 +- arch/powerpc/kernel/time.c | 2 + arch/powerpc/kexec/elf_64.c | 2 +- arch/powerpc/kexec/file_load_64.c | 35 ++ arch/powerpc/kvm/Kconfig | 1 + arch/powerpc/kvm/powerpc.c | 8 +- arch/powerpc/lib/sstep.c | 101 +++- arch/powerpc/platforms/pseries/dlpar.c | 7 +- arch/riscv/kernel/vdso/Makefile | 3 +- arch/s390/kernel/vtime.c | 3 +- arch/sparc/Kconfig | 2 +- arch/sparc/kernel/led.c | 2 + arch/sparc/lib/memset.S | 1 + arch/um/include/shared/skas/mm_id.h | 1 + arch/um/kernel/tlb.c | 19 +- arch/um/os-Linux/skas/process.c | 4 + arch/x86/crypto/aesni-intel_glue.c | 28 +- arch/x86/entry/common.c | 2 +- arch/x86/include/asm/virtext.h | 17 +- arch/x86/kernel/cpu/sgx/main.c | 14 +- arch/x86/kernel/msr.c | 7 + arch/x86/kernel/reboot.c | 30 +- arch/x86/kvm/emulate.c | 4 +- arch/x86/kvm/mmu/tdp_mmu.c | 3 +- arch/x86/kvm/svm/nested.c | 22 +- arch/x86/kvm/svm/svm.c | 8 +- arch/x86/kvm/x86.c | 1 + arch/x86/mm/fault.c | 27 +- arch/x86/mm/pat/memtype.c | 4 +- block/bfq-iosched.c | 1 + block/blk-settings.c | 12 + block/bsg.c | 4 +- block/genhd.c | 2 +- block/ioctl.c | 21 +- certs/blacklist.c | 2 +- crypto/ecdh_helper.c | 3 + crypto/michael_mic.c | 31 +- drivers/acpi/acpi_configfs.c | 7 +- drivers/acpi/property.c | 44 +- drivers/amba/bus.c | 20 +- drivers/ata/ahci_brcm.c | 14 +- drivers/auxdisplay/Kconfig | 3 - drivers/auxdisplay/ht16k33.c | 3 +- drivers/base/auxiliary.c | 13 +- drivers/base/base.h | 5 + drivers/base/init.c | 1 + drivers/base/regmap/regmap-sdw.c | 4 +- drivers/base/swnode.c | 8 +- drivers/block/floppy.c | 30 +- drivers/block/zram/zram_drv.c | 2 +- drivers/bluetooth/btqcomsmd.c | 27 +- drivers/bluetooth/btusb.c | 20 +- drivers/bluetooth/hci_ldisc.c | 41 +- drivers/bluetooth/hci_qca.c | 33 +- drivers/bluetooth/hci_serdev.c | 4 +- drivers/bus/mhi/core/init.c | 3 + drivers/char/hw_random/ingenic-trng.c | 6 +- drivers/char/hw_random/timeriomem-rng.c | 2 +- drivers/char/random.c | 2 +- drivers/char/tpm/tpm.h | 4 - drivers/char/tpm/tpm_tis_core.c | 50 +- drivers/clk/clk-ast2600.c | 37 +- drivers/clk/clk-divider.c | 9 +- drivers/clk/meson/clk-pll.c | 10 +- drivers/clk/qcom/gcc-msm8998.c | 100 ++-- drivers/clk/qcom/gcc-sc7180.c | 47 +- drivers/clk/qcom/lpass-gfm-sm8250.c | 8 +- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +- drivers/clocksource/Kconfig | 1 + drivers/clocksource/mxs_timer.c | 5 +- drivers/cpufreq/acpi-cpufreq.c | 62 +- drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +- drivers/cpufreq/freq_table.c | 8 +- drivers/cpufreq/intel_pstate.c | 21 +- drivers/cpufreq/qcom-cpufreq-hw.c | 40 +- .../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +++--- drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 + drivers/crypto/bcm/cipher.c | 2 +- drivers/crypto/bcm/cipher.h | 4 +- drivers/crypto/bcm/util.c | 2 +- drivers/crypto/qat/Kconfig | 2 +- drivers/crypto/talitos.c | 50 +- drivers/crypto/talitos.h | 1 + drivers/dax/bus.c | 2 +- drivers/dma/fsldma.c | 6 + drivers/dma/hsu/pci.c | 21 +- drivers/dma/idxd/dma.c | 1 + drivers/dma/owl-dma.c | 1 + drivers/dma/qcom/gpi.c | 2 +- drivers/dma/ti/k3-udma.c | 1 + drivers/firmware/arm_scmi/driver.c | 4 +- drivers/gpio/gpio-pcf857x.c | 2 +- drivers/gpu/drm/Kconfig | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22 +- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 + .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +- .../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++ drivers/gpu/drm/amd/display/dc/core/dc.c | 27 +- drivers/gpu/drm/amd/display/dc/dc_stream.h | 3 +- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 + .../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +- .../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 - .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +- .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 + .../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +- drivers/gpu/drm/drm_dp_mst_topology.c | 3 +- drivers/gpu/drm/drm_fb_helper.c | 15 +- drivers/gpu/drm/drm_modes.c | 4 +- drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +- drivers/gpu/drm/gma500/psb_drv.c | 2 + drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +- drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +- drivers/gpu/drm/lima/lima_sched.c | 2 +- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 10 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 5 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 3 +- drivers/gpu/drm/msm/msm_gem_submit.c | 2 + drivers/gpu/drm/msm/msm_kms.h | 8 +- .../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 + drivers/gpu/drm/nouveau/nouveau_chan.c | 1 + drivers/gpu/drm/nouveau/nouveau_connector.c | 1 + drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +- drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 + drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 59 +- drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 30 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 + drivers/gpu/drm/scheduler/sched_main.c | 3 + drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +- drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tegra/dsi.c | 2 +- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/hub.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- drivers/gpu/drm/tegra/vic.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 9 +- drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +- drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 1 + drivers/hid/hid-core.c | 3 + drivers/hid/hid-logitech-dj.c | 1 + drivers/hid/wacom_wac.c | 7 +- drivers/hsi/controllers/omap_ssi_core.c | 2 +- drivers/hv/channel_mgmt.c | 3 +- drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +- .../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +- drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++++++-- drivers/i2c/busses/i2c-brcmstb.c | 2 +- drivers/i2c/busses/i2c-exynos5.c | 8 +- drivers/i2c/busses/i2c-qcom-geni.c | 93 ++- drivers/i3c/master/Kconfig | 1 + drivers/ide/falconide.c | 3 +- drivers/infiniband/core/cm.c | 8 +- drivers/infiniband/core/cma.c | 70 ++- drivers/infiniband/core/user_mad.c | 17 +- drivers/infiniband/hw/hns/hns_roce_device.h | 11 +- drivers/infiniband/hw/hns/hns_roce_hem.c | 9 +- drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 16 + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 70 ++- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3 +- drivers/infiniband/hw/hns/hns_roce_main.c | 19 +- drivers/infiniband/hw/hns/hns_roce_mr.c | 56 +- drivers/infiniband/hw/hns/hns_roce_qp.c | 37 +- drivers/infiniband/hw/hns/hns_roce_srq.c | 52 +- drivers/infiniband/hw/mlx5/devx.c | 4 +- drivers/infiniband/hw/mlx5/main.c | 14 +- drivers/infiniband/hw/mlx5/qp.c | 27 +- drivers/infiniband/sw/rxe/rxe_net.c | 5 + drivers/infiniband/sw/rxe/rxe_recv.c | 27 +- drivers/infiniband/sw/siw/siw.h | 2 +- drivers/infiniband/sw/siw/siw_main.c | 2 +- drivers/infiniband/sw/siw/siw_qp.c | 271 +++++---- drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +- drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +- drivers/infiniband/sw/siw/siw_verbs.c | 20 +- drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 + drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +- drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 + drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +- drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 120 ++-- drivers/infiniband/ulp/rtrs/rtrs.c | 28 +- drivers/input/joydev.c | 7 +- drivers/input/joystick/xpad.c | 1 + drivers/input/keyboard/Kconfig | 2 +- drivers/input/misc/da7280.c | 3 + drivers/input/serio/i8042-x86ia64io.h | 4 + drivers/input/serio/serport.c | 4 +- drivers/input/touchscreen/elo.c | 4 +- drivers/input/touchscreen/raydium_i2c_ts.c | 3 +- drivers/input/touchscreen/st1232.c | 9 +- drivers/input/touchscreen/sur40.c | 1 + drivers/input/touchscreen/zinitix.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 + drivers/iommu/iommu.c | 23 +- drivers/iommu/mtk_iommu.c | 2 +- drivers/irqchip/Kconfig | 3 +- drivers/irqchip/irq-loongson-pch-msi.c | 2 +- drivers/irqchip/irq-ls-extirq.c | 2 +- drivers/macintosh/adb-iop.c | 6 +- drivers/mailbox/arm_mhuv2.c | 4 +- drivers/mailbox/sprd-mailbox.c | 2 +- drivers/md/bcache/bcache.h | 3 + drivers/md/bcache/btree.c | 21 +- drivers/md/bcache/journal.c | 4 +- drivers/md/bcache/super.c | 20 + drivers/md/dm-core.h | 4 + drivers/md/dm-crypt.c | 1 + drivers/md/dm-era-target.c | 93 +-- drivers/md/dm-table.c | 168 +++--- drivers/md/dm-writecache.c | 74 ++- drivers/md/dm.c | 62 +- drivers/md/dm.h | 2 +- drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/max9286.c | 2 +- drivers/media/i2c/ov5670.c | 3 +- drivers/media/pci/cx25821/cx25821-core.c | 4 +- drivers/media/pci/intel/ipu3/Kconfig | 3 +- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +- drivers/media/pci/saa7134/saa7134-empress.c | 5 +- drivers/media/pci/smipcie/smipcie-ir.c | 46 +- drivers/media/platform/aspeed-video.c | 6 +- drivers/media/platform/marvell-ccic/mcam-core.c | 2 + .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +- .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +- drivers/media/platform/pxa_camera.c | 3 + drivers/media/platform/qcom/camss/camss-video.c | 3 +- drivers/media/platform/ti-vpe/cal.c | 4 +- drivers/media/platform/vsp1/vsp1_drv.c | 4 +- drivers/media/rc/ir_toy.c | 1 + drivers/media/rc/mceusb.c | 2 +- drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +- drivers/media/tuners/qm1d1c0042.c | 4 +- drivers/media/usb/dvb-usb-v2/lmedm04.c | 2 +- drivers/media/usb/em28xx/em28xx-core.c | 6 +- drivers/media/usb/tm6000/tm6000-dvb.c | 4 + drivers/media/usb/uvc/uvc_v4l2.c | 18 +- drivers/media/v4l2-core/v4l2-ioctl.c | 32 +- drivers/memory/mtk-smi.c | 4 +- drivers/memory/ti-aemif.c | 8 +- drivers/mfd/altera-sysmgr.c | 3 +- drivers/mfd/bd9571mwv.c | 6 +- drivers/mfd/gateworks-gsc.c | 2 +- drivers/mfd/wm831x-auxadc.c | 3 +- drivers/misc/cardreader/rts5227.c | 5 + drivers/misc/eeprom/eeprom_93xx46.c | 1 + drivers/misc/fastrpc.c | 7 +- drivers/misc/mei/bus.c | 7 + drivers/misc/mei/hbm.c | 2 +- drivers/misc/mei/hw-me-regs.h | 5 + drivers/misc/mei/interrupt.c | 33 +- drivers/misc/mei/pci-me.c | 5 + drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +- drivers/mmc/host/owl-mmc.c | 9 +- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +- drivers/mmc/host/sdhci-esdhc-imx.c | 3 +- drivers/mmc/host/sdhci-pci-o2micro.c | 20 + drivers/mmc/host/sdhci-sprd.c | 6 +- drivers/mmc/host/usdhi6rol0.c | 4 +- drivers/mtd/devices/phram.c | 6 +- drivers/mtd/nand/raw/intel-nand-controller.c | 6 +- drivers/mtd/parsers/afs.c | 4 +- drivers/mtd/parsers/parser_imagetag.c | 4 + drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +- drivers/mtd/spi-nor/core.c | 10 +- drivers/mtd/spi-nor/sfdp.c | 5 +- drivers/net/Kconfig | 2 +- drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +- drivers/net/dsa/ocelot/felix.c | 16 +- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 14 + drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 3 +- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 39 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 + drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +- .../chelsio/inline_crypto/chtls/chtls_cm.h | 3 - drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +- drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +- drivers/net/ethernet/ibm/ibmvnic.c | 43 +- drivers/net/ethernet/ibm/ibmvnic.h | 7 +- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 62 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11 +- drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 +- drivers/net/ethernet/intel/ice/ice.h | 2 - drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +- drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +- drivers/net/ethernet/marvell/mvneta.c | 9 +- .../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +- .../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 + drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++--- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +- .../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +- .../mellanox/mlx5/core/en_accel/en_accel.h | 2 +- .../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 +-- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 22 +- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +- .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2 + drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +- drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +- drivers/net/ethernet/realtek/r8169_main.c | 4 +- .../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +- drivers/net/gtp.c | 1 - drivers/net/ipa/ipa_main.c | 4 +- drivers/net/phy/micrel.c | 1 + drivers/net/phy/mscc/Makefile | 1 + drivers/net/phy/mscc/mscc.h | 28 + drivers/net/phy/mscc/mscc_main.c | 608 +++++++++++-------- drivers/net/phy/mscc/mscc_serdes.c | 650 +++++++++++++++++++++ drivers/net/phy/mscc/mscc_serdes.h | 31 + drivers/net/phy/phy_device.c | 53 +- drivers/net/phy/sfp.c | 100 ++-- drivers/net/ppp/ppp_async.c | 3 +- drivers/net/ppp/ppp_synctty.c | 3 +- drivers/net/vxlan.c | 11 +- drivers/net/wireguard/device.c | 19 +- drivers/net/wireguard/device.h | 15 +- drivers/net/wireguard/peer.c | 28 +- drivers/net/wireguard/peer.h | 4 +- drivers/net/wireguard/queueing.c | 86 ++- drivers/net/wireguard/queueing.h | 45 +- drivers/net/wireguard/receive.c | 16 +- drivers/net/wireguard/send.c | 31 +- drivers/net/wireless/ath/ath10k/mac.c | 2 + drivers/net/wireless/ath/ath10k/snoc.c | 5 +- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 + drivers/net/wireless/ath/ath11k/mac.c | 11 +- drivers/net/wireless/ath/ath9k/debug.c | 5 +- drivers/net/wireless/broadcom/b43/phy_n.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 +- .../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 - .../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +- drivers/net/xen-netback/interface.c | 8 +- drivers/nvme/host/multipath.c | 4 + drivers/nvme/target/admin-cmd.c | 33 +- drivers/nvme/target/tcp.c | 59 +- drivers/nvmem/core.c | 5 +- drivers/nvmem/qcom-spmi-sdam.c | 7 +- drivers/of/fdt.c | 12 +- drivers/opp/of.c | 4 +- drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +- drivers/pci/controller/dwc/pcie-qcom.c | 4 +- drivers/pci/controller/pcie-rcar-host.c | 2 +- drivers/pci/controller/pcie-rockchip.c | 12 +- drivers/pci/controller/pcie-xilinx-cpm.c | 1 + drivers/pci/pci-bridge-emul.c | 11 +- drivers/pci/setup-res.c | 6 + drivers/pci/syscall.c | 10 +- drivers/perf/arm-cmn.c | 17 +- drivers/phy/Kconfig | 1 + drivers/phy/cadence/phy-cadence-torrent.c | 1 + drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +- drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +- drivers/platform/chrome/cros_ec_proto.c | 12 +- drivers/platform/x86/Kconfig | 4 +- drivers/power/reset/at91-sama5d2_shdwc.c | 2 +- drivers/power/supply/Kconfig | 1 + drivers/power/supply/axp20x_usb_power.c | 2 +- drivers/power/supply/cpcap-battery.c | 12 +- drivers/power/supply/cpcap-charger.c | 4 +- drivers/power/supply/smb347-charger.c | 12 +- drivers/pwm/pwm-iqs620a.c | 8 +- drivers/pwm/pwm-rockchip.c | 18 +- drivers/regulator/axp20x-regulator.c | 7 +- drivers/regulator/core.c | 6 +- drivers/regulator/qcom-rpmh-regulator.c | 26 + drivers/regulator/rohm-regulator.c | 9 +- drivers/regulator/s5m8767.c | 15 +- drivers/remoteproc/mtk_common.h | 1 + drivers/remoteproc/mtk_scp.c | 20 +- drivers/rtc/Kconfig | 3 +- drivers/rtc/rtc-rx6110.c | 4 +- drivers/s390/crypto/zcrypt_api.c | 14 + drivers/s390/virtio/virtio_ccw.c | 4 +- drivers/scsi/aic94xx/aic94xx_scb.c | 20 +- drivers/scsi/bnx2fc/Kconfig | 1 + drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +- drivers/scsi/isci/port.c | 11 +- drivers/scsi/libsas/sas_event.c | 66 ++- drivers/scsi/libsas/sas_init.c | 27 +- drivers/scsi/libsas/sas_internal.h | 5 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +- drivers/scsi/mvsas/mv_sas.c | 25 +- drivers/scsi/pm8001/pm8001_hwi.c | 40 +- drivers/scsi/pm8001/pm8001_sas.c | 7 +- drivers/scsi/pm8001/pm80xx_hwi.c | 35 +- drivers/scsi/qla2xxx/qla_dbg.c | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 3 +- drivers/scsi/sd.c | 6 +- drivers/scsi/sd_zbc.c | 6 +- drivers/scsi/ufs/ufshcd.c | 17 +- drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +- drivers/soc/aspeed/aspeed-socinfo.c | 33 +- drivers/soc/qcom/ocmem.c | 8 +- drivers/soc/qcom/socinfo.c | 2 +- drivers/soc/samsung/exynos-asv.c | 18 +- drivers/soc/ti/pm33xx.c | 5 +- drivers/soundwire/bus.c | 47 +- drivers/soundwire/cadence_master.c | 8 +- drivers/soundwire/debugfs.c | 2 +- drivers/soundwire/intel_init.c | 3 +- drivers/spi/spi-atmel.c | 2 +- drivers/spi/spi-cadence-quadspi.c | 2 +- drivers/spi/spi-dw-bt1.c | 2 +- drivers/spi/spi-fsl-spi.c | 2 +- drivers/spi/spi-imx.c | 2 +- drivers/spi/spi-pxa2xx-pci.c | 27 +- drivers/spi/spi-stm32.c | 4 + drivers/spi/spi-synquacer.c | 4 + drivers/spi/spi.c | 2 +- drivers/spmi/spmi-pmic-arb.c | 5 +- drivers/staging/gdm724x/gdm_usb.c | 10 +- drivers/staging/media/allegro-dvt/allegro-core.c | 3 +- drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +- drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +- drivers/staging/media/imx/imx-media-csc-scaler.c | 4 - drivers/staging/media/imx/imx-media-dev.c | 7 +- drivers/staging/media/imx/imx7-media-csi.c | 27 +- drivers/staging/mt7621-dma/Makefile | 2 +- .../mt7621-dma/{mtk-hsdma.c => hsdma-mt7621.c} | 2 +- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 + drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 2 +- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +- drivers/staging/wfx/data_tx.c | 10 +- drivers/staging/wfx/data_tx.h | 1 + drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +- drivers/tee/optee/rpc.c | 31 +- drivers/thermal/cpufreq_cooling.c | 2 +- drivers/tty/n_gsm.c | 3 +- drivers/tty/n_hdlc.c | 60 +- drivers/tty/n_null.c | 3 +- drivers/tty/n_r3964.c | 10 +- drivers/tty/n_tracerouter.c | 4 +- drivers/tty/n_tracesink.c | 4 +- drivers/tty/n_tty.c | 82 ++- drivers/tty/serial/stm32-usart.c | 24 +- drivers/tty/tty_io.c | 82 ++- drivers/usb/dwc2/hcd.c | 15 +- drivers/usb/dwc2/hcd_intr.c | 14 +- drivers/usb/dwc3/gadget.c | 19 +- drivers/usb/gadget/function/u_audio.c | 17 +- drivers/usb/musb/musb_core.c | 31 +- drivers/usb/serial/ftdi_sio.c | 5 +- drivers/usb/serial/mos7720.c | 4 +- drivers/usb/serial/mos7840.c | 4 +- drivers/usb/serial/option.c | 3 +- drivers/usb/serial/pl2303.c | 8 +- drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +- drivers/vfio/pci/vfio_pci_zdev.c | 4 + drivers/vfio/vfio_iommu_type1.c | 48 +- drivers/video/fbdev/Kconfig | 2 +- drivers/virt/vboxguest/vboxguest_utils.c | 18 +- drivers/w1/slaves/w1_therm.c | 22 +- drivers/watchdog/intel-mid_wdt.c | 8 +- drivers/watchdog/mei_wdt.c | 1 + drivers/watchdog/qcom-wdt.c | 13 +- fs/affs/namei.c | 4 +- fs/btrfs/backref.c | 9 +- fs/btrfs/backref.h | 9 +- fs/btrfs/block-group.c | 29 +- fs/btrfs/ctree.c | 7 +- fs/btrfs/delayed-ref.c | 56 +- fs/btrfs/delayed-ref.h | 16 +- fs/btrfs/extent-tree.c | 128 +--- fs/btrfs/free-space-cache.c | 6 +- fs/btrfs/inode.c | 3 +- fs/btrfs/relocation.c | 4 +- fs/btrfs/space-info.h | 17 + fs/ceph/caps.c | 10 +- fs/cifs/cifs_swn.c | 2 +- fs/cifs/connect.c | 259 ++++---- fs/cifs/dfs_cache.c | 33 +- fs/cifs/fs_context.c | 43 +- fs/debugfs/inode.c | 5 +- fs/erofs/xattr.c | 10 +- fs/erofs/zmap.c | 10 +- fs/eventpoll.c | 4 +- fs/exfat/exfat_raw.h | 4 + fs/exfat/super.c | 31 +- fs/ext4/Kconfig | 3 +- fs/ext4/namei.c | 7 +- fs/f2fs/compress.c | 5 +- fs/f2fs/data.c | 12 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 30 +- fs/f2fs/inline.c | 4 + fs/f2fs/super.c | 3 + fs/gfs2/bmap.c | 6 +- fs/gfs2/lock_dlm.c | 8 +- fs/gfs2/recovery.c | 4 +- fs/gfs2/util.c | 16 +- fs/io_uring.c | 17 +- fs/isofs/dir.c | 1 + fs/isofs/namei.c | 1 + fs/jffs2/summary.c | 3 + fs/jfs/jfs_dmap.c | 2 +- fs/nfs/nfs4proc.c | 15 +- fs/nfsd/nfsctl.c | 14 +- fs/ocfs2/cluster/heartbeat.c | 8 +- fs/proc/proc_sysctl.c | 4 +- fs/proc/self.c | 2 +- fs/proc/task_mmu.c | 9 +- fs/proc/thread_self.c | 7 + fs/pstore/platform.c | 4 +- fs/quota/quota_v2.c | 11 +- fs/ubifs/auth.c | 2 +- fs/ubifs/replay.c | 4 +- fs/ubifs/super.c | 4 +- fs/zonefs/super.c | 3 + include/acpi/acexcep.h | 10 +- include/asm-generic/vmlinux.lds.h | 16 +- include/linux/bpf.h | 8 +- include/linux/device-mapper.h | 5 + include/linux/entry-kvm.h | 14 + include/linux/eventpoll.h | 2 +- include/linux/filter.h | 2 +- include/linux/icmpv6.h | 28 +- include/linux/iommu.h | 4 +- include/linux/ipv6.h | 1 - include/linux/kexec.h | 5 + include/linux/key.h | 1 + include/linux/kgdb.h | 2 + include/linux/khugepaged.h | 2 + include/linux/memremap.h | 6 + include/linux/mfd/rohm-generic.h | 14 +- include/linux/rcupdate.h | 2 + include/linux/rmap.h | 3 +- include/linux/soundwire/sdw.h | 2 + include/linux/tpm.h | 5 +- include/linux/tty_ldisc.h | 3 +- include/linux/zsmalloc.h | 2 +- include/net/act_api.h | 6 +- include/net/icmp.h | 6 +- include/net/tcp.h | 9 +- include/scsi/libsas.h | 11 +- include/uapi/drm/drm_fourcc.h | 4 +- include/uapi/drm/drm_mode.h | 13 +- init/Kconfig | 11 + init/main.c | 1 + kernel/Makefile | 2 +- kernel/bpf/bpf_iter.c | 2 +- kernel/bpf/bpf_lru_list.c | 7 +- kernel/bpf/devmap.c | 4 +- kernel/bpf/verifier.c | 3 +- kernel/debug/debug_core.c | 11 + kernel/debug/kdb/kdb_private.h | 2 +- kernel/entry/common.c | 7 + kernel/kcsan/core.c | 26 +- kernel/kexec_file.c | 5 + kernel/kprobes.c | 31 +- kernel/locking/lockdep.c | 3 +- kernel/module.c | 164 +++++- kernel/module_signature.c | 2 +- kernel/module_signing.c | 2 +- kernel/printk/printk.c | 28 +- kernel/printk/printk_safe.c | 16 +- kernel/rcu/tree.c | 53 +- kernel/rcu/tree.h | 2 +- kernel/rcu/tree_plugin.h | 31 +- kernel/sched/fair.c | 45 +- kernel/sched/idle.c | 1 + kernel/seccomp.c | 2 + kernel/smp.c | 4 + kernel/tracepoint.c | 80 ++- mm/compaction.c | 43 +- mm/hugetlb.c | 14 +- mm/khugepaged.c | 22 +- mm/memcontrol.c | 30 +- mm/memory-failure.c | 6 + mm/memory.c | 16 +- mm/memremap.c | 15 + mm/slab_common.c | 4 +- mm/slub.c | 8 +- mm/vmscan.c | 9 +- mm/zsmalloc.c | 17 +- net/bluetooth/a2mp.c | 3 +- net/bluetooth/hci_core.c | 6 +- net/bluetooth/hci_request.c | 25 +- net/core/filter.c | 13 +- net/ipv4/icmp.c | 5 +- net/ipv6/icmp.c | 18 +- net/ipv6/ip6_icmp.c | 12 +- net/mac80211/mesh_hwmp.c | 2 +- net/nfc/nci/uart.c | 3 +- net/qrtr/tun.c | 12 +- net/sched/act_api.c | 106 ++-- net/sched/cls_api.c | 12 +- net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +- samples/Kconfig | 2 +- samples/watch_queue/watch_test.c | 2 +- security/commoncap.c | 12 +- security/integrity/evm/evm_crypto.c | 7 +- security/integrity/ima/ima_kexec.c | 3 + security/integrity/ima/ima_mok.c | 5 +- security/keys/Kconfig | 8 +- security/keys/key.c | 2 + security/keys/trusted-keys/trusted_tpm1.c | 22 +- security/keys/trusted-keys/trusted_tpm2.c | 22 +- security/selinux/hooks.c | 4 + sound/core/init.c | 4 + sound/core/pcm.c | 4 + sound/core/pcm_local.h | 1 + sound/core/pcm_native.c | 27 +- sound/firewire/fireface/ff-protocol-latter.c | 118 +++- sound/pci/hda/hda_intel.c | 2 + sound/pci/hda/patch_hdmi.c | 1 - sound/pci/hda/patch_realtek.c | 40 ++ sound/soc/codecs/cpcap.c | 12 +- sound/soc/codecs/cs42l56.c | 3 +- sound/soc/codecs/max98373.c | 2 +- sound/soc/codecs/rt5682-i2c.c | 3 + sound/soc/codecs/wsa881x.c | 1 + sound/soc/fsl/Kconfig | 1 + sound/soc/generic/simple-card-utils.c | 13 +- sound/soc/intel/boards/sof_sdw.c | 9 +- sound/soc/qcom/lpass-apq8016.c | 2 +- sound/soc/qcom/lpass-cpu.c | 30 +- sound/soc/qcom/lpass-lpaif-reg.h | 3 - sound/soc/qcom/lpass-sc7180.c | 2 +- sound/soc/qcom/lpass.h | 1 - sound/soc/qcom/qdsp6/q6asm-dai.c | 21 + sound/soc/qcom/qdsp6/q6routing.c | 18 - sound/soc/sh/siu.h | 2 +- sound/soc/sh/siu_pcm.c | 2 +- sound/soc/sof/debug.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 4 + sound/soc/sof/sof-pci-dev.c | 7 + sound/usb/card.h | 2 +- sound/usb/endpoint.c | 87 +-- sound/usb/implicit.c | 2 + sound/usb/pcm.c | 7 +- tools/lib/bpf/libbpf.c | 22 +- tools/objtool/arch/x86/special.c | 2 +- tools/objtool/check.c | 15 +- tools/objtool/check.h | 11 + tools/perf/builtin-record.c | 2 +- .../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +- tools/perf/tests/sample-parsing.c | 2 +- tools/perf/util/cgroup.c | 8 +- tools/perf/util/event.c | 2 + tools/perf/util/evlist.c | 8 + tools/perf/util/evlist.h | 4 + .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 +- .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 + tools/perf/util/intel-pt.c | 29 +- tools/perf/util/symbol.c | 7 +- tools/perf/util/unwind-libdw.c | 11 +- tools/testing/kunit/kunit_tool_test.py | 14 +- tools/testing/scatterlist/main.c | 1 - .../selftests/bpf/prog_tests/btf_map_in_map.c | 33 -- tools/testing/selftests/bpf/test_progs.c | 13 +- tools/testing/selftests/bpf/test_progs.h | 1 + tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +- tools/testing/selftests/dmabuf-heaps/Makefile | 2 +- .../trigger-synthetic_event_syntax_errors.tc | 35 +- tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +- tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +- tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +- tools/testing/selftests/wireguard/netns.sh | 15 +- 780 files changed, 7977 insertions(+), 3978 deletions(-)
From: Nick Desaulniers ndesaulniers@google.com
commit 3c4fa46b30c551b1df2fb1574a684f68bc22067c upstream.
We expect toolchains to produce these new debug info sections as part of DWARF v5. Add explicit placements to prevent the linker warnings from --orphan-section=warn.
Compilers may produce such sections with explicit -gdwarf-5, or based on the implicit default version of DWARF when -g is used via DEBUG_INFO. This implicit default changes over time, and has changed to DWARF v5 with GCC 11.
.debug_sup was mentioned in review, but without compilers producing it today, let's wait to add it until it becomes necessary.
Cc: stable@vger.kernel.org Link: https://bugzilla.redhat.com/show_bug.cgi?id=1922707 Reported-by: Chris Murphy lists@colorremedies.com Suggested-by: Fangrui Song maskray@google.com Reviewed-by: Nathan Chancellor nathan@kernel.org Reviewed-by: Mark Wielaard mark@klomp.org Tested-by: Sedat Dilek sedat.dilek@gmail.com Signed-off-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/asm-generic/vmlinux.lds.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -828,8 +828,13 @@ /* DWARF 4 */ \ .debug_types 0 : { *(.debug_types) } \ /* DWARF 5 */ \ + .debug_addr 0 : { *(.debug_addr) } \ + .debug_line_str 0 : { *(.debug_line_str) } \ + .debug_loclists 0 : { *(.debug_loclists) } \ .debug_macro 0 : { *(.debug_macro) } \ - .debug_addr 0 : { *(.debug_addr) } + .debug_names 0 : { *(.debug_names) } \ + .debug_rnglists 0 : { *(.debug_rnglists) } \ + .debug_str_offsets 0 : { *(.debug_str_offsets) }
/* Stabs debugging sections. */ #define STABS_DEBUG \
From: Stefano Garzarella sgarzare@redhat.com
commit dcfde1635e764fd69cc756c7780d144e288608e9 upstream.
It's legal to have 'offset + len' equal to sizeof(struct virtio_net_config), since 'ndev->config' is a 'struct virtio_net_config', so we can safely copy its content under this condition.
Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices") Cc: stable@vger.kernel.org Signed-off-by: Stefano Garzarella sgarzare@redhat.com Link: https://lore.kernel.org/r/20210208161741.104939-1-sgarzare@redhat.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Acked-by: Jason Wang jasowang@redhat.com Acked-by: Eli Cohen elic@nvidia.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1820,7 +1820,7 @@ static void mlx5_vdpa_get_config(struct struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
- if (offset + len < sizeof(struct virtio_net_config)) + if (offset + len <= sizeof(struct virtio_net_config)) memcpy(buf, (u8 *)&ndev->config + offset, len); }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
commit bc6de804d36b3709d54fa22bd128cbac91c11526 upstream.
debugfs_lookup() doesn't like it if it is passed an illegal name pointer, or if the filesystem isn't even initialized yet. If either of these happen, it will crash the system, so fix it up by properly testing for valid input and that we are up and running before trying to find a file in the filesystem.
Cc: "Rafael J. Wysocki" rafael@kernel.org Cc: stable stable@vger.kernel.org Reported-by: Michael Walle michael@walle.cc Tested-by: Michael Walle michael@walle.cc Tested-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210218100818.3622317-1-gregkh@linuxfoundation.or... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/debugfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -297,7 +297,7 @@ struct dentry *debugfs_lookup(const char { struct dentry *dentry;
- if (IS_ERR(parent)) + if (!debugfs_initialized() || IS_ERR_OR_NULL(name) || IS_ERR(parent)) return NULL;
if (!parent)
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
commit 56348560d495d2501e87db559a61de717cd3ab02 upstream.
Some subsystems want to add debugfs files at early boot, way before debugfs is initialized. This seems to work somehow as the vfs layer will not allow it to happen, but let's be explicit and test to ensure we are properly up and running before allowing files to be created.
Cc: "Rafael J. Wysocki" rafael@kernel.org Cc: stable stable@vger.kernel.org Reported-by: Michael Walle michael@walle.cc Reported-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210218100818.3622317-2-gregkh@linuxfoundation.or... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/debugfs/inode.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -318,6 +318,9 @@ static struct dentry *start_creating(con if (!(debugfs_allow & DEBUGFS_ALLOW_API)) return ERR_PTR(-EPERM);
+ if (!debugfs_initialized()) + return ERR_PTR(-ENOENT); + pr_debug("creating file '%s'\n", name);
if (IS_ERR(parent))
From: Dave Jiang dave.jiang@intel.com
commit 471b12c43f376d5203dbff0e91316eea11f6f4df upstream.
When the auxiliary device code is built into the kernel, it can be executed before the auxiliary bus is registered. This causes bus->p to be not allocated and triggers a NULL pointer dereference when the auxiliary bus device gets added with bus_add_device(). Call the auxiliary_bus_init() under driver_init() so the bus is initialized before devices.
Below is the kernel splat for the bug: [ 1.948215] BUG: kernel NULL pointer dereference, address: 0000000000000060 [ 1.950670] #PF: supervisor read access in kernel mode [ 1.950670] #PF: error_code(0x0000) - not-present page [ 1.950670] PGD 0 [ 1.950670] Oops: 0000 1 SMP NOPTI [ 1.950670] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.10.0-intel-nextsvmtest+ #2205 [ 1.950670] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 [ 1.950670] RIP: 0010:bus_add_device+0x64/0x140 [ 1.950670] Code: 00 49 8b 75 20 48 89 df e8 59 a1 ff ff 41 89 c4 85 c0 75 7b 48 8b 53 50 48 85 d2 75 03 48 8b 13 49 8b 85 a0 00 00 00 48 89 de <48> 8 78 60 48 83 c7 18 e8 ef d9 a9 ff 41 89 c4 85 c0 75 45 48 8b [ 1.950670] RSP: 0000:ff46032ac001baf8 EFLAGS: 00010246 [ 1.950670] RAX: 0000000000000000 RBX: ff4597f7414aa680 RCX: 0000000000000000 [ 1.950670] RDX: ff4597f74142bbc0 RSI: ff4597f7414aa680 RDI: ff4597f7414aa680 [ 1.950670] RBP: ff46032ac001bb10 R08: 0000000000000044 R09: 0000000000000228 [ 1.950670] R10: ff4597f741141b30 R11: ff4597f740182a90 R12: 0000000000000000 [ 1.950670] R13: ffffffffa5e936c0 R14: 0000000000000000 R15: 0000000000000000 [ 1.950670] FS: 0000000000000000(0000) GS:ff4597f7bba00000(0000) knlGS:0000000000000000 [ 1.950670] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1.950670] CR2: 0000000000000060 CR3: 000000002140c001 CR4: 0000000000f71ef0 [ 1.950670] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1.950670] DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 [ 1.950670] PKRU: 55555554 [ 1.950670] Call Trace: [ 1.950670] device_add+0x3ee/0x850 [ 1.950670] __auxiliary_device_add+0x47/0x60 [ 1.950670] idxd_pci_probe+0xf77/0x1180 [ 1.950670] local_pci_probe+0x4a/0x90 [ 1.950670] pci_device_probe+0xff/0x1b0 [ 1.950670] really_probe+0x1cf/0x440 [ 1.950670] ? rdinit_setup+0x31/0x31 [ 1.950670] driver_probe_device+0xe8/0x150 [ 1.950670] device_driver_attach+0x58/0x60 [ 1.950670] __driver_attach+0x8f/0x150 [ 1.950670] ? device_driver_attach+0x60/0x60 [ 1.950670] ? device_driver_attach+0x60/0x60 [ 1.950670] bus_for_each_dev+0x79/0xc0 [ 1.950670] ? kmem_cache_alloc_trace+0x323/0x430 [ 1.950670] driver_attach+0x1e/0x20 [ 1.950670] bus_add_driver+0x154/0x1f0 [ 1.950670] driver_register+0x70/0xc0 [ 1.950670] __pci_register_driver+0x54/0x60 [ 1.950670] idxd_init_module+0xe2/0xfc [ 1.950670] ? idma64_platform_driver_init+0x19/0x19 [ 1.950670] do_one_initcall+0x4a/0x1e0 [ 1.950670] kernel_init_freeable+0x1fc/0x25c [ 1.950670] ? rest_init+0xba/0xba [ 1.950670] kernel_init+0xe/0x116 [ 1.950670] ret_from_fork+0x1f/0x30 [ 1.950670] Modules linked in: [ 1.950670] CR2: 0000000000000060 [ 1.950670] --[ end trace cd7d1b226d3ca901 ]--
Fixes: 7de3697e9cbd ("Add auxiliary bus support") Reported-by: Jacob Pan jacob.jun.pan@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Acked-by: Dave Ertman david.m.ertman@intel.com Signed-off-by: Dave Jiang dave.jiang@intel.com Link: https://lore.kernel.org/r/20210210201611.1611074-1-dave.jiang@intel.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/base/auxiliary.c | 13 +++---------- drivers/base/base.h | 5 +++++ drivers/base/init.c | 1 + 3 files changed, 9 insertions(+), 10 deletions(-)
--- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -15,6 +15,7 @@ #include <linux/pm_runtime.h> #include <linux/string.h> #include <linux/auxiliary_bus.h> +#include "base.h"
static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id, const struct auxiliary_device *auxdev) @@ -260,19 +261,11 @@ void auxiliary_driver_unregister(struct } EXPORT_SYMBOL_GPL(auxiliary_driver_unregister);
-static int __init auxiliary_bus_init(void) +void __init auxiliary_bus_init(void) { - return bus_register(&auxiliary_bus_type); + WARN_ON(bus_register(&auxiliary_bus_type)); }
-static void __exit auxiliary_bus_exit(void) -{ - bus_unregister(&auxiliary_bus_type); -} - -module_init(auxiliary_bus_init); -module_exit(auxiliary_bus_exit); - MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Auxiliary Bus"); MODULE_AUTHOR("David Ertman david.m.ertman@intel.com"); --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -119,6 +119,11 @@ static inline int hypervisor_init(void) extern int platform_bus_init(void); extern void cpu_dev_init(void); extern void container_dev_init(void); +#ifdef CONFIG_AUXILIARY_BUS +extern void auxiliary_bus_init(void); +#else +static inline void auxiliary_bus_init(void) { } +#endif
struct kobject *virtual_device_parent(struct device *dev);
--- a/drivers/base/init.c +++ b/drivers/base/init.c @@ -32,6 +32,7 @@ void __init driver_init(void) */ of_core_init(); platform_bus_init(); + auxiliary_bus_init(); cpu_dev_init(); memory_dev_init(); container_dev_init();
From: Ahmed S. Darwish a.darwish@linutronix.de
commit 3f901c81dfad6930de5d4e6b582c4fde880cdada upstream.
The ->notify_ha_event() hook has long been removed from the libsas event interface.
Remove it from documentation.
Link: https://lore.kernel.org/r/20210118100955.1761652-2-a.darwish@linutronix.de Fixes: 042ebd293b86 ("scsi: libsas: kill useless ha_event and do some cleanup") Cc: stable@vger.kernel.org Reviewed-by: John Garry john.garry@huawei.com Reviewed-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/scsi/libsas.rst | 1 - 1 file changed, 1 deletion(-)
--- a/Documentation/scsi/libsas.rst +++ b/Documentation/scsi/libsas.rst @@ -189,7 +189,6 @@ num_phys The event interface::
/* LLDD calls these to notify the class of an event. */ - void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); void (*notify_port_event)(struct sas_phy *, enum port_event); void (*notify_phy_event)(struct sas_phy *, enum phy_event);
From: Quinn Tran qutran@marvell.com
commit 044c218b04503858ca4e17f61899c8baa0ae9ba1 upstream.
Mailbox Ch/dump ram extend expects mb register 10 to be set. If not set/clear, firmware can pick up garbage from previous invocation of this mailbox. Example: mctp dump can set mb10. On subsequent flash read which use mailbox cmd Ch, mb10 can retain previous value.
Link: https://lore.kernel.org/r/20210111093134.1206-6-njavali@marvell.com Cc: stable@vger.kernel.org Reviewed-by: Himanshu Madhani himanshu.madhani@oracle.com Signed-off-by: Quinn Tran qutran@marvell.com Signed-off-by: Nilesh Javali njavali@marvell.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/qla2xxx/qla_dbg.c | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -202,6 +202,7 @@ qla24xx_dump_ram(struct qla_hw_data *ha, wrt_reg_word(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED); wrt_reg_word(®->mailbox1, LSW(addr)); wrt_reg_word(®->mailbox8, MSW(addr)); + wrt_reg_word(®->mailbox10, 0);
wrt_reg_word(®->mailbox2, MSW(LSD(dump_dma))); wrt_reg_word(®->mailbox3, LSW(LSD(dump_dma))); --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4276,7 +4276,8 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, d if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) { mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; mcp->mb[8] = MSW(addr); - mcp->out_mb = MBX_8|MBX_0; + mcp->mb[10] = 0; + mcp->out_mb = MBX_10|MBX_8|MBX_0; } else { mcp->mb[0] = MBC_DUMP_RISC_RAM; mcp->out_mb = MBX_0;
From: Sumit Garg sumit.garg@linaro.org
commit 93f7a6d818deef69d0ba652d46bae6fbabbf365c upstream.
Currently kdb uses in_interrupt() to determine whether its library code has been called from the kgdb trap handler or from a saner calling context such as driver init. This approach is broken because in_interrupt() alone isn't able to determine kgdb trap handler entry from normal task context. This can happen during normal use of basic features such as breakpoints and can also be trivially reproduced using: echo g > /proc/sysrq-trigger
We can improve this by adding check for in_dbg_master() instead which explicitly determines if we are running in debugger context.
Cc: stable@vger.kernel.org Signed-off-by: Sumit Garg sumit.garg@linaro.org Link: https://lore.kernel.org/r/1611313556-4004-1-git-send-email-sumit.garg@linaro... Signed-off-by: Daniel Thompson daniel.thompson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/debug/kdb/kdb_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -230,7 +230,7 @@ extern struct task_struct *kdb_curr_task
#define kdb_task_has_cpu(p) (task_curr(p))
-#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +#define GFP_KDB (in_dbg_master() ? GFP_ATOMIC : GFP_KERNEL)
extern void *debug_kmalloc(size_t size, gfp_t flags); extern void debug_kfree(void *);
From: Ivan Zaentsev ivan.zaentsev@wirenboard.ru
commit 2f6055c26f1913763eabc66c7c27d0693561e966 upstream.
DS18B20 device driver returns an incorrect value for negative temperatures due to a missing sign-extension in w1_DS18B20_convert_temp().
Fix by using s16 temperature value when converting to int.
Fixes: 9ace0b4dab1c (w1: w1_therm: Add support for GXCAS GX20MH01 device.) Cc: stable stable@vger.kernel.org Reported-by: Paweł Marciniak sunwire@gmail.com Signed-off-by: Ivan Zaentsev ivan.zaentsev@wirenboard.ru Link: https://lore.kernel.org/r/20210121093021.224764-1-ivan.zaentsev@wirenboard.r... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/w1/slaves/w1_therm.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
--- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -667,28 +667,24 @@ static inline int w1_DS18B20_get_resolut */ static inline int w1_DS18B20_convert_temp(u8 rom[9]) { - int t; - u32 bv; + u16 bv; + s16 t; + + /* Signed 16-bit value to unsigned, cpu order */ + bv = le16_to_cpup((__le16 *)rom);
/* Config register bit R2 = 1 - GX20MH01 in 13 or 14 bit resolution mode */ if (rom[4] & 0x80) { - /* Signed 16-bit value to unsigned, cpu order */ - bv = le16_to_cpup((__le16 *)rom); - /* Insert two temperature bits from config register */ /* Avoid arithmetic shift of signed value */ bv = (bv << 2) | (rom[4] & 3); - - t = (int) sign_extend32(bv, 17); /* Degrees, lowest bit is 2^-6 */ - return (t*1000)/64; /* Millidegrees */ + t = (s16) bv; /* Degrees, lowest bit is 2^-6 */ + return (int)t * 1000 / 64; /* Sign-extend to int; millidegrees */ } - - t = (int)le16_to_cpup((__le16 *)rom); - return t*1000/16; + t = (s16)bv; /* Degrees, lowest bit is 2^-4 */ + return (int)t * 1000 / 16; /* Sign-extend to int; millidegrees */ }
- - /** * w1_DS18S20_convert_temp() - temperature computation for DS18S20 * @rom: data read from device RAM (8 data bytes + 1 CRC byte)
From: Ansuel Smith ansuelsmth@gmail.com
commit 2cfef1971aea6119ee27429181d6cb3383031ac2 upstream.
The use of PHY_REFCLK_USE_PAD introduced a regression for apq8064 devices. It was tested that while apq doesn't require the padding, ipq SoC must use it or the kernel hangs on boot.
Link: https://lore.kernel.org/r/20201019165555.8269-1-ansuelsmth@gmail.com Fixes: de3c4bf64897 ("PCI: qcom: Add support for tx term offset for rev 2.1.0") Reported-by: Ilia Mirkin imirkin@alum.mit.edu Signed-off-by: Ilia Mirkin imirkin@alum.mit.edu Signed-off-by: Ansuel Smith ansuelsmth@gmail.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Acked-by: Stanimir Varbanov svarbanov@mm-sol.com Cc: stable@vger.kernel.org # v4.19+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/controller/dwc/pcie-qcom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -398,7 +398,9 @@ static int qcom_pcie_init_2_1_0(struct q
/* enable external reference clock */ val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); - val &= ~PHY_REFCLK_USE_PAD; + /* USE_PAD is required only for ipq806x */ + if (!of_device_is_compatible(node, "qcom,pcie-apq8064")) + val &= ~PHY_REFCLK_USE_PAD; val |= PHY_REFCLK_SSP_EN; writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
From: Ard Biesheuvel ardb@kernel.org
commit 729e3a669d1b62e9876a671ac03ccba399a23b68 upstream.
The _DSM #5 method in the ACPI host bridge object tells us whether the OS must preserve the resource assignments done by firmware. If this is the case, we should not permit drivers to resize BARs on the fly. Make pci_resize_resource() take this into account.
Link: https://lore.kernel.org/r/20210109095353.13417-1-ardb@kernel.org Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Bjorn Helgaas bhelgaas@google.com Cc: stable@vger.kernel.org # v5.4+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pci/setup-res.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -410,10 +410,16 @@ EXPORT_SYMBOL(pci_release_resource); int pci_resize_resource(struct pci_dev *dev, int resno, int size) { struct resource *res = dev->resource + resno; + struct pci_host_bridge *host; int old, ret; u32 sizes; u16 cmd;
+ /* Check if we must preserve the firmware's resource assignment */ + host = pci_find_host_bridge(dev->bus); + if (host->preserve_config) + return -ENOTSUPP; + /* Make sure the resource isn't assigned before resizing it. */ if (!(res->flags & IORESOURCE_UNSET)) return -EBUSY;
From: Hans de Goede hdegoede@redhat.com
commit c35901b39ddc20077f4ae7b9f7bf344487f62212 upstream.
Do not use wait_event_interruptible when vbg_hgcm_call() gets called from kernel-context, such as it being called by the vboxsf filesystem code.
This fixes some filesystem related system calls on shared folders unexpectedly failing with -EINTR.
Fixes: 0532a1b0d045 ("virt: vbox: Implement passing requestor info to the host for VirtualBox 6.0.x") Reported-by: Ludovic Pouzenc bugreports@pouzenc.fr Signed-off-by: Hans de Goede hdegoede@redhat.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210121150754.147598-1-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/virt/vboxguest/vboxguest_utils.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
--- a/drivers/virt/vboxguest/vboxguest_utils.c +++ b/drivers/virt/vboxguest/vboxguest_utils.c @@ -468,7 +468,7 @@ static int hgcm_cancel_call(struct vbg_d * Cancellation fun. */ static int vbg_hgcm_do_call(struct vbg_dev *gdev, struct vmmdev_hgcm_call *call, - u32 timeout_ms, bool *leak_it) + u32 timeout_ms, bool interruptible, bool *leak_it) { int rc, cancel_rc, ret; long timeout; @@ -495,10 +495,15 @@ static int vbg_hgcm_do_call(struct vbg_d else timeout = msecs_to_jiffies(timeout_ms);
- timeout = wait_event_interruptible_timeout( - gdev->hgcm_wq, - hgcm_req_done(gdev, &call->header), - timeout); + if (interruptible) { + timeout = wait_event_interruptible_timeout(gdev->hgcm_wq, + hgcm_req_done(gdev, &call->header), + timeout); + } else { + timeout = wait_event_timeout(gdev->hgcm_wq, + hgcm_req_done(gdev, &call->header), + timeout); + }
/* timeout > 0 means hgcm_req_done has returned true, so success */ if (timeout > 0) @@ -631,7 +636,8 @@ int vbg_hgcm_call(struct vbg_dev *gdev, hgcm_call_init_call(call, client_id, function, parms, parm_count, bounce_bufs);
- ret = vbg_hgcm_do_call(gdev, call, timeout_ms, &leak_it); + ret = vbg_hgcm_do_call(gdev, call, timeout_ms, + requestor & VMMDEV_REQUESTOR_USERMODE, &leak_it); if (ret == 0) { *vbox_status = call->header.result; ret = hgcm_call_copy_back_result(call, parms, parm_count,
From: Jan Kara jack@suse.cz
commit 41e76c85660c022c6bf5713bfb6c21e64a487cec upstream.
bfq_setup_cooperator() uses bfqd->in_serv_last_pos so detect whether it makes sense to merge current bfq queue with the in-service queue. However if the in-service queue is freshly scheduled and didn't dispatch any requests yet, bfqd->in_serv_last_pos is stale and contains value from the previously scheduled bfq queue which can thus result in a bogus decision that the two queues should be merged. This bug can be observed for example with the following fio jobfile:
[global] direct=0 ioengine=sync invalidate=1 size=1g rw=read
[reader] numjobs=4 directory=/mnt
where the 4 processes will end up in the one shared bfq queue although they do IO to physically very distant files (for some reason I was able to observe this only with slice_idle=1ms setting).
Fix the problem by invalidating bfqd->in_serv_last_pos when switching in-service queue.
Fixes: 058fdecc6de7 ("block, bfq: fix in-service-queue check for queue merging") CC: stable@vger.kernel.org Signed-off-by: Jan Kara jack@suse.cz Acked-by: Paolo Valente paolo.valente@linaro.org Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/bfq-iosched.c | 1 + 1 file changed, 1 insertion(+)
--- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -2937,6 +2937,7 @@ static void __bfq_set_in_service_queue(s }
bfqd->in_service_queue = bfqq; + bfqd->in_serv_last_pos = 0; }
/*
From: Takashi Iwai tiwai@suse.de
commit fb3c293b82c31a9a68fbcf4e7a45fadd8a47ea2b upstream.
The commit f274baa49be6 ("ALSA: usb-audio: Allow non-vmalloc buffer for PCM buffers") introduced the mode to allocate coherent pages for PCM buffers, and it used bus->controller device as its DMA device. It turned out, however, that bus->sysdev is a more appropriate device to be used for DMA mapping in HCD code.
This patch corrects the device reference accordingly.
Note that, on most platforms, both point to the very same device, hence this patch doesn't change anything practically. But on platforms like xhcd-plat hcd, the change becomes effective.
Fixes: f274baa49be6 ("ALSA: usb-audio: Allow non-vmalloc buffer for PCM buffers") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210205144559.29555-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1558,7 +1558,7 @@ void snd_usb_preallocate_buffer(struct s { struct snd_pcm *pcm = subs->stream->pcm; struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; - struct device *dev = subs->dev->bus->controller; + struct device *dev = subs->dev->bus->sysdev;
if (snd_usb_use_vmalloc) snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
From: Rokudo Yan wu-yan@tcl.com
commit 2395928158059b8f9858365fce7713ce7fef62e4 upstream.
There exists multiple path may do zram compaction concurrently. 1. auto-compaction triggered during memory reclaim 2. userspace utils write zram<id>/compaction node
So, multiple threads may call zs_shrinker_scan/zs_compact concurrently. But pages_compacted is a per zsmalloc pool variable and modification of the variable is not serialized(through under class->lock). There are two issues here: 1. the pages_compacted may not equal to total number of pages freed(due to concurrently add). 2. zs_shrinker_scan may not return the correct number of pages freed(issued by current shrinker).
The fix is simple: 1. account the number of pages freed in zs_compact locally. 2. use actomic variable pages_compacted to accumulate total number.
Link: https://lkml.kernel.org/r/20210202122235.26885-1-wu-yan@tcl.com Fixes: 860c707dca155a56 ("zsmalloc: account the number of compacted pages") Signed-off-by: Rokudo Yan wu-yan@tcl.com Cc: Minchan Kim minchan@kernel.org Cc: Sergey Senozhatsky sergey.senozhatsky@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/block/zram/zram_drv.c | 2 +- include/linux/zsmalloc.h | 2 +- mm/zsmalloc.c | 17 +++++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-)
--- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1082,7 +1082,7 @@ static ssize_t mm_stat_show(struct devic zram->limit_pages << PAGE_SHIFT, max_used << PAGE_SHIFT, (u64)atomic64_read(&zram->stats.same_pages), - pool_stats.pages_compacted, + atomic_long_read(&pool_stats.pages_compacted), (u64)atomic64_read(&zram->stats.huge_pages), (u64)atomic64_read(&zram->stats.huge_pages_since)); up_read(&zram->init_lock); --- a/include/linux/zsmalloc.h +++ b/include/linux/zsmalloc.h @@ -35,7 +35,7 @@ enum zs_mapmode {
struct zs_pool_stats { /* How many pages were migrated (freed) */ - unsigned long pages_compacted; + atomic_long_t pages_compacted; };
struct zs_pool; --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -2213,11 +2213,13 @@ static unsigned long zs_can_compact(stru return obj_wasted * class->pages_per_zspage; }
-static void __zs_compact(struct zs_pool *pool, struct size_class *class) +static unsigned long __zs_compact(struct zs_pool *pool, + struct size_class *class) { struct zs_compact_control cc; struct zspage *src_zspage; struct zspage *dst_zspage = NULL; + unsigned long pages_freed = 0;
spin_lock(&class->lock); while ((src_zspage = isolate_zspage(class, true))) { @@ -2247,7 +2249,7 @@ static void __zs_compact(struct zs_pool putback_zspage(class, dst_zspage); if (putback_zspage(class, src_zspage) == ZS_EMPTY) { free_zspage(pool, class, src_zspage); - pool->stats.pages_compacted += class->pages_per_zspage; + pages_freed += class->pages_per_zspage; } spin_unlock(&class->lock); cond_resched(); @@ -2258,12 +2260,15 @@ static void __zs_compact(struct zs_pool putback_zspage(class, src_zspage);
spin_unlock(&class->lock); + + return pages_freed; }
unsigned long zs_compact(struct zs_pool *pool) { int i; struct size_class *class; + unsigned long pages_freed = 0;
for (i = ZS_SIZE_CLASSES - 1; i >= 0; i--) { class = pool->size_class[i]; @@ -2271,10 +2276,11 @@ unsigned long zs_compact(struct zs_pool continue; if (class->index != i) continue; - __zs_compact(pool, class); + pages_freed += __zs_compact(pool, class); } + atomic_long_add(pages_freed, &pool->stats.pages_compacted);
- return pool->stats.pages_compacted; + return pages_freed; } EXPORT_SYMBOL_GPL(zs_compact);
@@ -2291,13 +2297,12 @@ static unsigned long zs_shrinker_scan(st struct zs_pool *pool = container_of(shrinker, struct zs_pool, shrinker);
- pages_freed = pool->stats.pages_compacted; /* * Compact classes and calculate compaction delta. * Can run concurrently with a manually triggered * (by user) compaction. */ - pages_freed = zs_compact(pool) - pages_freed; + pages_freed = zs_compact(pool);
return pages_freed ? pages_freed : SHRINK_STOP; }
From: Alexander Lobakin alobakin@pm.me
commit 8ac7c87acdcac156670f9920c8acbd84308ff4b1 upstream.
MIPS uses its own declaration of rwdata, and thus it should be kept in sync with the asm-generic one. Currently PAGE_ALIGNED_DATA() is missing from the linker script, which emits the following ld warnings:
mips-alpine-linux-musl-ld: warning: orphan section `.data..page_aligned' from `arch/mips/kernel/vdso.o' being placed in section `.data..page_aligned' mips-alpine-linux-musl-ld: warning: orphan section `.data..page_aligned' from `arch/mips/vdso/vdso-image.o' being placed in section `.data..page_aligned'
Add the necessary declaration, so the mentioned structures will be placed in vmlinux as intended:
ffffffff80630580 D __end_once ffffffff80630580 D __start___dyndbg ffffffff80630580 D __start_once ffffffff80630580 D __stop___dyndbg ffffffff80634000 d mips_vdso_data ffffffff80638000 d vdso_data ffffffff80638580 D _gp ffffffff8063c000 T __init_begin ffffffff8063c000 D _edata ffffffff8063c000 T _sinittext
->
ffffffff805a4000 D __end_init_task ffffffff805a4000 D __nosave_begin ffffffff805a4000 D __nosave_end ffffffff805a4000 d mips_vdso_data ffffffff805a8000 d vdso_data ffffffff805ac000 D mmlist_lock ffffffff805ac080 D tasklist_lock
Fixes: ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") Signed-off-by: Alexander Lobakin alobakin@pm.me Reviewed-by: Kees Cook keescook@chromium.org Reviewed-by: Nathan Chancellor natechancellor@gmail.com Cc: stable@vger.kernel.org # 4.4+ Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+)
--- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -90,6 +90,7 @@ SECTIONS
INIT_TASK_DATA(THREAD_SIZE) NOSAVE_DATA + PAGE_ALIGNED_DATA(PAGE_SIZE) CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) DATA_DATA
From: Nathan Chancellor nathan@kernel.org
commit f5b6a74d9c08b19740ca056876bf6584acdba582 upstream.
clang produces .eh_frame sections when CONFIG_GCOV_KERNEL is enabled, even when -fno-asynchronous-unwind-tables is in KBUILD_CFLAGS:
$ make CC=clang vmlinux ... ld: warning: orphan section `.eh_frame' from `init/main.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/version.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/do_mounts.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/do_mounts_initrd.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/initramfs.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/calibrate.o' being placed in section `.eh_frame' ld: warning: orphan section `.eh_frame' from `init/init_task.o' being placed in section `.eh_frame' ...
$ rg "GCOV_KERNEL|GCOV_PROFILE_ALL" .config CONFIG_GCOV_KERNEL=y CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_GCOV_PROFILE_ALL=y
This was already handled for a couple of other options in commit d812db78288d ("vmlinux.lds.h: Avoid KASAN and KCSAN's unwanted sections") and there is an open LLVM bug for this issue. Take advantage of that section for this config as well so that there are no more orphan warnings.
Link: https://bugs.llvm.org/show_bug.cgi?id=46478 Link: https://github.com/ClangBuiltLinux/linux/issues/1069 Reported-by: kernel test robot lkp@intel.com Reviewed-by: Fangrui Song maskray@google.com Reviewed-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Nathan Chancellor nathan@kernel.org Fixes: d812db78288d ("vmlinux.lds.h: Avoid KASAN and KCSAN's unwanted sections") Cc: stable@vger.kernel.org Signed-off-by: Kees Cook keescook@chromium.org Link: https://lore.kernel.org/r/20210130004650.2682422-1-nathan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/asm-generic/vmlinux.lds.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -993,12 +993,13 @@ #endif
/* - * Clang's -fsanitize=kernel-address and -fsanitize=thread produce - * unwanted sections (.eh_frame and .init_array.*), but - * CONFIG_CONSTRUCTORS wants to keep any .init_array.* sections. + * Clang's -fprofile-arcs, -fsanitize=kernel-address, and + * -fsanitize=thread produce unwanted sections (.eh_frame + * and .init_array.*), but CONFIG_CONSTRUCTORS wants to + * keep any .init_array.* sections. * https://bugs.llvm.org/show_bug.cgi?id=46478 */ -#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN) +#if defined(CONFIG_GCOV_KERNEL) || defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN) # ifdef CONFIG_CONSTRUCTORS # define SANITIZER_DISCARDS \ *(.eh_frame)
From: Eric Biggers ebiggers@google.com
commit 11a0b5e0ec8c13bef06f7414f9e914506140d5cb upstream.
The RNDRESEEDCRNG ioctl reseeds the primary_crng from itself, which doesn't make sense. Reseed it from the input_pool instead.
Fixes: d848e5f8e1eb ("random: add new ioctl RNDRESEEDCRNG") Cc: stable@vger.kernel.org Cc: linux-crypto@vger.kernel.org Cc: Andy Lutomirski luto@kernel.org Cc: Jann Horn jannh@google.com Cc: Theodore Ts'o tytso@mit.edu Reviewed-by: Jann Horn jannh@google.com Acked-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Eric Biggers ebiggers@google.com Link: https://lore.kernel.org/r/20210112192818.69921-1-ebiggers@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1972,7 +1972,7 @@ static long random_ioctl(struct file *f, return -EPERM; if (crng_init < 2) return -ENODATA; - crng_reseed(&primary_crng, NULL); + crng_reseed(&primary_crng, &input_pool); crng_global_init_time = jiffies - 1; return 0; default:
From: Takashi Iwai tiwai@suse.de
commit 29bb274e94974669acb5186a75538f20df1508b6 upstream.
The PCM core should perform the sync for the pending stop operations at disconnection. Otherwise it may lead to unexpected access.
Currently the old user of sync_stop, USB-audio driver, has its own sync, so this isn't needed, but it's better to guarantee the sync in the PCM core level.
This patch adds the missing sync_stop call at PCM disconnection callback. It also assures the IRQ sync if it's specified in the card. snd_pcm_sync_stop() is slightly modified to be called also for any PCM substream object now.
Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203656.15959-2-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/core/init.c | 4 ++++ sound/core/pcm.c | 4 ++++ sound/core/pcm_local.h | 1 + sound/core/pcm_native.c | 16 ++++++++-------- 4 files changed, 17 insertions(+), 8 deletions(-)
--- a/sound/core/init.c +++ b/sound/core/init.c @@ -14,6 +14,7 @@ #include <linux/ctype.h> #include <linux/pm.h> #include <linux/completion.h> +#include <linux/interrupt.h>
#include <sound/core.h> #include <sound/control.h> @@ -416,6 +417,9 @@ int snd_card_disconnect(struct snd_card /* notify all devices that we are disconnected */ snd_device_disconnect_all(card);
+ if (card->sync_irq > 0) + synchronize_irq(card->sync_irq); + snd_info_card_disconnect(card); if (card->registered) { device_del(&card->card_dev); --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1111,6 +1111,10 @@ static int snd_pcm_dev_disconnect(struct } }
+ for (cidx = 0; cidx < 2; cidx++) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + snd_pcm_sync_stop(substream, false); + pcm_call_notify(pcm, n_disconnect); for (cidx = 0; cidx < 2; cidx++) { snd_unregister_device(&pcm->streams[cidx].dev); --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -63,6 +63,7 @@ static inline void snd_pcm_timer_done(st
void __snd_pcm_xrun(struct snd_pcm_substream *substream); void snd_pcm_group_init(struct snd_pcm_group *group); +void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq);
#ifdef CONFIG_SND_DMA_SGBUF struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -583,13 +583,13 @@ static inline void snd_pcm_timer_notify( #endif }
-static void snd_pcm_sync_stop(struct snd_pcm_substream *substream) +void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq) { - if (substream->runtime->stop_operating) { + if (substream->runtime && substream->runtime->stop_operating) { substream->runtime->stop_operating = false; - if (substream->ops->sync_stop) + if (substream->ops && substream->ops->sync_stop) substream->ops->sync_stop(substream); - else if (substream->pcm->card->sync_irq > 0) + else if (sync_irq && substream->pcm->card->sync_irq > 0) synchronize_irq(substream->pcm->card->sync_irq); } } @@ -686,7 +686,7 @@ static int snd_pcm_hw_params(struct snd_ if (atomic_read(&substream->mmap_count)) return -EBADFD;
- snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true);
params->rmask = ~0U; err = snd_pcm_hw_refine(substream, params); @@ -809,7 +809,7 @@ static int do_hw_free(struct snd_pcm_sub { int result = 0;
- snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); if (substream->ops->hw_free) result = substream->ops->hw_free(substream); if (substream->managed_buffer_alloc) @@ -1736,7 +1736,7 @@ static void snd_pcm_post_resume(struct s snd_pcm_trigger_tstamp(substream); runtime->status->state = runtime->status->suspended_state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); }
static const struct action_ops snd_pcm_action_resume = { @@ -1866,7 +1866,7 @@ static int snd_pcm_do_prepare(struct snd snd_pcm_state_t state) { int err; - snd_pcm_sync_stop(substream); + snd_pcm_sync_stop(substream, true); err = substream->ops->prepare(substream); if (err < 0) return err;
From: Takashi Iwai tiwai@suse.de
commit 2c87c1a49c9d113a9f3e8e951d7d64be5ff50ac1 upstream.
The current PCM code calls the sync_stop at the resume action due to the analogy to the PCM prepare call pattern. But, it makes little sense, as the sync should have been done rather at the suspend time, not at the resume time.
This patch corrects the sync_stop call at suspend/resume to assure the sync before finishing the suspend.
Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203656.15959-3-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/core/pcm_native.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1615,6 +1615,7 @@ static int snd_pcm_do_suspend(struct snd if (! snd_pcm_running(substream)) return 0; substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); + runtime->stop_operating = true; return 0; /* suspend unconditionally */ }
@@ -1691,6 +1692,12 @@ int snd_pcm_suspend_all(struct snd_pcm * return err; } } + + for (stream = 0; stream < 2; stream++) + for (substream = pcm->streams[stream].substream; + substream; substream = substream->next) + snd_pcm_sync_stop(substream, false); + return 0; } EXPORT_SYMBOL(snd_pcm_suspend_all); @@ -1736,7 +1743,6 @@ static void snd_pcm_post_resume(struct s snd_pcm_trigger_tstamp(substream); runtime->status->state = runtime->status->suspended_state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); - snd_pcm_sync_stop(substream, true); }
static const struct action_ops snd_pcm_action_resume = {
From: Takashi Iwai tiwai@suse.de
commit 700cb70730777c159a988e01daa93f20a1ae9b58 upstream.
The PCM stop operation sets the stop_operating flag for indicating the sync_stop post-process. This flag is, however, set unconditionally even if the PCM trigger weren't issued. This may lead to inconsistency in the driver side.
Correct the code to set stop_operating flag only after the trigger STOP is actually called.
Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203656.15959-4-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/core/pcm_native.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1421,8 +1421,10 @@ static int snd_pcm_do_stop(struct snd_pc snd_pcm_state_t state) { if (substream->runtime->trigger_master == substream && - snd_pcm_running(substream)) + snd_pcm_running(substream)) { substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); + substream->runtime->stop_operating = true; + } return 0; /* unconditonally stop all substreams */ }
@@ -1435,7 +1437,6 @@ static void snd_pcm_post_stop(struct snd runtime->status->state = state; snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); } - runtime->stop_operating = true; wake_up(&runtime->sleep); wake_up(&runtime->tsleep); }
From: Chris Wilson chris@chris-wilson.co.uk
commit e627d5923cae93fa4188f4c4afba6486169a1337 upstream.
CI reports that Baytail requires one more invalidate after CACHE_MODE for it to be happy.
Fixes: ace44e13e577 ("drm/i915/gt: Clear CACHE_MODE prior to clearing residuals") Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Mika Kuoppala mika.kuoppala@linux.intel.com Cc: Akeem G Abodunrin akeem.g.abodunrin@intel.com Reviewed-by: Mika Kuoppala mika.kuoppala@linux.intel.com Reviewed-by: Akeem G Abodunrin akeem.g.abodunrin@intel.com Cc: Hans de Goede hdegoede@redhat.com Cc: Diego Calleja diegocg@gmail.com Link: https://patchwork.freedesktop.org/patch/msgid/20210119110802.22228-1-chris@c... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/gen7_renderclear.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/gt/gen7_renderclear.c +++ b/drivers/gpu/drm/i915/gt/gen7_renderclear.c @@ -353,19 +353,21 @@ static void gen7_emit_pipeline_flush(str
static void gen7_emit_pipeline_invalidate(struct batch_chunk *batch) { - u32 *cs = batch_alloc_items(batch, 0, 8); + u32 *cs = batch_alloc_items(batch, 0, 10);
/* ivb: Stall before STATE_CACHE_INVALIDATE */ - *cs++ = GFX_OP_PIPE_CONTROL(4); + *cs++ = GFX_OP_PIPE_CONTROL(5); *cs++ = PIPE_CONTROL_STALL_AT_SCOREBOARD | PIPE_CONTROL_CS_STALL; *cs++ = 0; *cs++ = 0; + *cs++ = 0;
- *cs++ = GFX_OP_PIPE_CONTROL(4); + *cs++ = GFX_OP_PIPE_CONTROL(5); *cs++ = PIPE_CONTROL_STATE_CACHE_INVALIDATE; *cs++ = 0; *cs++ = 0; + *cs++ = 0;
batch_advance(batch, cs); } @@ -397,6 +399,7 @@ static void emit_batch(struct i915_vma * batch_add(&cmds, 0xffff0000); batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_1)); batch_add(&cmds, 0xffff0000 | PIXEL_SUBSPAN_COLLECT_OPT_DISABLE); + gen7_emit_pipeline_invalidate(&cmds); gen7_emit_pipeline_flush(&cmds);
/* Switch to the media pipeline and our base address */
From: Rakesh Pillai pillair@codeaurora.org
[ Upstream commit 31561e8557cd1eeba5806ac9ce820f8323b2201b ]
Currently if the copy engine pipe init fails for snoc based chipsets, the rri is not freed.
Fix this error handling for copy engine pipe init failure.
Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1
Fixes: 4945af5b264f ("ath10k: enable SRRI/DRRI support on ddr for WCN3990") Signed-off-by: Rakesh Pillai pillair@codeaurora.org Reviewed-by: Brian Norris briannorris@chromium.org Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/1607713210-18320-1-git-send-email-pillair@codeauro... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/snoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index bf9a8cb713dc0..1c3307e3b1085 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1045,12 +1045,13 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar, ret = ath10k_snoc_init_pipes(ar); if (ret) { ath10k_err(ar, "failed to initialize CE: %d\n", ret); - goto err_wlan_enable; + goto err_free_rri; }
return 0;
-err_wlan_enable: +err_free_rri: + ath10k_ce_free_rri(ar); ath10k_snoc_wlan_disable(ar);
return ret;
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 9a39a927be01d89e53f04304ab99a8761e08910d ]
Some resource should be released in the error handling path of the probe function, as already done in the remove function.
The remove function was fixed in commit 5052de8deff5 ("soc: qcom: smd: Transition client drivers from smd to rpmsg")
Fixes: 1511cc750c3d ("Bluetooth: Introduce Qualcomm WCNSS SMD based HCI driver") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btqcomsmd.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 98d53764871f5..2acb719e596f5 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -142,12 +142,16 @@ static int btqcomsmd_probe(struct platform_device *pdev)
btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD", btqcomsmd_cmd_callback, btq); - if (IS_ERR(btq->cmd_channel)) - return PTR_ERR(btq->cmd_channel); + if (IS_ERR(btq->cmd_channel)) { + ret = PTR_ERR(btq->cmd_channel); + goto destroy_acl_channel; + }
hdev = hci_alloc_dev(); - if (!hdev) - return -ENOMEM; + if (!hdev) { + ret = -ENOMEM; + goto destroy_cmd_channel; + }
hci_set_drvdata(hdev, btq); btq->hdev = hdev; @@ -161,14 +165,21 @@ static int btqcomsmd_probe(struct platform_device *pdev) hdev->set_bdaddr = qca_set_bdaddr_rome;
ret = hci_register_dev(hdev); - if (ret < 0) { - hci_free_dev(hdev); - return ret; - } + if (ret < 0) + goto hci_free_dev;
platform_set_drvdata(pdev, btq);
return 0; + +hci_free_dev: + hci_free_dev(hdev); +destroy_cmd_channel: + rpmsg_destroy_ept(btq->cmd_channel); +destroy_acl_channel: + rpmsg_destroy_ept(btq->acl_channel); + + return ret; }
static int btqcomsmd_remove(struct platform_device *pdev)
From: Claire Chang tientzu@chromium.org
[ Upstream commit afe0b1c86458f121b085271e4f3034017a90d4a3 ]
In hci_uart_write_work, there is a loop/goto checking the value of HCI_UART_TX_WAKEUP. If HCI_UART_TX_WAKEUP is set again, it keeps trying hci_uart_dequeue; otherwise, it clears HCI_UART_SENDING and returns.
In hci_uart_tx_wakeup, if HCI_UART_SENDING is already set, it sets HCI_UART_TX_WAKEUP, skips schedule_work and assumes the running/pending hci_uart_write_work worker will do hci_uart_dequeue properly.
However, if the HCI_UART_SENDING check in hci_uart_tx_wakeup is done after the loop breaks, but before HCI_UART_SENDING is cleared in hci_uart_write_work, the schedule_work is skipped incorrectly.
Fix this race by changing the order of HCI_UART_SENDING and HCI_UART_TX_WAKEUP modification.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Fixes: 82f5169bf3d3 ("Bluetooth: hci_uart: add serdev driver support library") Signed-off-by: Claire Chang tientzu@chromium.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_ldisc.c | 7 +++---- drivers/bluetooth/hci_serdev.c | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index f83d67eafc9f0..8be4d807d1370 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -127,10 +127,9 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) goto no_schedule;
- if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { - set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); + set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); + if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) goto no_schedule; - }
BT_DBG("");
@@ -174,10 +173,10 @@ restart: kfree_skb(skb); }
+ clear_bit(HCI_UART_SENDING, &hu->tx_state); if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) goto restart;
- clear_bit(HCI_UART_SENDING, &hu->tx_state); wake_up_bit(&hu->tx_state, HCI_UART_SENDING); }
diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index ef96ad06fa54e..9e03402ef1b37 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -83,9 +83,9 @@ static void hci_uart_write_work(struct work_struct *work) hci_uart_tx_complete(hu, hci_skb_pkt_type(skb)); kfree_skb(skb); } - } while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
- clear_bit(HCI_UART_SENDING, &hu->tx_state); + clear_bit(HCI_UART_SENDING, &hu->tx_state); + } while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)); }
/* ------- Interface to HCI layer ------ */
From: Christopher William Snowhill chris@kode54.net
[ Upstream commit a5687c644015a097304a2e47476c0ecab2065734 ]
Looks like this was missed when patching the source to clear the structures throughout, causing this one instance to clear the struct after the response id is assigned.
Fixes: eddb7732119d ("Bluetooth: A2MP: Fix not initializing all members") Signed-off-by: Christopher William Snowhill chris@kode54.net Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/a2mp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index da7fd7c8c2dc0..cc26e4c047ad0 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -381,9 +381,9 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, hdev = hci_dev_get(req->id); if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) { struct a2mp_amp_assoc_rsp rsp; - rsp.id = req->id;
memset(&rsp, 0, sizeof(rsp)); + rsp.id = req->id;
if (tmp) { rsp.status = A2MP_STATUS_COLLISION_OCCURED;
From: Adam Ford aford173@gmail.com
[ Upstream commit db030c5a9658846a42fbed4d43a8b5f28a2d7ab7 ]
The Bluetooth chip is capable of operating at 4Mbps, but the max-speed setting was on the UART node instead of the Bluetooth node, so the chip didn't operate at the correct speed resulting in choppy audio. Fix this by setting the max-speed in the proper node.
Fixes: a1d8a344f1ca ("arm64: dts: renesas: Introduce r8a774a1-beacon-rzg2m-kit") Signed-off-by: Adam Ford aford173@gmail.com Link: https://lore.kernel.org/r/20201213183759.223246-3-aford173@gmail.com Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi index 8ac167aa18f04..b93219a95afcd 100644 --- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi +++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi @@ -89,7 +89,6 @@ pinctrl-names = "default"; uart-has-rtscts; status = "okay"; - max-speed = <4000000>;
bluetooth { compatible = "brcm,bcm43438-bt"; @@ -98,6 +97,7 @@ device-wakeup-gpios = <&pca9654 5 GPIO_ACTIVE_HIGH>; clocks = <&osc_32k>; clock-names = "extclk"; + max-speed = <4000000>; }; };
From: Adam Ford aford173@gmail.com
[ Upstream commit 5a5da0b758b327b727c5392d7f11e046e113a195 ]
The fact the audio worked at all was a coincidence because the wrong gpio enable was used. Use the correct GPIO pin to ensure its operation.
Fixes: a1d8a344f1ca ("arm64: dts: renesas: Introduce r8a774a1-beacon-rzg2m-kit") Signed-off-by: Adam Ford aford173@gmail.com Link: https://lore.kernel.org/r/20201213183759.223246-6-aford173@gmail.com Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi index e66b5b36e4894..759734b7715bd 100644 --- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi +++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi @@ -150,7 +150,7 @@ regulator-name = "audio-1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - gpio = <&gpio_exp2 7 GPIO_ACTIVE_HIGH>; + gpio = <&gpio_exp4 1 GPIO_ACTIVE_HIGH>; enable-active-high; };
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit cb31334687db31c691901269d65074a7ffaecb18 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: b004a34bd0ff ("ARM: dts: exynos: Add exynos3250-artik5 dtsi file for ARTIK5 module") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Marek Szyprowski m.szyprowski@samsung.com Link: https://lore.kernel.org/r/20201210212903.216728-1-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos3250-artik5.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/exynos3250-artik5.dtsi index 04290ec4583a6..829c05b2c405f 100644 --- a/arch/arm/boot/dts/exynos3250-artik5.dtsi +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -79,7 +79,7 @@ pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx3>; - interrupts = <5 IRQ_TYPE_NONE>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps14_irq>; reg = <0x66>;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 8528cda2b7c667e9cd173aef1a677c71b7d5a096 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: e0cefb3f79d3 ("ARM: dts: add board dts file for Exynos3250-based Monk board") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20201210212903.216728-2-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos3250-monk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 69451566945dc..fae046e08a5dd 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -200,7 +200,7 @@ pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; wakeup-source;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 437ae60947716bb479e2f32466f49445c0509b1e ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: faaf348ef468 ("ARM: dts: Add board dts file for exynos3250-rinato") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Marek Szyprowski m.szyprowski@samsung.com Link: https://lore.kernel.org/r/20201210212903.216728-3-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos3250-rinato.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index a26e3e582a7e7..d64ccf4b7d324 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -270,7 +270,7 @@ pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; wakeup-source;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 77e6a5467cb8657cf8b5e610a30a4c502085e4f9 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: 53dd4138bb0a ("ARM: dts: Add exynos5250-spring device tree") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20201210212903.216728-4-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos5250-spring.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index 9d2baea62d0d7..fba1462b19dfd 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -109,7 +109,7 @@ compatible = "samsung,s5m8767-pmic"; reg = <0x66>; interrupt-parent = <&gpx3>; - interrupts = <2 IRQ_TYPE_NONE>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>; wakeup-source;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 1ac8893c4fa3d4a34915dc5cdab568a39db5086c ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. The falling edge interrupt will mostly work but it's not correct.
Fixes: 1fed2252713e ("ARM: dts: fix pinctrl for s2mps11-irq on exynos5420-arndale-octa") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Marek Szyprowski m.szyprowski@samsung.com Link: https://lore.kernel.org/r/20201210212903.216728-5-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index bf457d0c02ebd..1aad4859c5f14 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -349,7 +349,7 @@ reg = <0x66>;
interrupt-parent = <&gpx3>; - interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps11_irq>;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 3e7d9a583a24f7582c6bc29a0d4d624feedbc2f9 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. The falling edge interrupt will mostly work but it's not correct.
Fixes: aac4e0615341 ("ARM: dts: odroidxu3: Enable wake alarm of S2MPS11 RTC") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Marek Szyprowski m.szyprowski@samsung.com Link: https://lore.kernel.org/r/20201210212903.216728-6-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/exynos5422-odroid-core.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi index d0df560eb0db1..6d690b1db0994 100644 --- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi @@ -509,7 +509,7 @@ samsung,s2mps11-acokb-ground;
interrupt-parent = <&gpx0>; - interrupts = <4 IRQ_TYPE_EDGE_FALLING>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps11_irq>;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit e98e2367dfb4b6d7a80c8ce795c644124eff5f36 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: 01e5d2352152 ("arm64: dts: exynos: Add dts file for Exynos5433-based TM2 board") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Marek Szyprowski m.szyprowski@samsung.com Link: https://lore.kernel.org/r/20201210212903.216728-7-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi index 03486a8ffc67e..4c5106a0860d0 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi @@ -388,7 +388,7 @@ pmic@66 { compatible = "samsung,s2mps13-pmic"; interrupt-parent = <&gpa0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; samsung,s2mps11-wrstbi-ground;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit 1fea2eb2f5bbd3fbbe2513d2386b5f6e6db17fd7 ]
The Samsung PMIC datasheets describe the interrupt line as active low with a requirement of acknowledge from the CPU. Without specifying the interrupt type in Devicetree, kernel might apply some fixed configuration, not necessarily working for this hardware.
Fixes: 9589f7721e16 ("arm64: dts: Add S2MPS15 PMIC node on exynos7-espresso") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20201210212903.216728-8-krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts index 695d4c1406466..125c03f351d97 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -90,7 +90,7 @@ pmic@66 { compatible = "samsung,s2mps15-pmic"; reg = <0x66>; - interrupts = <2 IRQ_TYPE_NONE>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupt-parent = <&gpa0>; pinctrl-names = "default"; pinctrl-0 = <&pmic_irq>;
From: Zhang Qilong zhangqilong3@huawei.com
[ Upstream commit a2d522ff0f5cc26915c4ccee9457fd4b4e1edc48 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. We fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Fixes: 4f0a1a1ae3519 ("memory: mtk-smi: Invoke pm runtime_callback to enable clocks") Signed-off-by: Zhang Qilong zhangqilong3@huawei.com Link: https://lore.kernel.org/r/20201123102118.3866195-1-zhangqilong3@huawei.com Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/memory/mtk-smi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index ac350f8d1e20f..82d09b88240e1 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -130,7 +130,7 @@ static void mtk_smi_clk_disable(const struct mtk_smi *smi)
int mtk_smi_larb_get(struct device *larbdev) { - int ret = pm_runtime_get_sync(larbdev); + int ret = pm_runtime_resume_and_get(larbdev);
return (ret < 0) ? ret : 0; } @@ -374,7 +374,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev) int ret;
/* Power on smi-common. */ - ret = pm_runtime_get_sync(larb->smi_common_dev); + ret = pm_runtime_resume_and_get(larb->smi_common_dev); if (ret < 0) { dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret); return ret;
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit 71f8e707557b9bc25dc90a59a752528d4e7c1cbf ]
When __le32_to_cpu() fails, qca_memdump should be freed just like when vmalloc() fails.
Fixes: d841502c79e3f ("Bluetooth: hci_qca: Collect controller memory dump during SSR") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_qca.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 4a963682c7021..5dbcb7c42b805 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1024,7 +1024,9 @@ static void qca_controller_memdump(struct work_struct *work) dump_size = __le32_to_cpu(dump->dump_size); if (!(dump_size)) { bt_dev_err(hu->hdev, "Rx invalid memdump size"); + kfree(qca_memdump); kfree_skb(skb); + qca->qca_memdump = NULL; mutex_unlock(&qca->hci_memdump_lock); return; }
From: Phil Elwell phil@raspberrypi.com
[ Upstream commit 96ae327678eceabf455b11a88ba14ad540d4b046 ]
The addition of the local 'userdata' pointer to vchiq_irq_queue_bulk_tx_rx omitted the case where neither BLOCKING nor WAITING modes are used, in which case the value provided by the caller is not returned to them as expected, but instead it is replaced with a NULL. This lack of a suitable context may cause the application to crash or otherwise malfunction.
Fixes: 4184da4f316a ("staging: vchiq: fix __user annotations") Tested-by: Stefan Wahren stefan.wahren@i2se.com Acked-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Phil Elwell phil@raspberrypi.com Link: https://lore.kernel.org/r/20210105162030.1415213-2-phil@raspberrypi.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index f500a70438056..2a8883673ba11 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -958,7 +958,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, struct vchiq_service *service; struct bulk_waiter_node *waiter = NULL; bool found = false; - void *userdata = NULL; + void *userdata; int status = 0; int ret;
@@ -997,6 +997,8 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, "found bulk_waiter %pK for pid %d", waiter, current->pid); userdata = &waiter->bulk_waiter; + } else { + userdata = args->userdata; }
/*
From: Phil Elwell phil@raspberrypi.com
[ Upstream commit 88753cc19f087abe0d39644b844e67a59cfb5a3d ]
The recent change to the bulk transfer compat function missed the fact the relevant ioctl command is VCHIQ_IOC_QUEUE_BULK_TRANSMIT32, not VCHIQ_IOC_QUEUE_BULK_TRANSMIT, as any attempt to send a bulk block to the VPU would have shown.
Fixes: a4367cd2b231 ("staging: vchiq: convert compat bulk transfer") Acked-by: Arnd Bergmann arnd@arndb.de Acked-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Phil Elwell phil@raspberrypi.com Link: https://lore.kernel.org/r/20210105162030.1415213-3-phil@raspberrypi.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 2a8883673ba11..2ca5805b2fce0 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -1717,7 +1717,7 @@ vchiq_compat_ioctl_queue_bulk(struct file *file, { struct vchiq_queue_bulk_transfer32 args32; struct vchiq_queue_bulk_transfer args; - enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? + enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ? VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
if (copy_from_user(&args32, argp, sizeof(args32)))
From: Stephan Gerhold stephan@gerhold.net
[ Upstream commit 826e6faf49ae1eb065759a30832a2e34740bd8b1 ]
Unlike most MSM8916 boards, samsung-a5u uses WCN3660B instead of WCN3620 to support the 5 GHz band additionally.
WCN3660B has similar requirements as WCN3620, but it needs the XO clock to run at 48 MHz instead of 19.2 MHz. So far it was possible to describe that configuration using the qcom,wcn3680 compatible.
However, as of commit 8490987bdb9a ("wcn36xx: Hook and identify RF_IRIS_WCN3680"), the wcn36xx driver will now use the qcom,wcn3680 compatible to enable functionality specific to WCN3680. In particular, WCN3680 supports 802.11ac, which is not available in WCN3660B.
Use the new qcom,wcn3660b compatible to describe the chip properly.
Fixes: 0d7051999175 ("arm64: dts: msm8916-samsung-a5u: Override iris compatible") Signed-off-by: Stephan Gerhold stephan@gerhold.net Link: https://lore.kernel.org/r/20210106102134.59801-4-stephan@gerhold.net Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts index e39c04d977c25..dd35c3344358c 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts @@ -38,7 +38,7 @@
&pronto { iris { - compatible = "qcom,wcn3680"; + compatible = "qcom,wcn3660b"; }; };
From: Martin Blumenstingl martin.blumenstingl@googlemail.com
[ Upstream commit 025822884a4fd2d0af51dcf77ddc494e60c5ff63 ]
The timing-adjustment clock only has to be enabled when a) there is a 2ns RX delay configured using device-tree and b) the phy-mode indicates that the RX delay should be enabled.
Only enable the RX delay if both are true, instead of (by accident) also enabling it when there's the 2ns RX delay configured but the phy-mode incicates that the RX delay is not used.
Fixes: 9308c47640d515 ("net: stmmac: dwmac-meson8b: add support for the RX delay configuration") Reported-by: Andrew Lunn andrew@lunn.ch Reviewed-by: Andrew Lunn andrew@lunn.ch Reviewed-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index f184b00f51166..5f500141567d0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -301,7 +301,7 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac) return -EINVAL; }
- if (rx_dly_config & PRG_ETH0_ADJ_ENABLE) { + if (delay_config & PRG_ETH0_ADJ_ENABLE) { if (!dwmac->timing_adj_clk) { dev_err(dwmac->dev, "The timing-adjustment clock is mandatory for the RX delay re-timing\n");
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit a643bff752dcf72a07e1b2ab2f8587e4f51118be ]
Add bpf_patch_call_args() prototype. This function is called from BPF verifier and only if CONFIG_BPF_JIT_ALWAYS_ON is not defined. This fixes compiler warning about missing prototype in some kernel configurations.
Fixes: 1ea47e01ad6e ("bpf: add support for bpf_call to interpreter") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20210112075520.4103414-2-andrii@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/bpf.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 07cb5d15e7439..ef9309604b3e5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1403,7 +1403,10 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size) /* verify correctness of eBPF program */ int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, union bpf_attr __user *uattr); + +#ifndef CONFIG_BPF_JIT_ALWAYS_ON void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth); +#endif
struct btf *bpf_get_btf_vmlinux(void);
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit 6943c2b05bf09fd5c5729f7d7d803bf3f126cb9a ]
BPF interpreter uses extra input argument, so re-casts __bpf_call_base into __bpf_call_base_args. Avoid compiler warning about incompatible function prototypes by casting to void * first.
Fixes: 1ea47e01ad6e ("bpf: add support for bpf_call to interpreter") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20210112075520.4103414-3-andrii@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/filter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h index 29c27656165b2..5edf2b6608812 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -886,7 +886,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp); u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); #define __bpf_call_base_args \ ((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \ - __bpf_call_base) + (void *)__bpf_call_base)
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog); void bpf_jit_compile(struct bpf_prog *prog);
From: Cristian Marussi cristian.marussi@arm.com
[ Upstream commit a90b6543bf062d65292b2c76f1630507d1c9d8ec ]
Call scmi_notification_exit() only when SCMI platform driver instance has been really successfully removed.
Link: https://lore.kernel.org/r/20210112191326.29091-1-cristian.marussi@arm.com Fixes: 6b8a69131dc63 ("firmware: arm_scmi: Enable notification core") Signed-off-by: Cristian Marussi cristian.marussi@arm.com [sudeep.holla: Move the call outside the list mutex locking] Signed-off-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/arm_scmi/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 5392e1fc6b4ef..cacdf1589b101 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -848,8 +848,6 @@ static int scmi_remove(struct platform_device *pdev) struct scmi_info *info = platform_get_drvdata(pdev); struct idr *idr = &info->tx_idr;
- scmi_notification_exit(&info->handle); - mutex_lock(&scmi_list_mutex); if (info->users) ret = -EBUSY; @@ -860,6 +858,8 @@ static int scmi_remove(struct platform_device *pdev) if (ret) return ret;
+ scmi_notification_exit(&info->handle); + /* Safe to free channels since no more users */ ret = idr_for_each(idr, info->desc->ops->chan_free, idr); idr_destroy(&info->tx_idr);
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit cc72570747e43335f4933a24dd74d5653639176a ]
In recent Allwinner SoCs the first USB host controller (HCI0) shares the first PHY with the MUSB controller. Probably to make this sharing work, we were avoiding to declare this in the DT. This has two shortcomings: - U-Boot (which uses the same .dts) cannot use this port in host mode without a PHY linked, so we were loosing one USB port there. - It requires the MUSB driver to be enabled and loaded, although we don't actually use it.
To avoid those issues, let's add this PHY link to the A64 .dtsi file. After all PHY port 0 *is* connected to HCI0, so we should describe it as this. Remove the part from the Pinebook DTS which already had this property.
This makes it work in U-Boot, also improves compatiblity when no MUSB driver is loaded (for instance in distribution installers).
Fixes: dc03a047df1d ("arm64: allwinner: a64: add EHCI0/OHCI0 nodes to A64 DTSI") Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210113152630.28810-2-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 4 ---- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 896f34fd9fc3a..d07cf05549c32 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -126,8 +126,6 @@ };
&ehci0 { - phys = <&usbphy 0>; - phy-names = "usb"; status = "okay"; };
@@ -177,8 +175,6 @@ };
&ohci0 { - phys = <&usbphy 0>; - phy-names = "usb"; status = "okay"; };
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 51cc30e84e261..19e9b8ca8432f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -593,6 +593,8 @@ <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>, <&ccu RST_BUS_EHCI0>; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; };
@@ -603,6 +605,8 @@ clocks = <&ccu CLK_BUS_OHCI0>, <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; };
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit da2fb8457f71138d455cba82edec0d34f858e506 ]
In recent Allwinner SoCs the first USB host controller (HCI0) shares the first PHY with the MUSB controller. Probably to make this sharing work, we were avoiding to declare this in the DT. This has two shortcomings: - U-Boot (which uses the same .dts) cannot use this port in host mode without a PHY linked, so we were loosing one USB port there. - It requires the MUSB driver to be enabled and loaded, although we don't actually use it.
To avoid those issues, let's add this PHY link to the H6 .dtsi file. After all PHY port 0 *is* connected to HCI0, so we should describe it as this.
This makes it work in U-Boot, also improves compatiblity when no MUSB driver is loaded (for instance in distribution installers).
Fixes: eabb3d424b6d ("arm64: dts: allwinner: h6: add USB2-related device nodes") Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210113152630.28810-3-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 8a62a9fbe3475..f593cfeaecc9f 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -680,6 +680,8 @@ <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>, <&ccu RST_BUS_EHCI0>; + phys = <&usb2phy 0>; + phy-names = "usb"; status = "disabled"; };
@@ -690,6 +692,8 @@ clocks = <&ccu CLK_BUS_OHCI0>, <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>; + phys = <&usb2phy 0>; + phy-names = "usb"; status = "disabled"; };
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit 941432d007689f3774646e41a1439228b6c6ee0e ]
The SD card on the SoPine SoM module is somewhat concealed, so was originally defined as "non-removable". However there is a working card-detect pin (tested on two different SoM versions), and in certain SoM base boards it might be actually accessible at runtime. Also the Pine64-LTS shares the SoPine base .dtsi, so inherited the non-removable flag, even though the SD card slot is perfectly accessible and usable there. (It turns out that just *my* board has a broken card detect switch, so I originally thought CD wouldn't work on the LTS.)
Drop the "non-removable" flag to describe the SD card slot properly.
Fixes: c3904a269891 ("arm64: allwinner: a64: add DTSI file for SoPine SoM") Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210113152630.28810-5-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 - 1 file changed, 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi index c48692b06e1fa..3402cec87035b 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi @@ -32,7 +32,6 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; vmmc-supply = <®_dcdc1>; - non-removable; disable-wp; bus-width = <4>; cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit cfe6c487b9a1abc6197714ec5605716a5428cf03 ]
The H6 manual explicitly lists a frequency limit of 150 MHz for the bus frequency of the MMC controllers. So far we had no explicit limits in the DT, which limited eMMC to the spec defined frequencies, or whatever the driver defines (both Linux and FreeBSD use 52 MHz here).
Put those maximum frequencies in the SoC .dtsi, to allow higher speed modes (which still would need to be explicitly enabled, per board).
Tested with an eMMC using HS-200 on a Pine H64. Running at the spec'ed 200 MHz indeed fails with I/O errors, but 150 MHz seems to work stably.
Fixes: 8f54bd1595b3 ("arm64: allwinner: h6: add device tree nodes for MMC controllers") Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210113152630.28810-6-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index f593cfeaecc9f..77765d4a05ec9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -436,6 +436,7 @@ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; + max-frequency = <150000000>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -452,6 +453,7 @@ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&mmc1_pins>; + max-frequency = <150000000>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -468,6 +470,7 @@ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&mmc2_pins>; + max-frequency = <150000000>; status = "disabled"; #address-cells = <1>; #size-cells = <0>;
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit 948c657cc45e8ce48cb533d4e2106145fa765759 ]
In contrast to the H6 (and later) manuals, the A64 datasheet does not specify any limitations in the maximum possible frequency for eMMC controllers. However experimentation has found that a 150 MHz limit similar to other SoCs and also the MMC0 and MMC1 controllers on the A64 seems to exist for the MMC2 controller.
Limit the frequency for the MMC2 controller to 150 MHz in the SoC .dtsi. The Pinebook seems to be the an odd exception, since it apparently seems to work with 200 MHz as well, so overwrite this in its board .dts file.
Tested on a Pine64-LTS: 200 MHz HS-200 fails, 150 MHz HS-200 works.
Fixes: 22be992faea7 ("arm64: allwinner: a64: Increase the MMC max frequency") Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210113152630.28810-7-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 1 + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index d07cf05549c32..7ae16541d14f5 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -167,6 +167,7 @@ pinctrl-0 = <&mmc2_pins>, <&mmc2_ds_pin>; vmmc-supply = <®_dcdc1>; vqmmc-supply = <®_eldo1>; + max-frequency = <200000000>; bus-width = <8>; non-removable; cap-mmc-hw-reset; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 19e9b8ca8432f..57786fc120c30 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -514,7 +514,7 @@ resets = <&ccu RST_BUS_MMC2>; reset-names = "ahb"; interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; - max-frequency = <200000000>; + max-frequency = <150000000>; status = "disabled"; #address-cells = <1>; #size-cells = <0>;
From: Stephan Gerhold stephan@gerhold.net
[ Upstream commit 3716a583fe0bbe3babf4ce260064a7fa13d6d989 ]
When the BMC150 accelerometer/magnetometer was added to the device tree, the sensors were working without specifying any regulator supplies, likely because the regulators were on by default and then never turned off.
For some reason, this is no longer the case for pm8916_l17, which prevents the sensors from working in some cases.
Now that the bmc150_accel/bmc150_magn drivers can enable necessary regulators, declare the necessary regulator supplies to make the sensors work again.
Fixes: 079f81acf10f ("arm64: dts: qcom: msm8916-samsung-a2015: Add accelerometer/magnetometer") Signed-off-by: Stephan Gerhold stephan@gerhold.net Link: https://lore.kernel.org/r/20210111175358.97171-1-stephan@gerhold.net Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi index f91269492d729..f1af798abd749 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi @@ -106,6 +106,9 @@ interrupt-parent = <&msmgpio>; interrupts = <115 IRQ_TYPE_EDGE_RISING>;
+ vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l5>; + pinctrl-names = "default"; pinctrl-0 = <&accel_int_default>; }; @@ -113,6 +116,9 @@ magnetometer@12 { compatible = "bosch,bmc150_magn"; reg = <0x12>; + + vdd-supply = <&pm8916_l17>; + vddio-supply = <&pm8916_l5>; }; };
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 05f456286fd489558c72a4711d22a5612c965685 ]
If 'cpufreq_register_driver()' fails, we must release the resources allocated in 'brcm_avs_prepare_init()' as already done in the remove function.
To do that, introduce a new function 'brcm_avs_prepare_uninit()' in order to avoid code duplication. This also makes the code more readable (IMHO).
Fixes: de322e085995 ("cpufreq: brcmstb-avs-cpufreq: AVS CPUfreq driver for Broadcom STB SoCs") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr [ Viresh: Updated Subject ] Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/cpufreq/brcmstb-avs-cpufreq.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index 3e31e5d28b79c..e25ccb744187d 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -597,6 +597,16 @@ unmap_base: return ret; }
+static void brcm_avs_prepare_uninit(struct platform_device *pdev) +{ + struct private_data *priv; + + priv = platform_get_drvdata(pdev); + + iounmap(priv->avs_intr_base); + iounmap(priv->base); +} + static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *freq_table; @@ -732,21 +742,22 @@ static int brcm_avs_cpufreq_probe(struct platform_device *pdev)
brcm_avs_driver.driver_data = pdev;
- return cpufreq_register_driver(&brcm_avs_driver); + ret = cpufreq_register_driver(&brcm_avs_driver); + if (ret) + brcm_avs_prepare_uninit(pdev); + + return ret; }
static int brcm_avs_cpufreq_remove(struct platform_device *pdev) { - struct private_data *priv; int ret;
ret = cpufreq_unregister_driver(&brcm_avs_driver); if (ret) return ret;
- priv = platform_get_drvdata(pdev); - iounmap(priv->base); - iounmap(priv->avs_intr_base); + brcm_avs_prepare_uninit(pdev);
return 0; }
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 3657f729b6fb5f2c0bf693742de2dcd49c572aa1 ]
If 'cpufreq_unregister_driver()' fails, just WARN and continue, so that other resources are freed.
Fixes: de322e085995 ("cpufreq: brcmstb-avs-cpufreq: AVS CPUfreq driver for Broadcom STB SoCs") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr [ Viresh: Updated Subject ] Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/cpufreq/brcmstb-avs-cpufreq.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index e25ccb744187d..4153150e20db5 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -754,8 +754,7 @@ static int brcm_avs_cpufreq_remove(struct platform_device *pdev) int ret;
ret = cpufreq_unregister_driver(&brcm_avs_driver); - if (ret) - return ret; + WARN_ON(ret);
brcm_avs_prepare_uninit(pdev);
From: Chen-Yu Tsai wens@csie.org
[ Upstream commit c6433083f5930fdf52ad47c8c0459719c810dc89 ]
The gmac2phy is integrated with the PHY within the SoC. Any properties related to this integration can be included in the .dtsi file, instead of having board dts files specify them separately.
Add the clock_in_out property to specify the direction of the PHY clock. This is the minimum required to have gmac2phy working on Linux. Other examples include assigned-clocks, assigned-clock-rates, and assigned-clock-parents properties, but the hardware default plus the implementation requesting the appropriate clock rate also works.
Fixes: 9c4cc910fe28 ("ARM64: dts: rockchip: Add gmac2phy node support for rk3328") Signed-off-by: Chen-Yu Tsai wens@csie.org Link: https://lore.kernel.org/r/20210117100710.4857-2-wens@kernel.org Signed-off-by: Heiko Stuebner heiko@sntech.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index db0d5c8e5f96a..93c734d8a46c2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -928,6 +928,7 @@ phy-mode = "rmii"; phy-handle = <&phy>; snps,txpbl = <0x4>; + clock_in_out = "output"; status = "disabled";
mdio {
From: Maximilian Luz luzmaximilian@gmail.com
[ Upstream commit 3dfaea3811f8b6a89a347e8da9ab862cdf3e30fe ]
ACPICA commit 1a3a549286ea9db07d7ec700e7a70dd8bcc4354e
The macros to classify different AML exception codes are broken. For instance,
ACPI_ENV_EXCEPTION(Status)
will always evaluate to zero due to
#define AE_CODE_ENVIRONMENTAL 0x0000 #define ACPI_ENV_EXCEPTION(Status) (Status & AE_CODE_ENVIRONMENTAL)
Similarly, ACPI_AML_EXCEPTION(Status) will evaluate to a non-zero value for error codes of type AE_CODE_PROGRAMMER, AE_CODE_ACPI_TABLES, as well as AE_CODE_AML, and not just AE_CODE_AML as the name suggests.
This commit fixes those checks.
Fixes: d46b6537f0ce ("ACPICA: AML Parser: ignore all exceptions resulting from incorrect AML during table load") Link: https://github.com/acpica/acpica/commit/1a3a5492 Signed-off-by: Maximilian Luz luzmaximilian@gmail.com Signed-off-by: Bob Moore robert.moore@intel.com Signed-off-by: Erik Kaneda erik.kaneda@intel.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/acpi/acexcep.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 2fc624a617690..f8a4afb0279a3 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -59,11 +59,11 @@ struct acpi_exception_info {
#define AE_OK (acpi_status) 0x0000
-#define ACPI_ENV_EXCEPTION(status) (status & AE_CODE_ENVIRONMENTAL) -#define ACPI_AML_EXCEPTION(status) (status & AE_CODE_AML) -#define ACPI_PROG_EXCEPTION(status) (status & AE_CODE_PROGRAMMER) -#define ACPI_TABLE_EXCEPTION(status) (status & AE_CODE_ACPI_TABLES) -#define ACPI_CNTL_EXCEPTION(status) (status & AE_CODE_CONTROL) +#define ACPI_ENV_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ENVIRONMENTAL) +#define ACPI_AML_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_AML) +#define ACPI_PROG_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_PROGRAMMER) +#define ACPI_TABLE_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ACPI_TABLES) +#define ACPI_CNTL_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_CONTROL)
/* * Environmental exceptions
From: Jack Pham jackp@codeaurora.org
[ Upstream commit 7de8681be2cde9f6953d3be1fa6ce05f9fe6e637 ]
As per the kernel doc for usb_ep_dequeue(), it states that "this routine is asynchronous, that is, it may return before the completion routine runs". And indeed since v5.0 the dwc3 gadget driver updated its behavior to place dequeued requests on to a cancelled list to be given back later after the endpoint is stopped.
The free_ep() was incorrectly assuming that a request was ready to be freed after calling dequeue which results in a use-after-free in dwc3 when it traverses its cancelled list. Fix this by moving the usb_ep_free_request() call to the callback itself in case the ep is disabled.
Fixes: eb9fecb9e69b0 ("usb: gadget: f_uac2: split out audio core") Reported-and-tested-by: Ferry Toth fntoth@gmail.com Reviewed-and-tested-by: Peter Chen peter.chen@nxp.com Acked-by: Felipe Balbi balbi@kernel.org Signed-off-by: Jack Pham jackp@codeaurora.org Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20210118084642.322510-2-jbrunet@baylibre.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/gadget/function/u_audio.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index e6d32c5367812..908e49dafd620 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -89,7 +89,12 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) struct snd_uac_chip *uac = prm->uac;
/* i/f shutting down */ - if (!prm->ep_enabled || req->status == -ESHUTDOWN) + if (!prm->ep_enabled) { + usb_ep_free_request(ep, req); + return; + } + + if (req->status == -ESHUTDOWN) return;
/* @@ -336,8 +341,14 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
for (i = 0; i < params->req_number; i++) { if (prm->ureq[i].req) { - usb_ep_dequeue(ep, prm->ureq[i].req); - usb_ep_free_request(ep, prm->ureq[i].req); + if (usb_ep_dequeue(ep, prm->ureq[i].req)) + usb_ep_free_request(ep, prm->ureq[i].req); + /* + * If usb_ep_dequeue() cannot successfully dequeue the + * request, the request will be freed by the completion + * callback. + */ + prm->ureq[i].req = NULL; } }
From: Robert Foss robert.foss@linaro.org
[ Upstream commit d4863ef399a29cae3001b3fedfd2864e651055ba ]
Switch reset pin of ov8856 node from GPIO_ACTIVE_HIGH to GPIO_ACTIVE_LOW, this issue prevented the ov8856 from probing properly as it did not respon to I2C messages.
Fixes: d4919a44564b ("arm64: dts: qcom: sdm845-db845c: Add ov8856 & ov7251 camera nodes")
Signed-off-by: Robert Foss robert.foss@linaro.org Link: https://lore.kernel.org/r/20201221100955.148584-1-robert.foss@linaro.org Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index c0b93813ea9ac..c4ac6f5dc008d 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -1114,11 +1114,11 @@ reg = <0x10>;
// CAM0_RST_N - reset-gpios = <&tlmm 9 0>; + reset-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&cam0_default>; gpios = <&tlmm 13 0>, - <&tlmm 9 0>; + <&tlmm 9 GPIO_ACTIVE_LOW>;
clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; clock-names = "xvclk";
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 5fb33d8960dc7abdabc6fe599a30c2c99b082ef6 ]
These need to be < ARRAY_SIZE() instead of <= ARRAY_SIZE() to prevent accessing one element beyond the end of the array.
Acked-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Reviewed-by: Douglas Anderson dianders@chromium.org Reviewed-by: Stephen Boyd swboyd@chromium.org Fixes: e9247e2ce577 ("soc: qcom: socinfo: fix printing of pmic_model") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/YAf+o85Z9lgkq3Nw@mwanda Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soc/qcom/socinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index d21530d24253e..6daa3c5771d16 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -286,7 +286,7 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p) if (model < 0) return -EINVAL;
- if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model]) + if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) seq_printf(seq, "%s\n", pmic_models[model]); else seq_printf(seq, "unknown (%d)\n", model);
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 17ad4662595ea0c4fd7496b664523ef632e63349 ]
'am33xx_pm_rtc_setup()' allocates some resources that must be freed on the error. Commit 2152fbbd47c0 ("soc: ti: pm33xx: Simplify RTC usage to prepare to drop platform data") has introduced the use of these resources but has only updated the remove function.
Fix the error handling path of the probe function now.
Fixes: 2152fbbd47c0 ("soc: ti: pm33xx: Simplify RTC usage to prepare to drop platform data") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Signed-off-by: Santosh Shilimkar santosh.shilimkar@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soc/ti/pm33xx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c index 64f3e31055401..7bab4bbaf02dc 100644 --- a/drivers/soc/ti/pm33xx.c +++ b/drivers/soc/ti/pm33xx.c @@ -535,7 +535,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
ret = am33xx_push_sram_idle(); if (ret) - goto err_free_sram; + goto err_unsetup_rtc;
am33xx_pm_set_ipc_ops();
@@ -575,6 +575,9 @@ err_pm_runtime_put: err_pm_runtime_disable: pm_runtime_disable(dev); wkup_m3_ipc_put(m3_ipc); +err_unsetup_rtc: + iounmap(rtc_base_virt); + clk_put(rtc_fck); err_free_sram: am33xx_pm_free_sram(); pm33xx_dev = NULL;
From: Borislav Petkov bp@suse.de
[ Upstream commit bfe21ef195a9f2785747e698dfd19f75554e2d91 ]
Fix this build warning on 32-bit:
drivers/staging/media/atomisp/pci/hmm/hmm.c: In function ‘hmm_alloc’: drivers/staging/media/atomisp/pci/hmm/hmm.c:272:3: warning: format ‘%ld’ \ expects argument of type ‘long int’, but argument 6 has type ‘size_t {aka unsigned int}’ [-Wformat=] "%s: pages: 0x%08x (%ld bytes), type: %d from highmem %d, user ptr %p, cached %d\n", ^
Fixes: 03884c93560c ("media: atomisp: add debug for hmm alloc") Cc: Mauro Carvalho Chehab mchehab@kernel.org Cc: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Borislav Petkov bp@suse.de Link: https://lore.kernel.org/r/20201126181150.10576-1-bp@alien8.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm.c b/drivers/staging/media/atomisp/pci/hmm/hmm.c index e0eaff0f8a228..6a5ee46070898 100644 --- a/drivers/staging/media/atomisp/pci/hmm/hmm.c +++ b/drivers/staging/media/atomisp/pci/hmm/hmm.c @@ -269,7 +269,7 @@ ia_css_ptr hmm_alloc(size_t bytes, enum hmm_bo_type type, hmm_set(bo->start, 0, bytes);
dev_dbg(atomisp_dev, - "%s: pages: 0x%08x (%ld bytes), type: %d from highmem %d, user ptr %p, cached %d\n", + "%s: pages: 0x%08x (%zu bytes), type: %d from highmem %d, user ptr %p, cached %d\n", __func__, bo->start, bytes, type, from_highmem, userptr, cached);
return bo->start;
From: Pan Bian bianpan2016@163.com
[ Upstream commit 5a3ef03afe7e12982dc3b978f4c5077c907f7501 ]
Call hci_dev_put() to decrement reference count of HCI device hdev if fails to duplicate memory.
Fixes: 0b26ab9dce74 ("Bluetooth: AMP: Handle Accept phylink command status evt") Signed-off-by: Pan Bian bianpan2016@163.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/a2mp.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index cc26e4c047ad0..463bad58478b2 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -512,6 +512,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL); if (!assoc) { amp_ctrl_put(ctrl); + hci_dev_put(hdev); return -ENOMEM; }
From: Pan Bian bianpan2016@163.com
[ Upstream commit 28a758c861ff290e39d4f1ee0aa5df0f0b9a45ee ]
Jump to the label done to decrement the reference count of HCI device hdev on path that the Inquiry procedure is interrupted.
Fixes: 3e13fa1e1fab ("Bluetooth: Fix hci_inquiry ioctl usage") Signed-off-by: Pan Bian bianpan2016@163.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9d2c9a1c552fd..9f8573131b97e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1362,8 +1362,10 @@ int hci_inquiry(void __user *arg) * cleared). If it is interrupted by a signal, return -EINTR. */ if (wait_on_bit(&hdev->flags, HCI_INQUIRY, - TASK_INTERRUPTIBLE)) - return -EINTR; + TASK_INTERRUPTIBLE)) { + err = -EINTR; + goto done; + } }
/* for unlimited number of responses we will use buffer with
From: Pan Bian bianpan2016@163.com
[ Upstream commit 94e9dd43cf327366388c8f146bccdc6322c0d999 ]
Call of_node_put() to decrement the reference count of the child node child_np when jumping out of the loop body of for_each_available_child_of_node(), which is a macro that increments and decrements the reference count of child node. If the loop is broken, the reference of the child node should be dropped manually.
Fixes: 5a7c81547c1d ("memory: ti-aemif: introduce AEMIF driver") Signed-off-by: Pan Bian bianpan2016@163.com Link: https://lore.kernel.org/r/20210121090359.61763-1-bianpan2016@163.com Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/memory/ti-aemif.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index 159a16f5e7d67..51d20c2ccb755 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -378,8 +378,10 @@ static int aemif_probe(struct platform_device *pdev) */ for_each_available_child_of_node(np, child_np) { ret = of_aemif_parse_abus_config(pdev, child_np); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata && pdata->num_abus_data > 0) { for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) { @@ -405,8 +407,10 @@ static int aemif_probe(struct platform_device *pdev) for_each_available_child_of_node(np, child_np) { ret = of_platform_populate(child_np, NULL, dev_lookup, dev); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata) { for (i = 0; i < pdata->num_sub_devices; i++) {
From: Tony Lindgren tony@atomide.com
[ Upstream commit 44f416879a442600b006ef7dec3a6dc98bcf59c6 ]
We have gpio_86 wired internally to the bandgap thermal shutdown interrupt on 4430 like we have it on 4460 according to the TRM. This can be found easily by searching for TSHUT.
For some reason the thermal shutdown interrupt was never added for 4430, let's add it. I believe this is needed for the thermal shutdown interrupt handler ti_bandgap_tshut_irq_handler() to call orderly_poweroff().
Fixes: aa9bb4bb8878 ("arm: dts: add omap4430 thermal data") Cc: Carl Philipp Klemm philipp@uvos.xyz Cc: Daniel Lezcano daniel.lezcano@linaro.org Cc: Eduardo Valentin edubezval@gmail.com Cc: Merlijn Wajer merlijn@wizzup.org Cc: Pavel Machek pavel@ucw.cz Cc: Peter Ujfalusi peter.ujfalusi@gmail.com Cc: Sebastian Reichel sre@kernel.org Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/omap443x.dtsi | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi index cb309743de5da..dd8ef58cbaed4 100644 --- a/arch/arm/boot/dts/omap443x.dtsi +++ b/arch/arm/boot/dts/omap443x.dtsi @@ -33,10 +33,12 @@ };
ocp { + /* 4430 has only gpio_86 tshut and no talert interrupt */ bandgap: bandgap@4a002260 { reg = <0x4a002260 0x4 0x4a00232C 0x4>; compatible = "ti,omap4430-bandgap"; + gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
#thermal-sensor-cells = <0>; };
From: Guenter Roeck linux@roeck-us.net
[ Upstream commit 415fa1c7305dedbb345e2cc8ac91769bc1c83f1a ]
The DWC2 documentation states that transfers with zero data length should set the number of packets to 1 and the transfer length to 0. This is not currently the case for inbound transfers: the transfer length is set to the maximum packet length. This can have adverse effects if the chip actually does transfer data as it is programmed to do. Follow chip documentation and keep the transfer length set to 0 in that situation.
Fixes: 56f5b1cff22a1 ("staging: Core files for the DWC2 driver") Tested-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Reviewed-by: Douglas Anderson dianders@chromium.org Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Link: https://lore.kernel.org/r/20210113112052.17063-2-nsaenzjulienne@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc2/hcd.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index e9ac215b96633..fc3269f5faf19 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1313,19 +1313,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, if (num_packets > max_hc_pkt_count) { num_packets = max_hc_pkt_count; chan->xfer_len = num_packets * chan->max_packet; + } else if (chan->ep_is_in) { + /* + * Always program an integral # of max packets + * for IN transfers. + * Note: This assumes that the input buffer is + * aligned and sized accordingly. + */ + chan->xfer_len = num_packets * chan->max_packet; } } else { /* Need 1 packet for transfer length of 0 */ num_packets = 1; }
- if (chan->ep_is_in) - /* - * Always program an integral # of max packets for IN - * transfers - */ - chan->xfer_len = num_packets * chan->max_packet; - if (chan->ep_type == USB_ENDPOINT_XFER_INT || chan->ep_type == USB_ENDPOINT_XFER_ISOC) /*
From: Guenter Roeck linux@roeck-us.net
[ Upstream commit f74b68c61cbc4b2245022fcce038509333d63f6f ]
In some situations, the following error messages are reported.
dwc2 ff540000.usb: dwc2_hc_chhltd_intr_dma: Channel 1 - ChHltd set, but reason is unknown dwc2 ff540000.usb: hcint 0x00000002, intsts 0x04000021
This is sometimes followed by:
dwc2 ff540000.usb: dwc2_update_urb_state_abn(): trimming xfer length
and then:
WARNING: CPU: 0 PID: 0 at kernel/v4.19/drivers/usb/dwc2/hcd.c:2913 dwc2_assign_and_init_hc+0x98c/0x990
The warning suggests that an odd buffer address is to be used for DMA.
After an error is observed, the receive buffer may be full (urb->actual_length >= urb->length). However, the urb is still left in the queue unless three errors were observed in a row. When it is queued again, the dwc2 hcd code translates this into a 1-block transfer. If urb->actual_length (ie the total expected receive length) is not DMA-aligned, the buffer pointer programmed into the chip will be unaligned. This results in the observed warning.
To solve the problem, abort input transactions after an error with unknown cause if the entire packet was already received. This may be a bit drastic, but we don't really know why the transfer was aborted even though the entire packet was received. Aborting the transfer in this situation is less risky than accepting a potentially corrupted packet.
With this patch in place, the 'ChHltd set' and 'trimming xfer length' messages are still observed, but there are no more transfer attempts with odd buffer addresses.
Fixes: 151d0cbdbe860 ("usb: dwc2: make the scheduler handle excessive NAKs better") Cc: Boris ARZUR boris@konbu.org Cc: Douglas Anderson dianders@chromium.org Tested-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Reviewed-by: Douglas Anderson dianders@chromium.org Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Link: https://lore.kernel.org/r/20210113112052.17063-3-nsaenzjulienne@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc2/hcd_intr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index a052d39b4375e..12819e019e13c 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -1977,6 +1977,18 @@ error: qtd->error_count++; dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb, qtd, DWC2_HC_XFER_XACT_ERR); + /* + * We can get here after a completed transaction + * (urb->actual_length >= urb->length) which was not reported + * as completed. If that is the case, and we do not abort + * the transfer, a transfer of size 0 will be enqueued + * subsequently. If urb->actual_length is not DMA-aligned, + * the buffer will then point to an unaligned address, and + * the resulting behavior is undefined. Bail out in that + * situation. + */ + if (qtd->urb->actual_length >= qtd->urb->length) + qtd->error_count = 3; dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR); }
From: Guenter Roeck linux@roeck-us.net
[ Upstream commit 1a9e38cabd80356ffb98c2c88fec528ea9644fd5 ]
With some USB network adapters, such as DM96xx, the following message is seen for each maximum size receive packet.
dwc2 ff540000.usb: dwc2_update_urb_state(): trimming xfer length
This happens because the packet size requested by the driver is 1522 bytes, wMaxPacketSize is 64, the dwc2 driver configures the chip to receive 24*64 = 1536 bytes, and the chip does indeed send more than 1522 bytes of data. Since the event does not indicate an error condition, the message is just noise. Demote it to debug level.
Fixes: 7359d482eb4d3 ("staging: HCD files for the DWC2 driver") Tested-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Reviewed-by: Douglas Anderson dianders@chromium.org Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de Link: https://lore.kernel.org/r/20210113112052.17063-4-nsaenzjulienne@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc2/hcd_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 12819e019e13c..d5f4ec1b73b15 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -500,7 +500,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, &short_read);
if (urb->actual_length + xfer_length > urb->length) { - dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__); + dev_dbg(hsotg->dev, "%s(): trimming xfer length\n", __func__); xfer_length = urb->length - urb->actual_length; }
From: Chen-Yu Tsai wens@csie.org
[ Upstream commit 61834c967a929f6b4b7fcb91f43fa225cc29aa19 ]
The custom regulatory ruleset in the rtl8723bs driver lists an incorrect number of rules: one too many. This results in an out-of-bounds access, as detected by KASAN. This was possible thanks to the newly added support for KASAN on ARMv7.
Fix this by filling in the correct number of rules given.
KASAN report:
================================================================== BUG: KASAN: global-out-of-bounds in cfg80211_does_bw_fit_range+0x14/0x4c [cfg80211] Read of size 4 at addr bf20c254 by task ip/971
CPU: 2 PID: 971 Comm: ip Tainted: G C 5.11.0-rc2-00020-gf7fe528a7ebe #1 Hardware name: Allwinner sun8i Family [<c0113338>] (unwind_backtrace) from [<c010e8a4>] (show_stack+0x10/0x14) [<c010e8a4>] (show_stack) from [<c0e0f868>] (dump_stack+0x9c/0xb4) [<c0e0f868>] (dump_stack) from [<c0388284>] (print_address_description.constprop.2+0x1dc/0x2dc) [<c0388284>] (print_address_description.constprop.2) from [<c03885cc>] (kasan_report+0x1a8/0x1c4) [<c03885cc>] (kasan_report) from [<bf00a354>] (cfg80211_does_bw_fit_range+0x14/0x4c [cfg80211]) [<bf00a354>] (cfg80211_does_bw_fit_range [cfg80211]) from [<bf00b41c>] (freq_reg_info_regd.part.6+0x108/0x124 [> [<bf00b41c>] (freq_reg_info_regd.part.6 [cfg80211]) from [<bf00df00>] (handle_channel_custom.constprop.12+0x48/> [<bf00df00>] (handle_channel_custom.constprop.12 [cfg80211]) from [<bf00e150>] (wiphy_apply_custom_regulatory+0> [<bf00e150>] (wiphy_apply_custom_regulatory [cfg80211]) from [<bf1fb9e8>] (rtw_regd_init+0x60/0x70 [r8723bs]) [<bf1fb9e8>] (rtw_regd_init [r8723bs]) from [<bf1ee5a8>] (rtw_cfg80211_init_wiphy+0x164/0x1e8 [r8723bs]) [<bf1ee5a8>] (rtw_cfg80211_init_wiphy [r8723bs]) from [<bf1f8d50>] (_netdev_open+0xe4/0x28c [r8723bs]) [<bf1f8d50>] (_netdev_open [r8723bs]) from [<bf1f8f58>] (netdev_open+0x60/0x88 [r8723bs]) [<bf1f8f58>] (netdev_open [r8723bs]) from [<c0bb3730>] (__dev_open+0x178/0x220) [<c0bb3730>] (__dev_open) from [<c0bb3cdc>] (__dev_change_flags+0x258/0x2c4) [<c0bb3cdc>] (__dev_change_flags) from [<c0bb3d88>] (dev_change_flags+0x40/0x80) [<c0bb3d88>] (dev_change_flags) from [<c0bc86fc>] (do_setlink+0x538/0x1160) [<c0bc86fc>] (do_setlink) from [<c0bcf9e8>] (__rtnl_newlink+0x65c/0xad8) [<c0bcf9e8>] (__rtnl_newlink) from [<c0bcfeb0>] (rtnl_newlink+0x4c/0x6c) [<c0bcfeb0>] (rtnl_newlink) from [<c0bc67c8>] (rtnetlink_rcv_msg+0x1f8/0x454) [<c0bc67c8>] (rtnetlink_rcv_msg) from [<c0c330e4>] (netlink_rcv_skb+0xc4/0x1e0) [<c0c330e4>] (netlink_rcv_skb) from [<c0c32478>] (netlink_unicast+0x2c8/0x3c4) [<c0c32478>] (netlink_unicast) from [<c0c32894>] (netlink_sendmsg+0x320/0x5f0) [<c0c32894>] (netlink_sendmsg) from [<c0b75eb0>] (____sys_sendmsg+0x320/0x3e0) [<c0b75eb0>] (____sys_sendmsg) from [<c0b78394>] (___sys_sendmsg+0xe8/0x12c) [<c0b78394>] (___sys_sendmsg) from [<c0b78a50>] (__sys_sendmsg+0xc0/0x120) [<c0b78a50>] (__sys_sendmsg) from [<c0100060>] (ret_fast_syscall+0x0/0x58) Exception stack(0xc5693fa8 to 0xc5693ff0) 3fa0: 00000074 c7a39800 00000003 b6cee648 00000000 00000000 3fc0: 00000074 c7a39800 00000001 00000128 78d18349 00000000 b6ceeda0 004f7cb0 3fe0: 00000128 b6cee5e8 aeca151f aec1d746
The buggy address belongs to the variable: rtw_drv_halt+0xf908/0x6b4 [r8723bs]
Memory state around the buggy address: bf20c100: 00 00 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9 f9 bf20c180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bf20c200: 00 00 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9 f9
^ bf20c280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 bf20c300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ==================================================================
Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") Signed-off-by: Chen-Yu Tsai wens@csie.org Link: https://lore.kernel.org/r/20210108141401.31741-1-wens@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index 2833fc6901e6e..3f04b7a954ba0 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -34,7 +34,7 @@ NL80211_RRF_PASSIVE_SCAN)
static const struct ieee80211_regdomain rtw_regdom_rd = { - .n_reg_rules = 3, + .n_reg_rules = 2, .alpha2 = "99", .reg_rules = { RTW_2GHZ_CH01_11,
From: Misono Tomohiro misono.tomohiro@jp.fujitsu.com
[ Upstream commit 02a16aa13574c8526beadfc9ae8cc9b66315fa2d ]
Commit
a7e1f67ed29f ("x86/msr: Filter MSR writes")
introduced a module parameter to disable writing to the MSR device file and tainted the kernel upon writing. As MSR registers can be written by the X86_IOC_WRMSR_REGS ioctl too, the same filtering and tainting should be applied to the ioctl as well.
[ bp: Massage commit message and space out statements. ]
Fixes: a7e1f67ed29f ("x86/msr: Filter MSR writes") Signed-off-by: Misono Tomohiro misono.tomohiro@jp.fujitsu.com Signed-off-by: Borislav Petkov bp@suse.de Link: https://lkml.kernel.org/r/20210127122456.13939-1-misono.tomohiro@jp.fujitsu.... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kernel/msr.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 8a67d1fa8dc58..ed8ac6bcbafb2 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -182,6 +182,13 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) err = security_locked_down(LOCKDOWN_MSR); if (err) break; + + err = filter_write(regs[1]); + if (err) + return err; + + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + err = wrmsr_safe_regs_on_cpu(cpu, regs); if (err) break;
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 74477936a828a7c91a61ba7e625b7ce2299c8c98 ]
"make dtbs_check" fails with:
arch/arm64/boot/dts/renesas/r8a774b1-beacon-rzg2n-kit.dt.yaml: eeprom@50: compatible: 'oneOf' conditional failed, one must be fixed: 'microchip,at24c64' does not match '^(atmel|catalyst|microchip|nxp|ramtron|renesas|rohm|st),(24(c|cs|lc|mac)[0-9]+|spd)$'
Fix this by dropping the bogus "at" prefix.
Fixes: a1d8a344f1ca0709 ("arm64: dts: renesas: Introduce r8a774a1-beacon-rzg2m-kit") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Link: https://lore.kernel.org/r/20210128110136.2293490-1-geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi index b93219a95afcd..ea937a926c0e3 100644 --- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi +++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi @@ -148,7 +148,7 @@ };
eeprom@50 { - compatible = "microchip,at24c64", "atmel,24c64"; + compatible = "microchip,24c64", "atmel,24c64"; pagesize = <32>; read-only; /* Manufacturing EEPROM programmed at factory */ reg = <0x50>;
From: Marc Kleine-Budde mkl@pengutronix.de
[ Upstream commit 28eb119c042e8d3420b577b5b3ea851a111e7b2d ]
This patch fixes the reference to the errata for both the mcp2517fd and the mcp2518fd.
Fixes: f5b84dedf7eb ("can: mcp25xxfd: mcp25xxfd_probe(): add SPI clk limit related errata information") Link: https://lore.kernel.org/r/20210128104644.2982125-2-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index f07e8b737d31e..ee39e79927efb 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -2901,7 +2901,7 @@ static int mcp251xfd_probe(struct spi_device *spi) spi_get_device_id(spi)->driver_data;
/* Errata Reference: - * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 4. + * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789C 4. * * The SPI can write corrupted data to the RAM at fast SPI * speeds:
From: Rosen Penev rosenp@gmail.com
[ Upstream commit e011c9025a4691b5c734029577a920bd6c320994 ]
Split up the pins to match earlier definitions. Allows LEDs to flash properly.
Fixes: ced8025b569e ("ARM: dts: armada388-helios4")
Signed-off-by: Rosen Penev rosenp@gmail.com Signed-off-by: Gregory CLEMENT gregory.clement@bootlin.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/armada-388-helios4.dts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts index b3728de3bd3fa..5a6af7e83e445 100644 --- a/arch/arm/boot/dts/armada-388-helios4.dts +++ b/arch/arm/boot/dts/armada-388-helios4.dts @@ -70,6 +70,9 @@
system-leds { compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&helios_system_led_pins>; + status-led { label = "helios4:green:status"; gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; @@ -86,6 +89,9 @@
io-leds { compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&helios_io_led_pins>; + sata1-led { label = "helios4:green:ata1"; gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; @@ -286,9 +292,12 @@ "mpp39", "mpp40"; marvell,function = "sd0"; }; - helios_led_pins: helios-led-pins { - marvell,pins = "mpp24", "mpp25", - "mpp49", "mpp50", + helios_system_led_pins: helios-system-led-pins { + marvell,pins = "mpp24", "mpp25"; + marvell,function = "gpio"; + }; + helios_io_led_pins: helios-io-led-pins { + marvell,pins = "mpp49", "mpp50", "mpp52", "mpp53", "mpp54"; marvell,function = "gpio";
From: Rosen Penev rosenp@gmail.com
[ Upstream commit 46ecdfc1830eaa40a11d7f832089c82b0e67ea96 ]
Split up the pins for each fan. This is needed in order to control them
Fixes: ced8025b569e ("ARM: dts: armada388-helios4")
Signed-off-by: Rosen Penev rosenp@gmail.com Signed-off-by: Gregory CLEMENT gregory.clement@bootlin.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/armada-388-helios4.dts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts index 5a6af7e83e445..ec134e22bae3e 100644 --- a/arch/arm/boot/dts/armada-388-helios4.dts +++ b/arch/arm/boot/dts/armada-388-helios4.dts @@ -127,11 +127,15 @@ fan1: j10-pwm { compatible = "pwm-fan"; pwms = <&gpio1 9 40000>; /* Target freq:25 kHz */ + pinctrl-names = "default"; + pinctrl-0 = <&helios_fan1_pins>; };
fan2: j17-pwm { compatible = "pwm-fan"; pwms = <&gpio1 23 40000>; /* Target freq:25 kHz */ + pinctrl-names = "default"; + pinctrl-0 = <&helios_fan2_pins>; };
usb2_phy: usb2-phy { @@ -302,9 +306,12 @@ "mpp54"; marvell,function = "gpio"; }; - helios_fan_pins: helios-fan-pins { - marvell,pins = "mpp41", "mpp43", - "mpp48", "mpp55"; + helios_fan1_pins: helios_fan1_pins { + marvell,pins = "mpp41", "mpp43"; + marvell,function = "gpio"; + }; + helios_fan2_pins: helios_fan2_pins { + marvell,pins = "mpp48", "mpp55"; marvell,function = "gpio"; }; microsom_spi1_cs_pins: spi1-cs-pins {
From: Marek Behún kabel@kernel.org
[ Upstream commit a9d9bfcadfb43b856dbcf9419de75f7420d5a225 ]
The partition called "u-boot" in reality contains TF-A and U-Boot, and TF-A is before U-Boot.
Rename this parition to "a53-firmware" to avoid confusion for users, since they cannot simply build U-Boot from U-Boot repository and flash the resulting image there. Instead they have to build the firmware with the sources from the mox-boot-builder repository [1] and flash the a53-firmware.bin binary there.
[1] https://gitlab.nic.cz/turris/mox-boot-builder
Signed-off-by: Marek Behún kabel@kernel.org Fixes: 7109d817db2e ("arm64: dts: marvell: add DTS for Turris Mox") Cc: Gregory CLEMENT gregory.clement@bootlin.com Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Gregory CLEMENT gregory.clement@bootlin.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts index f5ec3b6447692..d239ab70ed995 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts @@ -205,7 +205,7 @@ };
partition@20000 { - label = "u-boot"; + label = "a53-firmware"; reg = <0x20000 0x160000>; };
From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit d7b9d9b31a3e55dcc9b5c289abfafe31efa5b5c4 ]
The debug message always prints rate=0 instead of a proper value, fix it.
Fixes: 6c591eec67cb ("OPP: Add helpers for reading the binding properties") Tested-by: Peter Geis pgwipeout@gmail.com Tested-by: Nicolas Chauvet kwizart@gmail.com Tested-by: Matt Merhar mattmerhar@protonmail.com Signed-off-by: Dmitry Osipenko digetx@gmail.com [ Viresh: Added Fixes tag ] Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/opp/of.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 03cb387236c4c..d0c0336be39b4 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -755,7 +755,6 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, struct device *dev, struct device_node *np) { struct dev_pm_opp *new_opp; - u64 rate = 0; u32 val; int ret; bool rate_not_available = false; @@ -772,7 +771,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
/* Check if the OPP supports hardware's hierarchy of versions or not */ if (!_opp_is_supported(dev, opp_table, np)) { - dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate); + dev_dbg(dev, "OPP not supported by hardware: %lu\n", + new_opp->rate); goto free_opp; }
From: Jupeng Zhong zhongjupeng@yulong.com
[ Upstream commit de71a6cb4bf24d8993b9ca90d1ddb131b60251a1 ]
In btusb_mtk_wmt_recv if skb_clone fails, the alocated skb should be released.
Omit the labels “err_out” and “err_free_skb” in this function implementation so that the desired exception handling code would be directly specified in the affected if branches.
Fixes: a1c49c434e15 ("btusb: Add protocol support for MediaTek MT7668U USB devices") Signed-off-by: Jupeng Zhong zhongjupeng@yulong.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index da57c561642c4..a4f834a50a988 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3195,7 +3195,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC); if (!skb) { hdev->stat.err_rx++; - goto err_out; + return; }
hci_skb_pkt_type(skb) = HCI_EVENT_PKT; @@ -3213,13 +3213,18 @@ static void btusb_mtk_wmt_recv(struct urb *urb) */ if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) { data->evt_skb = skb_clone(skb, GFP_ATOMIC); - if (!data->evt_skb) - goto err_out; + if (!data->evt_skb) { + kfree_skb(skb); + return; + } }
err = hci_recv_frame(hdev, skb); - if (err < 0) - goto err_free_skb; + if (err < 0) { + kfree_skb(data->evt_skb); + data->evt_skb = NULL; + return; + }
if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) { @@ -3228,11 +3233,6 @@ static void btusb_mtk_wmt_recv(struct urb *urb) wake_up_bit(&data->flags, BTUSB_TX_WAIT_VND_EVT); } -err_out: - return; -err_free_skb: - kfree_skb(data->evt_skb); - data->evt_skb = NULL; return; } else if (urb->status == -ENOENT) { /* Avoid suspend failed when usb_kill_urb */
From: Luca Weiss luca@z3ntu.xyz
[ Upstream commit 01f937ffc4686837d6c43dea80c6ade6cbd2940a ]
If ocmem probe fails for whatever reason, of_get_ocmem returned NULL. Without this, users must check for both NULL and IS_ERR on the returned pointer - which didn't happen in drivers/gpu/drm/msm/adreno/adreno_gpu.c leading to a NULL pointer dereference.
Reviewed-by: Brian Masney masneyb@onstation.org Fixes: 88c1e9404f1d ("soc: qcom: add OCMEM driver") Signed-off-by: Luca Weiss luca@z3ntu.xyz Link: https://lore.kernel.org/r/20210130142349.53335-1-luca@z3ntu.xyz Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soc/qcom/ocmem.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 7f9e9944d1eae..f1875dc31ae2c 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -189,6 +189,7 @@ struct ocmem *of_get_ocmem(struct device *dev) { struct platform_device *pdev; struct device_node *devnode; + struct ocmem *ocmem;
devnode = of_parse_phandle(dev->of_node, "sram", 0); if (!devnode || !devnode->parent) { @@ -202,7 +203,12 @@ struct ocmem *of_get_ocmem(struct device *dev) return ERR_PTR(-EPROBE_DEFER); }
- return platform_get_drvdata(pdev); + ocmem = platform_get_drvdata(pdev); + if (!ocmem) { + dev_err(dev, "Cannot get ocmem\n"); + return ERR_PTR(-ENODEV); + } + return ocmem; } EXPORT_SYMBOL(of_get_ocmem);
From: Vincent Knecht vincent.knecht@mailoo.org
[ Upstream commit d5ae2528b0b56cf054b27d48b0cb85330900082f ]
Fix `reserved` and `rfsa` unit address according to their reg address
Fixes: 7258e10e6a0b ("ARM: dts: msm8916: Update reserved-memory")
Signed-off-by: Vincent Knecht vincent.knecht@mailoo.org Link: https://lore.kernel.org/r/20210123104417.518105-1-vincent.knecht@mailoo.org Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 402e891a84ab6..d25f6dc751e99 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -56,7 +56,7 @@ no-map; };
- reserved@8668000 { + reserved@86680000 { reg = <0x0 0x86680000 0x0 0x80000>; no-map; }; @@ -69,7 +69,7 @@ qcom,client-id = <1>; };
- rfsa@867e00000 { + rfsa@867e0000 { reg = <0x0 0x867e0000 0x0 0x20000>; no-map; };
From: Artem Lapkin email2tema@gmail.com
[ Upstream commit 39be8f441f78908e97ff913571e10ec03387a63a ]
move &sd_emmc_a ... from /* */ commented area, because cant load wifi fw without sd-uhs-sdr50 option on VIM3L
[ 11.686590] brcmfmac: brcmf_chip_cores_check: CPU core not detected [ 11.696382] brcmfmac: brcmf_sdio_probe_attach: brcmf_chip_attach failed! [ 11.706240] brcmfmac: brcmf_sdio_probe: brcmf_sdio_probe_attach failed [ 11.715890] brcmfmac: brcmf_ops_sdio_probe: F2 error, probe failed -19... [ 13.718424] brcmfmac: brcmf_chip_recognition: chip backplane type 15 is not supported
Signed-off-by: Artem Lapkin art@khadas.com Fixes: f1bb924e8f5b ("arm64: dts: meson: fix mmc0 tuning error on Khadas VIM3") Reviewed-by: Neil Armstrong narmstrong@baylibre.com Signed-off-by: Kevin Hilman khilman@baylibre.com Link: https://lore.kernel.org/r/20210129085041.1408540-1-art@khadas.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts index 4b517ca720597..06de0b1ce7267 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts @@ -89,13 +89,12 @@ status = "okay"; };
-&sd_emmc_a { - sd-uhs-sdr50; -}; - &usb { phys = <&usb2_phy0>, <&usb2_phy1>; phy-names = "usb2-phy0", "usb2-phy1"; }; */
+&sd_emmc_a { + sd-uhs-sdr50; +};
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit efaa85cf2294d5e10a724e24356507eeb3836f72 ]
When version 2 of the PER_PLATFORM_ANT_GAIN_CMD was implemented, we started copying the values from the command that we have stored into a local instance. But we accidentally forgot to copy the enabled flag, so in practice PPAG is never really enabled. Fix this by copying the flag from our stored data a we should.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: f2134f66f40e ("iwlwifi: acpi: support ppag table command v2") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210131201908.24d7bf754ad5.I0e8abc2b87475... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 313e9f106f465..9e150c01f7b37 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -997,6 +997,8 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) return 0; }
+ ppag_table.v1.enabled = mvm->fwrt.ppag_table.v1.enabled; + cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD, IWL_FW_CMD_VER_UNKNOWN);
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 7f9942c61fa60eda7cc8e42f04bd25b7d175876e ]
Building with the clang integrated assembler produces a couple of errors for the s3c24xx fiq support:
arch/arm/mach-s3c/irq-s3c24xx-fiq.S:52:2: error: instruction 'subne' can not set flags, but 's' suffix specified subnes pc, lr, #4 @@ return, still have work to do
arch/arm/mach-s3c/irq-s3c24xx-fiq.S:64:1: error: invalid symbol redefinition s3c24xx_spi_fiq_txrx:
There are apparently two problems: one with extraneous or duplicate labels, and one with old-style opcode mnemonics. Stefan Agner has previously fixed other problems like this, but missed this particular file.
Fixes: bec0806cfec6 ("spi_s3c24xx: add FIQ pseudo-DMA support") Cc: Stefan Agner stefan@agner.ch Signed-off-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Nick Desaulniers ndesaulniers@google.com Reviewed-by: Nathan Chancellor nathan@kernel.org Link: https://lore.kernel.org/r/20210204162416.3030114-1-arnd@kernel.org Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-s3c/irq-s3c24xx-fiq.S b/arch/arm/mach-s3c/irq-s3c24xx-fiq.S index b54cbd0122413..5d238d9a798e1 100644 --- a/arch/arm/mach-s3c/irq-s3c24xx-fiq.S +++ b/arch/arm/mach-s3c/irq-s3c24xx-fiq.S @@ -35,7 +35,6 @@ @ and an offset to the irq acknowledgment word
ENTRY(s3c24xx_spi_fiq_rx) -s3c24xx_spi_fix_rx: .word fiq_rx_end - fiq_rx_start .word fiq_rx_irq_ack - fiq_rx_start fiq_rx_start: @@ -49,7 +48,7 @@ fiq_rx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do
@@ set IRQ controller so that next op will trigger IRQ mov fiq_rtmp, #0 @@ -61,7 +60,6 @@ fiq_rx_irq_ack: fiq_rx_end:
ENTRY(s3c24xx_spi_fiq_txrx) -s3c24xx_spi_fiq_txrx: .word fiq_txrx_end - fiq_txrx_start .word fiq_txrx_irq_ack - fiq_txrx_start fiq_txrx_start: @@ -76,7 +74,7 @@ fiq_txrx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do
mov fiq_rtmp, #0 str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ] @@ -88,7 +86,6 @@ fiq_txrx_irq_ack: fiq_txrx_end:
ENTRY(s3c24xx_spi_fiq_tx) -s3c24xx_spi_fix_tx: .word fiq_tx_end - fiq_tx_start .word fiq_tx_irq_ack - fiq_tx_start fiq_tx_start: @@ -101,7 +98,7 @@ fiq_tx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do
mov fiq_rtmp, #0 str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ]
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 67bc809752796acb2641ca343cad5b45eef31d7c ]
Storing a bogus i2c_client structure on the stack adds overhead and causes a compile-time warning:
drivers/tee/optee/rpc.c:493:6: error: stack frame size of 1056 bytes in function 'optee_handle_rpc' [-Werror,-Wframe-larger-than=] void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
Change the implementation of handle_rpc_func_cmd_i2c_transfer() to open-code the i2c_transfer() call, which makes it easier to read and avoids the warning.
Fixes: c05210ab9757 ("drivers: optee: allow op-tee to access devices on the i2c bus") Tested-by: Jorge Ramirez-Ortiz jorge@foundries.io Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Jens Wiklander jens.wiklander@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tee/optee/rpc.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index 1e3614e4798f0..6cbb3643c6c48 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -54,8 +54,9 @@ bad: static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, struct optee_msg_arg *arg) { - struct i2c_client client = { 0 }; struct tee_param *params; + struct i2c_adapter *adapter; + struct i2c_msg msg = { }; size_t i; int ret = -EOPNOTSUPP; u8 attr[] = { @@ -85,48 +86,48 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx, goto bad; }
- client.adapter = i2c_get_adapter(params[0].u.value.b); - if (!client.adapter) + adapter = i2c_get_adapter(params[0].u.value.b); + if (!adapter) goto bad;
if (params[1].u.value.a & OPTEE_MSG_RPC_CMD_I2C_FLAGS_TEN_BIT) { - if (!i2c_check_functionality(client.adapter, + if (!i2c_check_functionality(adapter, I2C_FUNC_10BIT_ADDR)) { - i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); goto bad; }
- client.flags = I2C_CLIENT_TEN; + msg.flags = I2C_M_TEN; }
- client.addr = params[0].u.value.c; - snprintf(client.name, I2C_NAME_SIZE, "i2c%d", client.adapter->nr); + msg.addr = params[0].u.value.c; + msg.buf = params[2].u.memref.shm->kaddr; + msg.len = params[2].u.memref.size;
switch (params[0].u.value.a) { case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD: - ret = i2c_master_recv(&client, params[2].u.memref.shm->kaddr, - params[2].u.memref.size); + msg.flags |= I2C_M_RD; break; case OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR: - ret = i2c_master_send(&client, params[2].u.memref.shm->kaddr, - params[2].u.memref.size); break; default: - i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); goto bad; }
+ ret = i2c_transfer(adapter, &msg, 1); + if (ret < 0) { arg->ret = TEEC_ERROR_COMMUNICATION; } else { - params[3].u.value.a = ret; + params[3].u.value.a = msg.len; if (optee_to_msg_param(arg->params, arg->num_params, params)) arg->ret = TEEC_ERROR_BAD_PARAMETERS; else arg->ret = TEEC_SUCCESS; }
- i2c_put_adapter(client.adapter); + i2c_put_adapter(adapter); kfree(params); return; bad:
From: Jérôme Pouiller jerome.pouiller@silabs.com
[ Upstream commit 26df933d9b83ea668304dc4ec641d52ea1fc4091 ]
When the firmware rejects a frame (because station become asleep or disconnected), the frame is re-queued in mac80211. However, the re-queued frame was 8 bytes longer than the original one (the size of the ICV for the encryption). So, when mac80211 try to send this frame again, it is a little bigger than expected. If the frame is re-queued secveral time it end with a skb_over_panic because the skb buffer is not large enough.
Note it only happens when device acts as an AP and encryption is enabled.
This patch more or less reverts the commit 049fde130419 ("staging: wfx: drop useless field from struct wfx_tx_priv").
Fixes: 049fde130419 ("staging: wfx: drop useless field from struct wfx_tx_priv") Signed-off-by: Jérôme Pouiller jerome.pouiller@silabs.com Link: https://lore.kernel.org/r/20210208135254.399964-1-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/wfx/data_tx.c | 10 +++++++++- drivers/staging/wfx/data_tx.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 36b36ef39d053..77fb104efdec1 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -331,6 +331,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, { struct hif_msg *hif_msg; struct hif_req_tx *req; + struct wfx_tx_priv *tx_priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -344,11 +345,14 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta,
// From now tx_info->control is unusable memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv)); + // Fill tx_priv + tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data; + tx_priv->icv_size = wfx_tx_get_icv_len(hw_key);
// Fill hif_msg WARN(skb_headroom(skb) < wmsg_len, "not enough space in skb"); WARN(offset & 1, "attempt to transmit an unaligned frame"); - skb_put(skb, wfx_tx_get_icv_len(hw_key)); + skb_put(skb, tx_priv->icv_size); skb_push(skb, wmsg_len); memset(skb->data, 0, wmsg_len); hif_msg = (struct hif_msg *)skb->data; @@ -484,6 +488,7 @@ static void wfx_tx_fill_rates(struct wfx_dev *wdev,
void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) { + const struct wfx_tx_priv *tx_priv; struct ieee80211_tx_info *tx_info; struct wfx_vif *wvif; struct sk_buff *skb; @@ -495,6 +500,7 @@ void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) return; } tx_info = IEEE80211_SKB_CB(skb); + tx_priv = wfx_skb_tx_priv(skb); wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface); WARN_ON(!wvif); if (!wvif) @@ -503,6 +509,8 @@ void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) // Note that wfx_pending_get_pkt_us_delay() get data from tx_info _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb)); wfx_tx_fill_rates(wdev, tx_info, arg); + skb_trim(skb, skb->len - tx_priv->icv_size); + // From now, you can touch to tx_info->status, but do not touch to // tx_priv anymore // FIXME: use ieee80211_tx_info_clear_status() diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 46c9fff7a870e..401363d6b563a 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -35,6 +35,7 @@ struct tx_policy_cache {
struct wfx_tx_priv { ktime_t xmit_timestamp; + unsigned char icv_size; };
void wfx_tx_policy_init(struct wfx_vif *wvif);
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit d30337da8677cd73cb19444436b311c13e57356f ]
Compiling with the clang integrated assembler warns about a recently added instruction:
<instantiation>:14:13: error: unknown token in expression ldr tmp1, =#0x00020010UL arch/arm/mach-at91/pm_suspend.S:542:2: note: while in macro instantiation at91_plla_enable
Remove the extra '#' character that is not used for the 'ldr' instruction when doing an indirect load of a constant.
Fixes: 4fd36e458392 ("ARM: at91: pm: add plla disable/enable support for sam9x60") Tested-by: Claudiu Beznea claudiu.beznea@microchip.com Reviewed-by: Claudiu Beznea claudiu.beznea@microchip.com Reviewed-by: Nathan Chancellor nathan@kernel.org Acked-by: Nicolas Ferre nicolas.ferre@microchip.com Link: https://lore.kernel.org/r/20210204160129.2249394-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/mach-at91/pm_suspend.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 0184de05c1be1..b683c2caa40b9 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -442,7 +442,7 @@ ENDPROC(at91_backup_mode) str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
/* step 2. */ - ldr tmp1, =#AT91_PMC_PLL_ACR_DEFAULT_PLLA + ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA str tmp1, [pmc, #AT91_PMC_PLL_ACR]
/* step 3. */
From: Anand K Mistry amistry@google.com
[ Upstream commit 2615e3cdbd9c0e864f5906279c952a309871d225 ]
The ieee80211_find_sta_by_ifaddr call in ath10k_wmi_tlv_parse_peer_stats_info must be called while holding the RCU read lock. Otherwise, the following warning will be seen when RCU usage checking is enabled:
============================= WARNING: suspicious RCU usage 5.10.3 #8 Tainted: G W ----------------------------- include/linux/rhashtable.h:594 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1 no locks held by ksoftirqd/1/16.
stack backtrace: CPU: 1 PID: 16 Comm: ksoftirqd/1 Tainted: G W 5.10.3 #8 Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.104.0 09/05/2019 Call Trace: dump_stack+0xab/0x115 sta_info_hash_lookup+0x71/0x1e9 [mac80211] ? lock_is_held_type+0xe6/0x12f ? __kasan_kmalloc+0xfb/0x112 ieee80211_find_sta_by_ifaddr+0x12/0x61 [mac80211] ath10k_wmi_tlv_parse_peer_stats_info+0xbd/0x10b [ath10k_core] ath10k_wmi_tlv_iter+0x8b/0x1a1 [ath10k_core] ? ath10k_wmi_tlv_iter+0x1a1/0x1a1 [ath10k_core] ath10k_wmi_tlv_event_peer_stats_info+0x103/0x13b [ath10k_core] ath10k_wmi_tlv_op_rx+0x722/0x80d [ath10k_core] ath10k_htc_rx_completion_handler+0x16e/0x1d7 [ath10k_core] ath10k_pci_process_rx_cb+0x116/0x22c [ath10k_pci] ? ath10k_htc_process_trailer+0x332/0x332 [ath10k_core] ? _raw_spin_unlock_irqrestore+0x34/0x61 ? lockdep_hardirqs_on+0x8e/0x12e ath10k_ce_per_engine_service+0x55/0x74 [ath10k_core] ath10k_ce_per_engine_service_any+0x76/0x84 [ath10k_core] ath10k_pci_napi_poll+0x49/0x141 [ath10k_pci] net_rx_action+0x11a/0x347 __do_softirq+0x2d3/0x539 run_ksoftirqd+0x4b/0x86 smpboot_thread_fn+0x1d0/0x2ab ? cpu_report_death+0x7f/0x7f kthread+0x189/0x191 ? cpu_report_death+0x7f/0x7f ? kthread_blkcg+0x31/0x31 ret_from_fork+0x22/0x30
Fixes: 0f7cb26830a6e ("ath10k: add rx bitrate report for SDIO") Signed-off-by: Anand K Mistry amistry@google.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210202134451.1.I0d2e83c42755671b7143504b62787fd0... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 7b5834157fe51..e6135795719a1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -240,8 +240,10 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 __le32_to_cpu(stat->last_tx_rate_code), __le32_to_cpu(stat->last_tx_bitrate_kbps));
+ rcu_read_lock(); sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL); if (!sta) { + rcu_read_unlock(); ath10k_warn(ar, "not found station for peer stats\n"); return -EINVAL; } @@ -251,6 +253,7 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps); arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code); arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps); + rcu_read_unlock();
return 0; }
From: Anand K Mistry amistry@google.com
[ Upstream commit 7df28718928d08034b36168200d67b558ce36f3d ]
ath10k_debug_fw_stats_request just be called with conf_mutex held, otherwise the following warning is seen when lock debugging is enabled:
WARNING: CPU: 0 PID: 793 at drivers/net/wireless/ath/ath10k/debug.c:357 ath10k_debug_fw_stats_request+0x12c/0x133 [ath10k_core] Modules linked in: snd_hda_codec_hdmi designware_i2s snd_hda_intel snd_intel_dspcfg snd_hda_codec i2c_piix4 snd_hwdep snd_hda_core acpi_als kfifo_buf industrialio snd_soc_max98357a snd_soc_adau7002 snd_soc_acp_da7219mx98357_mach snd_soc_da7219 acp_audio_dma ccm xt_MASQUERADE fuse ath10k_pci ath10k_core lzo_rle ath lzo_compress mac80211 zram cfg80211 r8152 mii joydev CPU: 0 PID: 793 Comm: wpa_supplicant Tainted: G W 5.10.9 #5 Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.104.0 09/05/2019 RIP: 0010:ath10k_debug_fw_stats_request+0x12c/0x133 [ath10k_core] Code: 1e bb a1 ff ff ff 4c 89 ef 48 c7 c6 d3 31 2e c0 89 da 31 c0 e8 bd f8 ff ff 89 d8 eb 02 31 c0 5b 41 5c 41 5d 41 5e 41 5f 5d c3 <0f> 0b e9 04 ff ff ff 0f 1f 44 00 00 55 48 89 e5 41 56 53 48 89 fb RSP: 0018:ffffb2478099f7d0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff9e432700cce0 RCX: 11c85cfd6b8e3b00 RDX: ffff9e432700cce0 RSI: ffff9e43127c5668 RDI: ffff9e4318deddf0 RBP: ffffb2478099f7f8 R08: 0000000000000002 R09: 00000003fd7068cc R10: ffffffffc01b2749 R11: ffffffffc029efaf R12: ffff9e432700c000 R13: ffff9e43127c33e0 R14: ffffb2478099f918 R15: ffff9e43127c33e0 FS: 00007f7ea48e2740(0000) GS:ffff9e432aa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000059aa799ddf38 CR3: 0000000118de2000 CR4: 00000000001506f0 Call Trace: ath10k_sta_statistics+0x4d/0x270 [ath10k_core] sta_set_sinfo+0x1be/0xaec [mac80211] ieee80211_get_station+0x58/0x76 [mac80211] rdev_get_station+0xf1/0x11e [cfg80211] nl80211_get_station+0x7f/0x146 [cfg80211] genl_rcv_msg+0x32e/0x35e ? nl80211_stop_ap+0x19/0x19 [cfg80211] ? nl80211_get_station+0x146/0x146 [cfg80211] ? genl_rcv+0x19/0x36 ? genl_rcv+0x36/0x36 netlink_rcv_skb+0x89/0xfb genl_rcv+0x28/0x36 netlink_unicast+0x169/0x23b netlink_sendmsg+0x38a/0x402 sock_sendmsg+0x72/0x76 ____sys_sendmsg+0x153/0x1cc ? copy_msghdr_from_user+0x5d/0x85 ___sys_sendmsg+0x7c/0xb5 ? lock_acquire+0x181/0x23d ? syscall_trace_enter+0x15e/0x160 ? find_held_lock+0x3d/0xb2 ? syscall_trace_enter+0x15e/0x160 ? sched_clock_cpu+0x15/0xc6 __sys_sendmsg+0x62/0x9a do_syscall_64+0x43/0x55 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Fixes: 4913e675630e ("ath10k: enable rx duration report default for wmi tlv") Signed-off-by: Anand K Mistry amistry@google.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210202144033.1.I9e556f9fb1110d58c31d04a8a1293995... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/mac.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 7d98250380ec5..e815aab412d7a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -9117,7 +9117,9 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw, if (!ath10k_peer_stats_enabled(ar)) return;
+ mutex_lock(&ar->conf_mutex); ath10k_debug_fw_stats_request(ar); + mutex_unlock(&ar->conf_mutex);
sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit c202e2ebe1dc454ad54fd0018c023ec553d47284 ]
This error path leads to a Smatch warning:
drivers/net/wireless/ath/ath11k/mac.c:4269 ath11k_mac_op_start() error: double unlocked '&ar->conf_mutex' (orig line 4251)
We're not holding the lock when we do the "goto err;" so it leads to a double unlock. The fix is to hold the lock for a little longer.
Fixes: c83c500b55b6 ("ath11k: enable idle power save mode") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com [kvalo@codeaurora.org: move also rcu_assign_pointer() call] Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/YBk4GoeE+yc0wlJH@mwanda Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath11k/mac.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index c1608f64ea95d..7d799fe6fbd89 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -4248,11 +4248,6 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) /* Configure the hash seed for hash based reo dest ring selection */ ath11k_wmi_pdev_lro_cfg(ar, ar->pdev->pdev_id);
- mutex_unlock(&ar->conf_mutex); - - rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], - &ab->pdevs[ar->pdev_idx]); - /* allow device to enter IMPS */ if (ab->hw_params.idle_ps) { ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_IDLE_PS_CONFIG, @@ -4262,6 +4257,12 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) goto err; } } + + mutex_unlock(&ar->conf_mutex); + + rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], + &ab->pdevs[ar->pdev_idx]); + return 0;
err:
From: Jae Hyun Yoo jae.hyun.yoo@intel.com
[ Upstream commit 3f94cf15583be554df7aaa651b8ff8e1b68fbe51 ]
If LPC SNOOP driver is registered ahead of lpc-ctrl module, LPC SNOOP block will be enabled without heart beating of LCLK until lpc-ctrl enables the LCLK. This issue causes improper handling on host interrupts when the host sends interrupt in that time frame. Then kernel eventually forcibly disables the interrupt with dumping stack and printing a 'nobody cared this irq' message out.
To prevent this issue, all LPC sub-nodes should enable LCLK individually so this patch adds clock control logic into the LPC SNOOP driver.
Fixes: 3772e5da4454 ("drivers/misc: Aspeed LPC snoop output using misc chardev") Signed-off-by: Jae Hyun Yoo jae.hyun.yoo@intel.com Signed-off-by: Vernon Mauery vernon.mauery@linux.intel.com Signed-off-by: John Wang wangzhiqiang.bj@bytedance.com Reviewed-by: Joel Stanley joel@jms.id.au Link: https://lore.kernel.org/r/20201208091748.1920-1-wangzhiqiang.bj@bytedance.co... Signed-off-by: Joel Stanley joel@jms.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 ++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index 682ba0eb4eba1..20acac6342eff 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -11,6 +11,7 @@ */
#include <linux/bitops.h> +#include <linux/clk.h> #include <linux/interrupt.h> #include <linux/fs.h> #include <linux/kfifo.h> @@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel { struct aspeed_lpc_snoop { struct regmap *regmap; int irq; + struct clk *clk; struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; };
@@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) return -ENODEV; }
+ lpc_snoop->clk = devm_clk_get(dev, NULL); + if (IS_ERR(lpc_snoop->clk)) { + rc = PTR_ERR(lpc_snoop->clk); + if (rc != -EPROBE_DEFER) + dev_err(dev, "couldn't get clock\n"); + return rc; + } + rc = clk_prepare_enable(lpc_snoop->clk); + if (rc) { + dev_err(dev, "couldn't enable clock\n"); + return rc; + } + rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev); if (rc) - return rc; + goto err;
rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) - return rc; + goto err;
/* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); - if (rc) + if (rc) { aspeed_lpc_disable_snoop(lpc_snoop, 0); + goto err; + } }
+ return 0; + +err: + clk_disable_unprepare(lpc_snoop->clk); + return rc; }
@@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) aspeed_lpc_disable_snoop(lpc_snoop, 0); aspeed_lpc_disable_snoop(lpc_snoop, 1);
+ clk_disable_unprepare(lpc_snoop->clk); + return 0; }
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit 5a6842455c113920001df83cffa28accceeb0927 ]
The value we receive from ACPI is a long long unsigned integer but the values should be treated as signed char. When comparing the received value with ACPI_PPAG_MIN_LB/HB, we were doing an unsigned comparison, so the negative value would actually be treated as a very high number.
To solve this issue, assign the value to our table of s8's before making the comparison, so the value is already converted when we do so.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210135352.b0ec69f312bc.If77fd9c61a96a... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 9e150c01f7b37..522d547f35d58 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -962,16 +962,23 @@ read_table: union acpi_object *ent;
ent = &wifi_pkg->package.elements[idx++]; - if (ent->type != ACPI_TYPE_INTEGER || - (j == 0 && ent->integer.value > ACPI_PPAG_MAX_LB) || - (j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) || - (j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) || - (j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) { - ppag_table.v1.enabled = cpu_to_le32(0); + if (ent->type != ACPI_TYPE_INTEGER) { ret = -EINVAL; goto out_free; } + gain[i * num_sub_bands + j] = ent->integer.value; + + if ((j == 0 && + (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_LB || + gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_LB)) || + (j != 0 && + (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB || + gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) { + ppag_table.v1.enabled = cpu_to_le32(0); + ret = -EINVAL; + goto out_free; + } } } ret = 0;
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit 551d793f65364c904921ac168d4b4028bb51be69 ]
When reading the PPAG table from ACPI, we should store everything in our fwrt structure, so it can be accessed later. But we had a local ppag_table variable in the function and were erroneously storing the enabled/disabled flag in it instead of storing it in the fwrt. Fix this by removing the local variable and storing everything directly in fwrt.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: f2134f66f40e ("iwlwifi: acpi: support ppag table command v2") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210135352.889862e6d393.I8b894c1b2b3fe... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 522d547f35d58..4d527409428d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -892,7 +892,6 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) { union acpi_object *wifi_pkg, *data, *enabled; - union iwl_ppag_table_cmd ppag_table; int i, j, ret, tbl_rev, num_sub_bands; int idx = 2; s8 *gain; @@ -946,8 +945,8 @@ read_table: goto out_free; }
- ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value); - if (!ppag_table.v1.enabled) { + mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value); + if (!mvm->fwrt.ppag_table.v1.enabled) { ret = 0; goto out_free; } @@ -975,7 +974,7 @@ read_table: (j != 0 && (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB || gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) { - ppag_table.v1.enabled = cpu_to_le32(0); + mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0); ret = -EINVAL; goto out_free; }
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit 659844d391826bfc5c8b4d9a06869ed51d859c76 ]
Some change conflicts apparently cause a confusion between a local variable being used to send the PPAG command and the introduction of a union for this command. Most parts of the local command were never copied from the stored data, so the FW was getting garbage in the tables instead of getting valid values.
Fix this by completely removing the local and using only the union that we have stored in fwrt.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: f2134f66f40e ("iwlwifi: acpi: support ppag table command v2") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210135352.d090e0301023.I7d57f4d7da9a3... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4d527409428d3..045765fa67bea 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -990,7 +990,6 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) { u8 cmd_ver; int i, j, ret, num_sub_bands, cmd_size; - union iwl_ppag_table_cmd ppag_table; s8 *gain;
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) { @@ -1003,15 +1002,13 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) return 0; }
- ppag_table.v1.enabled = mvm->fwrt.ppag_table.v1.enabled; - cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD, IWL_FW_CMD_VER_UNKNOWN); if (cmd_ver == 1) { num_sub_bands = IWL_NUM_SUB_BANDS; gain = mvm->fwrt.ppag_table.v1.gain[0]; - cmd_size = sizeof(ppag_table.v1); + cmd_size = sizeof(mvm->fwrt.ppag_table.v1); if (mvm->fwrt.ppag_ver == 2) { IWL_DEBUG_RADIO(mvm, "PPAG table is v2 but FW supports v1, sending truncated table\n"); @@ -1019,7 +1016,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) } else if (cmd_ver == 2) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; gain = mvm->fwrt.ppag_table.v2.gain[0]; - cmd_size = sizeof(ppag_table.v2); + cmd_size = sizeof(mvm->fwrt.ppag_table.v2); if (mvm->fwrt.ppag_ver == 1) { IWL_DEBUG_RADIO(mvm, "PPAG table is v1 but FW supports v2, sending padded table\n"); @@ -1039,7 +1036,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n"); ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD), - 0, cmd_size, &ppag_table); + 0, cmd_size, &mvm->fwrt.ppag_table); if (ret < 0) IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", ret);
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit 28db1862067cb09ebfdccfbc129a52c6fdb4c4d7 ]
The call to iwl_sar_geo_init() was moved to the end of the iwl_mvm_sar_geo_init() function, after the table revision is assigned to the FW command. But the revision is only known after iwl_sar_geo_init() is called, so we were always assigning zero to it.
Fix that by moving the assignment code after the iwl_sar_geo_init() function is called.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: 45acebf8d6a6 ("iwlwifi: fix sar geo table initialization") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210135352.cef55ef3a065.If96c60f08d24c... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 045765fa67bea..4c5609cdcbdee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -859,12 +859,10 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) if (cmd_ver == 3) { len = sizeof(cmd.v3); n_bands = ARRAY_SIZE(cmd.v3.table[0]); - cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); } else if (fw_has_api(&mvm->fwrt.fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) { len = sizeof(cmd.v2); n_bands = ARRAY_SIZE(cmd.v2.table[0]); - cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); } else { len = sizeof(cmd.v1); n_bands = ARRAY_SIZE(cmd.v1.table[0]); @@ -884,6 +882,16 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) if (ret) return 0;
+ /* + * Set the revision on versions that contain it. + * This must be done after calling iwl_sar_geo_init(). + */ + if (cmd_ver == 3) + cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); + else if (fw_has_api(&mvm->fwrt.fw->ucode_capa, + IWL_UCODE_TLV_API_SAR_TABLE_VER)) + cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); + return iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT), 0, len, &cmd);
From: Sara Sharon sara.sharon@intel.com
[ Upstream commit b8a86164454aa745ecb534d7477d50d440ea05b6 ]
We may want to remove it before it started (i.e. before the actual switch time).
Signed-off-by: Sara Sharon sara.sharon@intel.com Fixes: 58ddd9b6d194 ("iwlwifi: mvm: don't send a CSA command the firmware doesn't know") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210171218.835db8987b8a.Ic6c5d28d74430... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 3 --- 1 file changed, 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 4e1bdf13e5e71..0b012f8c9eb22 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -999,9 +999,6 @@ void iwl_mvm_remove_csa_period(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (!te_data->running) - return; - spin_lock_bh(&mvm->time_event_lock); id = te_data->id; spin_unlock_bh(&mvm->time_event_lock);
From: Marco Elver elver@google.com
[ Upstream commit 6df8fb83301d68ea0a0c0e1cbcc790fcc333ed12 ]
For double-checked locking in bpf_common_lru_push_free(), node->type is read outside the critical section and then re-checked under the lock. However, concurrent writes to node->type result in data races.
For example, the following concurrent access was observed by KCSAN:
write to 0xffff88801521bc22 of 1 bytes by task 10038 on cpu 1: __bpf_lru_node_move_in kernel/bpf/bpf_lru_list.c:91 __local_list_flush kernel/bpf/bpf_lru_list.c:298 ... read to 0xffff88801521bc22 of 1 bytes by task 10043 on cpu 0: bpf_common_lru_push_free kernel/bpf/bpf_lru_list.c:507 bpf_lru_push_free kernel/bpf/bpf_lru_list.c:555 ...
Fix the data races where node->type is read outside the critical section (for double-checked locking) by marking the access with READ_ONCE() as well as ensuring the variable is only accessed once.
Fixes: 3a08c2fd7634 ("bpf: LRU List") Reported-by: syzbot+3536db46dfa58c573458@syzkaller.appspotmail.com Reported-by: syzbot+516acdb03d3e27d91bcd@syzkaller.appspotmail.com Signed-off-by: Marco Elver elver@google.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Acked-by: Martin KaFai Lau kafai@fb.com Link: https://lore.kernel.org/bpf/20210209112701.3341724-1-elver@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/bpf_lru_list.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/bpf_lru_list.c b/kernel/bpf/bpf_lru_list.c index 1b6b9349cb857..d99e89f113c43 100644 --- a/kernel/bpf/bpf_lru_list.c +++ b/kernel/bpf/bpf_lru_list.c @@ -502,13 +502,14 @@ struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash) static void bpf_common_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node) { + u8 node_type = READ_ONCE(node->type); unsigned long flags;
- if (WARN_ON_ONCE(node->type == BPF_LRU_LIST_T_FREE) || - WARN_ON_ONCE(node->type == BPF_LRU_LOCAL_LIST_T_FREE)) + if (WARN_ON_ONCE(node_type == BPF_LRU_LIST_T_FREE) || + WARN_ON_ONCE(node_type == BPF_LRU_LOCAL_LIST_T_FREE)) return;
- if (node->type == BPF_LRU_LOCAL_LIST_T_PENDING) { + if (node_type == BPF_LRU_LOCAL_LIST_T_PENDING) { struct bpf_lru_locallist *loc_l;
loc_l = per_cpu_ptr(lru->common_lru.local_list, node->cpu);
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit 4a81598f0f39cffbf1c29c4a184063d513661c4a ]
When the interface goes up, we have already loaded the PNVM during init, so we don't load it anymore. But we still need to set the PNVM values in the context so that the FW can load it again.
Call set_pnvm when the PNVM is already loaded and change the trans_pcie implementation to accept a second call to set_pnvm when we have already allocated and, in this case, only set the values without allocating again.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: 6972592850c0 ("iwlwifi: read and parse PNVM file") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210172142.622546a3566f.I659a8b9aa944d... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 7 ++++++- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 895a907acdf0f..1e16f83b402b8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -227,6 +227,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, struct iwl_notification_wait pnvm_wait; static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, PNVM_INIT_COMPLETE_NTFY) }; + int ret;
/* if the SKU_ID is empty, there's nothing to do */ if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) @@ -236,7 +237,6 @@ int iwl_pnvm_load(struct iwl_trans *trans, if (!trans->pnvm_loaded) { const struct firmware *pnvm; char pnvm_name[64]; - int ret;
/* * The prefix unfortunately includes a hyphen at the end, so @@ -264,6 +264,11 @@ int iwl_pnvm_load(struct iwl_trans *trans,
release_firmware(pnvm); } + } else { + /* if we already loaded, we need to set it again */ + ret = iwl_trans_set_pnvm(trans, NULL, 0); + if (ret) + return ret; }
iwl_init_notification_wait(notif_wait, &pnvm_wait, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 5b5134dd49af8..8fba190e84cf3 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -298,17 +298,20 @@ int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0;
- ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->pnvm_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n", - ret); - return ret; + /* only allocate the DRAM if not allocated yet */ + if (!trans->pnvm_loaded) { + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) + return -EBUSY; + + ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, + &trans_pcie->pnvm_dram); + if (ret < 0) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n", + ret); + return ret; + } }
- if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) - return -EBUSY; - prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = cpu_to_le64(trans_pcie->pnvm_dram.physical); prph_sc_ctrl->pnvm_cfg.pnvm_size =
From: Luca Coelho luciano.coelho@intel.com
[ Upstream commit ff11a8ee2d2d0f78514ac9b42fb50c525ca695c7 ]
If the SKU_ID doesn't match, we don't increment the pointer and keep checking the same TLV over and over again.
We need to increment the pointer in all situtations, namely if the TLV is not a SKU_ID, if the SKU_ID matched or if the SKU_ID didn't match. So we can increment the pointer already before checking for these conditions to solve the problem.
Signed-off-by: Luca Coelho luciano.coelho@intel.com Fixes: 6972592850c0 ("iwlwifi: read and parse PNVM file") Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210210172142.de94d366f3ff.I9a5a54906cf0f... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 1e16f83b402b8..37ce4fe136c5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -198,14 +198,14 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, le32_to_cpu(sku_id->data[1]), le32_to_cpu(sku_id->data[2]));
+ data += sizeof(*tlv) + ALIGN(tlv_len, 4); + len -= ALIGN(tlv_len, 4); + if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) && trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) && trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { int ret;
- data += sizeof(*tlv) + ALIGN(tlv_len, 4); - len -= ALIGN(tlv_len, 4); - ret = iwl_pnvm_handle_section(trans, data, len); if (!ret) return 0;
From: Linus Lüssing ll@simonwunderlich.de
[ Upstream commit 12c8f3d1cdd84f01ee777b756db9dddc1f1c9d17 ]
When trying to set the noise floor via debugfs, a "data bus error" crash like the following can happen:
[ 88.433133] Data bus error, epc == 80221c28, ra == 83314e60 [ 88.438895] Oops[#1]: [ 88.441246] CPU: 0 PID: 7263 Comm: sh Not tainted 4.14.195 #0 [ 88.447174] task: 838a1c20 task.stack: 82d5e000 [ 88.451847] $ 0 : 00000000 00000030 deadc0de 83141de4 [ 88.457248] $ 4 : b810a2c4 0000a2c4 83230fd4 00000000 [ 88.462652] $ 8 : 0000000a 00000000 00000001 00000000 [ 88.468055] $12 : 7f8ef318 00000000 00000000 77f802a0 [ 88.473457] $16 : 83230080 00000002 0000001b 83230080 [ 88.478861] $20 : 83a1c3f8 00841000 77f7adb0 ffffff92 [ 88.484263] $24 : 00000fa4 77edd860 [ 88.489665] $28 : 82d5e000 82d5fda8 00000000 83314e60 [ 88.495070] Hi : 00000000 [ 88.498044] Lo : 00000000 [ 88.501040] epc : 80221c28 ioread32+0x8/0x10 [ 88.505671] ra : 83314e60 ath9k_hw_loadnf+0x88/0x520 [ath9k_hw] [ 88.512049] Status: 1000fc03 KERNEL EXL IE [ 88.516369] Cause : 5080801c (ExcCode 07) [ 88.520508] PrId : 00019374 (MIPS 24Kc) [ 88.524556] Modules linked in: ath9k ath9k_common pppoe ppp_async l2tp_ppp cdc_mbim batman_adv ath9k_hw ath sr9700 smsc95xx sierra_net rndis_host qmi_wwan pppox ppp_generic pl2303 nf_conntrack_ipv6 mcs7830 mac80211 kalmia iptable_nat ipt_REJECT ipt_MASQUERADE huawei_cdc_ncm ftdi_sio dm9601 cfg80211 cdc_subset cdc_ncm cdc_ether cdc_eem ax88179_178a asix xt_time xt_tcpudp xt_tcpmss xt_statistic xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_hl xt_ecn xt_dscp xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_NETMAP xt_LOG xt_HL xt_FLOWOFFLOAD xt_DSCP xt_CLASSIFY usbserial usbnet usbhid slhc rtl8150 r8152 pegasus nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_conntrack_ipv4 nf_nat_ipv4 nf_nat nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack [ 88.597894] libcrc32c kaweth iptable_mangle iptable_filter ipt_ECN ipheth ip_tables hso hid_generic crc_ccitt compat cdc_wdm cdc_acm br_netfilter hid evdev input_core nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables ip6t_REJECT x_tables nf_reject_ipv6 l2tp_netlink l2tp_core udp_tunnel ip6_udp_tunnel xfrm6_mode_tunnel xfrm6_mode_transport xfrm6_mode_beet ipcomp6 xfrm6_tunnel esp6 ah6 xfrm4_tunnel xfrm4_mode_tunnel xfrm4_mode_transport xfrm4_mode_beet ipcomp esp4 ah4 tunnel6 tunnel4 tun xfrm_user xfrm_ipcomp af_key xfrm_algo sha256_generic sha1_generic jitterentropy_rng drbg md5 hmac echainiv des_generic deflate zlib_inflate zlib_deflate cbc authenc crypto_acompress ehci_platform ehci_hcd gpio_button_hotplug usbcore nls_base usb_common crc16 mii aead crypto_null cryptomgr crc32c_generic [ 88.671671] crypto_hash [ 88.674292] Process sh (pid: 7263, threadinfo=82d5e000, task=838a1c20, tls=77f81efc) [ 88.682279] Stack : 00008060 00000008 00000200 00000000 00000000 00000000 00000000 00000002 [ 88.690916] 80500000 83230080 82d5fe22 00841000 77f7adb0 00000000 00000000 83156858 [ 88.699553] 00000000 8352fa00 83ad62b0 835302a8 00000000 300a00f8 00000003 82d5fe38 [ 88.708190] 82d5fef4 00000001 77f54dc4 77f80000 77f7adb0 c79fe901 00000000 00000000 [ 88.716828] 80510000 00000002 00841000 77f54dc4 77f80000 801ce4cc 0000000b 41824292 [ 88.725465] ... [ 88.727994] Call Trace: [ 88.730532] [<80221c28>] ioread32+0x8/0x10 [ 88.734765] Code: 00000000 8c820000 0000000f <03e00008> 00000000 08088708 00000000 aca40000 03e00008 [ 88.744846] [ 88.746464] ---[ end trace db226b2de1b69b9e ]--- [ 88.753477] Kernel panic - not syncing: Fatal exception [ 88.759981] Rebooting in 3 seconds..
The "REG_READ(ah, AR_PHY_AGC_CONTROL)" in ath9k_hw_loadnf() does not like being called when the hardware is asleep, leading to this crash.
The easiest way to reproduce this is trying to set nf_override while the hardware is down:
$ ip link set down dev wlan0 $ echo "-85" > /sys/kernel/debug/ieee80211/phy0/ath9k/nf_override
Fixing this crash by waking the hardware up before trying to set the noise floor. Similar to what other ath9k debugfs files do.
Tested on a Lima board from 8devices, which has a QCA 4531 chipset.
Fixes: b90189759a7f ("ath9k: add noise floor override option") Cc: Simon Wunderlich sw@simonwunderlich.de Signed-off-by: Linus Lüssing ll@simonwunderlich.de Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210209184352.4272-1-linus.luessing@c0d3.blue Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath9k/debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 017a43bc400ca..4c81b1d7f4171 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1223,8 +1223,11 @@ static ssize_t write_file_nf_override(struct file *file,
ah->nf_override = val;
- if (ah->curchan) + if (ah->curchan) { + ath9k_ps_wakeup(sc); ath9k_hw_loadnf(ah, ah->curchan); + ath9k_ps_restore(sc); + }
return count; }
From: Björn Töpel bjorn.topel@intel.com
[ Upstream commit 732fa32330667a80ce4985ca81b6e9d6b2ad2072 ]
The test_xdp_redirect.sh script uses a bash feature, '&>'. On systems, e.g. Debian, where '/bin/sh' is dash, this will not work as expected. Use bash in the shebang to get the expected behavior.
Further, using 'set -e' means that the error of a command cannot be captured without the command being executed with '&&' or '||'. Let us restructure the ping-commands, and use them as an if-expression, so that we can capture the return value.
v4: Added missing Fixes:, and removed local variables. (Andrii) v3: Reintroduced /bin/bash, and kept 'set -e'. (Andrii) v2: Kept /bin/sh and removed bashisms. (Randy)
Fixes: 996139e801fd ("selftests: bpf: add a test for XDP redirect") Signed-off-by: Björn Töpel bjorn.topel@intel.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Acked-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20210211082029.1687666-1-bjorn.topel@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_xdp_redirect.sh b/tools/testing/selftests/bpf/test_xdp_redirect.sh index dd80f0c84afb4..c033850886f44 100755 --- a/tools/testing/selftests/bpf/test_xdp_redirect.sh +++ b/tools/testing/selftests/bpf/test_xdp_redirect.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Create 2 namespaces with two veth peers, and # forward packets in-between using generic XDP # @@ -57,12 +57,8 @@ test_xdp_redirect() ip link set dev veth1 $xdpmode obj test_xdp_redirect.o sec redirect_to_222 &> /dev/null ip link set dev veth2 $xdpmode obj test_xdp_redirect.o sec redirect_to_111 &> /dev/null
- ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null - local ret1=$? - ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null - local ret2=$? - - if [ $ret1 -eq 0 -a $ret2 -eq 0 ]; then + if ip netns exec ns1 ping -c 1 10.1.1.22 &> /dev/null && + ip netns exec ns2 ping -c 1 10.1.1.11 &> /dev/null; then echo "selftests: test_xdp_redirect $xdpmode [PASS]"; else ret=1
From: Sukadev Bhattiprolu sukadev@linux.ibm.com
[ Upstream commit d4083d3c00f60a09ad82e3bf17ff57fec69c8aa6 ]
If set_link_state() fails for any reason, we still cleanup the adapter state and cannot recover from a partial close anyway. So set the adapter to CLOSED state. That way if a new soft/hard reset is processed, the adapter will remain in the CLOSED state until the next ibmvnic_open().
Fixes: 01d9bd792d16 ("ibmvnic: Reorganize device close") Signed-off-by: Sukadev Bhattiprolu sukadev@linux.ibm.com Reported-by: Abdul Haleem abdhalee@in.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index a536fdbf05e19..621be6d2da971 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1353,10 +1353,8 @@ static int __ibmvnic_close(struct net_device *netdev)
adapter->state = VNIC_CLOSING; rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN); - if (rc) - return rc; adapter->state = VNIC_CLOSED; - return 0; + return rc; }
static int ibmvnic_close(struct net_device *netdev)
From: Edwin Peer edwin.peer@broadcom.com
[ Upstream commit 132e0b65dc2b8bfa9721bfce834191f24fd1d7ed ]
A TX queue can potentially immediately timeout after it is stopped and the last TX timestamp on that queue was more than 5 seconds ago with carrier still up. Prevent these intermittent false TX timeouts by bringing down carrier first before calling netif_tx_disable().
Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Signed-off-by: Edwin Peer edwin.peer@broadcom.com Signed-off-by: Michael Chan michael.chan@broadcom.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index d10e4f85dd11a..1c96b7ba24f28 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8856,9 +8856,10 @@ void bnxt_tx_disable(struct bnxt *bp) txr->dev_state = BNXT_DEV_STATE_CLOSING; } } + /* Drop carrier first to prevent TX timeout */ + netif_carrier_off(bp->dev); /* Stop all TX queues */ netif_tx_disable(bp->dev); - netif_carrier_off(bp->dev); }
void bnxt_tx_enable(struct bnxt *bp)
From: Vasundhara Volam vasundhara-v.volam@broadcom.com
[ Upstream commit db28b6c77f4050f62599267a886b61fbd6504633 ]
The running fw.psid version is in decimal format but the stored fw.psid is in hex format. This can mislead the user to reset the NIC to activate the stored version to become the running version.
Fix it to display the stored fw.psid in decimal format.
Fixes: 1388875b3916 ("bnxt_en: Add stored FW version info to devlink info_get cb.") Signed-off-by: Vasundhara Volam vasundhara-v.volam@broadcom.com Signed-off-by: Michael Chan michael.chan@broadcom.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 6b7b69ed62db0..a9bcf887d2fbe 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -472,8 +472,8 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) { u32 ver = nvm_cfg_ver.vu32;
- sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF, - ver & 0xF); + sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf, + ver & 0xf); rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, DEVLINK_INFO_VERSION_GENERIC_FW_PSID, buf);
From: Juergen Gross jgross@suse.com
[ Upstream commit a3daf3d39132b405781be8d9ede0c449b244b64e ]
In case of a common event for rx and tx queue the event should be regarded to be spurious if no rx and no tx requests are pending.
Unfortunately the condition for testing that is wrong causing to decide a event being spurious if no rx OR no tx requests are pending.
Fix that plus using local variables for rx/tx pending indicators in order to split function calls and if condition.
Fixes: 23025393dbeb3b ("xen/netback: use lateeoi irq binding") Signed-off-by: Juergen Gross jgross@suse.com Reviewed-by: Jan Beulich jbeulich@suse.com Reviewed-by: Paul Durrant paul@xen.org Reviewed-by: Wei Liu wl@xen.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/xen-netback/interface.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index acb786d8b1d8f..e02a4fbb74de5 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -162,13 +162,15 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id) { struct xenvif_queue *queue = dev_id; int old; + bool has_rx, has_tx;
old = atomic_fetch_or(NETBK_COMMON_EOI, &queue->eoi_pending); WARN(old, "Interrupt while EOI pending\n");
- /* Use bitwise or as we need to call both functions. */ - if ((!xenvif_handle_tx_interrupt(queue) | - !xenvif_handle_rx_interrupt(queue))) { + has_tx = xenvif_handle_tx_interrupt(queue); + has_rx = xenvif_handle_rx_interrupt(queue); + + if (!has_rx && !has_tx) { atomic_andnot(NETBK_COMMON_EOI, &queue->eoi_pending); xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS); }
From: Ioana Ciornei ioana.ciornei@nxp.com
[ Upstream commit e12be9139cca26d689fe1a9257054b76752f725b ]
If xdp_do_redirect() fails, the calling driver should handle recycling or freeing of the page associated with the frame. The dpaa2-eth driver didn't do either of them and just incremented a counter. Fix this by trying to DMA map back the page and recycle it or, if the mapping fails, just free it.
Fixes: d678be1dc1ec ("dpaa2-eth: add XDP_REDIRECT support") Signed-off-by: Ioana Ciornei ioana.ciornei@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index fb0bcd18ec0c1..f1c2b3c7f7e99 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -399,10 +399,20 @@ static u32 dpaa2_eth_run_xdp(struct dpaa2_eth_priv *priv, xdp.frame_sz = DPAA2_ETH_RX_BUF_RAW_SIZE;
err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog); - if (unlikely(err)) + if (unlikely(err)) { + addr = dma_map_page(priv->net_dev->dev.parent, + virt_to_page(vaddr), 0, + priv->rx_buf_size, DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(priv->net_dev->dev.parent, addr))) { + free_pages((unsigned long)vaddr, 0); + } else { + ch->buf_count++; + dpaa2_eth_xdp_release_buf(priv, ch, addr); + } ch->stats.xdp_drop++; - else + } else { ch->stats.xdp_redirect++; + } break; }
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 4c0d2e96ba055bd8911bb8287def4f8ebbad15b6 ]
Claudiu reported that on his system S2R cuts off power to the PHY and after resuming certain PHY settings are lost. The PM folks confirmed that cutting off power to selected components in S2R is a valid case. Therefore resuming from S2R, same as from hibernation, has to assume that the PHY has power-on defaults. As a consequence use the restore callback also as resume callback. In addition make sure that the interrupt configuration is restored. Let's do this in phy_init_hw() and ensure that after this call actual interrupt configuration is in sync with phydev->interrupts. Currently, if interrupt was enabled before hibernation, we would resume with interrupt disabled because that's the power-on default.
This fix applies cleanly only after the commit marked as fixed.
I don't have an affected system, therefore change is compile-tested only.
[0] https://lore.kernel.org/netdev/1610120754-14331-1-git-send-email-claudiu.bez...
Fixes: 611d779af7ca ("net: phy: fix MDIO bus PM PHY resuming") Reported-by: Claudiu Beznea claudiu.beznea@microchip.com Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/phy_device.c | 53 ++++++++++++------------------------ 1 file changed, 17 insertions(+), 36 deletions(-)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 80c2e646c0934..71169e7d6177d 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -300,50 +300,22 @@ static int mdio_bus_phy_resume(struct device *dev)
phydev->suspended_by_mdio_bus = 0;
- ret = phy_resume(phydev); + ret = phy_init_hw(phydev); if (ret < 0) return ret;
-no_resume: - if (phydev->attached_dev && phydev->adjust_link) - phy_start_machine(phydev); - - return 0; -} - -static int mdio_bus_phy_restore(struct device *dev) -{ - struct phy_device *phydev = to_phy_device(dev); - struct net_device *netdev = phydev->attached_dev; - int ret; - - if (!netdev) - return 0; - - ret = phy_init_hw(phydev); + ret = phy_resume(phydev); if (ret < 0) return ret; - +no_resume: if (phydev->attached_dev && phydev->adjust_link) phy_start_machine(phydev);
return 0; }
-static const struct dev_pm_ops mdio_bus_phy_pm_ops = { - .suspend = mdio_bus_phy_suspend, - .resume = mdio_bus_phy_resume, - .freeze = mdio_bus_phy_suspend, - .thaw = mdio_bus_phy_resume, - .restore = mdio_bus_phy_restore, -}; - -#define MDIO_BUS_PHY_PM_OPS (&mdio_bus_phy_pm_ops) - -#else - -#define MDIO_BUS_PHY_PM_OPS NULL - +static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend, + mdio_bus_phy_resume); #endif /* CONFIG_PM */
/** @@ -554,7 +526,7 @@ static const struct device_type mdio_bus_phy_type = { .name = "PHY", .groups = phy_dev_groups, .release = phy_device_release, - .pm = MDIO_BUS_PHY_PM_OPS, + .pm = pm_ptr(&mdio_bus_phy_pm_ops), };
static int phy_request_driver_module(struct phy_device *dev, u32 phy_id) @@ -1143,10 +1115,19 @@ int phy_init_hw(struct phy_device *phydev) if (ret < 0) return ret;
- if (phydev->drv->config_init) + if (phydev->drv->config_init) { ret = phydev->drv->config_init(phydev); + if (ret < 0) + return ret; + }
- return ret; + if (phydev->drv->config_intr) { + ret = phydev->drv->config_intr(phydev); + if (ret < 0) + return ret; + } + + return 0; } EXPORT_SYMBOL(phy_init_hw);
From: Raed Salem raeds@nvidia.com
[ Upstream commit e33f9f5f2d3a5fa97728a43708f41da2d4faae65 ]
This limitation was inherited by previous Innova (FPGA) IPsec implementation, it uses its private set of RQ handlers which does not support XDP, for Connect-X this is no longer true.
Fix by keeping this limitation only for Innova IPsec supporting devices, as otherwise this limitation effectively wrongly blocks XDP for all future Connect-X devices for all flows even if IPsec offload is not used.
Fixes: 2d64663cd559 ("net/mlx5: IPsec: Add HW crypto offload support") Signed-off-by: Raed Salem raeds@nvidia.com Reviewed-by: Alaa Hleihel alaa@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 3fc7d18ac868b..92436569ce86b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4455,8 +4455,9 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog) return -EINVAL; }
- if (MLX5_IPSEC_DEV(priv->mdev)) { - netdev_warn(netdev, "can't set XDP with IPSec offload\n"); + if (mlx5_fpga_is_ipsec_device(priv->mdev)) { + netdev_warn(netdev, + "XDP is not available on Innova cards with IPsec support\n"); return -EINVAL; }
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit 019f93bc4ba3a0dcb77f448ee77fc4c9c1b89565 ]
When mlx5e_ethtool_set_coalesce doesn't change DIM state (enabled/disabled), it calls mlx5e_set_priv_channels_coalesce unconditionally, which in turn invokes a firmware command to set interrupt moderation parameters. It shouldn't happen while DIM manages those parameters dynamically (it might even be happening at the same time).
This patch fixes it by splitting mlx5e_set_priv_channels_coalesce into two functions (for RX and TX) and calling them only when DIM is disabled (for RX and TX respectively).
Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing") Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 302001d6661ea..d7ff5fa45cb7d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -525,7 +525,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev, #define MLX5E_MAX_COAL_FRAMES MLX5_MAX_CQ_COUNT
static void -mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) +mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) { struct mlx5_core_dev *mdev = priv->mdev; int tc; @@ -540,6 +540,17 @@ mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesc coal->tx_coalesce_usecs, coal->tx_max_coalesced_frames); } + } +} + +static void +mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) +{ + struct mlx5_core_dev *mdev = priv->mdev; + int i; + + for (i = 0; i < priv->channels.num; ++i) { + struct mlx5e_channel *c = priv->channels.c[i];
mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq, coal->rx_coalesce_usecs, @@ -596,7 +607,10 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, reset_tx = !!coal->use_adaptive_tx_coalesce != priv->channels.params.tx_dim_enabled;
if (!reset_rx && !reset_tx) { - mlx5e_set_priv_channels_coalesce(priv, coal); + if (!coal->use_adaptive_rx_coalesce) + mlx5e_set_priv_channels_rx_coalesce(priv, coal); + if (!coal->use_adaptive_tx_coalesce) + mlx5e_set_priv_channels_tx_coalesce(priv, coal); priv->channels.params = new_channels.params; goto out; }
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit 65ba8594a238c20e458b3d2d39d91067cbffd0b1 ]
struct mlx5e_params contains fields ({rx,tx}_cq_moderation) that depend on two things: whether DIM is enabled and the state of a private flag (MLX5E_PFLAG_{RX,TX}_CQE_BASED_MODER). Whenever the DIM state changes, mlx5e_reset_{rx,tx}_moderation is called to update the fields, however, only if the channels are open. The flow where the channels are closed misses the required update of the fields. This commit moves the calls of mlx5e_reset_{rx,tx}_moderation, so that they run in both flows.
Fixes: ebeaf084ad5c ("net/mlx5e: Properly set default values when disabling adaptive moderation") Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index d7ff5fa45cb7d..8612c388db7d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -597,24 +597,9 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, tx_moder->pkts = coal->tx_max_coalesced_frames; new_channels.params.tx_dim_enabled = !!coal->use_adaptive_tx_coalesce;
- if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { - priv->channels.params = new_channels.params; - goto out; - } - /* we are opened */ - reset_rx = !!coal->use_adaptive_rx_coalesce != priv->channels.params.rx_dim_enabled; reset_tx = !!coal->use_adaptive_tx_coalesce != priv->channels.params.tx_dim_enabled;
- if (!reset_rx && !reset_tx) { - if (!coal->use_adaptive_rx_coalesce) - mlx5e_set_priv_channels_rx_coalesce(priv, coal); - if (!coal->use_adaptive_tx_coalesce) - mlx5e_set_priv_channels_tx_coalesce(priv, coal); - priv->channels.params = new_channels.params; - goto out; - } - if (reset_rx) { u8 mode = MLX5E_GET_PFLAG(&new_channels.params, MLX5E_PFLAG_RX_CQE_BASED_MODER); @@ -628,6 +613,20 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, mlx5e_reset_tx_moderation(&new_channels.params, mode); }
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { + priv->channels.params = new_channels.params; + goto out; + } + + if (!reset_rx && !reset_tx) { + if (!coal->use_adaptive_rx_coalesce) + mlx5e_set_priv_channels_rx_coalesce(priv, coal); + if (!coal->use_adaptive_tx_coalesce) + mlx5e_set_priv_channels_tx_coalesce(priv, coal); + priv->channels.params = new_channels.params; + goto out; + } + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
out:
From: Shay Drory shayd@nvidia.com
[ Upstream commit 51d138c2610a236c1ed0059d034ee4c74f452b86 ]
Currently, when we discover a fatal error, we are queueing a work that will wait for a lock in order to enter the device to error state. Meanwhile, FW commands are still being processed, and gets timeouts. This can block the driver for few minutes before the work will manage to get the lock and enter to error state.
Setting the device to error state before queueing health work, in order to avoid FW commands being processed while the work is waiting for the lock.
Fixes: c1d4d2e92ad6 ("net/mlx5: Avoid calling sleeping function by the health poll thread") Signed-off-by: Shay Drory shayd@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/mellanox/mlx5/core/health.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 54523bed16cd3..0c32c485eb588 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -190,6 +190,16 @@ static bool reset_fw_if_needed(struct mlx5_core_dev *dev) return true; }
+static void enter_error_state(struct mlx5_core_dev *dev, bool force) +{ + if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */ + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + mlx5_cmd_flush(dev); + } + + mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); +} + void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) { bool err_detected = false; @@ -208,12 +218,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force) goto unlock; }
- if (mlx5_health_check_fatal_sensors(dev) || force) { /* protected state setting */ - dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; - mlx5_cmd_flush(dev); - } - - mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1); + enter_error_state(dev, force); unlock: mutex_unlock(&dev->intf_state_mutex); } @@ -613,7 +618,7 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work) priv = container_of(health, struct mlx5_priv, health); dev = container_of(priv, struct mlx5_core_dev, priv);
- mlx5_enter_error_state(dev, false); + enter_error_state(dev, false); if (IS_ERR_OR_NULL(health->fw_fatal_reporter)) { if (mlx5_health_try_recover(dev)) mlx5_core_err(dev, "health recovery failed\n"); @@ -707,8 +712,9 @@ static void poll_health(struct timer_list *t) mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error); dev->priv.health.fatal_error = fatal_error; print_health_info(dev); + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; mlx5_trigger_health_work(dev); - goto out; + return; }
count = ioread32be(health->health_counter);
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit 4d6e6b0c6d4bed8a7128500701354e2dc6098fa3 ]
The commit cited below switched from using napi_synchronize to synchronize_rcu to have a guarantee that it will finish in finite time. However, on average, synchronize_rcu takes more time than napi_synchronize. Given that it's called multiple times per channel on deactivation, it accumulates to a significant amount, which causes timeouts in some applications (for example, when using bonding with NetworkManager).
This commit replaces synchronize_rcu with synchronize_net, which is faster when called under rtnl_lock, allowing to speed up the described flow.
Fixes: 9c25a22dfb00 ("net/mlx5e: Use synchronize_rcu to sync with NAPI") Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h index d487e5e371625..8d991c3b7a503 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h @@ -83,7 +83,7 @@ static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state); /* Let other device's napi(s) and XSK wakeups see our new state. */ - synchronize_rcu(); + synchronize_net(); }
static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c index d87c345878d3d..f4bce1365639e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c @@ -111,7 +111,7 @@ err_free_cparam: void mlx5e_close_xsk(struct mlx5e_channel *c) { clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state); - synchronize_rcu(); /* Sync with the XSK wakeup and with NAPI. */ + synchronize_net(); /* Sync with the XSK wakeup and with NAPI. */
mlx5e_close_rq(&c->xskrq); mlx5e_close_cq(&c->xskrq.cq); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index 6a1d82503ef8f..0f13b661f7f98 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -663,7 +663,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx); set_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags); mlx5e_set_ktls_rx_priv_ctx(tls_ctx, NULL); - synchronize_rcu(); /* Sync with NAPI */ + synchronize_net(); /* Sync with NAPI */ if (!cancel_work_sync(&priv_rx->rule.work)) /* completion is needed, as the priv_rx in the add flow * is maintained on the wqe info (wi), not on the socket. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 92436569ce86b..5fb0ab71d79ce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -914,7 +914,7 @@ void mlx5e_activate_rq(struct mlx5e_rq *rq) void mlx5e_deactivate_rq(struct mlx5e_rq *rq) { clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state); - synchronize_rcu(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ + synchronize_net(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ }
void mlx5e_close_rq(struct mlx5e_rq *rq) @@ -1348,7 +1348,7 @@ void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) struct mlx5_wq_cyc *wq = &sq->wq;
clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - synchronize_rcu(); /* Sync with NAPI to prevent netif_tx_wake_queue. */ + synchronize_net(); /* Sync with NAPI to prevent netif_tx_wake_queue. */
mlx5e_tx_disable_queue(sq->txq);
@@ -1423,7 +1423,7 @@ void mlx5e_activate_icosq(struct mlx5e_icosq *icosq) void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq) { clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state); - synchronize_rcu(); /* Sync with NAPI. */ + synchronize_net(); /* Sync with NAPI. */ }
void mlx5e_close_icosq(struct mlx5e_icosq *sq) @@ -1502,7 +1502,7 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq) struct mlx5e_channel *c = sq->channel;
clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - synchronize_rcu(); /* Sync with NAPI. */ + synchronize_net(); /* Sync with NAPI. */
mlx5e_destroy_sq(c->mdev, sq->sqn); mlx5e_free_xdpsq_descs(sq);
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit b850bbff965129c34f50962638c0a66c82563536 ]
wait_for_resync is unreliable - if it timeouts, priv_rx will be freed anyway. However, mlx5e_ktls_handle_get_psv_completion will be called sooner or later, leading to use-after-free. For example, it can happen if a CQ error happened, and ICOSQ stopped, but later on the queues are destroyed, and ICOSQ is flushed with mlx5e_free_icosq_descs.
This patch converts the lifecycle of priv_rx to fully refcount-based, so that the struct won't be freed before the refcount goes to zero.
Fixes: 0419d8c9d8f8 ("net/mlx5e: kTLS, Add kTLS RX resync support") Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../mellanox/mlx5/core/en_accel/ktls_rx.c | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index 0f13b661f7f98..d06532d0baa43 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -57,6 +57,20 @@ struct mlx5e_ktls_offload_context_rx { struct mlx5e_ktls_rx_resync_ctx resync; };
+static bool mlx5e_ktls_priv_rx_put(struct mlx5e_ktls_offload_context_rx *priv_rx) +{ + if (!refcount_dec_and_test(&priv_rx->resync.refcnt)) + return false; + + kfree(priv_rx); + return true; +} + +static void mlx5e_ktls_priv_rx_get(struct mlx5e_ktls_offload_context_rx *priv_rx) +{ + refcount_inc(&priv_rx->resync.refcnt); +} + static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn) { int err, inlen; @@ -326,7 +340,7 @@ static void resync_handle_work(struct work_struct *work) priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync);
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) { - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); return; }
@@ -334,7 +348,7 @@ static void resync_handle_work(struct work_struct *work) sq = &c->async_icosq;
if (resync_post_get_progress_params(sq, priv_rx)) - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); }
static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync, @@ -377,7 +391,11 @@ unlock: return err; }
-/* Function is called with elevated refcount, it decreases it. */ +/* Function can be called with the refcount being either elevated or not. + * It decreases the refcount and may free the kTLS priv context. + * Refcount is not elevated only if tls_dev_del has been called, but GET_PSV was + * already in flight. + */ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, struct mlx5e_icosq *sq) { @@ -410,7 +428,7 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq)); priv_rx->stats->tls_resync_req_end++; out: - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx); dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE); kfree(buf); } @@ -431,9 +449,9 @@ static bool resync_queue_get_psv(struct sock *sk) return false;
resync = &priv_rx->resync; - refcount_inc(&resync->refcnt); + mlx5e_ktls_priv_rx_get(priv_rx); if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work))) - refcount_dec(&resync->refcnt); + mlx5e_ktls_priv_rx_put(priv_rx);
return true; } @@ -625,31 +643,6 @@ err_create_key: return err; }
-/* Elevated refcount on the resync object means there are - * outstanding operations (uncompleted GET_PSV WQEs) that - * will read the resync / priv_rx objects once completed. - * Wait for them to avoid use-after-free. - */ -static void wait_for_resync(struct net_device *netdev, - struct mlx5e_ktls_rx_resync_ctx *resync) -{ -#define MLX5E_KTLS_RX_RESYNC_TIMEOUT 20000 /* msecs */ - unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5E_KTLS_RX_RESYNC_TIMEOUT); - unsigned int refcnt; - - do { - refcnt = refcount_read(&resync->refcnt); - if (refcnt == 1) - return; - - msleep(20); - } while (time_before(jiffies, exp_time)); - - netdev_warn(netdev, - "Failed waiting for kTLS RX resync refcnt to be released (%u).\n", - refcnt); -} - void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) { struct mlx5e_ktls_offload_context_rx *priv_rx; @@ -671,8 +664,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) wait_for_completion(&priv_rx->add_ctx); resync = &priv_rx->resync; if (cancel_work_sync(&resync->work)) - refcount_dec(&resync->refcnt); - wait_for_resync(netdev, resync); + mlx5e_ktls_priv_rx_put(priv_rx);
priv_rx->stats->tls_del++; if (priv_rx->rule.rule) @@ -680,5 +672,9 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
mlx5_core_destroy_tir(mdev, priv_rx->tirn); mlx5_ktls_destroy_key(mdev, priv_rx->key_id); - kfree(priv_rx); + /* priv_rx should normally be freed here, but if there is an outstanding + * GET_PSV, deallocation will be delayed until the CQE for GET_PSV is + * processed. + */ + mlx5e_ktls_priv_rx_put(priv_rx); }
From: Shay Drory shayd@nvidia.com
[ Upstream commit d89ddaae1766f8fe571ea6eb63ec098ff556f1dd ]
Devlink reload can't be allowed on a multi port slave device, because reload of slave device doesn't take effect.
The right flow is to disable devlink reload for multi port slave device. Hence, disabling it in mlx5_core probing.
Fixes: 4383cfcc65e7 ("net/mlx5: Add devlink reload") Signed-off-by: Shay Drory shayd@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index ca6f2fc39ea0a..ba1a4ae28097d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1396,7 +1396,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id) dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
pci_save_state(pdev); - devlink_reload_enable(devlink); + if (!mlx5_core_is_mp_slave(dev)) + devlink_reload_enable(devlink); return 0;
err_load_one:
From: Shay Drory shayd@nvidia.com
[ Upstream commit c70f8597fcc1399ef6d5b5ce648a31d887d5dba2 ]
In dual port mode, setting roce enabled/disable for the slave device have no effect. e.g.: the slave device roce status remain unchanged. Therefore disable it and add an error message. Enable or disable roce of the master device affect both master and slave devices.
Fixes: cc9defcbb8fa ("net/mlx5: Handle "enable_roce" devlink param") Signed-off-by: Shay Drory shayd@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 3261d0dc11044..317ce6b80b23b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -273,6 +273,10 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); return -EOPNOTSUPP; } + if (mlx5_core_is_mp_slave(dev)) { + NL_SET_ERR_MSG_MOD(extack, "Multi port slave device can't configure RoCE"); + return -EOPNOTSUPP; + }
return 0; }
From: Shay Drory shayd@nvidia.com
[ Upstream commit 7ab91f2b03367f9d25dd807ebdfb0d67295e0e41 ]
In lag mode, setting roce enabled/disable of lag device have no effect. e.g.: bond device (roce/vf_lag) roce status remain unchanged. Therefore disable it and add an error message.
Fixes: cc9defcbb8fa ("net/mlx5: Handle "enable_roce" devlink param") Signed-off-by: Shay Drory shayd@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 317ce6b80b23b..c7073193db140 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -273,8 +273,8 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); return -EOPNOTSUPP; } - if (mlx5_core_is_mp_slave(dev)) { - NL_SET_ERR_MSG_MOD(extack, "Multi port slave device can't configure RoCE"); + if (mlx5_core_is_mp_slave(dev) || mlx5_lag_is_active(dev)) { + NL_SET_ERR_MSG_MOD(extack, "Multi port slave/Lag device can't configure RoCE"); return -EOPNOTSUPP; }
From: Shay Drory shayd@nvidia.com
[ Upstream commit edac23c2b3d3ac64cfcd351087295893671adbf5 ]
Devlink reload can't be allowed on lag devices since reloading one lag device will cause traffic on the bond to get stucked. Users who wish to reload a lag device, need to remove the device from the bond, and only then reload it.
Fixes: 4383cfcc65e7 ("net/mlx5: Add devlink reload") Signed-off-by: Shay Drory shayd@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index c7073193db140..41474e42a819a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -128,6 +128,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, { struct mlx5_core_dev *dev = devlink_priv(devlink);
+ if (mlx5_lag_is_active(dev)) { + NL_SET_ERR_MSG_MOD(extack, "reload is unsupported in Lag mode\n"); + return -EOPNOTSUPP; + } + switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: mlx5_unload_one(dev, false);
From: Oz Shlomo ozsh@nvidia.com
[ Upstream commit a2173131526dc845eb1968a15bc192b3fc2ff000 ]
The ct entry object is accessed by the ct add, del, stats and restore methods. In addition, it is referenced from several hash tables.
The lifetime of the ct entry object was not managed which triggered race conditions as in the following kasan dump: [ 3374.973945] ================================================================== [ 3374.988552] BUG: KASAN: use-after-free in memcmp+0x4c/0x98 [ 3374.999590] Read of size 1 at addr ffff00036129ea55 by task ksoftirqd/1/15 [ 3375.016415] CPU: 1 PID: 15 Comm: ksoftirqd/1 Tainted: G O 5.4.31+ #1 [ 3375.055301] Call trace: [ 3375.060214] dump_backtrace+0x0/0x238 [ 3375.067580] show_stack+0x24/0x30 [ 3375.074244] dump_stack+0xe0/0x118 [ 3375.081085] print_address_description.isra.9+0x74/0x3d0 [ 3375.091771] __kasan_report+0x198/0x1e8 [ 3375.099486] kasan_report+0xc/0x18 [ 3375.106324] __asan_load1+0x60/0x68 [ 3375.113338] memcmp+0x4c/0x98 [ 3375.119409] mlx5e_tc_ct_restore_flow+0x3a4/0x6f8 [mlx5_core] [ 3375.131073] mlx5e_rep_tc_update_skb+0x1d4/0x2f0 [mlx5_core] [ 3375.142553] mlx5e_handle_rx_cqe_rep+0x198/0x308 [mlx5_core] [ 3375.154034] mlx5e_poll_rx_cq+0x2a0/0x1060 [mlx5_core] [ 3375.164459] mlx5e_napi_poll+0x1d4/0xa78 [mlx5_core] [ 3375.174453] net_rx_action+0x28c/0x7a8 [ 3375.182004] __do_softirq+0x1b4/0x5d0
Manage the lifetime of the ct entry object by using synchornization mechanisms for concurrent access.
Fixes: ac991b48d43c ("net/mlx5e: CT: Offload established flows") Signed-off-by: Roi Dayan roid@nvidia.com Signed-off-by: Oz Shlomo ozsh@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++++++++++----- 1 file changed, 192 insertions(+), 67 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index 6bc6b48a56dc7..24e2c0d955b99 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -12,6 +12,7 @@ #include <net/flow_offload.h> #include <net/netfilter/nf_flow_table.h> #include <linux/workqueue.h> +#include <linux/refcount.h> #include <linux/xarray.h>
#include "lib/fs_chains.h" @@ -51,11 +52,11 @@ struct mlx5_tc_ct_priv { struct mlx5_flow_table *ct_nat; struct mlx5_flow_table *post_ct; struct mutex control_lock; /* guards parallel adds/dels */ - struct mutex shared_counter_lock; struct mapping_ctx *zone_mapping; struct mapping_ctx *labels_mapping; enum mlx5_flow_namespace_type ns_type; struct mlx5_fs_chains *chains; + spinlock_t ht_lock; /* protects ft entries */ };
struct mlx5_ct_flow { @@ -124,6 +125,10 @@ struct mlx5_ct_counter { bool is_shared; };
+enum { + MLX5_CT_ENTRY_FLAG_VALID, +}; + struct mlx5_ct_entry { struct rhash_head node; struct rhash_head tuple_node; @@ -134,6 +139,12 @@ struct mlx5_ct_entry { struct mlx5_ct_tuple tuple; struct mlx5_ct_tuple tuple_nat; struct mlx5_ct_zone_rule zone_rules[2]; + + struct mlx5_tc_ct_priv *ct_priv; + struct work_struct work; + + refcount_t refcnt; + unsigned long flags; };
static const struct rhashtable_params cts_ht_params = { @@ -740,6 +751,87 @@ err_attr: return err; }
+static bool +mlx5_tc_ct_entry_valid(struct mlx5_ct_entry *entry) +{ + return test_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags); +} + +static struct mlx5_ct_entry * +mlx5_tc_ct_entry_get(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_tuple *tuple) +{ + struct mlx5_ct_entry *entry; + + entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, tuple, + tuples_ht_params); + if (entry && mlx5_tc_ct_entry_valid(entry) && + refcount_inc_not_zero(&entry->refcnt)) { + return entry; + } else if (!entry) { + entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht, + tuple, tuples_nat_ht_params); + if (entry && mlx5_tc_ct_entry_valid(entry) && + refcount_inc_not_zero(&entry->refcnt)) + return entry; + } + + return entry ? ERR_PTR(-EINVAL) : NULL; +} + +static void mlx5_tc_ct_entry_remove_from_tuples(struct mlx5_ct_entry *entry) +{ + struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv; + + rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, + &entry->tuple_nat_node, + tuples_nat_ht_params); + rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node, + tuples_ht_params); +} + +static void mlx5_tc_ct_entry_del(struct mlx5_ct_entry *entry) +{ + struct mlx5_tc_ct_priv *ct_priv = entry->ct_priv; + + mlx5_tc_ct_entry_del_rules(ct_priv, entry); + + spin_lock_bh(&ct_priv->ht_lock); + mlx5_tc_ct_entry_remove_from_tuples(entry); + spin_unlock_bh(&ct_priv->ht_lock); + + mlx5_tc_ct_counter_put(ct_priv, entry); + kfree(entry); +} + +static void +mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry) +{ + if (!refcount_dec_and_test(&entry->refcnt)) + return; + + mlx5_tc_ct_entry_del(entry); +} + +static void mlx5_tc_ct_entry_del_work(struct work_struct *work) +{ + struct mlx5_ct_entry *entry = container_of(work, struct mlx5_ct_entry, work); + + mlx5_tc_ct_entry_del(entry); +} + +static void +__mlx5_tc_ct_entry_put(struct mlx5_ct_entry *entry) +{ + struct mlx5e_priv *priv; + + if (!refcount_dec_and_test(&entry->refcnt)) + return; + + priv = netdev_priv(entry->ct_priv->netdev); + INIT_WORK(&entry->work, mlx5_tc_ct_entry_del_work); + queue_work(priv->wq, &entry->work); +} + static struct mlx5_ct_counter * mlx5_tc_ct_counter_create(struct mlx5_tc_ct_priv *ct_priv) { @@ -792,16 +884,26 @@ mlx5_tc_ct_shared_counter_get(struct mlx5_tc_ct_priv *ct_priv, }
/* Use the same counter as the reverse direction */ - mutex_lock(&ct_priv->shared_counter_lock); - rev_entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &rev_tuple, - tuples_ht_params); - if (rev_entry) { - if (refcount_inc_not_zero(&rev_entry->counter->refcount)) { - mutex_unlock(&ct_priv->shared_counter_lock); - return rev_entry->counter; - } + spin_lock_bh(&ct_priv->ht_lock); + rev_entry = mlx5_tc_ct_entry_get(ct_priv, &rev_tuple); + + if (IS_ERR(rev_entry)) { + spin_unlock_bh(&ct_priv->ht_lock); + goto create_counter; + } + + if (rev_entry && refcount_inc_not_zero(&rev_entry->counter->refcount)) { + ct_dbg("Using shared counter entry=0x%p rev=0x%p\n", entry, rev_entry); + shared_counter = rev_entry->counter; + spin_unlock_bh(&ct_priv->ht_lock); + + mlx5_tc_ct_entry_put(rev_entry); + return shared_counter; } - mutex_unlock(&ct_priv->shared_counter_lock); + + spin_unlock_bh(&ct_priv->ht_lock); + +create_counter:
shared_counter = mlx5_tc_ct_counter_create(ct_priv); if (IS_ERR(shared_counter)) { @@ -866,10 +968,14 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, if (!meta_action) return -EOPNOTSUPP;
- entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, - cts_ht_params); - if (entry) - return 0; + spin_lock_bh(&ct_priv->ht_lock); + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); + if (entry && refcount_inc_not_zero(&entry->refcnt)) { + spin_unlock_bh(&ct_priv->ht_lock); + mlx5_tc_ct_entry_put(entry); + return -EEXIST; + } + spin_unlock_bh(&ct_priv->ht_lock);
entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) @@ -878,6 +984,8 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, entry->tuple.zone = ft->zone; entry->cookie = flow->cookie; entry->restore_cookie = meta_action->ct_metadata.cookie; + refcount_set(&entry->refcnt, 2); + entry->ct_priv = ct_priv;
err = mlx5_tc_ct_rule_to_tuple(&entry->tuple, flow_rule); if (err) @@ -888,35 +996,40 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, if (err) goto err_set;
- err = rhashtable_insert_fast(&ct_priv->ct_tuples_ht, - &entry->tuple_node, - tuples_ht_params); + spin_lock_bh(&ct_priv->ht_lock); + + err = rhashtable_lookup_insert_fast(&ft->ct_entries_ht, &entry->node, + cts_ht_params); + if (err) + goto err_entries; + + err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_ht, + &entry->tuple_node, + tuples_ht_params); if (err) goto err_tuple;
if (memcmp(&entry->tuple, &entry->tuple_nat, sizeof(entry->tuple))) { - err = rhashtable_insert_fast(&ct_priv->ct_tuples_nat_ht, - &entry->tuple_nat_node, - tuples_nat_ht_params); + err = rhashtable_lookup_insert_fast(&ct_priv->ct_tuples_nat_ht, + &entry->tuple_nat_node, + tuples_nat_ht_params); if (err) goto err_tuple_nat; } + spin_unlock_bh(&ct_priv->ht_lock);
err = mlx5_tc_ct_entry_add_rules(ct_priv, flow_rule, entry, ft->zone_restore_id); if (err) goto err_rules;
- err = rhashtable_insert_fast(&ft->ct_entries_ht, &entry->node, - cts_ht_params); - if (err) - goto err_insert; + set_bit(MLX5_CT_ENTRY_FLAG_VALID, &entry->flags); + mlx5_tc_ct_entry_put(entry); /* this function reference */
return 0;
-err_insert: - mlx5_tc_ct_entry_del_rules(ct_priv, entry); err_rules: + spin_lock_bh(&ct_priv->ht_lock); if (mlx5_tc_ct_entry_has_nat(entry)) rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, &entry->tuple_nat_node, tuples_nat_ht_params); @@ -925,47 +1038,43 @@ err_tuple_nat: &entry->tuple_node, tuples_ht_params); err_tuple: + rhashtable_remove_fast(&ft->ct_entries_ht, + &entry->node, + cts_ht_params); +err_entries: + spin_unlock_bh(&ct_priv->ht_lock); err_set: kfree(entry); - netdev_warn(ct_priv->netdev, - "Failed to offload ct entry, err: %d\n", err); + if (err != -EEXIST) + netdev_warn(ct_priv->netdev, "Failed to offload ct entry, err: %d\n", err); return err; }
-static void -mlx5_tc_ct_del_ft_entry(struct mlx5_tc_ct_priv *ct_priv, - struct mlx5_ct_entry *entry) -{ - mlx5_tc_ct_entry_del_rules(ct_priv, entry); - mutex_lock(&ct_priv->shared_counter_lock); - if (mlx5_tc_ct_entry_has_nat(entry)) - rhashtable_remove_fast(&ct_priv->ct_tuples_nat_ht, - &entry->tuple_nat_node, - tuples_nat_ht_params); - rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node, - tuples_ht_params); - mutex_unlock(&ct_priv->shared_counter_lock); - mlx5_tc_ct_counter_put(ct_priv, entry); - -} - static int mlx5_tc_ct_block_flow_offload_del(struct mlx5_ct_ft *ft, struct flow_cls_offload *flow) { + struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv; unsigned long cookie = flow->cookie; struct mlx5_ct_entry *entry;
- entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, - cts_ht_params); - if (!entry) + spin_lock_bh(&ct_priv->ht_lock); + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); + if (!entry) { + spin_unlock_bh(&ct_priv->ht_lock); return -ENOENT; + }
- mlx5_tc_ct_del_ft_entry(ft->ct_priv, entry); - WARN_ON(rhashtable_remove_fast(&ft->ct_entries_ht, - &entry->node, - cts_ht_params)); - kfree(entry); + if (!mlx5_tc_ct_entry_valid(entry)) { + spin_unlock_bh(&ct_priv->ht_lock); + return -EINVAL; + } + + rhashtable_remove_fast(&ft->ct_entries_ht, &entry->node, cts_ht_params); + mlx5_tc_ct_entry_remove_from_tuples(entry); + spin_unlock_bh(&ct_priv->ht_lock); + + mlx5_tc_ct_entry_put(entry);
return 0; } @@ -974,19 +1083,30 @@ static int mlx5_tc_ct_block_flow_offload_stats(struct mlx5_ct_ft *ft, struct flow_cls_offload *f) { + struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv; unsigned long cookie = f->cookie; struct mlx5_ct_entry *entry; u64 lastuse, packets, bytes;
- entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, - cts_ht_params); - if (!entry) + spin_lock_bh(&ct_priv->ht_lock); + entry = rhashtable_lookup_fast(&ft->ct_entries_ht, &cookie, cts_ht_params); + if (!entry) { + spin_unlock_bh(&ct_priv->ht_lock); return -ENOENT; + } + + if (!mlx5_tc_ct_entry_valid(entry) || !refcount_inc_not_zero(&entry->refcnt)) { + spin_unlock_bh(&ct_priv->ht_lock); + return -EINVAL; + } + + spin_unlock_bh(&ct_priv->ht_lock);
mlx5_fc_query_cached(entry->counter->counter, &bytes, &packets, &lastuse); flow_stats_update(&f->stats, bytes, packets, 0, lastuse, FLOW_ACTION_HW_STATS_DELAYED);
+ mlx5_tc_ct_entry_put(entry); return 0; }
@@ -1478,11 +1598,9 @@ err_mapping: static void mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg) { - struct mlx5_tc_ct_priv *ct_priv = arg; struct mlx5_ct_entry *entry = ptr;
- mlx5_tc_ct_del_ft_entry(ct_priv, entry); - kfree(entry); + mlx5_tc_ct_entry_put(entry); }
static void @@ -1960,6 +2078,7 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains, goto err_mapping_labels; }
+ spin_lock_init(&ct_priv->ht_lock); ct_priv->ns_type = ns_type; ct_priv->chains = chains; ct_priv->netdev = priv->netdev; @@ -1994,7 +2113,6 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
idr_init(&ct_priv->fte_ids); mutex_init(&ct_priv->control_lock); - mutex_init(&ct_priv->shared_counter_lock); rhashtable_init(&ct_priv->zone_ht, &zone_params); rhashtable_init(&ct_priv->ct_tuples_ht, &tuples_ht_params); rhashtable_init(&ct_priv->ct_tuples_nat_ht, &tuples_nat_ht_params); @@ -2037,7 +2155,6 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv) rhashtable_destroy(&ct_priv->ct_tuples_nat_ht); rhashtable_destroy(&ct_priv->zone_ht); mutex_destroy(&ct_priv->control_lock); - mutex_destroy(&ct_priv->shared_counter_lock); idr_destroy(&ct_priv->fte_ids); kfree(ct_priv); } @@ -2059,14 +2176,22 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv, if (!mlx5_tc_ct_skb_to_tuple(skb, &tuple, zone)) return false;
- entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &tuple, - tuples_ht_params); - if (!entry) - entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_nat_ht, - &tuple, tuples_nat_ht_params); - if (!entry) + spin_lock(&ct_priv->ht_lock); + + entry = mlx5_tc_ct_entry_get(ct_priv, &tuple); + if (!entry) { + spin_unlock(&ct_priv->ht_lock); + return false; + } + + if (IS_ERR(entry)) { + spin_unlock(&ct_priv->ht_lock); return false; + } + spin_unlock(&ct_priv->ht_lock);
tcf_ct_flow_table_restore_skb(skb, entry->restore_cookie); + __mlx5_tc_ct_entry_put(entry); + return true; }
From: Moshe Shemesh moshe@nvidia.com
[ Upstream commit e1c3940c6003d820c787473c65711b49c2d1bc42 ]
Check that tunnel offload is required before setting Software Parser offsets to get Geneve HW offload. In case of Geneve packet we check HW offload support of SWP in mlx5e_tunnel_features_check() and set features accordingly, this should be reflected in skb offload requested by the kernel and we should add the Software Parser offsets only if requested. Otherwise, in case HW doesn't support SWP for Geneve, data path will mistakenly try to offload Geneve SKBs with skb->encapsulation set, regardless of whether offload was requested or not on this specific SKB.
Fixes: e3cfc7e6b7bd ("net/mlx5e: TX, Add geneve tunnel stateless offload support") Signed-off-by: Moshe Shemesh moshe@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h index 1fae7fab8297e..ff81b69a59a9b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h @@ -173,7 +173,7 @@ static inline bool mlx5e_accel_tx_eseg(struct mlx5e_priv *priv, #endif
#if IS_ENABLED(CONFIG_GENEVE) - if (skb->encapsulation) + if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) mlx5e_tx_tunnel_accel(skb, eseg, ihs); #endif
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 6194f7e6473be78acdc5d03edd116944bdbb2c4e ]
The multiplication of the u32 variables tx_time and estimated_retx is performed using a 32 bit multiplication and the result is stored in a u64 result. This has a potential u32 overflow issue, so avoid this by casting tx_time to a u64 to force a 64 bit multiply.
Addresses-Coverity: ("Unintentional integer overflow") Fixes: 050ac52cbe1f ("mac80211: code for on-demand Hybrid Wireless Mesh Protocol") Signed-off-by: Colin Ian King colin.king@canonical.com Link: https://lore.kernel.org/r/20210205175352.208841-1-colin.king@canonical.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/mesh_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 313eee12410ec..3db514c4c63ab 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -356,7 +356,7 @@ u32 airtime_link_metric_get(struct ieee80211_local *local, */ tx_time = (device_constant + 10 * test_frame_len / rate); estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); - result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT); + result = ((u64)tx_time * estimated_retx) >> (2 * ARITH_SHIFT); return (u32)result; }
From: Martin KaFai Lau kafai@fb.com
[ Upstream commit d2836dddc95d5dd82c7cb23726c97d8c9147f050 ]
When libbpf initializes the kernel's struct_ops in "bpf_map__init_kern_struct_ops()", it enforces all pointer types must be a function pointer and rejects others. It turns out to be too strict. For example, when directly using "struct tcp_congestion_ops" from vmlinux.h, it has a "struct module *owner" member and it is set to NULL in a bpf_tcp_cc.o.
Instead, it only needs to ensure the member is a function pointer if it has been set (relocated) to a bpf-prog. This patch moves the "btf_is_func_proto(kern_mtype)" check after the existing "if (!prog) { continue; }". The original debug message in "if (!prog) { continue; }" is also removed since it is no longer valid. Beside, there is a later debug message to tell which function pointer is set.
The "btf_is_func_proto(mtype)" has already been guaranteed in "bpf_object__collect_st_ops_relos()" which has been run before "bpf_map__init_kern_struct_ops()". Thus, this check is removed.
v2: - Remove outdated debug message (Andrii) Remove because there is a later debug message to tell which function pointer is set. - Following mtype->type is no longer needed. Remove: "skip_mods_and_typedefs(btf, mtype->type, &mtype_id)" - Do "if (!prog)" test before skip_mods_and_typedefs.
Fixes: 590a00888250 ("bpf: libbpf: Add STRUCT_OPS support") Signed-off-by: Martin KaFai Lau kafai@fb.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Acked-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20210212021030.266932-1-kafai@fb.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/lib/bpf/libbpf.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 6ae748f6ea118..a0d4fc4de4027 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -883,24 +883,24 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map, if (btf_is_ptr(mtype)) { struct bpf_program *prog;
- mtype = skip_mods_and_typedefs(btf, mtype->type, &mtype_id); + prog = st_ops->progs[i]; + if (!prog) + continue; + kern_mtype = skip_mods_and_typedefs(kern_btf, kern_mtype->type, &kern_mtype_id); - if (!btf_is_func_proto(mtype) || - !btf_is_func_proto(kern_mtype)) { - pr_warn("struct_ops init_kern %s: non func ptr %s is not supported\n", + + /* mtype->type must be a func_proto which was + * guaranteed in bpf_object__collect_st_ops_relos(), + * so only check kern_mtype for func_proto here. + */ + if (!btf_is_func_proto(kern_mtype)) { + pr_warn("struct_ops init_kern %s: kernel member %s is not a func ptr\n", map->name, mname); return -ENOTSUP; }
- prog = st_ops->progs[i]; - if (!prog) { - pr_debug("struct_ops init_kern %s: func ptr %s is not set\n", - map->name, mname); - continue; - } - prog->attach_btf_id = kern_type_id; prog->expected_attach_type = kern_member_idx;
From: Yonghong Song yhs@fb.com
[ Upstream commit 17d8beda277a36203585943e70c7909b60775fd5 ]
Commit 15d83c4d7cef ("bpf: Allow loading of a bpf_iter program") cached btf_id in struct bpf_iter_target_info so later on if it can be checked cheaply compared to checking registered names.
syzbot found a bug that uninitialized value may occur to bpf_iter_target_info->btf_id. This is because we allocated bpf_iter_target_info structure with kmalloc and never initialized field btf_id afterwards. This uninitialized btf_id is typically compared to a u32 bpf program func proto btf_id, and the chance of being equal is extremely slim.
This patch fixed the issue by using kzalloc which will also prevent future likely instances due to adding new fields.
Fixes: 15d83c4d7cef ("bpf: Allow loading of a bpf_iter program") Reported-by: syzbot+580f4f2a272e452d55cb@syzkaller.appspotmail.com Signed-off-by: Yonghong Song yhs@fb.com Signed-off-by: Alexei Starovoitov ast@kernel.org Link: https://lore.kernel.org/bpf/20210212005926.2875002-1-yhs@fb.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/bpf_iter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c index 5454161407f1f..a0d9eade9c804 100644 --- a/kernel/bpf/bpf_iter.c +++ b/kernel/bpf/bpf_iter.c @@ -287,7 +287,7 @@ int bpf_iter_reg_target(const struct bpf_iter_reg *reg_info) { struct bpf_iter_target_info *tinfo;
- tinfo = kmalloc(sizeof(*tinfo), GFP_KERNEL); + tinfo = kzalloc(sizeof(*tinfo), GFP_KERNEL); if (!tinfo) return -ENOMEM;
From: Jun'ichi Nomura junichi.nomura@nec.com
[ Upstream commit 7d4553b69fb335496c597c31590e982485ebe071 ]
The devmap bulk queue is allocated with GFP_ATOMIC and the allocation may fail if there is no available space in existing percpu pool.
Since commit 75ccae62cb8d42 ("xdp: Move devmap bulk queue into struct net_device") moved the bulk queue allocation to NETDEV_REGISTER callback, whose context is allowed to sleep, use GFP_KERNEL instead of GFP_ATOMIC to let percpu allocator extend the pool when needed and avoid possible failure of netdev registration.
As the required alignment is natural, we can simply use alloc_percpu().
Fixes: 75ccae62cb8d42 ("xdp: Move devmap bulk queue into struct net_device") Signed-off-by: Jun'ichi Nomura junichi.nomura@nec.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Cc: Toke Høiland-Jørgensen toke@redhat.com Link: https://lore.kernel.org/bpf/20210209082451.GA44021@jeru.linux.bs1.fc.nec.co.... Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/devmap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index f6e9c68afdd42..85d9d1b72a33a 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -802,9 +802,7 @@ static int dev_map_notification(struct notifier_block *notifier, break;
/* will be freed in free_netdev() */ - netdev->xdp_bulkq = - __alloc_percpu_gfp(sizeof(struct xdp_dev_bulk_queue), - sizeof(void *), GFP_ATOMIC); + netdev->xdp_bulkq = alloc_percpu(struct xdp_dev_bulk_queue); if (!netdev->xdp_bulkq) return NOTIFY_BAD;
From: Jesper Dangaard Brouer brouer@redhat.com
[ Upstream commit 2c0a10af688c02adcf127aad29e923e0056c6b69 ]
BPF end-user on Cilium slack-channel (Carlo Carraro) wants to use bpf_fib_lookup for doing MTU-check, but *prior* to extending packet size, by adjusting fib_params 'tot_len' with the packet length plus the expected encap size. (Just like the bpf_check_mtu helper supports). He discovered that for SKB ctx the param->tot_len was not used, instead skb->len was used (via MTU check in is_skb_forwardable() that checks against netdev MTU).
Fix this by using fib_params 'tot_len' for MTU check. If not provided (e.g. zero) then keep existing TC behaviour intact. Notice that 'tot_len' for MTU check is done like XDP code-path, which checks against FIB-dst MTU.
V16: - Revert V13 optimization, 2nd lookup is against egress/resulting netdev
V13: - Only do ifindex lookup one time, calling dev_get_by_index_rcu().
V10: - Use same method as XDP for 'tot_len' MTU check
Fixes: 4c79579b44b1 ("bpf: Change bpf_fib_lookup to return lookup status") Reported-by: Carlo Carraro colrack@gmail.com Signed-off-by: Jesper Dangaard Brouer brouer@redhat.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/161287789444.790810.15247494756551413508.stgit@f... Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/filter.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c index 255aeee724026..ee665720a41a0 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -5552,6 +5552,7 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, { struct net *net = dev_net(skb->dev); int rc = -EAFNOSUPPORT; + bool check_mtu = false;
if (plen < sizeof(*params)) return -EINVAL; @@ -5559,22 +5560,28 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT)) return -EINVAL;
+ if (params->tot_len) + check_mtu = true; + switch (params->family) { #if IS_ENABLED(CONFIG_INET) case AF_INET: - rc = bpf_ipv4_fib_lookup(net, params, flags, false); + rc = bpf_ipv4_fib_lookup(net, params, flags, check_mtu); break; #endif #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: - rc = bpf_ipv6_fib_lookup(net, params, flags, false); + rc = bpf_ipv6_fib_lookup(net, params, flags, check_mtu); break; #endif }
- if (!rc) { + if (rc == BPF_FIB_LKUP_RET_SUCCESS && !check_mtu) { struct net_device *dev;
+ /* When tot_len isn't provided by user, check skb + * against MTU of FIB lookup resulting net_device + */ dev = dev_get_by_index_rcu(net, params->ifindex); if (!is_skb_forwardable(dev, skb)) rc = BPF_FIB_LKUP_RET_FRAG_NEEDED;
From: Matthieu Baerts matthieu.baerts@tessares.net
[ Upstream commit f384221a381751508f390b36d0e51bd5a7beb627 ]
Info from received MPCapable SYN were printed instead of the ones from received MPCapable 3rd ACK.
Fixes: fed61c4b584c ("selftests: mptcp: make 2nd net namespace use tcp syn cookies unconditionally") Signed-off-by: Matthieu Baerts matthieu.baerts@tessares.net Signed-off-by: Mat Martineau mathew.j.martineau@linux.intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh index 2cfd87d94db89..e927df83efb91 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh @@ -493,7 +493,7 @@ do_transfer() echo "${listener_ns} SYNRX: ${cl_proto} -> ${srv_proto}: expect ${expect_synrx}, got ${stat_synrx_now_l}" fi if [ $expect_ackrx -ne $stat_ackrx_now_l ] ;then - echo "${listener_ns} ACKRX: ${cl_proto} -> ${srv_proto}: expect ${expect_synrx}, got ${stat_synrx_now_l}" + echo "${listener_ns} ACKRX: ${cl_proto} -> ${srv_proto}: expect ${expect_ackrx}, got ${stat_ackrx_now_l} " fi
if [ $retc -eq 0 ] && [ $rets -eq 0 ];then
From: Eric Dumazet edumazet@google.com
[ Upstream commit f969dc5a885736842c3511ecdea240fbb02d25d9 ]
While commit 24adbc1676af ("tcp: fix SO_RCVLOWAT hangs with fat skbs") fixed an issue vs too small sk_rcvbuf for given sk_rcvlowat constraint, it missed to address issue caused by memory pressure.
1) If we are under memory pressure and socket receive queue is empty. First incoming packet is allowed to be queued, after commit 76dfa6082032 ("tcp: allow one skb to be received per socket under memory pressure")
But we do not send EPOLLIN yet, in case tcp_data_ready() sees sk_rcvlowat is bigger than skb length.
2) Then, when next packet comes, it is dropped, and we directly call sk->sk_data_ready().
3) If application is using poll(), tcp_poll() will then use tcp_stream_is_readable() and decide the socket receive queue is not yet filled, so nothing will happen.
Even when sender retransmits packets, phases 2) & 3) repeat and flow is effectively frozen, until memory pressure is off.
Fix is to consider tcp_under_memory_pressure() to take care of global memory pressure or memcg pressure.
Fixes: 24adbc1676af ("tcp: fix SO_RCVLOWAT hangs with fat skbs") Signed-off-by: Eric Dumazet edumazet@google.com Reported-by: Arjun Roy arjunroy@google.com Suggested-by: Wei Wang weiwan@google.com Reviewed-by: Wei Wang weiwan@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/tcp.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h index 25bbada379c46..244208f6f6c2a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1431,8 +1431,13 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied); */ static inline bool tcp_rmem_pressure(const struct sock *sk) { - int rcvbuf = READ_ONCE(sk->sk_rcvbuf); - int threshold = rcvbuf - (rcvbuf >> 3); + int rcvbuf, threshold; + + if (tcp_under_memory_pressure(sk)) + return true; + + rcvbuf = READ_ONCE(sk->sk_rcvbuf); + threshold = rcvbuf - (rcvbuf >> 3);
return atomic_read(&sk->sk_rmem_alloc) > threshold; }
From: Robert Hancock robert.hancock@calian.com
[ Upstream commit 57baf8cc70ea4cf5503c9d42f31f6a86d7f5ff1a ]
This driver is set up to use a clock mapping in the device tree if it is present, but still work without one for backward compatibility. However, if getting the clock returns -EPROBE_DEFER, then we need to abort and return that error from our driver initialization so that the probe can be retried later after the clock is set up.
Move clock initialization to earlier in the process so we do not waste as much effort if the clock is not yet available. Switch to use devm_clk_get_optional and abort initialization on any error reported. Also enable the clock regardless of whether the controller is using an MDIO bus, as the clock is required in any case.
Fixes: 09a0354cadec267be7f ("net: axienet: Use clock framework to get device clock rate") Signed-off-by: Robert Hancock robert.hancock@calian.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/xilinx/xilinx_axienet_main.c | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 6fea980acf646..b4a0bfce5b762 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1817,6 +1817,18 @@ static int axienet_probe(struct platform_device *pdev) lp->options = XAE_OPTION_DEFAULTS; lp->rx_bd_num = RX_BD_NUM_DEFAULT; lp->tx_bd_num = TX_BD_NUM_DEFAULT; + + lp->clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(lp->clk)) { + ret = PTR_ERR(lp->clk); + goto free_netdev; + } + ret = clk_prepare_enable(lp->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock: %d\n", ret); + goto free_netdev; + } + /* Map device registers */ ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0); lp->regs = devm_ioremap_resource(&pdev->dev, ethres); @@ -1992,20 +2004,6 @@ static int axienet_probe(struct platform_device *pdev)
lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); if (lp->phy_node) { - lp->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(lp->clk)) { - dev_warn(&pdev->dev, "Failed to get clock: %ld\n", - PTR_ERR(lp->clk)); - lp->clk = NULL; - } else { - ret = clk_prepare_enable(lp->clk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable clock: %d\n", - ret); - goto free_netdev; - } - } - ret = axienet_mdio_setup(lp); if (ret) dev_warn(&pdev->dev,
From: Ayush Sawal ayush.sawal@chelsio.com
[ Upstream commit 2355a6773a2cb0d2dce13432dde78497f1d6617b ]
The Max imm data size in cxgb4 is not similar to the max imm data size in the chtls. This caused an mismatch in output of is_ofld_imm() of cxgb4 and chtls. So fixed this by keeping the max wreq size of imm data same in both chtls and cxgb4 as MAX_IMM_OFLD_TX_DATA_WR_LEN.
As cxgb4's max imm. data value for ofld packets is changed to MAX_IMM_OFLD_TX_DATA_WR_LEN. Using the same in cxgbit also.
Fixes: 36bedb3f2e5b8 ("crypto: chtls - Inline TLS record Tx") Signed-off-by: Ayush Sawal ayush.sawal@chelsio.com Acked-by: Jakub Kicinski kuba@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 ++++++++--- .../ethernet/chelsio/inline_crypto/chtls/chtls_cm.h | 3 --- drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-- 4 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1b49f2fa9b185..34546f5312eee 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -46,6 +46,9 @@ #define MAX_ULD_QSETS 16 #define MAX_ULD_NPORTS 4
+/* ulp_mem_io + ulptx_idata + payload + padding */ +#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) + /* CPL message priority levels */ enum { CPL_PRIORITY_DATA = 0, /* data messages */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 196652a114c5f..3334c9e2152ab 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2842,17 +2842,22 @@ int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb) * @skb: the packet * * Returns true if a packet can be sent as an offload WR with immediate - * data. We currently use the same limit as for Ethernet packets. + * data. + * FW_OFLD_TX_DATA_WR limits the payload to 255 bytes due to 8-bit field. + * However, FW_ULPTX_WR commands have a 256 byte immediate only + * payload limit. */ static inline int is_ofld_imm(const struct sk_buff *skb) { struct work_request_hdr *req = (struct work_request_hdr *)skb->data; unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi));
- if (opcode == FW_CRYPTO_LOOKASIDE_WR) + if (unlikely(opcode == FW_ULPTX_WR)) + return skb->len <= MAX_IMM_ULPTX_WR_LEN; + else if (opcode == FW_CRYPTO_LOOKASIDE_WR) return skb->len <= SGE_MAX_WR_LEN; else - return skb->len <= MAX_IMM_TX_PKT_LEN; + return skb->len <= MAX_IMM_OFLD_TX_DATA_WR_LEN; }
/** diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h index 47ba81e42f5d0..b1161bdeda4dc 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h @@ -50,9 +50,6 @@ #define MIN_RCV_WND (24 * 1024U) #define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
-/* ulp_mem_io + ulptx_idata + payload + padding */ -#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) - /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ #define TX_HEADER_LEN \ (sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr)) diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 9b3eb2e8c92ad..b926e1d6c7b8e 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -86,8 +86,7 @@ static int cxgbit_is_ofld_imm(const struct sk_buff *skb) if (likely(cxgbit_skcb_flags(skb) & SKCBF_TX_ISO)) length += sizeof(struct cpl_tx_data_iso);
-#define MAX_IMM_TX_PKT_LEN 256 - return length <= MAX_IMM_TX_PKT_LEN; + return length <= MAX_IMM_OFLD_TX_DATA_WR_LEN; }
/*
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 4773acf3d4b50768bf08e9e97a204819e9ea0895 ]
The documentation for the PHY update [1] states:
Loop 4 times with index i
If PHY Revision >= 3 Copy table[i] to coef[i] Otherwise Set coef[i] to 0
the copy of the table to coef is currently implemented the wrong way around, table is being updated from uninitialized values in coeff. Fix this by swapping the assignment around.
[1] https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal/
Fixes: 2f258b74d13c ("b43: N-PHY: implement restoring general configuration") Addresses-Coverity: ("Uninitialized scalar variable") Signed-off-by: Colin Ian King colin.king@canonical.com Acked-by: Larry Finger Larry.Finger@lwfinger.net Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/broadcom/b43/phy_n.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c index b669dff24b6e0..665b737fbb0d8 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -5311,7 +5311,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
for (i = 0; i < 4; i++) { if (dev->phy.rev >= 3) - table[i] = coef[i]; + coef[i] = table[i]; else coef[i] = 0; }
From: Ilya Leoshkevich iii@linux.ibm.com
[ Upstream commit 45159b27637b0fef6d5ddb86fc7c46b13c77960f ]
test_global_func4 fails on s390 as reported by Yauheni in [1].
The immediate problem is that the zext code includes the instruction, whose result needs to be zero-extended, into the zero-extension patchlet, and if this instruction happens to be a branch, then its delta is not adjusted. As a result, the verifier rejects the program later.
However, according to [2], as far as the verifier's algorithm is concerned and as specified by the insn_no_def() function, branching insns do not define anything. This includes call insns, even though one might argue that they define %r0.
This means that the real problem is that zero extension kicks in at all. This happens because clear_caller_saved_regs() sets BPF_REG_0's subreg_def after global function calls. This can be fixed in many ways; this patch mimics what helper function call handling already does.
[1] https://lore.kernel.org/bpf/20200903140542.156624-1-yauheni.kaliuta@redhat.c... [2] https://lore.kernel.org/bpf/CAADnVQ+2RPKcftZw8d+B1UwB35cpBhpF5u3OocNh90D9pET...
Fixes: 51c39bb1d5d1 ("bpf: Introduce function-by-function verification") Reported-by: Yauheni Kaliuta yauheni.kaliuta@redhat.com Signed-off-by: Ilya Leoshkevich iii@linux.ibm.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20210212040408.90109-1-iii@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/verifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 20babdd06278f..33683eafea90e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -4834,8 +4834,9 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, subprog); clear_caller_saved_regs(env, caller->regs);
- /* All global functions return SCALAR_VALUE */ + /* All global functions return a 64-bit SCALAR_VALUE */ mark_reg_unknown(env, caller->regs, BPF_REG_0); + caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
/* continue with next insn after call */ return 0;
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 42557dab78edc8235aba5b441f2eb35f725a0ede ]
dma_rmb() barrier is added to load the long term buffer before copying it to socket buffer; and dma_wmb() barrier is added to update the long term buffer before it being accessed by VIOS (virtual i/o server).
Fixes: 032c5e82847a ("Driver for IBM System i/p VNIC protocol") Signed-off-by: Lijun Pan ljp@linux.ibm.com Acked-by: Thomas Falcon tlfalcon@linux.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 621be6d2da971..f6402a20ba320 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1700,6 +1700,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) skb_copy_from_linear_data(skb, dst, skb->len); }
+ /* post changes to long_term_buff *dst before VIOS accessing it */ + dma_wmb(); + tx_pool->consumer_index = (tx_pool->consumer_index + 1) % tx_pool->num_buffers;
@@ -2539,6 +2542,8 @@ restart_poll: offset = be16_to_cpu(next->rx_comp.off_frame_data); flags = next->rx_comp.flags; skb = rx_buff->skb; + /* load long_term_buff before copying to skb */ + dma_rmb(); skb_copy_to_linear_data(skb, rx_buff->data + offset, length);
From: Lijun Pan ljp@linux.ibm.com
[ Upstream commit 7d3a7b9ea59ddb223aec59b45fa1713c633aaed4 ]
Timeout reset will trigger the VIOS to unmap it automatically, similarly as FAILVOER and MOBILITY events. If we unmap it in the linux side, we will see errors like "30000003: Error 4 in REQUEST_UNMAP_RSP". So, don't call send_request_unmap for timeout reset.
Fixes: ed651a10875f ("ibmvnic: Updated reset handling") Signed-off-by: Lijun Pan ljp@linux.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index f6402a20ba320..cd201f89ce6c0 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -247,8 +247,13 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter, if (!ltb->buff) return;
+ /* VIOS automatically unmaps the long term buffer at remote + * end for the following resets: + * FAILOVER, MOBILITY, TIMEOUT. + */ if (adapter->reset_reason != VNIC_RESET_FAILOVER && - adapter->reset_reason != VNIC_RESET_MOBILITY) + adapter->reset_reason != VNIC_RESET_MOBILITY && + adapter->reset_reason != VNIC_RESET_TIMEOUT) send_request_unmap(adapter, ltb->map_id); dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); }
From: Sukadev Bhattiprolu sukadev@linux.ibm.com
[ Upstream commit 4a41c421f3676fdeea91733cf434dcf319c4c351 ]
The work queue is used to queue reset requests like CHANGE-PARAM or FAILOVER resets for the worker thread. When the adapter is being removed the adapter state is set to VNIC_REMOVING and the work queue is flushed so no new work is added. However the check for adapter being removed is racy in that the adapter can go into REMOVING state just after we check and we might end up adding work just as it is being flushed (or after).
The ->rwi_lock is already being used to serialize queue/dequeue work. Extend its usage ensure there is no race when scheduling/flushing work.
Fixes: 6954a9e4192b ("ibmvnic: Flush existing work items before device removal") Signed-off-by: Sukadev Bhattiprolu sukadev@linux.ibm.com Cc:Uwe Kleine-König uwe@kleine-koenig.org Cc:Saeed Mahameed saeed@kernel.org Reviewed-by: Dany Madden drt@linux.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 27 ++++++++++++++++++++------- drivers/net/ethernet/ibm/ibmvnic.h | 5 ++++- 2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index cd201f89ce6c0..13ae7eee7ef5f 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2395,6 +2395,8 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, unsigned long flags; int ret;
+ spin_lock_irqsave(&adapter->rwi_lock, flags); + /* * If failover is pending don't schedule any other reset. * Instead let the failover complete. If there is already a @@ -2415,14 +2417,11 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, goto err; }
- spin_lock_irqsave(&adapter->rwi_lock, flags); - list_for_each(entry, &adapter->rwi_list) { tmp = list_entry(entry, struct ibmvnic_rwi, list); if (tmp->reset_reason == reason) { netdev_dbg(netdev, "Skipping matching reset, reason=%d\n", reason); - spin_unlock_irqrestore(&adapter->rwi_lock, flags); ret = EBUSY; goto err; } @@ -2430,8 +2429,6 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
rwi = kzalloc(sizeof(*rwi), GFP_ATOMIC); if (!rwi) { - spin_unlock_irqrestore(&adapter->rwi_lock, flags); - ibmvnic_close(netdev); ret = ENOMEM; goto err; } @@ -2444,12 +2441,17 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, } rwi->reset_reason = reason; list_add_tail(&rwi->list, &adapter->rwi_list); - spin_unlock_irqrestore(&adapter->rwi_lock, flags); netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason); schedule_work(&adapter->ibmvnic_reset);
- return 0; + ret = 0; err: + /* ibmvnic_close() below can block, so drop the lock first */ + spin_unlock_irqrestore(&adapter->rwi_lock, flags); + + if (ret == ENOMEM) + ibmvnic_close(netdev); + return -ret; }
@@ -5467,7 +5469,18 @@ static int ibmvnic_remove(struct vio_dev *dev) unsigned long flags;
spin_lock_irqsave(&adapter->state_lock, flags); + + /* If ibmvnic_reset() is scheduling a reset, wait for it to + * finish. Then, set the state to REMOVING to prevent it from + * scheduling any more work and to have reset functions ignore + * any resets that have already been scheduled. Drop the lock + * after setting state, so __ibmvnic_reset() which is called + * from the flush_work() below, can make progress. + */ + spin_lock_irqsave(&adapter->rwi_lock, flags); adapter->state = VNIC_REMOVING; + spin_unlock_irqrestore(&adapter->rwi_lock, flags); + spin_unlock_irqrestore(&adapter->state_lock, flags);
flush_work(&adapter->ibmvnic_reset); diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index c09c3f6bba9f2..3cccbba703658 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -1081,6 +1081,7 @@ struct ibmvnic_adapter { struct tasklet_struct tasklet; enum vnic_state state; enum ibmvnic_reset_reason reset_reason; + /* when taking both state and rwi locks, take state lock first */ spinlock_t rwi_lock; struct list_head rwi_list; struct work_struct ibmvnic_reset; @@ -1097,6 +1098,8 @@ struct ibmvnic_adapter { struct ibmvnic_tunables desired; struct ibmvnic_tunables fallback;
- /* Used for serializatin of state field */ + /* Used for serialization of state field. When taking both state + * and rwi locks, take state lock first. + */ spinlock_t state_lock; };
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit d19741b0f54487cf3a11307900f8633935cd2849 ]
In general it is desirable that cleanup is the reverse process of setup. In this case I am not seeing any particular issue, but with the introduction of devlink-sb for felix, a non-obvious decision had to be made as to where to put its cleanup method. When there's a convention in place, that decision becomes obvious.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/ocelot/felix.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 45fdb1256dbfe..4aa81034347e2 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -654,14 +654,14 @@ static void felix_teardown(struct dsa_switch *ds) struct felix *felix = ocelot_to_felix(ocelot); int port;
- if (felix->info->mdio_bus_free) - felix->info->mdio_bus_free(ocelot); + ocelot_deinit_timestamp(ocelot); + ocelot_deinit(ocelot);
for (port = 0; port < ocelot->num_phys_ports; port++) ocelot_deinit_port(ocelot, port); - ocelot_deinit_timestamp(ocelot); - /* stop workqueue thread */ - ocelot_deinit(ocelot); + + if (felix->info->mdio_bus_free) + felix->info->mdio_bus_free(ocelot); }
static int felix_hwtstamp_get(struct dsa_switch *ds, int port,
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 42b5adbbac03bdb396192316c015fa3e64ffd5a1 ]
ocelot_init_port is called only if dsa_is_unused_port == false, however ocelot_deinit_port is called unconditionally. This causes a warning in the skb_queue_purge inside ocelot_deinit_port saying that the spin lock protecting ocelot_port->tx_skbs was not initialized.
Fixes: e5fb512d81d0 ("net: mscc: ocelot: deinitialize only initialized ports") Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/ocelot/felix.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 4aa81034347e2..0f1ee4a4fa55a 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -657,8 +657,12 @@ static void felix_teardown(struct dsa_switch *ds) ocelot_deinit_timestamp(ocelot); ocelot_deinit(ocelot);
- for (port = 0; port < ocelot->num_phys_ports; port++) + for (port = 0; port < ocelot->num_phys_ports; port++) { + if (dsa_is_unused_port(ds, port)) + continue; + ocelot_deinit_port(ocelot, port); + }
if (felix->info->mdio_bus_free) felix->info->mdio_bus_free(ocelot);
From: Bjarni Jonasson bjarni.jonasson@microchip.com
[ Upstream commit 3cc2c646be0b22037f31c958e96c0544a073d108 ]
At Power-On Reset, transients may cause the LCPLL to lock onto a clock that is momentarily unstable. This is normally seen in QSGMII setups where the higher speed 6G SerDes is being used. This patch adds an initial LCPLL Reset to the PHY (first instance) to avoid this issue.
Fixes: e4f9ba642f0b ("net: phy: mscc: add support for VSC8514 PHY.") Signed-off-by: Steen Hegelund steen.hegelund@microchip.com Signed-off-by: Bjarni Jonasson bjarni.jonasson@microchip.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/mscc/mscc.h | 8 + drivers/net/phy/mscc/mscc_main.c | 350 ++++++++++++++++++++----------- 2 files changed, 236 insertions(+), 122 deletions(-)
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 9481bce94c2ed..c2023f93c0b24 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -102,6 +102,7 @@ enum rgmii_clock_delay { #define PHY_MCB_S6G_READ BIT(30)
#define PHY_S6G_PLL5G_CFG0 0x06 +#define PHY_S6G_PLL5G_CFG2 0x08 #define PHY_S6G_LCPLL_CFG 0x11 #define PHY_S6G_PLL_CFG 0x2b #define PHY_S6G_COMMON_CFG 0x2c @@ -121,6 +122,9 @@ enum rgmii_clock_delay { #define PHY_S6G_PLL_FSM_CTRL_DATA_POS 8 #define PHY_S6G_PLL_FSM_ENA_POS 7
+#define PHY_S6G_CFG2_FSM_DIS 1 +#define PHY_S6G_CFG2_FSM_CLK_BP 23 + #define MSCC_EXT_PAGE_ACCESS 31 #define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */ #define MSCC_PHY_PAGE_EXTENDED 0x0001 /* Extended registers */ @@ -412,6 +416,10 @@ struct vsc8531_edge_rate_table { }; #endif /* CONFIG_OF_MDIO */
+enum csr_target { + MACRO_CTRL = 0x07, +}; + #if IS_ENABLED(CONFIG_MACSEC) int vsc8584_macsec_init(struct phy_device *phydev); void vsc8584_handle_macsec_interrupt(struct phy_device *phydev); diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 2f2157e3deab5..7830340b9cdc8 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -710,6 +710,113 @@ static int phy_base_read(struct phy_device *phydev, u32 regnum) return __phy_package_read(phydev, regnum); }
+static u32 vsc85xx_csr_read(struct phy_device *phydev, + enum csr_target target, u32 reg) +{ + unsigned long deadline; + u32 val, val_l, val_h; + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL); + + /* CSR registers are grouped under different Target IDs. + * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and + * MSCC_EXT_PAGE_CSR_CNTL_19 registers. + * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20 + * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19. + */ + + /* Setup the Target ID */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20, + MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2)); + + if ((target >> 2 == 0x1) || (target >> 2 == 0x3)) + /* non-MACsec access */ + target &= 0x3; + else + target = 0; + + /* Trigger CSR Action - Read into the CSR's */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19, + MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ | + MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) | + MSCC_PHY_CSR_CNTL_19_TARGET(target)); + + /* Wait for register access*/ + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19); + } while (time_before(jiffies, deadline) && + !(val & MSCC_PHY_CSR_CNTL_19_CMD)); + + if (!(val & MSCC_PHY_CSR_CNTL_19_CMD)) + return 0xffffffff; + + /* Read the Least Significant Word (LSW) (17) */ + val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17); + + /* Read the Most Significant Word (MSW) (18) */ + val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18); + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_STANDARD); + + return (val_h << 16) | val_l; +} + +static int vsc85xx_csr_write(struct phy_device *phydev, + enum csr_target target, u32 reg, u32 val) +{ + unsigned long deadline; + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL); + + /* CSR registers are grouped under different Target IDs. + * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and + * MSCC_EXT_PAGE_CSR_CNTL_19 registers. + * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20 + * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19. + */ + + /* Setup the Target ID */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20, + MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2)); + + /* Write the Least Significant Word (LSW) (17) */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val); + + /* Write the Most Significant Word (MSW) (18) */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16)); + + if ((target >> 2 == 0x1) || (target >> 2 == 0x3)) + /* non-MACsec access */ + target &= 0x3; + else + target = 0; + + /* Trigger CSR Action - Write into the CSR's */ + phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19, + MSCC_PHY_CSR_CNTL_19_CMD | + MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) | + MSCC_PHY_CSR_CNTL_19_TARGET(target)); + + /* Wait for register access */ + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19); + } while (time_before(jiffies, deadline) && + !(val & MSCC_PHY_CSR_CNTL_19_CMD)); + + if (!(val & MSCC_PHY_CSR_CNTL_19_CMD)) + return -ETIMEDOUT; + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_STANDARD); + + return 0; +} + /* bus->mdio_lock should be locked when using this function */ static void vsc8584_csr_write(struct phy_device *phydev, u16 addr, u32 val) { @@ -1131,6 +1238,92 @@ out: return ret; }
+/* Access LCPLL Cfg_2 */ +static void vsc8584_pll5g_cfg2_wr(struct phy_device *phydev, + bool disable_fsm) +{ + u32 rd_dat; + + rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2); + rd_dat &= ~BIT(PHY_S6G_CFG2_FSM_DIS); + rd_dat |= (disable_fsm << PHY_S6G_CFG2_FSM_DIS); + vsc85xx_csr_write(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2, rd_dat); +} + +/* trigger a read to the spcified MCB */ +static int vsc8584_mcb_rd_trig(struct phy_device *phydev, + u32 mcb_reg_addr, u8 mcb_slave_num) +{ + u32 rd_dat = 0; + + /* read MCB */ + vsc85xx_csr_write(phydev, MACRO_CTRL, mcb_reg_addr, + (0x40000000 | (1L << mcb_slave_num))); + + return read_poll_timeout(vsc85xx_csr_read, rd_dat, + !(rd_dat & 0x40000000), + 4000, 200000, 0, + phydev, MACRO_CTRL, mcb_reg_addr); +} + +/* trigger a write to the spcified MCB */ +static int vsc8584_mcb_wr_trig(struct phy_device *phydev, + u32 mcb_reg_addr, + u8 mcb_slave_num) +{ + u32 rd_dat = 0; + + /* write back MCB */ + vsc85xx_csr_write(phydev, MACRO_CTRL, mcb_reg_addr, + (0x80000000 | (1L << mcb_slave_num))); + + return read_poll_timeout(vsc85xx_csr_read, rd_dat, + !(rd_dat & 0x80000000), + 4000, 200000, 0, + phydev, MACRO_CTRL, mcb_reg_addr); +} + +/* Sequence to Reset LCPLL for the VIPER and ELISE PHY */ +static int vsc8584_pll5g_reset(struct phy_device *phydev) +{ + bool dis_fsm; + int ret = 0; + + ret = vsc8584_mcb_rd_trig(phydev, 0x11, 0); + if (ret < 0) + goto done; + dis_fsm = 1; + + /* Reset LCPLL */ + vsc8584_pll5g_cfg2_wr(phydev, dis_fsm); + + /* write back LCPLL MCB */ + ret = vsc8584_mcb_wr_trig(phydev, 0x11, 0); + if (ret < 0) + goto done; + + /* 10 mSec sleep while LCPLL is hold in reset */ + usleep_range(10000, 20000); + + /* read LCPLL MCB into CSRs */ + ret = vsc8584_mcb_rd_trig(phydev, 0x11, 0); + if (ret < 0) + goto done; + dis_fsm = 0; + + /* Release the Reset of LCPLL */ + vsc8584_pll5g_cfg2_wr(phydev, dis_fsm); + + /* write back LCPLL MCB */ + ret = vsc8584_mcb_wr_trig(phydev, 0x11, 0); + if (ret < 0) + goto done; + + usleep_range(110000, 200000); +done: + return ret; +} + /* bus->mdio_lock should be locked when using this function */ static int vsc8584_config_pre_init(struct phy_device *phydev) { @@ -1569,8 +1762,16 @@ static int vsc8514_config_pre_init(struct phy_device *phydev) {0x16b2, 0x00007000}, {0x16b4, 0x00000814}, }; + struct device *dev = &phydev->mdio.dev; unsigned int i; u16 reg; + int ret; + + ret = vsc8584_pll5g_reset(phydev); + if (ret < 0) { + dev_err(dev, "failed LCPLL reset, ret: %d\n", ret); + return ret; + }
phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
@@ -1605,101 +1806,6 @@ static int vsc8514_config_pre_init(struct phy_device *phydev) return 0; }
-static u32 vsc85xx_csr_ctrl_phy_read(struct phy_device *phydev, - u32 target, u32 reg) -{ - unsigned long deadline; - u32 val, val_l, val_h; - - phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL); - - /* CSR registers are grouped under different Target IDs. - * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and - * MSCC_EXT_PAGE_CSR_CNTL_19 registers. - * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20 - * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19. - */ - - /* Setup the Target ID */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20, - MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2)); - - /* Trigger CSR Action - Read into the CSR's */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19, - MSCC_PHY_CSR_CNTL_19_CMD | MSCC_PHY_CSR_CNTL_19_READ | - MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) | - MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3)); - - /* Wait for register access*/ - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); - do { - usleep_range(500, 1000); - val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19); - } while (time_before(jiffies, deadline) && - !(val & MSCC_PHY_CSR_CNTL_19_CMD)); - - if (!(val & MSCC_PHY_CSR_CNTL_19_CMD)) - return 0xffffffff; - - /* Read the Least Significant Word (LSW) (17) */ - val_l = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_17); - - /* Read the Most Significant Word (MSW) (18) */ - val_h = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_18); - - phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, - MSCC_PHY_PAGE_STANDARD); - - return (val_h << 16) | val_l; -} - -static int vsc85xx_csr_ctrl_phy_write(struct phy_device *phydev, - u32 target, u32 reg, u32 val) -{ - unsigned long deadline; - - phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_CSR_CNTL); - - /* CSR registers are grouped under different Target IDs. - * 6-bit Target_ID is split between MSCC_EXT_PAGE_CSR_CNTL_20 and - * MSCC_EXT_PAGE_CSR_CNTL_19 registers. - * Target_ID[5:2] maps to bits[3:0] of MSCC_EXT_PAGE_CSR_CNTL_20 - * and Target_ID[1:0] maps to bits[13:12] of MSCC_EXT_PAGE_CSR_CNTL_19. - */ - - /* Setup the Target ID */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_20, - MSCC_PHY_CSR_CNTL_20_TARGET(target >> 2)); - - /* Write the Least Significant Word (LSW) (17) */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_17, (u16)val); - - /* Write the Most Significant Word (MSW) (18) */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_18, (u16)(val >> 16)); - - /* Trigger CSR Action - Write into the CSR's */ - phy_base_write(phydev, MSCC_EXT_PAGE_CSR_CNTL_19, - MSCC_PHY_CSR_CNTL_19_CMD | - MSCC_PHY_CSR_CNTL_19_REG_ADDR(reg) | - MSCC_PHY_CSR_CNTL_19_TARGET(target & 0x3)); - - /* Wait for register access */ - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); - do { - usleep_range(500, 1000); - val = phy_base_read(phydev, MSCC_EXT_PAGE_CSR_CNTL_19); - } while (time_before(jiffies, deadline) && - !(val & MSCC_PHY_CSR_CNTL_19_CMD)); - - if (!(val & MSCC_PHY_CSR_CNTL_19_CMD)) - return -ETIMEDOUT; - - phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, - MSCC_PHY_PAGE_STANDARD); - - return 0; -} - static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, u32 op) { @@ -1707,15 +1813,15 @@ static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, u32 val; int ret;
- ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, reg, - op | (1 << mcb)); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg, + op | (1 << mcb)); if (ret) return -EINVAL;
deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); do { usleep_range(500, 1000); - val = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, reg); + val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg);
if (val == 0xffffffff) return -EIO; @@ -1796,41 +1902,41 @@ static int vsc8514_config_init(struct phy_device *phydev) /* lcpll mcb */ phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); /* pll5gcfg0 */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL5G_CFG0, 0x7036f145); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_PLL5G_CFG0, 0x7036f145); if (ret) goto err;
phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); /* pllcfg */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL_CFG, - (3 << PHY_S6G_PLL_ENA_OFFS_POS) | - (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS) - | (0 << PHY_S6G_PLL_FSM_ENA_POS)); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_PLL_CFG, + (3 << PHY_S6G_PLL_ENA_OFFS_POS) | + (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS) + | (0 << PHY_S6G_PLL_FSM_ENA_POS)); if (ret) goto err;
/* commoncfg */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_COMMON_CFG, - (0 << PHY_S6G_SYS_RST_POS) | - (0 << PHY_S6G_ENA_LANE_POS) | - (0 << PHY_S6G_ENA_LOOP_POS) | - (0 << PHY_S6G_QRATE_POS) | - (3 << PHY_S6G_IF_MODE_POS)); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_COMMON_CFG, + (0 << PHY_S6G_SYS_RST_POS) | + (0 << PHY_S6G_ENA_LANE_POS) | + (0 << PHY_S6G_ENA_LOOP_POS) | + (0 << PHY_S6G_QRATE_POS) | + (3 << PHY_S6G_IF_MODE_POS)); if (ret) goto err;
/* misccfg */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_MISC_CFG, 1); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_MISC_CFG, 1); if (ret) goto err;
/* gpcfg */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_GPC_CFG, 768); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_GPC_CFG, 768); if (ret) goto err;
@@ -1841,8 +1947,8 @@ static int vsc8514_config_init(struct phy_device *phydev) usleep_range(500, 1000); phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); /* read 6G MCB into CSRs */ - reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL_STATUS); + reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, + PHY_S6G_PLL_STATUS); if (reg == 0xffffffff) { phy_unlock_mdio_bus(phydev); return -EIO; @@ -1856,8 +1962,8 @@ static int vsc8514_config_init(struct phy_device *phydev) }
/* misccfg */ - ret = vsc85xx_csr_ctrl_phy_write(phydev, PHY_MCB_TARGET, - PHY_S6G_MISC_CFG, 0); + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, + PHY_S6G_MISC_CFG, 0); if (ret) goto err;
@@ -1868,8 +1974,8 @@ static int vsc8514_config_init(struct phy_device *phydev) usleep_range(500, 1000); phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); /* read 6G MCB into CSRs */ - reg = vsc85xx_csr_ctrl_phy_read(phydev, PHY_MCB_TARGET, - PHY_S6G_IB_STATUS0); + reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, + PHY_S6G_IB_STATUS0); if (reg == 0xffffffff) { phy_unlock_mdio_bus(phydev); return -EIO;
From: Shyam Sundar S K Shyam-sundar.S-k@amd.com
[ Upstream commit 30b7edc82ec82578f4f5e6706766f0a9535617d3 ]
Sometimes mailbox commands timeout when the RX data path becomes unresponsive. This prevents the submission of new mailbox commands to DXIO. This patch identifies the timeout and resets the RX data path so that the next message can be submitted properly.
Fixes: 549b32af9f7c ("amd-xgbe: Simplify mailbox interface rate change code") Co-developed-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Shyam Sundar S K Shyam-sundar.S-k@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-common.h | 14 +++++++++++ drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 28 ++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index b40d4377cc71d..b2cd3bdba9f89 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -1279,10 +1279,18 @@ #define MDIO_PMA_10GBR_FECCTRL 0x00ab #endif
+#ifndef MDIO_PMA_RX_CTRL1 +#define MDIO_PMA_RX_CTRL1 0x8051 +#endif + #ifndef MDIO_PCS_DIG_CTRL #define MDIO_PCS_DIG_CTRL 0x8000 #endif
+#ifndef MDIO_PCS_DIGITAL_STAT +#define MDIO_PCS_DIGITAL_STAT 0x8010 +#endif + #ifndef MDIO_AN_XNP #define MDIO_AN_XNP 0x0016 #endif @@ -1358,6 +1366,8 @@ #define XGBE_KR_TRAINING_ENABLE BIT(1)
#define XGBE_PCS_CL37_BP BIT(12) +#define XGBE_PCS_PSEQ_STATE_MASK 0x1c +#define XGBE_PCS_PSEQ_STATE_POWER_GOOD 0x10
#define XGBE_AN_CL37_INT_CMPLT BIT(0) #define XGBE_AN_CL37_INT_MASK 0x01 @@ -1375,6 +1385,10 @@ #define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 #define XGBE_PMA_CDR_TRACK_EN_ON 0x01
+#define XGBE_PMA_RX_RST_0_MASK BIT(4) +#define XGBE_PMA_RX_RST_0_RESET_ON 0x10 +#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 + /* Bit setting and getting macros * The get macro will extract the current bit field value from within * the variable diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 859ded0c06b05..087948085ae19 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1953,6 +1953,27 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata) xgbe_phy_put_comm_ownership(pdata); }
+static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, + XGBE_PCS_PSEQ_STATE_MASK); + if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { + /* Mailbox command timed out, reset of RX block is required. + * This can be done by asseting the reset bit and wait for + * its compeletion. + */ + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); + ndelay(20); + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF); + usleep_range(40, 50); + netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n"); + } +} + static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int cmd, unsigned int sub_cmd) { @@ -1960,9 +1981,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int wait;
/* Log if a previous command did not complete */ - if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { netif_dbg(pdata, link, pdata->netdev, "firmware mailbox not ready for command\n"); + xgbe_phy_rx_reset(pdata); + }
/* Construct the command */ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); @@ -1984,6 +2007,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
netif_dbg(pdata, link, pdata->netdev, "firmware mailbox command did not complete\n"); + + /* Reset on error */ + xgbe_phy_rx_reset(pdata); }
static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
From: Shyam Sundar S K Shyam-sundar.S-k@amd.com
[ Upstream commit 186edbb510bd60e748f93975989ccba25ee99c50 ]
The current driver calls netif_carrier_off() late in the link tear down which can result in a netdev watchdog timeout.
Calling netif_carrier_off() immediately after netif_tx_stop_all_queues() avoids the warning.
------------[ cut here ]------------ NETDEV WATCHDOG: enp3s0f2 (amd-xgbe): transmit queue 0 timed out WARNING: CPU: 3 PID: 0 at net/sched/sch_generic.c:461 dev_watchdog+0x20d/0x220 Modules linked in: amd_xgbe(E) amd-xgbe 0000:03:00.2 enp3s0f2: Link is Down CPU: 3 PID: 0 Comm: swapper/3 Tainted: G E Hardware name: AMD Bilby-RV2/Bilby-RV2, BIOS RBB1202A 10/18/2019 RIP: 0010:dev_watchdog+0x20d/0x220 Code: 00 49 63 4e e0 eb 92 4c 89 e7 c6 05 c6 e2 c1 00 01 e8 e7 ce fc ff 89 d9 48 RSP: 0018:ffff90cfc28c3e88 EFLAGS: 00010286 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000006 RDX: 0000000000000007 RSI: 0000000000000086 RDI: ffff90cfc28d63c0 RBP: ffff90cfb977845c R08: 0000000000000050 R09: 0000000000196018 R10: ffff90cfc28c3ef8 R11: 0000000000000000 R12: ffff90cfb9778000 R13: 0000000000000003 R14: ffff90cfb9778480 R15: 0000000000000010 FS: 0000000000000000(0000) GS:ffff90cfc28c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f240ff2d9d0 CR3: 00000001e3e0a000 CR4: 00000000003406e0 Call Trace: <IRQ> ? pfifo_fast_reset+0x100/0x100 call_timer_fn+0x2b/0x130 run_timer_softirq+0x3e8/0x440 ? enqueue_hrtimer+0x39/0x90
Fixes: e722ec82374b ("amd-xgbe: Update the BelFuse quirk to support SGMII") Co-developed-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Shyam Sundar S K Shyam-sundar.S-k@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 1 + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 2709a2db56577..395eb0b526802 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1368,6 +1368,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) return;
netif_tx_stop_all_queues(netdev); + netif_carrier_off(pdata->netdev);
xgbe_stop_timers(pdata); flush_workqueue(pdata->dev_workqueue); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 93ef5a30cb8d9..19ee4db0156d6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1396,7 +1396,6 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) pdata->phy_if.phy_impl.stop(pdata);
pdata->phy.link = 0; - netif_carrier_off(pdata->netdev);
xgbe_phy_adjust_link(pdata); }
From: Shyam Sundar S K Shyam-sundar.S-k@amd.com
[ Upstream commit 84fe68eb67f9499309cffd97c1ba269de125ff14 ]
Normally, auto negotiation and reconnect should be automatically done by the hardware. But there seems to be an issue where auto negotiation has to be restarted manually. This happens because of link training and so even though still connected to the partner the link never "comes back". This needs an auto-negotiation restart.
Also, a change in xgbe-mdio is needed to get ethtool to recognize the link down and get the link change message. This change is only required in a backplane connection mode.
Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") Co-developed-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Shyam Sundar S K Shyam-sundar.S-k@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 19ee4db0156d6..4e97b48695220 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1345,7 +1345,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) &an_restart); if (an_restart) { xgbe_phy_config_aneg(pdata); - return; + goto adjust_link; }
if (pdata->phy.link) { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 087948085ae19..d3f72faecd1da 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2610,6 +2610,14 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) if (reg & MDIO_STAT1_LSTATUS) return 1;
+ if (pdata->phy.autoneg == AUTONEG_ENABLE && + phy_data->port_mode == XGBE_PORT_MODE_BACKPLANE) { + if (!test_bit(XGBE_LINK_INIT, &pdata->dev_state)) { + netif_carrier_off(pdata->netdev); + *an_restart = 1; + } + } + /* No link, attempt a receiver reset cycle */ if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { phy_data->rrc_count = 0;
From: Shyam Sundar S K Shyam-sundar.S-k@amd.com
[ Upstream commit 9eab3fdb419916f66a72d1572f68d82cd9b3f963 ]
Frequent link up/down events can happen when a Bel Fuse SFP part is connected to the amd-xgbe device. Try to avoid the frequent link issues by resetting the PHY as documented in Bel Fuse SFP datasheets.
Fixes: e722ec82374b ("amd-xgbe: Update the BelFuse quirk to support SGMII") Co-developed-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Sudheesh Mavila sudheesh.mavila@amd.com Signed-off-by: Shyam Sundar S K Shyam-sundar.S-k@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index d3f72faecd1da..18e48b3bc402b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -922,6 +922,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) if ((phy_id & 0xfffffff0) != 0x03625d10) return false;
+ /* Reset PHY - wait for self-clearing reset bit to clear */ + genphy_soft_reset(phy_data->phydev); + /* Disable RGMII mode */ phy_write(phy_data->phydev, 0x18, 0x7007); reg = phy_read(phy_data->phydev, 0x18);
From: Maxime Chevallier maxime.chevallier@bootlin.com
[ Upstream commit cf9bf871280d9e0a8869d98c2602d29caf69dfa3 ]
According to Errata #23 "The per-CPU GbE interrupt is limited to Core 0", we can't use the per-cpu interrupt mechanism on the Armada 3700 familly.
This is correctly checked for RSS configuration, but the initial queue mapping is still done by having the queues spread across all the CPUs in the system, both in the init path and in the cpu_hotplug path.
Fixes: 2636ac3cc2b4 ("net: mvneta: Add network support for Armada 3700 SoC") Signed-off-by: Maxime Chevallier maxime.chevallier@bootlin.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/marvell/mvneta.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index bc4d8d1444019..fd5b33646ea71 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3432,7 +3432,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp, return -ENOMEM;
/* Setup XPS mapping */ - if (txq_number > 1) + if (pp->neta_armada3700) + cpu = 0; + else if (txq_number > 1) cpu = txq->id % num_present_cpus(); else cpu = pp->rxq_def % num_present_cpus(); @@ -4210,6 +4212,11 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node) node_online); struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+ /* Armada 3700's per-cpu interrupt for mvneta is broken, all interrupts + * are routed to CPU 0, so we don't need all the cpu-hotplug support + */ + if (pp->neta_armada3700) + return 0;
spin_lock(&pp->lock); /*
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 3af409ca278d4a8d50e91f9f7c4c33b175645cf3 ]
The following call path suggests that calling unregister_netdev on an interface that is up will first bring it down.
enetc_pf_remove -> unregister_netdev -> unregister_netdevice_queue -> unregister_netdevice_many -> dev_close_many -> __dev_close_many -> enetc_close -> enetc_stop -> phylink_stop
However, enetc first destroys the phylink instance, then calls unregister_netdev. This is already dissimilar to the setup (and error path teardown path) from enetc_pf_probe, but more than that, it is buggy because it is invalid to call phylink_stop after phylink_destroy.
So let's first unregister the netdev (and let the .ndo_stop events consume themselves), then destroy the phylink instance, then free the netdev.
Fixes: 71b77a7a27a3 ("enetc: Migrate to PHYLINK and PCS_LYNX") Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 3eb5f1375bd4c..515c5b29d7aab 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -1157,14 +1157,15 @@ static void enetc_pf_remove(struct pci_dev *pdev) struct enetc_ndev_priv *priv;
priv = netdev_priv(si->ndev); - enetc_phylink_destroy(priv); - enetc_mdiobus_destroy(pf);
if (pf->num_vfs) enetc_sriov_configure(pdev, 0);
unregister_netdev(si->ndev);
+ enetc_phylink_destroy(priv); + enetc_mdiobus_destroy(pf); + enetc_free_msix(priv);
enetc_free_si_resources(priv);
From: Abhishek Pandit-Subedi abhishekpandit@chromium.org
[ Upstream commit 295fa2a5647b13681594bb1bcc76c74619035218 ]
Add a missing SUSPEND_SCAN_ENABLE in passive scan, remove the separate function for configuring le scan during suspend and update the request complete function to clear both enable and disable tasks.
Fixes: dce0a4be8054 ("Bluetooth: Set missing suspend task bits") Reviewed-by: Alain Michaud alainm@chromium.org Signed-off-by: Abhishek Pandit-Subedi abhishekpandit@chromium.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_request.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 71bffd7454720..5aa7bd5030a21 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1087,6 +1087,8 @@ void hci_req_add_le_passive_scan(struct hci_request *req) if (hdev->suspended) { window = hdev->le_scan_window_suspend; interval = hdev->le_scan_int_suspend; + + set_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks); } else if (hci_is_le_conn_scanning(hdev)) { window = hdev->le_scan_window_connect; interval = hdev->le_scan_int_connect; @@ -1170,19 +1172,6 @@ static void hci_req_set_event_filter(struct hci_request *req) hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); }
-static void hci_req_config_le_suspend_scan(struct hci_request *req) -{ - /* Before changing params disable scan if enabled */ - if (hci_dev_test_flag(req->hdev, HCI_LE_SCAN)) - hci_req_add_le_scan_disable(req, false); - - /* Configure params and enable scanning */ - hci_req_add_le_passive_scan(req); - - /* Block suspend notifier on response */ - set_bit(SUSPEND_SCAN_ENABLE, req->hdev->suspend_tasks); -} - static void cancel_adv_timeout(struct hci_dev *hdev) { if (hdev->adv_instance_timeout) { @@ -1245,8 +1234,10 @@ static void suspend_req_complete(struct hci_dev *hdev, u8 status, u16 opcode) { bt_dev_dbg(hdev, "Request complete opcode=0x%x, status=0x%x", opcode, status); - if (test_and_clear_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks) || - test_and_clear_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks)) { + if (test_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks) || + test_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks)) { + clear_bit(SUSPEND_SCAN_ENABLE, hdev->suspend_tasks); + clear_bit(SUSPEND_SCAN_DISABLE, hdev->suspend_tasks); wake_up(&hdev->suspend_wait_q); } } @@ -1336,7 +1327,7 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next) /* Enable event filter for paired devices */ hci_req_set_event_filter(&req); /* Enable passive scan at lower duty cycle */ - hci_req_config_le_suspend_scan(&req); + __hci_update_background_scan(&req); /* Pause scan changes again. */ hdev->scanning_paused = true; hci_req_run(&req, suspend_req_complete); @@ -1346,7 +1337,7 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
hci_req_clear_event_filter(&req); /* Reset passive/background scanning to normal */ - hci_req_config_le_suspend_scan(&req); + __hci_update_background_scan(&req);
/* Unpause directed advertising */ hdev->advertising_paused = false;
From: Rafał Miłecki rafal@milecki.pl
[ Upstream commit 56098be85d19cd56b59d7b3854ea035cc8cb9e95 ]
BCM4908 has controller that needs different IRQ handling just like the BCM63138. Describe it properly.
On Linux this change fixes: brcmstb_nand ff801800.nand: timeout waiting for command 0x9 brcmstb_nand ff801800.nand: intfc status d0000000
Signed-off-by: Rafał Miłecki rafal@milecki.pl Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi index f873dc44ce9ca..55d9b56ac749d 100644 --- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi @@ -164,7 +164,7 @@ nand@1800 { #address-cells = <1>; #size-cells = <0>; - compatible = "brcm,brcmnand-v7.1", "brcm,brcmnand"; + compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.1", "brcm,brcmnand"; reg = <0x1800 0x600>, <0x2000 0x10>; reg-names = "nand", "nand-int-base"; interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
From: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org
[ Upstream commit ad3a9c0ec2d2baed936cfdd05870f9d1e1f40e0e ]
During SSR after memory dump collection,BT controller will be powered off, powered on and then FW will be downloaded.During suspend if BT controller is powered off due to SSR then we should wait until SSR is completed and then suspend.
Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend") Signed-off-by: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_qca.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 5dbcb7c42b805..17a3859326dc7 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -50,7 +50,8 @@ #define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000 #define CMD_TRANS_TIMEOUT_MS 100 #define MEMDUMP_TIMEOUT_MS 8000 -#define IBS_DISABLE_SSR_TIMEOUT_MS (MEMDUMP_TIMEOUT_MS + 1000) +#define IBS_DISABLE_SSR_TIMEOUT_MS \ + (MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS) #define FW_DOWNLOAD_TIMEOUT_MS 3000
/* susclk rate */ @@ -2102,7 +2103,12 @@ static int __maybe_unused qca_suspend(struct device *dev)
set_bit(QCA_SUSPENDING, &qca->flags);
- if (test_bit(QCA_BT_OFF, &qca->flags)) + /* During SSR after memory dump collection, controller will be + * powered off and then powered on.If controller is powered off + * during SSR then we should wait until SSR is completed. + */ + if (test_bit(QCA_BT_OFF, &qca->flags) && + !test_bit(QCA_SSR_TRIGGERED, &qca->flags)) return 0;
if (test_bit(QCA_IBS_DISABLED, &qca->flags)) { @@ -2112,7 +2118,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
/* QCA_IBS_DISABLED flag is set to true, During FW download * and during memory dump collection. It is reset to false, - * After FW download complete and after memory dump collections. + * After FW download complete. */ wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED, TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout)); @@ -2124,10 +2130,6 @@ static int __maybe_unused qca_suspend(struct device *dev) } }
- /* After memory dump collection, Controller is powered off.*/ - if (test_bit(QCA_BT_OFF, &qca->flags)) - return 0; - cancel_work_sync(&qca->ws_awake_device); cancel_work_sync(&qca->ws_awake_rx);
From: Erwan Le Ray erwan.leray@foss.st.com
[ Upstream commit e7997f7ff7f8154d477f6f976698d868a2ac3934 ]
DMA initialization error handling is not properly implemented in the driver. Fix DMA initialization error handling by: - moving TX DMA descriptor request error handling in a new dedicated fallback_err label - adding error handling to TX DMA descriptor submission - adding error handling to RX DMA descriptor submission
This patch depends on '24832ca3ee85 ("tty: serial: stm32-usart: Remove set but unused 'cookie' variables")' which unfortunately doesn't include a "Fixes" tag.
Fixes: 3489187204eb ("serial: stm32: adding dma support") Signed-off-by: Erwan Le Ray erwan.leray@foss.st.com Link: https://lore.kernel.org/r/20210106162203.28854-2-erwan.leray@foss.st.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/stm32-usart.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index f4de32d3f2afe..6248304a001f4 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -383,17 +383,18 @@ static void stm32_transmit_chars_dma(struct uart_port *port) DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
- if (!desc) { - for (i = count; i > 0; i--) - stm32_transmit_chars_pio(port); - return; - } + if (!desc) + goto fallback_err;
desc->callback = stm32_tx_dma_complete; desc->callback_param = port;
/* Push current DMA TX transaction in the pending queue */ - dmaengine_submit(desc); + if (dma_submit_error(dmaengine_submit(desc))) { + /* dma no yet started, safe to free resources */ + dmaengine_terminate_async(stm32port->tx_ch); + goto fallback_err; + }
/* Issue pending DMA TX requests */ dma_async_issue_pending(stm32port->tx_ch); @@ -402,6 +403,11 @@ static void stm32_transmit_chars_dma(struct uart_port *port)
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); port->icount.tx += count; + return; + +fallback_err: + for (i = count; i > 0; i--) + stm32_transmit_chars_pio(port); }
static void stm32_transmit_chars(struct uart_port *port) @@ -1130,7 +1136,11 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, desc->callback_param = NULL;
/* Push current DMA transaction in the pending queue */ - dmaengine_submit(desc); + ret = dma_submit_error(dmaengine_submit(desc)); + if (ret) { + dmaengine_terminate_sync(stm32port->rx_ch); + goto config_err; + }
/* Issue pending DMA requests */ dma_async_issue_pending(stm32port->rx_ch);
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit 936f8946bdb48239f4292812d4d2e26c6d328c95 ]
__bpf_free_used_maps() is always defined in kernel/bpf/core.c, while include/linux/bpf.h is guarding it behind CONFIG_BPF_SYSCALL. Move it out of that guard region and fix compiler warning.
Fixes: a2ea07465c8d ("bpf: Fix missing prog untrack in release_maps") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20210112075520.4103414-4-andrii@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/bpf.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index ef9309604b3e5..6e585dbc10df3 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1206,8 +1206,6 @@ void bpf_prog_sub(struct bpf_prog *prog, int i); void bpf_prog_inc(struct bpf_prog *prog); struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog); void bpf_prog_put(struct bpf_prog *prog); -void __bpf_free_used_maps(struct bpf_prog_aux *aux, - struct bpf_map **used_maps, u32 len);
void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock); void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock); @@ -1676,6 +1674,9 @@ static inline struct bpf_prog *bpf_prog_get_type(u32 ufd, return bpf_prog_get_type_dev(ufd, type, false); }
+void __bpf_free_used_maps(struct bpf_prog_aux *aux, + struct bpf_map **used_maps, u32 len); + bool bpf_prog_get_ok(struct bpf_prog *, enum bpf_prog_type *, bool);
int bpf_prog_offload_compile(struct bpf_prog *prog);
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit 635599bace259a2c42741c3ea61bfa7be6f15556 ]
If some of the subtests use module BTFs through ksyms, they will cause bpf_prog to take a refcount on bpf_testmod module, which will prevent it from successfully unloading. Module's refcnt is decremented when bpf_prog is freed, which generally happens in RCU callback. So we need to trigger syncronize_rcu() in the kernel, which can be achieved nicely with membarrier(MEMBARRIER_CMD_SHARED) or membarrier(MEMBARRIER_CMD_GLOBAL) syscall. So do that in kernel_sync_rcu() and make it available to other test inside the test_progs. This synchronize_rcu() is called before attempting to unload bpf_testmod.
Fixes: 9f7fa225894c ("selftests/bpf: Add bpf_testmod kernel module for testing") Suggested-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Acked-by: Yonghong Song yhs@fb.com Acked-by: Hao Luo haoluo@google.com Link: https://lore.kernel.org/bpf/20210112075520.4103414-5-andrii@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../selftests/bpf/prog_tests/btf_map_in_map.c | 33 ------------------- tools/testing/selftests/bpf/test_progs.c | 11 +++++++ tools/testing/selftests/bpf/test_progs.h | 1 + 3 files changed, 12 insertions(+), 33 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c b/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c index 76ebe4c250f11..eb90a6b8850d2 100644 --- a/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c +++ b/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c @@ -20,39 +20,6 @@ static __u32 bpf_map_id(struct bpf_map *map) return info.id; }
-/* - * Trigger synchronize_rcu() in kernel. - * - * ARRAY_OF_MAPS/HASH_OF_MAPS lookup/update operations trigger synchronize_rcu() - * if looking up an existing non-NULL element or updating the map with a valid - * inner map FD. Use this fact to trigger synchronize_rcu(): create map-in-map, - * create a trivial ARRAY map, update map-in-map with ARRAY inner map. Then - * cleanup. At the end, at least one synchronize_rcu() would be called. - */ -static int kern_sync_rcu(void) -{ - int inner_map_fd, outer_map_fd, err, zero = 0; - - inner_map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 4, 1, 0); - if (CHECK(inner_map_fd < 0, "inner_map_create", "failed %d\n", -errno)) - return -1; - - outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL, - sizeof(int), inner_map_fd, 1, 0); - if (CHECK(outer_map_fd < 0, "outer_map_create", "failed %d\n", -errno)) { - close(inner_map_fd); - return -1; - } - - err = bpf_map_update_elem(outer_map_fd, &zero, &inner_map_fd, 0); - if (err) - err = -errno; - CHECK(err, "outer_map_update", "failed %d\n", err); - close(inner_map_fd); - close(outer_map_fd); - return err; -} - static void test_lookup_update(void) { int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id; diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 7d077d48cadd0..213628ee721c1 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -11,6 +11,7 @@ #include <signal.h> #include <string.h> #include <execinfo.h> /* backtrace */ +#include <linux/membarrier.h>
#define EXIT_NO_TEST 2 #define EXIT_ERR_SETUP_INFRA 3 @@ -370,8 +371,18 @@ static int delete_module(const char *name, int flags) return syscall(__NR_delete_module, name, flags); }
+/* + * Trigger synchronize_rcu() in kernel. + */ +int kern_sync_rcu(void) +{ + return syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0, 0); +} + static void unload_bpf_testmod(void) { + if (kern_sync_rcu()) + fprintf(env.stderr, "Failed to trigger kernel-side RCU sync!\n"); if (delete_module("bpf_testmod", 0)) { if (errno == ENOENT) { if (env.verbosity > VERBOSE_NONE) diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 115953243f623..e49e2fdde9425 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -219,6 +219,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name); int compare_map_keys(int map1_fd, int map2_fd); int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len); int extract_build_id(char *build_id, size_t size); +int kern_sync_rcu(void);
#ifdef __x86_64__ #define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep"
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
[ Upstream commit 74097d805edb9305a2a588a8ece82d2495ff5a88 ]
sdhc_2 uses 19200000 Hz clock rather than wrongly specified xo_board (39400000 Hz). Specify correct clock to fix DLL setup for SDR104 mode.
Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Fixes: c4cf0300be84 ("arm64: dts: qcom: sm8250: Add support for SDC2") Link: https://lore.kernel.org/r/20210109011252.3436533-1-dmitry.baryshkov@linaro.o... Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi index 65acd1f381eba..1ae90e8b70f32 100644 --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -1657,7 +1657,7 @@
clocks = <&gcc GCC_SDCC2_AHB_CLK>, <&gcc GCC_SDCC2_APPS_CLK>, - <&xo_board>; + <&rpmhcc RPMH_CXO_CLK>; clock-names = "iface", "core", "xo"; iommus = <&apps_smmu 0x4a0 0x0>; qcom,dll-config = <0x0007642c>;
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
[ Upstream commit abf2c58aaa776cf43daf0fc4fd20082c71583c6b ]
Lower drive strength for microSD data and CMD pins from 16 to 10. This fixes spurious card removal issues observed on some boards. Also this change allows us to re-enable 1.8V support, which seems to work with lowered drive strength.
Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Cc: Veerabhadrarao Badiganti vbadigan@codeaurora.org Fixes: 53a8ccf1c7e5 ("arm64: dts: qcom: rb5: Add support for uSD card") Link: https://lore.kernel.org/r/20201217183341.3186402-1-dmitry.baryshkov@linaro.o... Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index ce22d4fa383e6..f86cc5140d3b9 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -491,8 +491,6 @@ vqmmc-supply = <&vreg_l6c_2p96>; cd-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>; bus-width = <4>; - /* there seem to be issues with HS400-1.8V mode, so disable it */ - no-1-8-v; no-sdio; no-emmc; }; @@ -706,13 +704,13 @@ cmd { pins = "sdc2_cmd"; bias-pull-up; - drive-strength = <16>; + drive-strength = <10>; };
data { pins = "sdc2_data"; bias-pull-up; - drive-strength = <16>; + drive-strength = <10>; }; };
From: Linus Torvalds torvalds@linux-foundation.org
[ Upstream commit 3b830a9c34d5897be07176ce4e6f2d75e2c8cfd7 ]
The tty line discipline .read() function was passed the final user pointer destination as an argument, which doesn't match the 'write()' function, and makes it very inconvenient to do a splice method for ttys.
This is a conversion to use a kernel buffer instead.
NOTE! It does this by passing the tty line discipline ->read() function an additional "cookie" to fill in, and an offset into the cookie data.
The line discipline can fill in the cookie data with its own private information, and then the reader will repeat the read until either the cookie is cleared or it runs out of data.
The only real user of this is N_HDLC, which can use this to handle big packets, even if the kernel buffer is smaller than the whole packet.
Cc: Christoph Hellwig hch@lst.de Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_ldisc.c | 34 +++++++-------- drivers/input/serio/serport.c | 4 +- drivers/net/ppp/ppp_async.c | 3 +- drivers/net/ppp/ppp_synctty.c | 3 +- drivers/tty/n_gsm.c | 3 +- drivers/tty/n_hdlc.c | 60 +++++++++++++++++-------- drivers/tty/n_null.c | 3 +- drivers/tty/n_r3964.c | 10 ++--- drivers/tty/n_tracerouter.c | 4 +- drivers/tty/n_tracesink.c | 4 +- drivers/tty/n_tty.c | 82 +++++++++++++++-------------------- drivers/tty/tty_io.c | 64 +++++++++++++++++++++++++-- include/linux/tty_ldisc.h | 3 +- net/nfc/nci/uart.c | 3 +- 14 files changed, 178 insertions(+), 102 deletions(-)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 8be4d807d1370..637c5b8c2aa1a 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -801,7 +801,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file, * We don't provide read/write/poll interface for user space. */ static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) { return 0; } @@ -818,29 +819,28 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty, return 0; }
+static struct tty_ldisc_ops hci_uart_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "n_hci", + .open = hci_uart_tty_open, + .close = hci_uart_tty_close, + .read = hci_uart_tty_read, + .write = hci_uart_tty_write, + .ioctl = hci_uart_tty_ioctl, + .compat_ioctl = hci_uart_tty_ioctl, + .poll = hci_uart_tty_poll, + .receive_buf = hci_uart_tty_receive, + .write_wakeup = hci_uart_tty_wakeup, +}; + static int __init hci_uart_init(void) { - static struct tty_ldisc_ops hci_uart_ldisc; int err;
BT_INFO("HCI UART driver ver %s", VERSION);
/* Register the tty discipline */ - - memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc)); - hci_uart_ldisc.magic = TTY_LDISC_MAGIC; - hci_uart_ldisc.name = "n_hci"; - hci_uart_ldisc.open = hci_uart_tty_open; - hci_uart_ldisc.close = hci_uart_tty_close; - hci_uart_ldisc.read = hci_uart_tty_read; - hci_uart_ldisc.write = hci_uart_tty_write; - hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; - hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl; - hci_uart_ldisc.poll = hci_uart_tty_poll; - hci_uart_ldisc.receive_buf = hci_uart_tty_receive; - hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; - hci_uart_ldisc.owner = THIS_MODULE; - err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); if (err) { BT_ERR("HCI line discipline registration failed. (%d)", err); diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 8ac970a423de6..33e9d9bfd036f 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -156,7 +156,9 @@ out: * returning 0 characters. */
-static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr) +static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, + unsigned char *kbuf, size_t nr, + void **cookie, unsigned long offset) { struct serport *serport = (struct serport*) tty->disc_data; struct serio *serio; diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index 29a0917a81e60..f14a9d190de91 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -259,7 +259,8 @@ static int ppp_asynctty_hangup(struct tty_struct *tty) */ static ssize_t ppp_asynctty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t count) + unsigned char *buf, size_t count, + void **cookie, unsigned long offset) { return -EAGAIN; } diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index 0f338752c38b9..f774b7e52da44 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -257,7 +257,8 @@ static int ppp_sync_hangup(struct tty_struct *tty) */ static ssize_t ppp_sync_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t count) + unsigned char *buf, size_t count, + void **cookie, unsigned long offset) { return -EAGAIN; } diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c676fa89ee0b6..51dafc06f5414 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2559,7 +2559,8 @@ static void gsmld_write_wakeup(struct tty_struct *tty) */
static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) { return -EOPNOTSUPP; } diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 12557ee1edb68..1363e659dc1db 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -416,13 +416,19 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, * Returns the number of bytes returned or error code. */ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, - __u8 __user *buf, size_t nr) + __u8 *kbuf, size_t nr, + void **cookie, unsigned long offset) { struct n_hdlc *n_hdlc = tty->disc_data; int ret = 0; struct n_hdlc_buf *rbuf; DECLARE_WAITQUEUE(wait, current);
+ /* Is this a repeated call for an rbuf we already found earlier? */ + rbuf = *cookie; + if (rbuf) + goto have_rbuf; + add_wait_queue(&tty->read_wait, &wait);
for (;;) { @@ -436,25 +442,8 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, set_current_state(TASK_INTERRUPTIBLE);
rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); - if (rbuf) { - if (rbuf->count > nr) { - /* too large for caller's buffer */ - ret = -EOVERFLOW; - } else { - __set_current_state(TASK_RUNNING); - if (copy_to_user(buf, rbuf->buf, rbuf->count)) - ret = -EFAULT; - else - ret = rbuf->count; - } - - if (n_hdlc->rx_free_buf_list.count > - DEFAULT_RX_BUF_COUNT) - kfree(rbuf); - else - n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); + if (rbuf) break; - }
/* no data */ if (tty_io_nonblock(tty, file)) { @@ -473,6 +462,39 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, remove_wait_queue(&tty->read_wait, &wait); __set_current_state(TASK_RUNNING);
+ if (!rbuf) + return ret; + *cookie = rbuf; + +have_rbuf: + /* Have we used it up entirely? */ + if (offset >= rbuf->count) + goto done_with_rbuf; + + /* More data to go, but can't copy any more? EOVERFLOW */ + ret = -EOVERFLOW; + if (!nr) + goto done_with_rbuf; + + /* Copy as much data as possible */ + ret = rbuf->count - offset; + if (ret > nr) + ret = nr; + memcpy(kbuf, rbuf->buf+offset, ret); + offset += ret; + + /* If we still have data left, we leave the rbuf in the cookie */ + if (offset < rbuf->count) + return ret; + +done_with_rbuf: + *cookie = NULL; + + if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) + kfree(rbuf); + else + n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); + return ret;
} /* end of n_hdlc_tty_read() */ diff --git a/drivers/tty/n_null.c b/drivers/tty/n_null.c index 96feabae47407..ce03ae78f5c6a 100644 --- a/drivers/tty/n_null.c +++ b/drivers/tty/n_null.c @@ -20,7 +20,8 @@ static void n_null_close(struct tty_struct *tty) }
static ssize_t n_null_read(struct tty_struct *tty, struct file *file, - unsigned char __user * buf, size_t nr) + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) { return -EOPNOTSUPP; } diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 934dd2fb2ec80..3161f0a535e37 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -129,7 +129,7 @@ static void remove_client_block(struct r3964_info *pInfo, static int r3964_open(struct tty_struct *tty); static void r3964_close(struct tty_struct *tty); static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - unsigned char __user * buf, size_t nr); + void *cookie, unsigned char *buf, size_t nr); static ssize_t r3964_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr); static int r3964_ioctl(struct tty_struct *tty, struct file *file, @@ -1058,7 +1058,8 @@ static void r3964_close(struct tty_struct *tty) }
static ssize_t r3964_read(struct tty_struct *tty, struct file *file, - unsigned char __user * buf, size_t nr) + unsigned char *kbuf, size_t nr, + void **cookie, unsigned long offset) { struct r3964_info *pInfo = tty->disc_data; struct r3964_client_info *pClient; @@ -1109,10 +1110,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, kfree(pMsg); TRACE_M("r3964_read - msg kfree %p", pMsg);
- if (copy_to_user(buf, &theMsg, ret)) { - ret = -EFAULT; - goto unlock; - } + memcpy(kbuf, &theMsg, ret);
TRACE_PS("read - return %d", ret); goto unlock; diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c index 4479af4d2fa5c..3490ed51b1a3c 100644 --- a/drivers/tty/n_tracerouter.c +++ b/drivers/tty/n_tracerouter.c @@ -118,7 +118,9 @@ static void n_tracerouter_close(struct tty_struct *tty) * -EINVAL */ static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) { + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) +{ return -EINVAL; }
diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c index d96ba82cc3569..1d9931041fd8b 100644 --- a/drivers/tty/n_tracesink.c +++ b/drivers/tty/n_tracesink.c @@ -115,7 +115,9 @@ static void n_tracesink_close(struct tty_struct *tty) * -EINVAL */ static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) { + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) +{ return -EINVAL; }
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 219e85756171b..0bd32ae8a269d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -164,29 +164,24 @@ static void zero_buffer(struct tty_struct *tty, u8 *buffer, int size) memset(buffer, 0x00, size); }
-static int tty_copy_to_user(struct tty_struct *tty, void __user *to, - size_t tail, size_t n) +static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n) { struct n_tty_data *ldata = tty->disc_data; size_t size = N_TTY_BUF_SIZE - tail; void *from = read_buf_addr(ldata, tail); - int uncopied;
if (n > size) { tty_audit_add_data(tty, from, size); - uncopied = copy_to_user(to, from, size); - zero_buffer(tty, from, size - uncopied); - if (uncopied) - return uncopied; + memcpy(to, from, size); + zero_buffer(tty, from, size); to += size; n -= size; from = ldata->read_buf; }
tty_audit_add_data(tty, from, n); - uncopied = copy_to_user(to, from, n); - zero_buffer(tty, from, n - uncopied); - return uncopied; + memcpy(to, from, n); + zero_buffer(tty, from, n); }
/** @@ -1944,15 +1939,16 @@ static inline int input_available_p(struct tty_struct *tty, int poll) /** * copy_from_read_buf - copy read data directly * @tty: terminal device - * @b: user data + * @kbp: data * @nr: size of data * * Helper function to speed up n_tty_read. It is only called when - * ICANON is off; it copies characters straight from the tty queue to - * user space directly. It can be profitably called twice; once to - * drain the space from the tail pointer to the (physical) end of the - * buffer, and once to drain the space from the (physical) beginning of - * the buffer to head pointer. + * ICANON is off; it copies characters straight from the tty queue. + * + * It can be profitably called twice; once to drain the space from + * the tail pointer to the (physical) end of the buffer, and once + * to drain the space from the (physical) beginning of the buffer + * to head pointer. * * Called under the ldata->atomic_read_lock sem * @@ -1962,7 +1958,7 @@ static inline int input_available_p(struct tty_struct *tty, int poll) */
static int copy_from_read_buf(struct tty_struct *tty, - unsigned char __user **b, + unsigned char **kbp, size_t *nr)
{ @@ -1978,8 +1974,7 @@ static int copy_from_read_buf(struct tty_struct *tty, n = min(*nr, n); if (n) { unsigned char *from = read_buf_addr(ldata, tail); - retval = copy_to_user(*b, from, n); - n -= retval; + memcpy(*kbp, from, n); is_eof = n == 1 && *from == EOF_CHAR(tty); tty_audit_add_data(tty, from, n); zero_buffer(tty, from, n); @@ -1988,7 +1983,7 @@ static int copy_from_read_buf(struct tty_struct *tty, if (L_EXTPROC(tty) && ldata->icanon && is_eof && (head == ldata->read_tail)) n = 0; - *b += n; + *kbp += n; *nr -= n; } return retval; @@ -1997,12 +1992,12 @@ static int copy_from_read_buf(struct tty_struct *tty, /** * canon_copy_from_read_buf - copy read data in canonical mode * @tty: terminal device - * @b: user data + * @kbp: data * @nr: size of data * * Helper function for n_tty_read. It is only called when ICANON is on; * it copies one line of input up to and including the line-delimiting - * character into the user-space buffer. + * character into the result buffer. * * NB: When termios is changed from non-canonical to canonical mode and * the read buffer contains data, n_tty_set_termios() simulates an EOF @@ -2018,14 +2013,14 @@ static int copy_from_read_buf(struct tty_struct *tty, */
static int canon_copy_from_read_buf(struct tty_struct *tty, - unsigned char __user **b, + unsigned char **kbp, size_t *nr) { struct n_tty_data *ldata = tty->disc_data; size_t n, size, more, c; size_t eol; size_t tail; - int ret, found = 0; + int found = 0;
/* N.B. avoid overrun if nr == 0 */ if (!*nr) @@ -2061,10 +2056,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", __func__, eol, found, n, c, tail, more);
- ret = tty_copy_to_user(tty, *b, tail, n); - if (ret) - return -EFAULT; - *b += n; + tty_copy(tty, *kbp, tail, n); + *kbp += n; *nr -= n;
if (found) @@ -2129,10 +2122,11 @@ static int job_control(struct tty_struct *tty, struct file *file) */
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) + unsigned char *kbuf, size_t nr, + void **cookie, unsigned long offset) { struct n_tty_data *ldata = tty->disc_data; - unsigned char __user *b = buf; + unsigned char *kb = kbuf; DEFINE_WAIT_FUNC(wait, woken_wake_function); int c; int minimum, time; @@ -2178,17 +2172,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, /* First test for status change. */ if (packet && tty->link->ctrl_status) { unsigned char cs; - if (b != buf) + if (kb != kbuf) break; spin_lock_irq(&tty->link->ctrl_lock); cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; spin_unlock_irq(&tty->link->ctrl_lock); - if (put_user(cs, b)) { - retval = -EFAULT; - break; - } - b++; + *kb++ = cs; nr--; break; } @@ -2231,24 +2221,20 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, }
if (ldata->icanon && !L_EXTPROC(tty)) { - retval = canon_copy_from_read_buf(tty, &b, &nr); + retval = canon_copy_from_read_buf(tty, &kb, &nr); if (retval) break; } else { int uncopied;
/* Deal with packet mode. */ - if (packet && b == buf) { - if (put_user(TIOCPKT_DATA, b)) { - retval = -EFAULT; - break; - } - b++; + if (packet && kb == kbuf) { + *kb++ = TIOCPKT_DATA; nr--; }
- uncopied = copy_from_read_buf(tty, &b, &nr); - uncopied += copy_from_read_buf(tty, &b, &nr); + uncopied = copy_from_read_buf(tty, &kb, &nr); + uncopied += copy_from_read_buf(tty, &kb, &nr); if (uncopied) { retval = -EFAULT; break; @@ -2257,7 +2243,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
n_tty_check_unthrottle(tty);
- if (b - buf >= minimum) + if (kb - kbuf >= minimum) break; if (time) timeout = time; @@ -2269,8 +2255,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, remove_wait_queue(&tty->read_wait, &wait); mutex_unlock(&ldata->atomic_read_lock);
- if (b - buf) - retval = b - buf; + if (kb - kbuf) + retval = kb - kbuf;
return retval; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 082da38762fc7..0c11c65d27431 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -829,6 +829,65 @@ static void tty_update_time(struct timespec64 *time) time->tv_sec = sec; }
+/* + * Iterate on the ldisc ->read() function until we've gotten all + * the data the ldisc has for us. + * + * The "cookie" is something that the ldisc read function can fill + * in to let us know that there is more data to be had. + * + * We promise to continue to call the ldisc until it stops returning + * data or clears the cookie. The cookie may be something that the + * ldisc maintains state for and needs to free. + */ +static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct file *file, + char __user *buf, size_t count) +{ + int retval = 0; + void *cookie = NULL; + unsigned long offset = 0; + char kernel_buf[64]; + + do { + int size, uncopied; + + size = count > sizeof(kernel_buf) ? sizeof(kernel_buf) : count; + size = ld->ops->read(tty, file, kernel_buf, size, &cookie, offset); + if (!size) + break; + + /* + * A ldisc read error return will override any previously copied + * data (eg -EOVERFLOW from HDLC) + */ + if (size < 0) { + memzero_explicit(kernel_buf, sizeof(kernel_buf)); + return size; + } + + uncopied = copy_to_user(buf+offset, kernel_buf, size); + size -= uncopied; + offset += size; + count -= size; + + /* + * If the user copy failed, we still need to do another ->read() + * call if we had a cookie to let the ldisc clear up. + * + * But make sure size is zeroed. + */ + if (unlikely(uncopied)) { + count = 0; + retval = -EFAULT; + } + } while (cookie); + + /* We always clear tty buffer in case they contained passwords */ + memzero_explicit(kernel_buf, sizeof(kernel_buf)); + return offset ? offset : retval; +} + + /** * tty_read - read method for tty device files * @file: pointer to tty file @@ -862,10 +921,9 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, ld = tty_ldisc_ref_wait(tty); if (!ld) return hung_up_tty_read(file, buf, count, ppos); + i = -EIO; if (ld->ops->read) - i = ld->ops->read(tty, file, buf, count); - else - i = -EIO; + i = iterate_tty_read(ld, tty, file, buf, count); tty_ldisc_deref(ld);
if (i > 0) diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index b1e6043e99175..572a079761165 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -185,7 +185,8 @@ struct tty_ldisc_ops { void (*close)(struct tty_struct *); void (*flush_buffer)(struct tty_struct *tty); ssize_t (*read)(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr); + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset); ssize_t (*write)(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr); int (*ioctl)(struct tty_struct *tty, struct file *file, diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c index 11b554ce07ffc..1204c438e87dc 100644 --- a/net/nfc/nci/uart.c +++ b/net/nfc/nci/uart.c @@ -292,7 +292,8 @@ static int nci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
/* We don't provide read/write/poll interface for user space. */ static ssize_t nci_uart_tty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) + unsigned char *buf, size_t nr, + void **cookie, unsigned long offset) { return 0; }
From: Linus Torvalds torvalds@linux-foundation.org
[ Upstream commit dd78b0c483e33225e0e0782b0ed887129b00f956 ]
Now that the ldisc read() function takes kernel pointers, it's fairly straightforward to make the tty file operations use .read_iter() instead of .read().
That automatically gives us vread() and friends, and also makes it possible to do .splice_read() on ttys again.
Fixes: 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops") Reported-by: Oliver Giles ohw.giles@gmail.com Cc: Christoph Hellwig hch@lst.de Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/tty_io.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 0c11c65d27431..623738d8e32c8 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -142,7 +142,7 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex);
-static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t tty_read(struct kiocb *, struct iov_iter *); static ssize_t tty_write(struct kiocb *, struct iov_iter *); static __poll_t tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); @@ -473,8 +473,9 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file)
static const struct file_operations tty_fops = { .llseek = no_llseek, - .read = tty_read, + .read_iter = tty_read, .write_iter = tty_write, + .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, @@ -487,8 +488,9 @@ static const struct file_operations tty_fops = {
static const struct file_operations console_fops = { .llseek = no_llseek, - .read = tty_read, + .read_iter = tty_read, .write_iter = redirected_tty_write, + .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, @@ -840,16 +842,17 @@ static void tty_update_time(struct timespec64 *time) * data or clears the cookie. The cookie may be something that the * ldisc maintains state for and needs to free. */ -static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct file *file, - char __user *buf, size_t count) +static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, + struct file *file, struct iov_iter *to) { int retval = 0; void *cookie = NULL; unsigned long offset = 0; char kernel_buf[64]; + size_t count = iov_iter_count(to);
do { - int size, uncopied; + int size, copied;
size = count > sizeof(kernel_buf) ? sizeof(kernel_buf) : count; size = ld->ops->read(tty, file, kernel_buf, size, &cookie, offset); @@ -865,10 +868,9 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct return size; }
- uncopied = copy_to_user(buf+offset, kernel_buf, size); - size -= uncopied; - offset += size; - count -= size; + copied = copy_to_iter(kernel_buf, size, to); + offset += copied; + count -= copied;
/* * If the user copy failed, we still need to do another ->read() @@ -876,7 +878,7 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct * * But make sure size is zeroed. */ - if (unlikely(uncopied)) { + if (unlikely(copied != size)) { count = 0; retval = -EFAULT; } @@ -903,10 +905,10 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct * read calls may be outstanding in parallel. */
-static ssize_t tty_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) +static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) { int i; + struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); struct tty_struct *tty = file_tty(file); struct tty_ldisc *ld; @@ -919,11 +921,9 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, /* We want to wait for the line discipline to sort out in this situation */ ld = tty_ldisc_ref_wait(tty); - if (!ld) - return hung_up_tty_read(file, buf, count, ppos); i = -EIO; - if (ld->ops->read) - i = iterate_tty_read(ld, tty, file, buf, count); + if (ld && ld->ops->read) + i = iterate_tty_read(ld, tty, file, to); tty_ldisc_deref(ld);
if (i > 0) @@ -2945,7 +2945,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
static int this_tty(const void *t, struct file *file, unsigned fd) { - if (likely(file->f_op->read != tty_read)) + if (likely(file->f_op->read_iter != tty_read)) return 0; return file_tty(file) != t ? 0 : fd + 1; }
From: Sami Tolvanen samitolvanen@google.com
[ Upstream commit 31bf92881714fe9962d43d097b5114a9b4ad0a12 ]
device_initcall() expects a function of type initcall_t, which returns an integer. Change the signature of sgx_init() to match.
Fixes: e7e0545299d8c ("x86/sgx: Initialize metadata for Enclave Page Cache (EPC) sections") Signed-off-by: Sami Tolvanen samitolvanen@google.com Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Darren Kenny darren.kenny@oracle.com Reviewed-by: Jarkko Sakkinen jarkko@kernel.org Link: https://lkml.kernel.org/r/20210113232311.277302-1-samitolvanen@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kernel/cpu/sgx/main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index c519fc5f69480..8df81a3ed9457 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -700,25 +700,27 @@ static bool __init sgx_page_cache_init(void) return true; }
-static void __init sgx_init(void) +static int __init sgx_init(void) { int ret; int i;
if (!cpu_feature_enabled(X86_FEATURE_SGX)) - return; + return -ENODEV;
if (!sgx_page_cache_init()) - return; + return -ENOMEM;
- if (!sgx_page_reclaimer_init()) + if (!sgx_page_reclaimer_init()) { + ret = -ENOMEM; goto err_page_cache; + }
ret = sgx_drv_init(); if (ret) goto err_kthread;
- return; + return 0;
err_kthread: kthread_stop(ksgxd_tsk); @@ -728,6 +730,8 @@ err_page_cache: vfree(sgx_epc_sections[i].pages); memunmap(sgx_epc_sections[i].virt_addr); } + + return ret; }
device_initcall(sgx_init);
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit 86ce322d21eb032ed8fdd294d0fb095d2debb430 ]
Fix bug in handling bpf_testmod unloading that will cause test_progs exiting prematurely if bpf_testmod unloading failed. This is especially problematic when running a subset of test_progs that doesn't require root permissions and doesn't rely on bpf_testmod, yet will fail immediately due to exit(1) in unload_bpf_testmod().
Fixes: 9f7fa225894c ("selftests/bpf: Add bpf_testmod kernel module for testing") Signed-off-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20210126065019.1268027-1-andrii@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/bpf/test_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 213628ee721c1..6396932b97e29 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -390,7 +390,7 @@ static void unload_bpf_testmod(void) return; } fprintf(env.stderr, "Failed to unload bpf_testmod.ko from kernel: %d\n", -errno); - exit(1); + return; } if (env.verbosity > VERBOSE_NONE) fprintf(stdout, "Successfully unloaded bpf_testmod.ko.\n");
From: Yongqiang Niu yongqiang.niu@mediatek.com
[ Upstream commit 431368c2648b59e5485a1b5f1276a83d885fb44b ]
property name must include only lowercase and '-'
Fixes: 91f9c963ce79 ("arm64: dts: mt8183: Add display nodes for MT8183") Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com Signed-off-by: Hsin-Yi Wang hsinyi@chromium.org Reviewed-by: Chun-Kuang Hu chunkuang.hu@kernel.org Reviewed-by: Enric Balletbo i Serra enric.balletbo@collabora.com Link: https://lore.kernel.org/r/20210128112314.1304160-2-hsinyi@chromium.org Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 5b782a4769e7e..6c84ccb709af6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -1011,7 +1011,7 @@ clocks = <&mmsys CLK_MM_DISP_RDMA0>; iommus = <&iommu M4U_PORT_DISP_RDMA0>; mediatek,larb = <&larb0>; - mediatek,rdma_fifo_size = <5120>; + mediatek,rdma-fifo-size = <5120>; mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xb000 0x1000>; };
@@ -1023,7 +1023,7 @@ clocks = <&mmsys CLK_MM_DISP_RDMA1>; iommus = <&iommu M4U_PORT_DISP_RDMA1>; mediatek,larb = <&larb0>; - mediatek,rdma_fifo_size = <2048>; + mediatek,rdma-fifo-size = <2048>; mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0xc000 0x1000>; };
From: Yongqiang Niu yongqiang.niu@mediatek.com
[ Upstream commit 9a2cb5eba7ad4fa7ccb3a4aa754f5263111e8f96 ]
mt8183 gamma is different with mt8173 remove mt8173 compatible name for mt8183 gamma
Fixes: 91f9c963ce79 ("arm64: dts: mt8183: Add display nodes for MT8183") Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com Signed-off-by: Hsin-Yi Wang hsinyi@chromium.org Reviewed-by: Enric Balletbo i Serra enric.balletbo@collabora.com Link: https://lore.kernel.org/r/20210128112314.1304160-3-hsinyi@chromium.org Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 6c84ccb709af6..9c0073cfad452 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -1055,8 +1055,7 @@ };
gamma0: gamma@14011000 { - compatible = "mediatek,mt8183-disp-gamma", - "mediatek,mt8173-disp-gamma"; + compatible = "mediatek,mt8183-disp-gamma"; reg = <0 0x14011000 0 0x1000>; interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_LOW>; power-domains = <&spm MT8183_POWER_DOMAIN_DISP>;
From: Enric Balletbo i Serra enric.balletbo@collabora.com
[ Upstream commit 2f99fb6e46b0e982bb6ab18b24a08fa318f740ea ]
The MT8183 display PWM device will not work until the associated power-domain is enabled. Add the power-domain reference to the node allows the display PWM driver to operate and the backlight turn on.
Fixes: f15722c0fef0 ("arm64: dts: mt8183: Add pwm and backlight node") Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Reviewed-by: Hsin-Yi Wang hsinyi@chromium.org Link: https://lore.kernel.org/r/20210113215723.71966-1-enric.balletbo@collabora.co... Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 9c0073cfad452..64fbba76597c8 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -661,6 +661,7 @@ compatible = "mediatek,mt8183-disp-pwm"; reg = <0 0x1100e000 0 0x1000>; interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_LOW>; + power-domains = <&spm MT8183_POWER_DOMAIN_DISP>; #pwm-cells = <2>; clocks = <&topckgen CLK_TOP_MUX_DISP_PWM>, <&infracfg CLK_INFRA_DISP_PWM>;
From: Pali Rohár pali@kernel.org
[ Upstream commit 426c6cbc409cbda9ab1a9dbf15d3c2ef947eb8c1 ]
The workaround for VSOL V2801F brand based GPON SFP modules added in commit 0d035bed2a4a ("net: sfp: VSOL V2801F / CarlitoxxPro CPGOS03-0490 v2.0 workaround") works only for IDs added explicitly to the list. Since there are rebranded modules where OEM vendors put different strings into the vendor name field, we cannot base workaround on IDs only.
Moreover the issue which the above mentioned commit tried to work around is generic not only to VSOL based modules, but rather to all GPON modules based on Realtek RTL8672 and RTL9601C chips.
These include at least the following GPON modules: * V-SOL V2801F * C-Data FD511GX-RM0 * OPTON GP801R * BAUDCOM BD-1234-SFM * CPGOS03-0490 v2.0 * Ubiquiti U-Fiber Instant * EXOT EGS1
These Realtek chips have broken EEPROM emulator which for N-byte read operation returns just the first byte of EEPROM data, followed by N-1 zeros.
Introduce a new function, sfp_id_needs_byte_io(), which detects SFP modules with broken EEPROM emulator based on N-1 zeros and switch to 1 byte EEPROM reading operation.
Function sfp_i2c_read() now always uses single byte reading when it is required and when function sfp_hwmon_probe() detects single byte access, it disables registration of hwmon device, because in this case we cannot reliably and atomically read 2 bytes as is required by the standard for retrieving values from diagnostic area.
(These Realtek chips are broken in a way that violates SFP standards for diagnostic interface. Kernel in this case simply cannot do anything less of skipping registration of the hwmon interface.)
This patch fixes reading of EEPROM content from SFP modules based on Realtek RTL8672 and RTL9601C chips. Diagnostic interface of EEPROM stays broken and cannot be fixed.
Fixes: 0d035bed2a4a ("net: sfp: VSOL V2801F / CarlitoxxPro CPGOS03-0490 v2.0 workaround") Co-developed-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Pali Rohár pali@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/sfp.c | 100 ++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 33 deletions(-)
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index 91d74c1a920ab..f2b5e467a8001 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -336,19 +336,11 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, size_t len) { struct i2c_msg msgs[2]; - size_t block_size; + u8 bus_addr = a2 ? 0x51 : 0x50; + size_t block_size = sfp->i2c_block_size; size_t this_len; - u8 bus_addr; int ret;
- if (a2) { - block_size = 16; - bus_addr = 0x51; - } else { - block_size = sfp->i2c_block_size; - bus_addr = 0x50; - } - msgs[0].addr = bus_addr; msgs[0].flags = 0; msgs[0].len = 1; @@ -1282,6 +1274,20 @@ static void sfp_hwmon_probe(struct work_struct *work) struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work); int err, i;
+ /* hwmon interface needs to access 16bit registers in atomic way to + * guarantee coherency of the diagnostic monitoring data. If it is not + * possible to guarantee coherency because EEPROM is broken in such way + * that does not support atomic 16bit read operation then we have to + * skip registration of hwmon device. + */ + if (sfp->i2c_block_size < 2) { + dev_info(sfp->dev, + "skipping hwmon device registration due to broken EEPROM\n"); + dev_info(sfp->dev, + "diagnostic EEPROM area cannot be read atomically to guarantee data coherency\n"); + return; + } + err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag)); if (err < 0) { if (sfp->hwmon_tries--) { @@ -1642,26 +1648,30 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable) return 0; }
-/* Some modules (Nokia 3FE46541AA) lock up if byte 0x51 is read as a - * single read. Switch back to reading 16 byte blocks unless we have - * a CarlitoxxPro module (rebranded VSOL V2801F). Even more annoyingly, - * some VSOL V2801F have the vendor name changed to OEM. +/* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL + * V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do + * not support multibyte reads from the EEPROM. Each multi-byte read + * operation returns just one byte of EEPROM followed by zeros. There is + * no way to identify which modules are using Realtek RTL8672 and RTL9601C + * chips. Moreover every OEM of V-SOL V2801F module puts its own vendor + * name and vendor id into EEPROM, so there is even no way to detect if + * module is V-SOL V2801F. Therefore check for those zeros in the read + * data and then based on check switch to reading EEPROM to one byte + * at a time. */ -static int sfp_quirk_i2c_block_size(const struct sfp_eeprom_base *base) +static bool sfp_id_needs_byte_io(struct sfp *sfp, void *buf, size_t len) { - if (!memcmp(base->vendor_name, "VSOL ", 16)) - return 1; - if (!memcmp(base->vendor_name, "OEM ", 16) && - !memcmp(base->vendor_pn, "V2801F ", 16)) - return 1; + size_t i, block_size = sfp->i2c_block_size;
- /* Some modules can't cope with long reads */ - return 16; -} + /* Already using byte IO */ + if (block_size == 1) + return false;
-static void sfp_quirks_base(struct sfp *sfp, const struct sfp_eeprom_base *base) -{ - sfp->i2c_block_size = sfp_quirk_i2c_block_size(base); + for (i = 1; i < len; i += block_size) { + if (memchr_inv(buf + i, '\0', min(block_size - 1, len - i))) + return false; + } + return true; }
static int sfp_cotsworks_fixup_check(struct sfp *sfp, struct sfp_eeprom_id *id) @@ -1705,11 +1715,11 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) u8 check; int ret;
- /* Some modules (CarlitoxxPro CPGOS03-0490) do not support multibyte - * reads from the EEPROM, so start by reading the base identifying - * information one byte at a time. + /* Some SFP modules and also some Linux I2C drivers do not like reads + * longer than 16 bytes, so read the EEPROM in chunks of 16 bytes at + * a time. */ - sfp->i2c_block_size = 1; + sfp->i2c_block_size = 16;
ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base)); if (ret < 0) { @@ -1723,6 +1733,33 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) return -EAGAIN; }
+ /* Some SFP modules (e.g. Nokia 3FE46541AA) lock up if read from + * address 0x51 is just one byte at a time. Also SFF-8472 requires + * that EEPROM supports atomic 16bit read operation for diagnostic + * fields, so do not switch to one byte reading at a time unless it + * is really required and we have no other option. + */ + if (sfp_id_needs_byte_io(sfp, &id.base, sizeof(id.base))) { + dev_info(sfp->dev, + "Detected broken RTL8672/RTL9601C emulated EEPROM\n"); + dev_info(sfp->dev, + "Switching to reading EEPROM to one byte at a time\n"); + sfp->i2c_block_size = 1; + + ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base)); + if (ret < 0) { + if (report) + dev_err(sfp->dev, "failed to read EEPROM: %d\n", + ret); + return -EAGAIN; + } + + if (ret != sizeof(id.base)) { + dev_err(sfp->dev, "EEPROM short read: %d\n", ret); + return -EAGAIN; + } + } + /* Cotsworks do not seem to update the checksums when they * do the final programming with the final module part number, * serial number and date code. @@ -1757,9 +1794,6 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) } }
- /* Apply any early module-specific quirks */ - sfp_quirks_base(sfp, &id.base); - ret = sfp_read(sfp, false, SFP_CC_BASE + 1, &id.ext, sizeof(id.ext)); if (ret < 0) { if (report)
From: Peter Geis pgwipeout@gmail.com
[ Upstream commit 3029a563ac0ccd39b9dc53eadfb9c0e3fb57a449 ]
Ouya fails to detect the eMMC module when booted via certain bootloaders. Fastboot and hard-kexec bootloaders fail while u-boot does not. It was discovered that the issue manifests if the sdmmc4 alternate configuration clock pin is input disabled.
Ouya uses sdmmc4 in the primary pin configuration. It is unknown why this occurs, though it is likely related to other eMMC limitations experienced on Ouya.
For now, fix it by enabling input on cam_mclk_pcc0.
Fixes: d7195ac5c9c5 ("ARM: tegra: Add device-tree for Ouya") Reported-by: Matt Merhar mattmerhar@protonmail.com Tested-by: Matt Merhar mattmerhar@protonmail.com Signed-off-by: Peter Geis pgwipeout@gmail.com Acked-by: Thierry Reding treding@nvidia.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/dts/tegra30-ouya.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/tegra30-ouya.dts b/arch/arm/boot/dts/tegra30-ouya.dts index 74da1360d297c..0368b3b816ef2 100644 --- a/arch/arm/boot/dts/tegra30-ouya.dts +++ b/arch/arm/boot/dts/tegra30-ouya.dts @@ -4352,8 +4352,8 @@ nvidia,pins = "cam_mclk_pcc0"; nvidia,function = "vi_alt3"; nvidia,pull = <TEGRA_PIN_PULL_NONE>; - nvidia,tristate = <TEGRA_PIN_ENABLE>; - nvidia,enable-input = <TEGRA_PIN_DISABLE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; }; pcc1 { nvidia,pins = "pcc1";
From: Matthias Brugger mbrugger@suse.com
[ Upstream commit 18d6e3f6744d6105ab61de790170cb60534eeebc ]
The header file of GCE should be for MT8183 SoC instead of MT8173.
Fixes: 91f9c963ce79 ("arm64: dts: mt8183: Add display nodes for MT8183") Reported-by: CK Hu ck.hu@mediatek.com Signed-off-by: Matthias Brugger mbrugger@suse.com
Reviewed-by: Chun-Kuang Hu chunkuang.hu@kernel.org Link: https://lore.kernel.org/r/20210131101726.804-1-matthias.bgg@kernel.org Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 64fbba76597c8..36a90dd2fa7c6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -6,7 +6,7 @@ */
#include <dt-bindings/clock/mt8183-clk.h> -#include <dt-bindings/gce/mt8173-gce.h> +#include <dt-bindings/gce/mt8183-gce.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/memory/mt8183-larb-port.h>
From: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org
[ Upstream commit 1bb0c66332babc5cbc4581d962da0b03af9f23e8 ]
QCA_IBS_DISABLED flag will be set after memorydump started from controller.Currently qca_suspend() is waiting for SSR to complete based on flag QCA_IBS_DISABLED.Added to check for QCA_SSR_TRIGGERED flag too.
Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend") Signed-off-by: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_qca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 17a3859326dc7..ff2fb68a45b1e 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2111,7 +2111,8 @@ static int __maybe_unused qca_suspend(struct device *dev) !test_bit(QCA_SSR_TRIGGERED, &qca->flags)) return 0;
- if (test_bit(QCA_IBS_DISABLED, &qca->flags)) { + if (test_bit(QCA_IBS_DISABLED, &qca->flags) || + test_bit(QCA_SSR_TRIGGERED, &qca->flags)) { wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ? IBS_DISABLE_SSR_TIMEOUT_MS : FW_DOWNLOAD_TIMEOUT_MS;
From: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org
[ Upstream commit 55c0bd77479b60ea29fd390faf4545cfb3a1d79e ]
If BT SoC is running with ROM FW then just return in qca_suspend function as ROM FW does not support in-band sleep.
Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend") Signed-off-by: Venkata Lakshmi Narayana Gubba gubbaven@codeaurora.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/hci_qca.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index ff2fb68a45b1e..de36af63e1825 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -77,7 +77,8 @@ enum qca_flags { QCA_MEMDUMP_COLLECTION, QCA_HW_ERROR_EVENT, QCA_SSR_TRIGGERED, - QCA_BT_OFF + QCA_BT_OFF, + QCA_ROM_FW };
enum qca_capabilities { @@ -1664,6 +1665,7 @@ static int qca_setup(struct hci_uart *hu) if (ret) return ret;
+ clear_bit(QCA_ROM_FW, &qca->flags); /* Patch downloading has to be done without IBS mode */ set_bit(QCA_IBS_DISABLED, &qca->flags);
@@ -1721,12 +1723,14 @@ retry: hu->hdev->cmd_timeout = qca_cmd_timeout; } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ + set_bit(QCA_ROM_FW, &qca->flags); ret = 0; } else if (ret == -EAGAIN) { /* * Userspace firmware loader will return -EAGAIN in case no * patch/nvm-config is found, so run with original fw/config. */ + set_bit(QCA_ROM_FW, &qca->flags); ret = 0; }
@@ -2103,6 +2107,12 @@ static int __maybe_unused qca_suspend(struct device *dev)
set_bit(QCA_SUSPENDING, &qca->flags);
+ /* if BT SoC is running with default firmware then it does not + * support in-band sleep + */ + if (test_bit(QCA_ROM_FW, &qca->flags)) + return 0; + /* During SSR after memory dump collection, controller will be * powered off and then powered on.If controller is powered off * during SSR then we should wait until SSR is completed.
From: Joel Stanley joel@jms.id.au
[ Upstream commit d0e72be77e7995923fac73f27cf7a75d3d1a4dec ]
Aspeed's u-boot sdk has been updated with the SoC IDs for the AST2605 variant, as well as A2 and A3 variants of the 2600 family.
From u-boot's arch/arm/mach-aspeed/ast2600/scu_info.c:
SOC_ID("AST2600-A0", 0x0500030305000303), SOC_ID("AST2600-A1", 0x0501030305010303), SOC_ID("AST2620-A1", 0x0501020305010203), SOC_ID("AST2600-A2", 0x0502030305010303), SOC_ID("AST2620-A2", 0x0502020305010203), SOC_ID("AST2605-A2", 0x0502010305010103), SOC_ID("AST2600-A3", 0x0503030305030303), SOC_ID("AST2620-A3", 0x0503020305030203), SOC_ID("AST2605-A3", 0x0503010305030103),
Fixes: e0218dca5787 ("soc: aspeed: Add soc info driver") Link: https://lore.kernel.org/r/20210210114651.334324-1-joel@jms.id.au Signed-off-by: Joel Stanley joel@jms.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soc/aspeed/aspeed-socinfo.c | 33 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c index 773930e0cb100..e3215f826d17a 100644 --- a/drivers/soc/aspeed/aspeed-socinfo.c +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -25,6 +25,7 @@ static struct { /* AST2600 */ { "AST2600", 0x05000303 }, { "AST2620", 0x05010203 }, + { "AST2605", 0x05030103 }, };
static const char *siliconid_to_name(u32 siliconid) @@ -43,14 +44,30 @@ static const char *siliconid_to_name(u32 siliconid) static const char *siliconid_to_rev(u32 siliconid) { unsigned int rev = (siliconid >> 16) & 0xff; - - switch (rev) { - case 0: - return "A0"; - case 1: - return "A1"; - case 3: - return "A2"; + unsigned int gen = (siliconid >> 24) & 0xff; + + if (gen < 0x5) { + /* AST2500 and below */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 3: + return "A2"; + } + } else { + /* AST2600 */ + switch (rev) { + case 0: + return "A0"; + case 1: + return "A1"; + case 2: + return "A2"; + case 3: + return "A3"; + } }
return "??";
From: Parav Pandit parav@nvidia.com
[ Upstream commit 0e22bfb7c046e7c8ae339f396e78a0976633698c ]
rate_bytes_ps is a 64-bit field. It passed as 32-bit field to apply_police_params(). Due to this when police rate is higher than 4Gbps, 32-bit calculation ignores the carry. This results in incorrect rate configurationn the device.
Fix it by performing 64-bit calculation.
Fixes: fcb64c0f5640 ("net/mlx5: E-Switch, add ingress rate support") Signed-off-by: Parav Pandit parav@nvidia.com Reviewed-by: Eli Cohen elic@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index dd0bfbacad474..717fbaa6ce736 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -5040,7 +5040,7 @@ static int apply_police_params(struct mlx5e_priv *priv, u64 rate, */ if (rate) { rate = (rate * BITS_PER_BYTE) + 500000; - rate_mbps = max_t(u32, do_div(rate, 1000000), 1); + rate_mbps = max_t(u64, do_div(rate, 1000000), 1); }
err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps);
From: Raed Salem raeds@nvidia.com
[ Upstream commit e4484d9df5000a18916e0bbcee50828eac8e293e ]
This limitation was inherited by previous Innova (FPGA) IPsec implementation, it uses its private set of RQ handlers which does not support striding rq, for Connect-X this is no longer true.
Fix by keeping this limitation only for Innova IPsec supporting devices, as otherwise this limitation effectively wrongly blocks striding RQs for all future Connect-X devices for all flows even if IPsec offload is not used.
Fixes: 2d64663cd559 ("net/mlx5: IPsec: Add HW crypto offload support") Signed-off-by: Raed Salem raeds@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 +++-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 5fb0ab71d79ce..3edc826cc6bbe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -65,6 +65,7 @@ #include "en/devlink.h" #include "lib/mlx5.h" #include "en/ptp.h" +#include "fpga/ipsec.h"
bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev) { @@ -106,7 +107,7 @@ bool mlx5e_striding_rq_possible(struct mlx5_core_dev *mdev, if (!mlx5e_check_fragmented_striding_rq_cap(mdev)) return false;
- if (MLX5_IPSEC_DEV(mdev)) + if (mlx5_fpga_is_ipsec_device(mdev)) return false;
if (params->xdp_prog) { @@ -2069,7 +2070,7 @@ static void mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev, int i;
#ifdef CONFIG_MLX5_EN_IPSEC - if (MLX5_IPSEC_DEV(mdev)) + if (mlx5_fpga_is_ipsec_device(mdev)) byte_count += MLX5E_METADATA_ETHER_LEN; #endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index ca4b55839a8a7..4864deed9dc94 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1795,8 +1795,8 @@ int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool
rq->handle_rx_cqe = priv->profile->rx_handlers->handle_rx_cqe_mpwqe; #ifdef CONFIG_MLX5_EN_IPSEC - if (MLX5_IPSEC_DEV(mdev)) { - netdev_err(netdev, "MPWQE RQ with IPSec offload not supported\n"); + if (mlx5_fpga_is_ipsec_device(mdev)) { + netdev_err(netdev, "MPWQE RQ with Innova IPSec offload not supported\n"); return -EINVAL; } #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c index cc67366495b09..22bee49902327 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c @@ -124,7 +124,7 @@ struct mlx5_fpga_ipsec { struct ida halloc; };
-static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) +bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) { if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga)) return false; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h index db88eb4c49e34..8931b55844773 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h @@ -43,6 +43,7 @@ u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev); const struct mlx5_flow_cmds * mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type); void mlx5_fpga_ipsec_build_fs_cmds(void); +bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev); #else static inline const struct mlx5_accel_ipsec_ops *mlx5_fpga_ipsec_ops(struct mlx5_core_dev *mdev) @@ -55,6 +56,7 @@ mlx5_fs_cmd_get_default_ipsec_fpga_cmds(enum fs_flow_table_type type) }
static inline void mlx5_fpga_ipsec_build_fs_cmds(void) {}; +static inline bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) { return false; }
#endif /* CONFIG_MLX5_FPGA_IPSEC */ #endif /* __MLX5_FPGA_IPSEC_H__ */
From: Maxim Mikityanskiy maximmi@mellanox.com
[ Upstream commit ebf79b6be67c0a77a9ab7cdf74c43fd7d9619f0c ]
The commit mentioned below has split the parameters of ICOSQ and async ICOSQ, but it contained a typo: the CQ parameters were swapped for ICOSQ and async ICOSQ. Async ICOSQ is longer than the normal ICOSQ, and the CQ size must be the same as the size of the corresponding SQ, but due to this bug, the CQ of async ICOSQ was much shorter than async ICOSQ itself. It led to overflows of the CQ with such messages in dmesg, in particular, when running multiple kTLS-offloaded streams:
mlx5_core 0000:08:00.0: cq_err_event_notifier:529:(pid 9422): CQ error on CQN 0x406, syndrome 0x1 mlx5_core 0000:08:00.0 eth2: mlx5e_cq_error_event: cqn=0x000406 event=0x04
This commit fixes the issue by using the corresponding parameters for ICOSQ and async ICOSQ.
Fixes: c293ac927fbb ("net/mlx5e: Refactor build channel params") Signed-off-by: Maxim Mikityanskiy maximmi@mellanox.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 3edc826cc6bbe..a2e0b548bf570 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1827,12 +1827,12 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
mlx5e_build_create_cq_param(&ccp, c);
- err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp, + err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp, &c->async_icosq.cq); if (err) return err;
- err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp, + err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp, &c->icosq.cq); if (err) goto err_close_async_icosq_cq;
From: Dany Madden drt@linux.ibm.com
[ Upstream commit a6f2fe5f108c11ff8023d07f9c00cc3c9c3203b8 ]
The supported indirect subcrq entries on Power8 is 16. Power9 supports 128. Redefined this value to 16 to minimize the driver from having to reset when migrating between Power9 and Power8. In our rx/tx performance testing, we found no performance difference between 16 and 128 at this time.
Fixes: f019fb6392e5 ("ibmvnic: Introduce indirect subordinate Command Response Queue buffer") Signed-off-by: Dany Madden drt@linux.ibm.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 3cccbba703658..72fea3b1c87d9 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -31,7 +31,7 @@ #define IBMVNIC_BUFFS_PER_POOL 100 #define IBMVNIC_MAX_QUEUES 16 #define IBMVNIC_MAX_QUEUE_SZ 4096 -#define IBMVNIC_MAX_IND_DESCS 128 +#define IBMVNIC_MAX_IND_DESCS 16 #define IBMVNIC_IND_ARR_SZ (IBMVNIC_MAX_IND_DESCS * 32)
#define IBMVNIC_TSO_BUF_SZ 65536
From: Alex Elder elder@linaro.org
[ Upstream commit 25c5a7e89b1de80f4b04ad5365b2e05fefd92279 ]
We configure the minimum and maximum number of various types of IPA resources in ipa_resource_config(). It iterates over resource types in the configuration data and assigns resource limits to each resource group for each type.
Unfortunately, we are repeatedly initializing the resource data for the first type, rather than initializing each of the types whose limits are specified.
Fix this bug.
Fixes: 4a0d7579d466e ("net: ipa: avoid going past end of resource group array") Signed-off-by: Alex Elder elder@linaro.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ipa/ipa_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 84bb8ae927252..eb1c8396bcdd9 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -581,10 +581,10 @@ ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data) return -EINVAL;
for (i = 0; i < data->resource_src_count; i++) - ipa_resource_config_src(ipa, data->resource_src); + ipa_resource_config_src(ipa, &data->resource_src[i]);
for (i = 0; i < data->resource_dst_count; i++) - ipa_resource_config_dst(ipa, data->resource_dst); + ipa_resource_config_dst(ipa, &data->resource_dst[i]);
return 0; }
From: Bjarni Jonasson bjarni.jonasson@microchip.com
[ Upstream commit 85e97f0b984eb36cba0ecaf87c66a9f7445d73dc ]
The current IB serdes calibration algorithm (performed by the onboard 8051) has proven to be unstable for the VSC8514 QSGMII phy. A new algorithm has been developed based on 'Frequency-offset Jittered-Injection' or 'FoJi' method which solves all known issues. This patch disables the 8051 algorithm and replaces it with the new FoJi algorithm. The calibration is now performed in a new file (mscc_serdes.c), which can act as an placeholder for future serdes configurations.
Fixes: e4f9ba642f0b ("net: phy: mscc: add support for VSC8514 PHY.") Signed-off-by: Steen Hegelund steen.hegelund@microchip.com Signed-off-by: Bjarni Jonasson bjarni.jonasson@microchip.com Tested-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/mscc/Makefile | 1 + drivers/net/phy/mscc/mscc.h | 16 + drivers/net/phy/mscc/mscc_main.c | 308 +++++++------- drivers/net/phy/mscc/mscc_serdes.c | 650 +++++++++++++++++++++++++++++ drivers/net/phy/mscc/mscc_serdes.h | 31 ++ 5 files changed, 840 insertions(+), 166 deletions(-) create mode 100644 drivers/net/phy/mscc/mscc_serdes.c create mode 100644 drivers/net/phy/mscc/mscc_serdes.h
diff --git a/drivers/net/phy/mscc/Makefile b/drivers/net/phy/mscc/Makefile index d8e22a4eeeffa..78d84194f79ae 100644 --- a/drivers/net/phy/mscc/Makefile +++ b/drivers/net/phy/mscc/Makefile @@ -4,6 +4,7 @@
obj-$(CONFIG_MICROSEMI_PHY) := mscc.o mscc-objs := mscc_main.o +mscc-objs += mscc_serdes.o
ifdef CONFIG_MACSEC mscc-objs += mscc_macsec.o diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index c2023f93c0b24..2028c319f14dd 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -339,6 +339,10 @@ enum rgmii_clock_delay { #define VSC8584_REVB 0x0001 #define MSCC_DEV_REV_MASK GENMASK(3, 0)
+#define MSCC_ROM_TRAP_SERDES_6G_CFG 0x1E48 +#define MSCC_RAM_TRAP_SERDES_6G_CFG 0x1E4F +#define PATCH_VEC_ZERO_EN 0x0100 + struct reg_val { u16 reg; u32 val; @@ -420,6 +424,18 @@ enum csr_target { MACRO_CTRL = 0x07, };
+u32 vsc85xx_csr_read(struct phy_device *phydev, + enum csr_target target, u32 reg); + +int vsc85xx_csr_write(struct phy_device *phydev, + enum csr_target target, u32 reg, u32 val); + +int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val); +int phy_base_read(struct phy_device *phydev, u32 regnum); +int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb); +int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb); +int vsc8584_cmd(struct phy_device *phydev, u16 val); + #if IS_ENABLED(CONFIG_MACSEC) int vsc8584_macsec_init(struct phy_device *phydev); void vsc8584_handle_macsec_interrupt(struct phy_device *phydev); diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 7830340b9cdc8..0e6e7076a740e 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -17,7 +17,7 @@ #include <linux/of.h> #include <linux/netdevice.h> #include <dt-bindings/net/mscc-phy-vsc8531.h> - +#include "mscc_serdes.h" #include "mscc.h"
static const struct vsc85xx_hw_stat vsc85xx_hw_stats[] = { @@ -689,7 +689,7 @@ out_unlock: }
/* phydev->bus->mdio_lock should be locked when using this function */ -static int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val) +int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val) { if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) { dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n"); @@ -700,7 +700,7 @@ static int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val) }
/* phydev->bus->mdio_lock should be locked when using this function */ -static int phy_base_read(struct phy_device *phydev, u32 regnum) +int phy_base_read(struct phy_device *phydev, u32 regnum) { if (unlikely(!mutex_is_locked(&phydev->mdio.bus->mdio_lock))) { dev_err(&phydev->mdio.dev, "MDIO bus lock not held!\n"); @@ -710,8 +710,8 @@ static int phy_base_read(struct phy_device *phydev, u32 regnum) return __phy_package_read(phydev, regnum); }
-static u32 vsc85xx_csr_read(struct phy_device *phydev, - enum csr_target target, u32 reg) +u32 vsc85xx_csr_read(struct phy_device *phydev, + enum csr_target target, u32 reg) { unsigned long deadline; u32 val, val_l, val_h; @@ -764,8 +764,8 @@ static u32 vsc85xx_csr_read(struct phy_device *phydev, return (val_h << 16) | val_l; }
-static int vsc85xx_csr_write(struct phy_device *phydev, - enum csr_target target, u32 reg, u32 val) +int vsc85xx_csr_write(struct phy_device *phydev, + enum csr_target target, u32 reg, u32 val) { unsigned long deadline;
@@ -826,7 +826,7 @@ static void vsc8584_csr_write(struct phy_device *phydev, u16 addr, u32 val) }
/* bus->mdio_lock should be locked when using this function */ -static int vsc8584_cmd(struct phy_device *phydev, u16 val) +int vsc8584_cmd(struct phy_device *phydev, u16 val) { unsigned long deadline; u16 reg_val; @@ -1734,6 +1734,100 @@ static int vsc85xx_config_init(struct phy_device *phydev) return 0; }
+static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, + u32 op) +{ + unsigned long deadline; + u32 val; + int ret; + + ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg, + op | (1 << mcb)); + if (ret) + return -EINVAL; + + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg); + + if (val == 0xffffffff) + return -EIO; + + } while (time_before(jiffies, deadline) && (val & op)); + + if (val & op) + return -ETIMEDOUT; + + return 0; +} + +/* Trigger a read to the specified MCB */ +int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) +{ + return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ); +} + +/* Trigger a write to the specified MCB */ +int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) +{ + return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE); +} + +static int vsc8514_config_host_serdes(struct phy_device *phydev) +{ + int ret; + u16 val; + + ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_EXTENDED_GPIO); + if (ret) + return ret; + + val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); + val &= ~MAC_CFG_MASK; + val |= MAC_CFG_QSGMII; + ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val); + if (ret) + return ret; + + ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_STANDARD); + if (ret) + return ret; + + ret = vsc8584_cmd(phydev, PROC_CMD_NOP); + if (ret) + return ret; + + ret = vsc8584_cmd(phydev, + PROC_CMD_MCB_ACCESS_MAC_CONF | + PROC_CMD_RST_CONF_PORT | + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC); + if (ret) { + dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n", + __func__, ret); + return ret; + } + + /* Apply 6G SerDes FOJI Algorithm + * Initial condition requirement: + * 1. hold 8051 in reset + * 2. disable patch vector 0, in order to allow IB cal poll during FoJi + * 3. deassert 8051 reset after change patch vector status + * 4. proceed with FoJi (vsc85xx_sd6g_config_v2) + */ + vsc8584_micro_assert_reset(phydev); + val = phy_base_read(phydev, MSCC_INT_MEM_CNTL); + /* clear bit 8, to disable patch vector 0 */ + val &= ~PATCH_VEC_ZERO_EN; + ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, val); + /* Enable 8051 clock, don't set patch present, disable PRAM clock override */ + vsc8584_micro_deassert_reset(phydev, false); + + return vsc85xx_sd6g_config_v2(phydev); +} + static int vsc8514_config_pre_init(struct phy_device *phydev) { /* These are the settings to override the silicon default @@ -1803,56 +1897,48 @@ static int vsc8514_config_pre_init(struct phy_device *phydev) reg &= ~SMI_BROADCAST_WR_EN; phy_base_write(phydev, MSCC_PHY_EXT_CNTL_STATUS, reg);
- return 0; -} - -static int __phy_write_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb, - u32 op) -{ - unsigned long deadline; - u32 val; - int ret; + /* Add pre-patching commands to: + * 1. enable 8051 clock, operate 8051 clock at 125 MHz + * instead of HW default 62.5MHz + * 2. write patch vector 0, to skip IB cal polling executed + * as part of the 0x80E0 ROM command + */ + vsc8584_micro_deassert_reset(phydev, false);
- ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, reg, - op | (1 << mcb)); + vsc8584_micro_assert_reset(phydev); + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, + MSCC_PHY_PAGE_EXTENDED_GPIO); + /* ROM address to trap, for patch vector 0 */ + reg = MSCC_ROM_TRAP_SERDES_6G_CFG; + ret = phy_base_write(phydev, MSCC_TRAP_ROM_ADDR(1), reg); if (ret) - return -EINVAL; - - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); - do { - usleep_range(500, 1000); - val = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, reg); - - if (val == 0xffffffff) - return -EIO; - - } while (time_before(jiffies, deadline) && (val & op)); - - if (val & op) - return -ETIMEDOUT; - - return 0; -} - -/* Trigger a read to the specified MCB */ -static int phy_update_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) -{ - return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_READ); -} + goto err; + /* RAM address to jump to, when patch vector 0 enabled */ + reg = MSCC_RAM_TRAP_SERDES_6G_CFG; + ret = phy_base_write(phydev, MSCC_PATCH_RAM_ADDR(1), reg); + if (ret) + goto err; + reg = phy_base_read(phydev, MSCC_INT_MEM_CNTL); + reg |= PATCH_VEC_ZERO_EN; /* bit 8, enable patch vector 0 */ + ret = phy_base_write(phydev, MSCC_INT_MEM_CNTL, reg); + if (ret) + goto err;
-/* Trigger a write to the specified MCB */ -static int phy_commit_mcb_s6g(struct phy_device *phydev, u32 reg, u8 mcb) -{ - return __phy_write_mcb_s6g(phydev, reg, mcb, PHY_MCB_S6G_WRITE); + /* Enable 8051 clock, don't set patch present + * yet, disable PRAM clock override + */ + vsc8584_micro_deassert_reset(phydev, false); + return ret; + err: + /* restore 8051 and bail w error */ + vsc8584_micro_deassert_reset(phydev, false); + return ret; }
static int vsc8514_config_init(struct phy_device *phydev) { struct vsc8531_private *vsc8531 = phydev->priv; - unsigned long deadline; int ret, i; - u16 val; - u32 reg;
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
@@ -1869,123 +1955,13 @@ static int vsc8514_config_init(struct phy_device *phydev) * do the correct init sequence for all PHYs that are package-critical * in this pre-init function. */ - if (phy_package_init_once(phydev)) - vsc8514_config_pre_init(phydev); - - ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, - MSCC_PHY_PAGE_EXTENDED_GPIO); - if (ret) - goto err; - - val = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); - - val &= ~MAC_CFG_MASK; - val |= MAC_CFG_QSGMII; - ret = phy_base_write(phydev, MSCC_PHY_MAC_CFG_FASTLINK, val); - if (ret) - goto err; - - ret = phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, - MSCC_PHY_PAGE_STANDARD); - if (ret) - goto err; - - ret = vsc8584_cmd(phydev, - PROC_CMD_MCB_ACCESS_MAC_CONF | - PROC_CMD_RST_CONF_PORT | - PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC); - if (ret) - goto err; - - /* 6g mcb */ - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); - /* lcpll mcb */ - phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); - /* pll5gcfg0 */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL5G_CFG0, 0x7036f145); - if (ret) - goto err; - - phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); - /* pllcfg */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL_CFG, - (3 << PHY_S6G_PLL_ENA_OFFS_POS) | - (120 << PHY_S6G_PLL_FSM_CTRL_DATA_POS) - | (0 << PHY_S6G_PLL_FSM_ENA_POS)); - if (ret) - goto err; - - /* commoncfg */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_COMMON_CFG, - (0 << PHY_S6G_SYS_RST_POS) | - (0 << PHY_S6G_ENA_LANE_POS) | - (0 << PHY_S6G_ENA_LOOP_POS) | - (0 << PHY_S6G_QRATE_POS) | - (3 << PHY_S6G_IF_MODE_POS)); - if (ret) - goto err; - - /* misccfg */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_MISC_CFG, 1); - if (ret) - goto err; - - /* gpcfg */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_GPC_CFG, 768); - if (ret) - goto err; - - phy_commit_mcb_s6g(phydev, PHY_S6G_DFT_CFG2, 0); - - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); - do { - usleep_range(500, 1000); - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, - 0); /* read 6G MCB into CSRs */ - reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, - PHY_S6G_PLL_STATUS); - if (reg == 0xffffffff) { - phy_unlock_mdio_bus(phydev); - return -EIO; - } - - } while (time_before(jiffies, deadline) && (reg & BIT(12))); - - if (reg & BIT(12)) { - phy_unlock_mdio_bus(phydev); - return -ETIMEDOUT; - } - - /* misccfg */ - ret = vsc85xx_csr_write(phydev, PHY_MCB_TARGET, - PHY_S6G_MISC_CFG, 0); - if (ret) - goto err; - - phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); - - deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); - do { - usleep_range(500, 1000); - phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, - 0); /* read 6G MCB into CSRs */ - reg = vsc85xx_csr_read(phydev, PHY_MCB_TARGET, - PHY_S6G_IB_STATUS0); - if (reg == 0xffffffff) { - phy_unlock_mdio_bus(phydev); - return -EIO; - } - - } while (time_before(jiffies, deadline) && !(reg & BIT(8))); - - if (!(reg & BIT(8))) { - phy_unlock_mdio_bus(phydev); - return -ETIMEDOUT; + if (phy_package_init_once(phydev)) { + ret = vsc8514_config_pre_init(phydev); + if (ret) + goto err; + ret = vsc8514_config_host_serdes(phydev); + if (ret) + goto err; }
phy_unlock_mdio_bus(phydev); diff --git a/drivers/net/phy/mscc/mscc_serdes.c b/drivers/net/phy/mscc/mscc_serdes.c new file mode 100644 index 0000000000000..b3e854f53d675 --- /dev/null +++ b/drivers/net/phy/mscc/mscc_serdes.c @@ -0,0 +1,650 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Driver for Microsemi VSC85xx PHYs + * + * Author: Bjarni Jonasson bjarni.jonassoni@microchip.com + * License: Dual MIT/GPL + * Copyright (c) 2021 Microsemi Corporation + */ + +#include <linux/phy.h> +#include "mscc_serdes.h" +#include "mscc.h" + +static int pll5g_detune(struct phy_device *phydev) +{ + u32 rd_dat; + int ret; + + rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2); + rd_dat &= ~PHY_S6G_PLL5G_CFG2_GAIN_MASK; + rd_dat |= PHY_S6G_PLL5G_CFG2_ENA_GAIN; + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_PLL5G_CFG2, rd_dat); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int pll5g_tune(struct phy_device *phydev) +{ + u32 rd_dat; + int ret; + + rd_dat = vsc85xx_csr_read(phydev, MACRO_CTRL, PHY_S6G_PLL5G_CFG2); + rd_dat &= ~PHY_S6G_PLL5G_CFG2_ENA_GAIN; + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_PLL5G_CFG2, rd_dat); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_pll_cfg_wr(struct phy_device *phydev, + const u32 pll_ena_offs, + const u32 pll_fsm_ctrl_data, + const u32 pll_fsm_ena) +{ + int ret; + + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_PLL_CFG, + (pll_fsm_ena << PHY_S6G_PLL_ENA_OFFS_POS) | + (pll_fsm_ctrl_data << PHY_S6G_PLL_FSM_CTRL_DATA_POS) | + (pll_ena_offs << PHY_S6G_PLL_FSM_ENA_POS)); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_common_cfg_wr(struct phy_device *phydev, + const u32 sys_rst, + const u32 ena_lane, + const u32 ena_loop, + const u32 qrate, + const u32 if_mode, + const u32 pwd_tx) +{ + /* ena_loop = 8 for eloop */ + /* = 4 for floop */ + /* = 2 for iloop */ + /* = 1 for ploop */ + /* qrate = 1 for SGMII, 0 for QSGMII */ + /* if_mode = 1 for SGMII, 3 for QSGMII */ + + int ret; + + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_COMMON_CFG, + (sys_rst << PHY_S6G_SYS_RST_POS) | + (ena_lane << PHY_S6G_ENA_LANE_POS) | + (ena_loop << PHY_S6G_ENA_LOOP_POS) | + (qrate << PHY_S6G_QRATE_POS) | + (if_mode << PHY_S6G_IF_MODE_POS)); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_des_cfg_wr(struct phy_device *phydev, + const u32 des_phy_ctrl, + const u32 des_mbtr_ctrl, + const u32 des_bw_hyst, + const u32 des_bw_ana, + const u32 des_cpmd_sel) +{ + u32 reg_val; + int ret; + + /* configurable terms */ + reg_val = (des_phy_ctrl << PHY_S6G_DES_PHY_CTRL_POS) | + (des_mbtr_ctrl << PHY_S6G_DES_MBTR_CTRL_POS) | + (des_cpmd_sel << PHY_S6G_DES_CPMD_SEL_POS) | + (des_bw_hyst << PHY_S6G_DES_BW_HYST_POS) | + (des_bw_ana << PHY_S6G_DES_BW_ANA_POS); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_DES_CFG, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_ib_cfg0_wr(struct phy_device *phydev, + const u32 ib_rtrm_adj, + const u32 ib_sig_det_clk_sel, + const u32 ib_reg_pat_sel_offset, + const u32 ib_cal_ena) +{ + u32 base_val; + u32 reg_val; + int ret; + + /* constant terms */ + base_val = 0x60a85837; + /* configurable terms */ + reg_val = base_val | (ib_rtrm_adj << 25) | + (ib_sig_det_clk_sel << 16) | + (ib_reg_pat_sel_offset << 8) | + (ib_cal_ena << 3); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_CFG0, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_ib_cfg1_wr(struct phy_device *phydev, + const u32 ib_tjtag, + const u32 ib_tsdet, + const u32 ib_scaly, + const u32 ib_frc_offset, + const u32 ib_filt_offset) +{ + u32 ib_filt_val; + u32 reg_val = 0; + int ret; + + /* constant terms */ + ib_filt_val = 0xe0; + /* configurable terms */ + reg_val = (ib_tjtag << 17) + (ib_tsdet << 12) + (ib_scaly << 8) + + ib_filt_val + (ib_filt_offset << 4) + (ib_frc_offset << 0); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_CFG1, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_ib_cfg2_wr(struct phy_device *phydev, + const u32 ib_tinfv, + const u32 ib_tcalv, + const u32 ib_ureg) +{ + u32 ib_cfg2_val; + u32 base_val; + int ret; + + /* constant terms */ + base_val = 0x0f878010; + /* configurable terms */ + ib_cfg2_val = base_val | ((ib_tinfv) << 28) | ((ib_tcalv) << 5) | + (ib_ureg << 0); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_CFG2, + ib_cfg2_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_ib_cfg3_wr(struct phy_device *phydev, + const u32 ib_ini_hp, + const u32 ib_ini_mid, + const u32 ib_ini_lp, + const u32 ib_ini_offset) +{ + u32 reg_val; + int ret; + + reg_val = (ib_ini_hp << 24) + (ib_ini_mid << 16) + + (ib_ini_lp << 8) + (ib_ini_offset << 0); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_CFG3, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_ib_cfg4_wr(struct phy_device *phydev, + const u32 ib_max_hp, + const u32 ib_max_mid, + const u32 ib_max_lp, + const u32 ib_max_offset) +{ + u32 reg_val; + int ret; + + reg_val = (ib_max_hp << 24) + (ib_max_mid << 16) + + (ib_max_lp << 8) + (ib_max_offset << 0); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_CFG4, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_misc_cfg_wr(struct phy_device *phydev, + const u32 lane_rst) +{ + int ret; + + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_MISC_CFG, + lane_rst); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_gp_cfg_wr(struct phy_device *phydev, const u32 gp_cfg_val) +{ + int ret; + + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_GP_CFG, + gp_cfg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_dft_cfg2_wr(struct phy_device *phydev, + const u32 rx_ji_ampl, + const u32 rx_step_freq, + const u32 rx_ji_ena, + const u32 rx_waveform_sel, + const u32 rx_freqoff_dir, + const u32 rx_freqoff_ena) +{ + u32 reg_val; + int ret; + + /* configurable terms */ + reg_val = (rx_ji_ampl << 8) | (rx_step_freq << 4) | + (rx_ji_ena << 3) | (rx_waveform_sel << 2) | + (rx_freqoff_dir << 1) | rx_freqoff_ena; + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_IB_DFT_CFG2, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +static int vsc85xx_sd6g_dft_cfg0_wr(struct phy_device *phydev, + const u32 prbs_sel, + const u32 test_mode, + const u32 rx_dft_ena) +{ + u32 reg_val; + int ret; + + /* configurable terms */ + reg_val = (prbs_sel << 20) | (test_mode << 16) | (rx_dft_ena << 2); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_DFT_CFG0, + reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +/* Access LCPLL Cfg_0 */ +static int vsc85xx_pll5g_cfg0_wr(struct phy_device *phydev, + const u32 selbgv820) +{ + u32 base_val; + u32 reg_val; + int ret; + + /* constant terms */ + base_val = 0x7036f145; + /* configurable terms */ + reg_val = base_val | (selbgv820 << 23); + ret = vsc85xx_csr_write(phydev, MACRO_CTRL, + PHY_S6G_PLL5G_CFG0, reg_val); + if (ret) + dev_err(&phydev->mdio.dev, "%s: write error\n", __func__); + return ret; +} + +int vsc85xx_sd6g_config_v2(struct phy_device *phydev) +{ + u32 ib_sig_det_clk_sel_cal = 0; + u32 ib_sig_det_clk_sel_mm = 7; + u32 pll_fsm_ctrl_data = 60; + unsigned long deadline; + u32 des_bw_ana_val = 3; + u32 ib_tsdet_cal = 16; + u32 ib_tsdet_mm = 5; + u32 ib_rtrm_adj; + u32 if_mode = 1; + u32 gp_iter = 5; + u32 val32 = 0; + u32 qrate = 1; + u32 iter; + int val = 0; + int ret; + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); + + /* Detune/Unlock LCPLL */ + ret = pll5g_detune(phydev); + if (ret) + return ret; + + /* 0. Reset RCPLL */ + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 0, 0, qrate, if_mode, 0); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); + if (ret) + return ret; + + /* 1. Configure sd6g for SGMII prior to sd6g_IB_CAL */ + ib_rtrm_adj = 13; + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg3_wr(phydev, 0, 31, 1, 31); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63); + if (ret) + return ret; + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 2. Start rcpll_fsm */ + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, + PHY_S6G_PLL_STATUS); + /* wait for bit 12 to clear */ + } while (time_before(jiffies, deadline) && (val32 & BIT(12))); + + if (val32 & BIT(12)) + return -ETIMEDOUT; + + /* 4. Release digital reset and disable transmitter */ + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 5. Apply a frequency offset on RX-side (using internal FoJi logic) */ + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768); + if (ret) + return ret; + ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 2, 0, 0, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 2); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 6. Prepare required settings for IBCAL */ + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_cal, 0, 0); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 7. Start IB_CAL */ + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, + ib_sig_det_clk_sel_cal, 0, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + /* 11 cycles (for ViperA) or 5 cycles (for ViperB & Elise) w/ SW clock */ + for (iter = 0; iter < gp_iter; iter++) { + /* set gp(0) */ + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 769); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + /* clear gp(0) */ + ret = vsc85xx_sd6g_gp_cfg_wr(phydev, 768); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + } + + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 1, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_cal, 15, 0, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 8. Wait for IB cal to complete */ + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, + PHY_S6G_IB_STATUS0); + /* wait for bit 8 to set */ + } while (time_before(jiffies, deadline) && (~val32 & BIT(8))); + + if (~val32 & BIT(8)) + return -ETIMEDOUT; + + /* 9. Restore cfg values for mission mode */ + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 10. Re-enable transmitter */ + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 11. Disable frequency offset generation (using internal FoJi logic) */ + ret = vsc85xx_sd6g_dft_cfg2_wr(phydev, 0, 0, 0, 0, 0, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_dft_cfg0_wr(phydev, 0, 0, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* Tune/Re-lock LCPLL */ + ret = pll5g_tune(phydev); + if (ret) + return ret; + + /* 12. Configure for Final Configuration and Settings */ + /* a. Reset RCPLL */ + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 0, 1, 0, qrate, if_mode, 0); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* b. Configure sd6g for desired operating mode */ + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_GPIO); + ret = phy_base_read(phydev, MSCC_PHY_MAC_CFG_FASTLINK); + if ((ret & MAC_CFG_MASK) == MAC_CFG_QSGMII) { + /* QSGMII */ + pll_fsm_ctrl_data = 120; + qrate = 0; + if_mode = 3; + des_bw_ana_val = 5; + val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_QSGMII_MAC; + + ret = vsc8584_cmd(phydev, val); + if (ret) { + dev_err(&phydev->mdio.dev, "%s: QSGMII error: %d\n", + __func__, ret); + return ret; + } + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); + } else if ((ret & MAC_CFG_MASK) == MAC_CFG_SGMII) { + /* SGMII */ + pll_fsm_ctrl_data = 60; + qrate = 1; + if_mode = 1; + des_bw_ana_val = 3; + + val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT | + PROC_CMD_READ_MOD_WRITE_PORT | PROC_CMD_SGMII_MAC; + + ret = vsc8584_cmd(phydev, val); + if (ret) { + dev_err(&phydev->mdio.dev, "%s: SGMII error: %d\n", + __func__, ret); + return ret; + } + + phy_base_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD); + } else { + dev_err(&phydev->mdio.dev, "%s: invalid mac_if: %x\n", + __func__, ret); + } + + ret = phy_update_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); + if (ret) + return ret; + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + ret = vsc85xx_pll5g_cfg0_wr(phydev, 4); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_S6G_LCPLL_CFG, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_des_cfg_wr(phydev, 6, 2, 5, des_bw_ana_val, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg0_wr(phydev, ib_rtrm_adj, ib_sig_det_clk_sel_mm, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg1_wr(phydev, 8, ib_tsdet_mm, 15, 0, 1); + if (ret) + return ret; + ret = vsc85xx_sd6g_common_cfg_wr(phydev, 1, 1, 0, qrate, if_mode, 0); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg2_wr(phydev, 3, 13, 5); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg3_wr(phydev, 0, 31, 1, 31); + if (ret) + return ret; + ret = vsc85xx_sd6g_ib_cfg4_wr(phydev, 63, 63, 2, 63); + if (ret) + return ret; + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 13. Start rcpll_fsm */ + ret = vsc85xx_sd6g_pll_cfg_wr(phydev, 3, pll_fsm_ctrl_data, 1); + if (ret) + return ret; + ret = phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + + /* 14. Wait for PLL cal to complete */ + deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS); + do { + usleep_range(500, 1000); + ret = phy_update_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); + if (ret) + return ret; + val32 = vsc85xx_csr_read(phydev, MACRO_CTRL, + PHY_S6G_PLL_STATUS); + /* wait for bit 12 to clear */ + } while (time_before(jiffies, deadline) && (val32 & BIT(12))); + + if (val32 & BIT(12)) + return -ETIMEDOUT; + + /* release lane reset */ + ret = vsc85xx_sd6g_misc_cfg_wr(phydev, 0); + if (ret) + return ret; + + return phy_commit_mcb_s6g(phydev, PHY_MCB_S6G_CFG, 0); +} diff --git a/drivers/net/phy/mscc/mscc_serdes.h b/drivers/net/phy/mscc/mscc_serdes.h new file mode 100644 index 0000000000000..2a6371322af91 --- /dev/null +++ b/drivers/net/phy/mscc/mscc_serdes.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Driver for Microsemi VSC85xx PHYs + * + * Copyright (c) 2021 Microsemi Corporation + */ + +#ifndef _MSCC_SERDES_PHY_H_ +#define _MSCC_SERDES_PHY_H_ + +#define PHY_S6G_PLL5G_CFG2_GAIN_MASK GENMASK(9, 5) +#define PHY_S6G_PLL5G_CFG2_ENA_GAIN 1 + +#define PHY_S6G_DES_PHY_CTRL_POS 13 +#define PHY_S6G_DES_MBTR_CTRL_POS 10 +#define PHY_S6G_DES_CPMD_SEL_POS 8 +#define PHY_S6G_DES_BW_HYST_POS 5 +#define PHY_S6G_DES_BW_ANA_POS 1 +#define PHY_S6G_DES_CFG 0x21 +#define PHY_S6G_IB_CFG0 0x22 +#define PHY_S6G_IB_CFG1 0x23 +#define PHY_S6G_IB_CFG2 0x24 +#define PHY_S6G_IB_CFG3 0x25 +#define PHY_S6G_IB_CFG4 0x26 +#define PHY_S6G_GP_CFG 0x2E +#define PHY_S6G_DFT_CFG0 0x35 +#define PHY_S6G_IB_DFT_CFG2 0x37 + +int vsc85xx_sd6g_config_v2(struct phy_device *phydev); + +#endif /* _MSCC_PHY_SERDES_H_ */
From: Bjarni Jonasson bjarni.jonasson@microchip.com
[ Upstream commit ca0d7fd0a58dfc9503775dae7daee341c115e0c7 ]
The 'coma mode' (configurable through sw or hw) provides an optional feature that may be used to control when the PHYs become active. The typical usage is to synchronize the link-up time across all PHY instances. This patch releases coma mode if not done by hardware, otherwise the phys will not link-up.
Fixes: e4f9ba642f0b ("net: phy: mscc: add support for VSC8514 PHY.") Signed-off-by: Steen Hegelund steen.hegelund@microchip.com Signed-off-by: Bjarni Jonasson bjarni.jonasson@microchip.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/mscc/mscc.h | 4 ++++ drivers/net/phy/mscc/mscc_main.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+)
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 2028c319f14dd..a50235fdf7d99 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -140,6 +140,10 @@ enum rgmii_clock_delay { #define MSCC_PHY_PAGE_1588 0x1588 /* PTP (1588) */ #define MSCC_PHY_PAGE_TEST 0x2a30 /* Test reg */ #define MSCC_PHY_PAGE_TR 0x52b5 /* Token ring registers */ +#define MSCC_PHY_GPIO_CONTROL_2 14 + +#define MSCC_PHY_COMA_MODE 0x2000 /* input(1) / output(0) */ +#define MSCC_PHY_COMA_OUTPUT 0x1000 /* value to output */
/* Extended Page 1 Registers */ #define MSCC_PHY_CU_MEDIA_CRC_VALID_CNT 18 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 0e6e7076a740e..3a7705228ed59 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -1516,6 +1516,21 @@ static void vsc8584_get_base_addr(struct phy_device *phydev) vsc8531->addr = addr; }
+static void vsc85xx_coma_mode_release(struct phy_device *phydev) +{ + /* The coma mode (pin or reg) provides an optional feature that + * may be used to control when the PHYs become active. + * Alternatively the COMA_MODE pin may be connected low + * so that the PHYs are fully active once out of reset. + */ + + /* Enable output (mode=0) and write zero to it */ + vsc85xx_phy_write_page(phydev, MSCC_PHY_PAGE_EXTENDED_GPIO); + __phy_modify(phydev, MSCC_PHY_GPIO_CONTROL_2, + MSCC_PHY_COMA_MODE | MSCC_PHY_COMA_OUTPUT, 0); + vsc85xx_phy_write_page(phydev, MSCC_PHY_PAGE_STANDARD); +} + static int vsc8584_config_init(struct phy_device *phydev) { struct vsc8531_private *vsc8531 = phydev->priv; @@ -1962,6 +1977,7 @@ static int vsc8514_config_init(struct phy_device *phydev) ret = vsc8514_config_host_serdes(phydev); if (ret) goto err; + vsc85xx_coma_mode_release(phydev); }
phy_unlock_mdio_bus(phydev);
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit c6c90c70db4d9a0989111d6b994d545659410f7a ]
It looks like SPARC64 requires FB_ATY_CT to build without errors, so have FB_ATY select FB_ATY_CT if both SPARC64 and PCI are enabled instead of using "default y if SPARC64 && PCI", which is not strong enough to prevent build errors.
As it currently is, FB_ATY_CT can be disabled, resulting in build errors:
ERROR: modpost: "aty_postdividers" [drivers/video/fbdev/aty/atyfb.ko] undefined! ERROR: modpost: "aty_ld_pll_ct" [drivers/video/fbdev/aty/atyfb.ko] undefined!
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Fixes: f7018c213502 ("video: move fbdev to drivers/video/fbdev") Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: "David S. Miller" davem@davemloft.net Cc: sparclinux@vger.kernel.org Cc: Tomi Valkeinen tomi.valkeinen@ti.com Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Cc: Daniel Vetter daniel.vetter@ffwll.ch Cc: David Airlie airlied@linux.ie Cc: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com Cc: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20201127031752.10371-1-rdunlap... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/video/fbdev/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index cfb7f5612ef0f..4f02db65dedec 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1269,6 +1269,7 @@ config FB_ATY select FB_CFB_IMAGEBLIT select FB_BACKLIGHT if FB_ATY_BACKLIGHT select FB_MACMODES if PPC + select FB_ATY_CT if SPARC64 && PCI help This driver supports graphics boards with the ATI Mach64 chips. Say Y if you have such a graphics board. @@ -1279,7 +1280,6 @@ config FB_ATY config FB_ATY_CT bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" depends on PCI && FB_ATY - default y if SPARC64 && PCI help Say Y here to support use of ATI's 64-bit Rage boards (or other boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
From: Jialin Zhang zhangjialin11@huawei.com
[ Upstream commit 6926872ae24452d4f2176a3ba2dee659497de2c4 ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: 5c49fd3aa0ab ("gma500: Add the core DRM files and headers") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20201130020216.1906141-1-zhang... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/gma500/psb_drv.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index cc2d59e8471da..134068f9328d5 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -312,6 +312,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_err;
+ ret = -ENOMEM; + dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0); if (!dev_priv->mmu) goto out_err;
From: Simon Ser contact@emersion.fr
[ Upstream commit a7e2e1c50450c6a0f020b35960edecbe25dde520 ]
It seems like we can't have nice things, so let's just document the disappointing behaviour instead.
The previous version assumed the kernel would perform the probing work when appropriate, however this is not the case today. Update the documentation to reflect reality.
v2:
- Improve commit message to explain why this change is made (Pekka) - Keep the bit about flickering (Daniel) - Explain when user-space should force-probe, and when it shouldn't (Daniel)
Signed-off-by: Simon Ser contact@emersion.fr Fixes: 2ac5ef3b2362 ("drm: document drm_mode_get_connector") Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Reviewed-by: Pekka Paalanen pekka.paalanen@collabora.com Cc: Ville Syrjala ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/AxqLnTAsFCRishOVB5CLsqIesmrMrm... Signed-off-by: Sasha Levin sashal@kernel.org --- include/uapi/drm/drm_mode.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index b49fbf2bdc408..1c064627e6c33 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -414,15 +414,12 @@ enum drm_mode_subconnector { * * If the @count_modes field is set to zero, the kernel will perform a forced * probe on the connector to refresh the connector status, modes and EDID. - * A forced-probe can be slow and the ioctl will block. A force-probe can cause - * flickering and temporary freezes, so it should not be performed - * automatically. + * A forced-probe can be slow, might cause flickering and the ioctl will block. * - * User-space shouldn't need to force-probe connectors in general: the kernel - * will automatically take care of probing connectors that don't support - * hot-plug detection when appropriate. However, user-space may force-probe - * connectors on user request (e.g. clicking a "Scan connectors" button, or - * opening a UI to manage screens). + * User-space needs to force-probe connectors to ensure their metadata is + * up-to-date at startup and after receiving a hot-plug event. User-space + * may perform a forced-probe when the user explicitly requests it. User-space + * shouldn't perform a forced-probe in other situations. */ struct drm_mode_get_connector { /** @encoders_ptr: Pointer to ``__u32`` array of object IDs. */
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 15ccc39b3aab667c6fa131206f01f31bfbccdf6a ]
The main problem with this error handling was that it didn't clean up if i2c_add_numbered_adapter() failed. This code is pretty old, and doesn't match with today's checkpatch.pl standards so I took the opportunity to tidy it up a bit. I changed the NULL comparison, and removed the WARNING message if kzalloc() fails and updated the label names.
Fixes: 1b082ccf5901 ("gma500: Add Oaktrail support") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Patrik Jakobsson patrik.r.jakobsson@gmail.com Link: https://patchwork.freedesktop.org/patch/msgid/X8ikkAqZfnDO2lu6@mwanda Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c index e281070611480..fc9a34ed58bd1 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c @@ -279,11 +279,8 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev) hdmi_dev = pci_get_drvdata(dev);
i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); - if (i2c_dev == NULL) { - DRM_ERROR("Can't allocate interface\n"); - ret = -ENOMEM; - goto exit; - } + if (!i2c_dev) + return -ENOMEM;
i2c_dev->adap = &oaktrail_hdmi_i2c_adapter; i2c_dev->status = I2C_STAT_INIT; @@ -300,16 +297,23 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev) oaktrail_hdmi_i2c_adapter.name, hdmi_dev); if (ret) { DRM_ERROR("Failed to request IRQ for I2C controller\n"); - goto err; + goto free_dev; }
/* Adapter registration */ ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter); - return ret; + if (ret) { + DRM_ERROR("Failed to add I2C adapter\n"); + goto free_irq; + }
-err: + return 0; + +free_irq: + free_irq(dev->irq, hdmi_dev); +free_dev: kfree(i2c_dev); -exit: + return ret; }
From: Chuhong Yuan hslester96@gmail.com
[ Upstream commit 0a260e731d6c4c17547ac275a2cde888a9eb4a3d ]
setcmap_legacy() does not call drm_modeset_unlock_all() in some exits, add the missed unlocks with goto to fix it.
Fixes: 964c60063bff ("drm/fb-helper: separate the fb_setcmap helper into atomic and legacy paths") Signed-off-by: Chuhong Yuan hslester96@gmail.com Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20201203144248.418281-1-hslest... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_fb_helper.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 4b81195106875..e82db0f4e7715 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -946,11 +946,15 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info) drm_modeset_lock_all(fb_helper->dev); drm_client_for_each_modeset(modeset, &fb_helper->client) { crtc = modeset->crtc; - if (!crtc->funcs->gamma_set || !crtc->gamma_size) - return -EINVAL; + if (!crtc->funcs->gamma_set || !crtc->gamma_size) { + ret = -EINVAL; + goto out; + }
- if (cmap->start + cmap->len > crtc->gamma_size) - return -EINVAL; + if (cmap->start + cmap->len > crtc->gamma_size) { + ret = -EINVAL; + goto out; + }
r = crtc->gamma_store; g = r + crtc->gamma_size; @@ -963,8 +967,9 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info) ret = crtc->funcs->gamma_set(crtc, r, g, b, crtc->gamma_size, NULL); if (ret) - return ret; + goto out; } +out: drm_modeset_unlock_all(fb_helper->dev);
return ret;
From: Linus Walleij linus.walleij@linaro.org
[ Upstream commit 47b1adc1d2a3b39233a56e183296b335222c9a6d ]
The DSI version of the panel behaved instable and close scrutiny of the vendor driver from the Samsung GT-S8190 shows a different initialization sequence for the DSI mode panel than the DPI mode panel.
Make the initialization depend on whether we are in DSI or DPI mode and handle the differences.
After this the panel on the GT-I8190 becomes much more stable.
Also spell out some more custom DCS commands found in the vendor source code to cut down a bit on magic where we can.
Fixes: f0aee45ffc8b ("drm/panel: s6e63m0: Fix init sequence") Signed-off-by: Linus Walleij linus.walleij@linaro.org Reviewed-by: Sam Ravnborg sam@ravnborg.org Cc: Stephan Gerhold stephan@gerhold.net Link: https://patchwork.freedesktop.org/patch/msgid/20201205122229.1952980-1-linus... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 6b4e97bfd46ee..bf6d704d4d272 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -25,6 +25,14 @@ /* Manufacturer Command Set */ #define MCS_ELVSS_ON 0xb1 #define MCS_TEMP_SWIRE 0xb2 +#define MCS_PENTILE_1 0xb3 +#define MCS_PENTILE_2 0xb4 +#define MCS_GAMMA_DELTA_Y_RED 0xb5 +#define MCS_GAMMA_DELTA_X_RED 0xb6 +#define MCS_GAMMA_DELTA_Y_GREEN 0xb7 +#define MCS_GAMMA_DELTA_X_GREEN 0xb8 +#define MCS_GAMMA_DELTA_Y_BLUE 0xb9 +#define MCS_GAMMA_DELTA_X_BLUE 0xba #define MCS_MIECTL1 0xc0 #define MCS_BCMODE 0xc1 #define MCS_ERROR_CHECK 0xd5 @@ -281,6 +289,7 @@ struct s6e63m0 { struct backlight_device *bl_dev; u8 lcd_type; u8 elvss_pulse; + bool dsi_mode;
struct regulator_bulk_data supplies[2]; struct gpio_desc *reset_gpio; @@ -395,9 +404,21 @@ static int s6e63m0_check_lcd_type(struct s6e63m0 *ctx)
static void s6e63m0_init(struct s6e63m0 *ctx) { - s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL, - 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9f, - 0x63, 0x8f, 0x1a, 0x33, 0x0d, 0x00, 0x00); + /* + * We do not know why there is a difference in the DSI mode. + * (No datasheet.) + * + * In the vendor driver this sequence is called + * "SEQ_PANEL_CONDITION_SET" or "DCS_CMD_SEQ_PANEL_COND_SET". + */ + if (ctx->dsi_mode) + s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL, + 0x01, 0x2c, 0x2c, 0x07, 0x07, 0x5f, 0xb3, + 0x6d, 0x97, 0x1d, 0x3a, 0x0f, 0x00, 0x00); + else + s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL, + 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9f, + 0x63, 0x8f, 0x1a, 0x33, 0x0d, 0x00, 0x00);
s6e63m0_dcs_write_seq_static(ctx, MCS_DISCTL, 0x02, 0x03, 0x1c, 0x10, 0x10); @@ -414,40 +435,40 @@ static void s6e63m0_init(struct s6e63m0 *ctx)
s6e63m0_dcs_write_seq_static(ctx, MCS_SRCCTL, 0x00, 0x8e, 0x07); - s6e63m0_dcs_write_seq_static(ctx, 0xb3, 0x6c); + s6e63m0_dcs_write_seq_static(ctx, MCS_PENTILE_1, 0x6c);
- s6e63m0_dcs_write_seq_static(ctx, 0xb5, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_Y_RED, 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17, 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b, 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a, 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1e, 0x1e);
- s6e63m0_dcs_write_seq_static(ctx, 0xb6, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_X_RED, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66);
- s6e63m0_dcs_write_seq_static(ctx, 0xb7, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_Y_GREEN, 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17, 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b, 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a, 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1e, 0x1e);
- s6e63m0_dcs_write_seq_static(ctx, 0xb8, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_X_GREEN, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66);
- s6e63m0_dcs_write_seq_static(ctx, 0xb9, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_Y_BLUE, 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17, 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b, 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a, 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1e, 0x1e);
- s6e63m0_dcs_write_seq_static(ctx, 0xba, + s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_DELTA_X_BLUE, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66); @@ -704,6 +725,7 @@ int s6e63m0_probe(struct device *dev, if (!ctx) return -ENOMEM;
+ ctx->dsi_mode = dsi_mode; ctx->dcs_read = dcs_read; ctx->dcs_write = dcs_write; dev_set_drvdata(dev, ctx);
From: Guido Günther agx@sigxcpu.org
[ Upstream commit dd396dbc4d7811c1567cc43faa4b9ad68094c44d ]
We've seen some (non permanent) burn in and bad white balance on some of the panels. Adding this bit from a vendor supplied sequence fixes it.
Fixes: 72967d5616d3 ("drm/panel: Add panel driver for the Mantix MLAF057WE51-X DSI panel") Signed-off-by: Guido Günther agx@sigxcpu.org Reviewed-by: Linus Walleij linus.walleij@linaro.org Reviewed-by: Sam Ravnborg sam@ravnborg.org Link: https://patchwork.freedesktop.org/patch/msgid/8451831b60d5ecb73a156613d98218... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c index 0c5f22e95c2db..624d17b96a693 100644 --- a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c +++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c @@ -22,6 +22,7 @@ /* Manufacturer specific Commands send via DSI */ #define MANTIX_CMD_OTP_STOP_RELOAD_MIPI 0x41 #define MANTIX_CMD_INT_CANCEL 0x4C +#define MANTIX_CMD_SPI_FINISH 0x90
struct mantix { struct device *dev; @@ -66,6 +67,10 @@ static int mantix_init_sequence(struct mantix *ctx) dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00); msleep(20);
+ dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5); + dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F); + msleep(20); + dev_dbg(dev, "Panel init sequence done\n"); return 0; }
From: Maxime Ripard maxime@cerno.tech
[ Upstream commit 320e84dc6111ecc1c957e2b186d4d2bafee6bde2 ]
Commit 63495f6b4aed ("drm/vc4: hdmi: Make sure our clock rate is within limits") was intended to compute the pixel rate to make sure we remain within the boundaries of what the hardware can provide.
However, unlike what mode_valid was checking for, we forgot to take into account the clock doubling flag that can be set for modes. Let's honor that flag if it's there.
Acked-by: Thomas Zimmermann tzimmermann@suse.de Reported-by: Thomas Zimmermann tzimmermann@suse.de Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Fixes: 63495f6b4aed ("drm/vc4: hdmi: Make sure our clock rate is within limits") Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://patchwork.freedesktop.org/patch/msgid/20201215154243.540115-4-maxime... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 98cab0bbe92d8..2013f83ef50b6 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -790,6 +790,9 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, pixel_rate = mode->clock * 1000; }
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK) + pixel_rate = pixel_rate * 2; + if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) return -EINVAL;
From: Linus Walleij linus.walleij@linaro.org
[ Upstream commit 1f20bf5921de420071fdb1d55cda7550ae137bcd ]
The "max-brightness" is a standard backlight property that we need to support for the Samsung GT-I8190 Golden because the display will go black if we crank up the brightness too high.
As the platform needs this ability to give picture this is a regression fix along with the addition of the property to the GT-I8190 device tree.
Cc: Stephan Gerhold stephan@gerhold.net Fixes: 9c3f0a0dd6a1 ("drm/panel: s6e63m0: Implement 28 backlight levels") Signed-off-by: Linus Walleij linus.walleij@linaro.org Reviewed-by: Sam Ravnborg sam@ravnborg.org Link: https://patchwork.freedesktop.org/patch/msgid/20201214222210.238081-1-linus.... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index bf6d704d4d272..603c5dfe87682 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -692,12 +692,12 @@ static const struct backlight_ops s6e63m0_backlight_ops = { .update_status = s6e63m0_set_brightness, };
-static int s6e63m0_backlight_register(struct s6e63m0 *ctx) +static int s6e63m0_backlight_register(struct s6e63m0 *ctx, u32 max_brightness) { struct backlight_properties props = { .type = BACKLIGHT_RAW, - .brightness = MAX_BRIGHTNESS, - .max_brightness = MAX_BRIGHTNESS + .brightness = max_brightness, + .max_brightness = max_brightness, }; struct device *dev = ctx->dev; int ret = 0; @@ -719,6 +719,7 @@ int s6e63m0_probe(struct device *dev, bool dsi_mode) { struct s6e63m0 *ctx; + u32 max_brightness; int ret;
ctx = devm_kzalloc(dev, sizeof(struct s6e63m0), GFP_KERNEL); @@ -734,6 +735,14 @@ int s6e63m0_probe(struct device *dev, ctx->enabled = false; ctx->prepared = false;
+ ret = device_property_read_u32(dev, "max-brightness", &max_brightness); + if (ret) + max_brightness = MAX_BRIGHTNESS; + if (max_brightness > MAX_BRIGHTNESS) { + dev_err(dev, "illegal max brightness specified\n"); + max_brightness = MAX_BRIGHTNESS; + } + ctx->supplies[0].supply = "vdd3"; ctx->supplies[1].supply = "vci"; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), @@ -753,7 +762,7 @@ int s6e63m0_probe(struct device *dev, dsi_mode ? DRM_MODE_CONNECTOR_DSI : DRM_MODE_CONNECTOR_DPI);
- ret = s6e63m0_backlight_register(ctx); + ret = s6e63m0_backlight_register(ctx, max_brightness); if (ret < 0) return ret;
From: Corentin Labbe clabbe@baylibre.com
[ Upstream commit 583513510a7acd2306787865bcd19ebb2f629d42 ]
When running the non-optimized cipher function, SS produce partial random output. This is due to linearize buffers being reseted after each loop.
For preserving stack, instead of moving them back to start of function, I move them in sun4i_ss_ctx.
Fixes: 8d3bcb9900ca ("crypto: sun4i-ss - reduce stack usage") Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 12 ++++-------- drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 ++ 2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c index b72de8939497b..19f1aa577ed4d 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -233,8 +233,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
while (oleft) { if (ileft) { - char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ - /* * todo is the number of consecutive 4byte word that we * can read from current SG @@ -256,12 +254,12 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) */ todo = min(rx_cnt * 4 - ob, ileft); todo = min_t(size_t, todo, mi.length - oi); - memcpy(buf + ob, mi.addr + oi, todo); + memcpy(ss->buf + ob, mi.addr + oi, todo); ileft -= todo; oi += todo; ob += todo; if (!(ob % 4)) { - writesl(ss->base + SS_RXFIFO, buf, + writesl(ss->base + SS_RXFIFO, ss->buf, ob / 4); ob = 0; } @@ -295,13 +293,11 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) oo = 0; } } else { - char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ - /* * read obl bytes in bufo, we read at maximum for * emptying the device */ - readsl(ss->base + SS_TXFIFO, bufo, tx_cnt); + readsl(ss->base + SS_TXFIFO, ss->bufo, tx_cnt); obl = tx_cnt * 4; obo = 0; do { @@ -313,7 +309,7 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) */ todo = min_t(size_t, mo.length - oo, obl - obo); - memcpy(mo.addr + oo, bufo + obo, todo); + memcpy(mo.addr + oo, ss->bufo + obo, todo); oleft -= todo; obo += todo; oo += todo; diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h index 5c291e4a6857b..c242fccb2ab67 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h @@ -148,6 +148,8 @@ struct sun4i_ss_ctx { struct reset_control *reset; struct device *dev; struct resource *res; + char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ + char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ spinlock_t slock; /* control the use of the device */ #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG u32 seed[SS_SEED_LEN / BITS_PER_LONG];
From: Corentin Labbe clabbe@baylibre.com
[ Upstream commit 9bc3dd24e7dccd50757db743a3635ad5b0497e6e ]
With the recent kmap change, some tests which were conditional on CONFIG_DEBUG_HIGHMEM now are enabled by default. This permit to detect a problem in sun4i-ss usage of kmap.
sun4i-ss uses two kmap via sg_miter (one for input, one for output), but using two kmap at the same time is hard: "the ordering has to be correct and with sg_miter that's probably hard to get right." (quoting Tlgx)
So the easiest solution is to never have two sg_miter/kmap open at the same time. After each use of sg_miter, I store the current index, for being able to resume sg_miter to the right place.
Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator") Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- .../allwinner/sun4i-ss/sun4i-ss-cipher.c | 109 +++++++++++------- 1 file changed, 65 insertions(+), 44 deletions(-)
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c index 19f1aa577ed4d..1f8a38d131928 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -30,6 +30,8 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) unsigned int ileft = areq->cryptlen; unsigned int oleft = areq->cryptlen; unsigned int todo; + unsigned long pi = 0, po = 0; /* progress for in and out */ + bool miter_err; struct sg_mapping_iter mi, mo; unsigned int oi, oo; /* offset for in and out */ unsigned long flags; @@ -55,39 +57,51 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) } writel(mode, ss->base + SS_CTL);
- sg_miter_start(&mi, areq->src, sg_nents(areq->src), - SG_MITER_FROM_SG | SG_MITER_ATOMIC); - sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), - SG_MITER_TO_SG | SG_MITER_ATOMIC); - sg_miter_next(&mi); - sg_miter_next(&mo); - if (!mi.addr || !mo.addr) { - dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); - err = -EINVAL; - goto release_ss; - }
ileft = areq->cryptlen / 4; oleft = areq->cryptlen / 4; oi = 0; oo = 0; do { - todo = min(rx_cnt, ileft); - todo = min_t(size_t, todo, (mi.length - oi) / 4); - if (todo) { - ileft -= todo; - writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); - oi += todo * 4; - } - if (oi == mi.length) { - sg_miter_next(&mi); - oi = 0; + if (ileft) { + sg_miter_start(&mi, areq->src, sg_nents(areq->src), + SG_MITER_FROM_SG | SG_MITER_ATOMIC); + if (pi) + sg_miter_skip(&mi, pi); + miter_err = sg_miter_next(&mi); + if (!miter_err || !mi.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } + todo = min(rx_cnt, ileft); + todo = min_t(size_t, todo, (mi.length - oi) / 4); + if (todo) { + ileft -= todo; + writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); + oi += todo * 4; + } + if (oi == mi.length) { + pi += mi.length; + oi = 0; + } + sg_miter_stop(&mi); }
spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces);
+ sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), + SG_MITER_TO_SG | SG_MITER_ATOMIC); + if (po) + sg_miter_skip(&mo, po); + miter_err = sg_miter_next(&mo); + if (!miter_err || !mo.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } todo = min(tx_cnt, oleft); todo = min_t(size_t, todo, (mo.length - oo) / 4); if (todo) { @@ -96,9 +110,10 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) oo += todo * 4; } if (oo == mo.length) { - sg_miter_next(&mo); oo = 0; + po += mo.length; } + sg_miter_stop(&mo); } while (oleft);
if (areq->iv) { @@ -109,8 +124,6 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) }
release_ss: - sg_miter_stop(&mi); - sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); spin_unlock_irqrestore(&ss->slock, flags); return err; @@ -162,6 +175,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) unsigned int oleft = areq->cryptlen; unsigned int todo; struct sg_mapping_iter mi, mo; + unsigned long pi = 0, po = 0; /* progress for in and out */ + bool miter_err; unsigned int oi, oo; /* offset for in and out */ unsigned int ob = 0; /* offset in buf */ unsigned int obo = 0; /* offset in bufo*/ @@ -215,17 +230,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) } writel(mode, ss->base + SS_CTL);
- sg_miter_start(&mi, areq->src, sg_nents(areq->src), - SG_MITER_FROM_SG | SG_MITER_ATOMIC); - sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), - SG_MITER_TO_SG | SG_MITER_ATOMIC); - sg_miter_next(&mi); - sg_miter_next(&mo); - if (!mi.addr || !mo.addr) { - dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); - err = -EINVAL; - goto release_ss; - } ileft = areq->cryptlen; oleft = areq->cryptlen; oi = 0; @@ -233,6 +237,16 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq)
while (oleft) { if (ileft) { + sg_miter_start(&mi, areq->src, sg_nents(areq->src), + SG_MITER_FROM_SG | SG_MITER_ATOMIC); + if (pi) + sg_miter_skip(&mi, pi); + miter_err = sg_miter_next(&mi); + if (!miter_err || !mi.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } /* * todo is the number of consecutive 4byte word that we * can read from current SG @@ -265,31 +279,38 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) } } if (oi == mi.length) { - sg_miter_next(&mi); + pi += mi.length; oi = 0; } + sg_miter_stop(&mi); }
spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces); - dev_dbg(ss->dev, - "%x %u/%zu %u/%u cnt=%u %u/%zu %u/%u cnt=%u %u\n", - mode, - oi, mi.length, ileft, areq->cryptlen, rx_cnt, - oo, mo.length, oleft, areq->cryptlen, tx_cnt, ob);
if (!tx_cnt) continue; + sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), + SG_MITER_TO_SG | SG_MITER_ATOMIC); + if (po) + sg_miter_skip(&mo, po); + miter_err = sg_miter_next(&mo); + if (!miter_err || !mo.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } /* todo in 4bytes word */ todo = min(tx_cnt, oleft / 4); todo = min_t(size_t, todo, (mo.length - oo) / 4); + if (todo) { readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); oleft -= todo * 4; oo += todo * 4; if (oo == mo.length) { - sg_miter_next(&mo); + po += mo.length; oo = 0; } } else { @@ -314,12 +335,14 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) obo += todo; oo += todo; if (oo == mo.length) { + po += mo.length; sg_miter_next(&mo); oo = 0; } } while (obo < obl); /* bufo must be fully used here */ } + sg_miter_stop(&mo); } if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { @@ -329,8 +352,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) }
release_ss: - sg_miter_stop(&mi); - sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); spin_unlock_irqrestore(&ss->slock, flags);
From: Ard Biesheuvel ardb@kernel.org
[ Upstream commit 15deb4333cd6d4e1e3216582e4c531ec40a6b060 ]
Commit 69b6f2e817e5b ("crypto: arm64/aes-neon - limit exposed routines if faster driver is enabled") intended to hide modes from the plain NEON driver that are also implemented by the faster bit sliced NEON one if both are enabled. However, the defined() CPP function does not detect if the bit sliced NEON driver is enabled as a module. So instead, let's use IS_ENABLED() here.
Fixes: 69b6f2e817e5b ("crypto: arm64/aes-neon - limit exposed routines if ...") Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/crypto/aes-glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 34b8a89197be3..cafb5b96be0e6 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -55,7 +55,7 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); #define aes_mac_update neon_aes_mac_update MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 NEON"); #endif -#if defined(USE_V8_CRYPTO_EXTENSIONS) || !defined(CONFIG_CRYPTO_AES_ARM64_BS) +#if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS) MODULE_ALIAS_CRYPTO("ecb(aes)"); MODULE_ALIAS_CRYPTO("cbc(aes)"); MODULE_ALIAS_CRYPTO("ctr(aes)"); @@ -650,7 +650,7 @@ static int __maybe_unused xts_decrypt(struct skcipher_request *req) }
static struct skcipher_alg aes_algs[] = { { -#if defined(USE_V8_CRYPTO_EXTENSIONS) || !defined(CONFIG_CRYPTO_AES_ARM64_BS) +#if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS) .base = { .cra_name = "__ecb(aes)", .cra_driver_name = "__ecb-aes-" MODE,
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit c4ff41b93d1f10d1b8be258c31a0436c5769fc00 ]
In case of error, we should call 'clk_disable_unprepare()' to undo a previous 'clk_prepare_enable()' call, as already done in the remove function.
Fixes: 406346d22278 ("hwrng: ingenic - Add hardware TRNG for Ingenic X1830") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Tested-by: 周琰杰 (Zhou Yanjie) zhouyanjie@wanyeetech.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/char/hw_random/ingenic-trng.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/char/hw_random/ingenic-trng.c b/drivers/char/hw_random/ingenic-trng.c index 954a8411d67d2..0eb80f786f4dd 100644 --- a/drivers/char/hw_random/ingenic-trng.c +++ b/drivers/char/hw_random/ingenic-trng.c @@ -113,13 +113,17 @@ static int ingenic_trng_probe(struct platform_device *pdev) ret = hwrng_register(&trng->rng); if (ret) { dev_err(&pdev->dev, "Failed to register hwrng\n"); - return ret; + goto err_unprepare_clk; }
platform_set_drvdata(pdev, trng);
dev_info(&pdev->dev, "Ingenic DTRNG driver registered\n"); return 0; + +err_unprepare_clk: + clk_disable_unprepare(trng->clk); + return ret; }
static int ingenic_trng_remove(struct platform_device *pdev)
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit ce814ad4bb52bfc7c0472e6da0aa742ab88f4361 ]
The "channel" is added to the "dev->channels" but then if v4l2_m2m_ctx_init() fails then we free "channel" but it's still on the list so it could lead to a use after free. Let's not add it to the list until after v4l2_m2m_ctx_init() succeeds.
Fixes: cc62c74749a3 ("media: allegro: add missed checks in allegro_open()") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Michael Tretter m.tretter@pengutronix.de Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 9f718f43282bc..640451134072b 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -2483,8 +2483,6 @@ static int allegro_open(struct file *file) INIT_LIST_HEAD(&channel->buffers_reference); INIT_LIST_HEAD(&channel->buffers_intermediate);
- list_add(&channel->list, &dev->channels); - channel->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, channel, allegro_queue_init);
@@ -2493,6 +2491,7 @@ static int allegro_open(struct file *file) goto error; }
+ list_add(&channel->list, &dev->channels); file->private_data = &channel->fh; v4l2_fh_add(&channel->fh);
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit a1f31cc4e98e1833f53fd2c6e9a218d6b86f5388 ]
The newly added driver requires DMA support and fails to build when that is disabled:
aarch64-linux-ld: sound/soc/fsl/fsl_aud2htx.o: in function `fsl_aud2htx_probe': fsl_aud2htx.c:(.text+0x3e0): undefined reference to `imx_pcm_dma_init'
Fixes: 8a24c834c053 ("ASoC: fsl_aud2htx: Add aud2htx module driver") Signed-off-by: Arnd Bergmann arnd@arndb.de Acked-by: Nicolin Chen nicoleotsuka@gmail.com Link: https://lore.kernel.org/r/20210103135327.3630973-1-arnd@kernel.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/fsl/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 84db0b7b9d593..d7f30036d4343 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -108,6 +108,7 @@ config SND_SOC_FSL_XCVR config SND_SOC_FSL_AUD2HTX tristate "AUDIO TO HDMI TX module support" depends on ARCH_MXC || COMPILE_TEST + select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n help Say Y if you want to add AUDIO TO HDMI TX support for NXP.
From: Marco Elver elver@google.com
[ Upstream commit 71a076f4a61a6c779794ad286f356b39725edc3b ]
Rewrite kcsan_prandom_u32_max() to not depend on code that might be instrumented, removing any dependency on lib/random32.c. The rewrite implements a simple linear congruential generator, that is sufficient for our purposes (for udelay() and skip_watch counter randomness).
The initial motivation for this was to allow enabling KCSAN for kernel/sched (remove KCSAN_SANITIZE := n from kernel/sched/Makefile), with CONFIG_DEBUG_PREEMPT=y. Without this change, we could observe recursion:
check_access() [via instrumentation] kcsan_setup_watchpoint() reset_kcsan_skip() kcsan_prandom_u32_max() get_cpu_var() preempt_disable() preempt_count_add() [in kernel/sched/core.c] check_access() [via instrumentation]
Note, while this currently does not affect an unmodified kernel, it'd be good to keep a KCSAN kernel working when KCSAN_SANITIZE := n is removed from kernel/sched/Makefile to permit testing scheduler code with KCSAN if desired.
Fixes: cd290ec24633 ("kcsan: Use tracing-safe version of prandom") Signed-off-by: Marco Elver elver@google.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/kcsan/core.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index 3994a217bde76..3bf98db9c702d 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -12,7 +12,6 @@ #include <linux/moduleparam.h> #include <linux/percpu.h> #include <linux/preempt.h> -#include <linux/random.h> #include <linux/sched.h> #include <linux/uaccess.h>
@@ -101,7 +100,7 @@ static atomic_long_t watchpoints[CONFIG_KCSAN_NUM_WATCHPOINTS + NUM_SLOTS-1]; static DEFINE_PER_CPU(long, kcsan_skip);
/* For kcsan_prandom_u32_max(). */ -static DEFINE_PER_CPU(struct rnd_state, kcsan_rand_state); +static DEFINE_PER_CPU(u32, kcsan_rand_state);
static __always_inline atomic_long_t *find_watchpoint(unsigned long addr, size_t size, @@ -275,20 +274,17 @@ should_watch(const volatile void *ptr, size_t size, int type, struct kcsan_ctx * }
/* - * Returns a pseudo-random number in interval [0, ep_ro). See prandom_u32_max() - * for more details. - * - * The open-coded version here is using only safe primitives for all contexts - * where we can have KCSAN instrumentation. In particular, we cannot use - * prandom_u32() directly, as its tracepoint could cause recursion. + * Returns a pseudo-random number in interval [0, ep_ro). Simple linear + * congruential generator, using constants from "Numerical Recipes". */ static u32 kcsan_prandom_u32_max(u32 ep_ro) { - struct rnd_state *state = &get_cpu_var(kcsan_rand_state); - const u32 res = prandom_u32_state(state); + u32 state = this_cpu_read(kcsan_rand_state); + + state = 1664525 * state + 1013904223; + this_cpu_write(kcsan_rand_state, state);
- put_cpu_var(kcsan_rand_state); - return (u32)(((u64) res * ep_ro) >> 32); + return state % ep_ro; }
static inline void reset_kcsan_skip(void) @@ -639,10 +635,14 @@ static __always_inline void check_access(const volatile void *ptr, size_t size,
void __init kcsan_init(void) { + int cpu; + BUG_ON(!in_task());
kcsan_debugfs_init(); - prandom_seed_full_state(&kcsan_rand_state); + + for_each_possible_cpu(cpu) + per_cpu(kcsan_rand_state, cpu) = (u32)get_cycles();
/* * We are in the init task, and no other tasks should be running;
From: Qinglang Miao miaoqinglang@huawei.com
[ Upstream commit 136ce7684bc1ff4a088812f600c63daca50b32c2 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in a reference leak here.
A new function pm_runtime_resume_and_get is introduced in [0] to keep usage counter balanced. So We fix the reference leak by replacing it with new funtion.
[0] dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter")
Fixes: e08e934d6c28 ("drm: rcar-du: Add support for CMM") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Qinglang Miao miaoqinglang@huawei.com Acked-by: Jacopo Mondi jacopo@jmondi.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c index c578095b09a53..382d53f8a22e8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_cmm.c +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c @@ -122,7 +122,7 @@ int rcar_cmm_enable(struct platform_device *pdev) { int ret;
- ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret;
From: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
[ Upstream commit 53ced169373aab52d3b5da0fee6a342002d1876d ]
On D3 and E3 platforms, the LVDS encoder includes a PLL that can generate a clock for the corresponding CRTC, used even when the CRTC output to a non-LVDS port. This mechanism is supported by the driver, but the implementation is broken in dual-link LVDS mode. In that case, the LVDS1 drm_encoder is skipped, which causes a crash when trying to access its bridge later on.
Fix this by storing bridge pointers internally instead of retrieving them from the encoder. The rcar_du_device encoders field isn't used anymore and can be dropped.
Fixes: 8e8fddab0d0a ("drm: rcar-du: Skip LVDS1 output on Gen3 when using dual-link LVDS mode") Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com Reviewed-by: Jacopo Mondi jacopo+renesas@jmondi.org Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 ++-------- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +++--- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 ++++- 3 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index b5fb941e0f534..e23b9c7b4afeb 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -730,13 +730,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, */ if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { - struct rcar_du_encoder *encoder = - rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index]; + struct drm_bridge *bridge = rcdu->lvds[rcrtc->index]; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - struct drm_bridge *bridge;
- bridge = drm_bridge_chain_get_first_bridge(&encoder->base); rcar_lvds_clk_enable(bridge, mode->clock * 1000); }
@@ -764,15 +761,12 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { - struct rcar_du_encoder *encoder = - rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index]; - struct drm_bridge *bridge; + struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
/* * Disable the LVDS clock output, see * rcar_du_crtc_atomic_enable(). */ - bridge = drm_bridge_chain_get_first_bridge(&encoder->base); rcar_lvds_clk_disable(bridge); }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 61504c54e2ecf..3597a179bfb78 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -20,10 +20,10 @@
struct clk; struct device; +struct drm_bridge; struct drm_device; struct drm_property; struct rcar_du_device; -struct rcar_du_encoder;
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK BIT(0) /* Per-CRTC IRQ and clock */ #define RCAR_DU_FEATURE_VSP1_SOURCE BIT(1) /* Has inputs from VSP1 */ @@ -71,6 +71,7 @@ struct rcar_du_device_info { #define RCAR_DU_MAX_CRTCS 4 #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) #define RCAR_DU_MAX_VSPS 4 +#define RCAR_DU_MAX_LVDS 2
struct rcar_du_device { struct device *dev; @@ -83,11 +84,10 @@ struct rcar_du_device { struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS]; unsigned int num_crtcs;
- struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX]; - struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; struct platform_device *cmms[RCAR_DU_MAX_CRTCS]; struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; + struct drm_bridge *lvds[RCAR_DU_MAX_LVDS];
struct { struct drm_property *colorkey; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index b0335da0c1614..50fc14534fa4d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -57,7 +57,6 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, if (renc == NULL) return -ENOMEM;
- rcdu->encoders[output] = renc; renc->output = output; encoder = rcar_encoder_to_drm_encoder(renc);
@@ -91,6 +90,10 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ret = -EPROBE_DEFER; goto done; } + + if (output == RCAR_DU_OUTPUT_LVDS0 || + output == RCAR_DU_OUTPUT_LVDS1) + rcdu->lvds[output - RCAR_DU_OUTPUT_LVDS0] = bridge; }
/*
From: Wang Xiaojun wangxiaojun11@huawei.com
[ Upstream commit 8d7d33f6be06f929ac2c5e8ea2323fec272790d4 ]
of_parse_phandle and of_find_device_by_node may return NULL which cannot be checked by IS_ERR.
Fixes: 8de707aeb452 ("drm: rcar-du: kms: Initialize CMM instances") Signed-off-by: Wang Xiaojun wangxiaojun11@huawei.com Reported-by: Hulk Robot hulkci@huawei.com Acked-by: Jacopo Mondi jacopo+renesas@jmondi.org Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
[Replace -ENODEV with -EINVAL]
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 72dda446355fe..7015e22872bbe 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -700,10 +700,10 @@ static int rcar_du_cmm_init(struct rcar_du_device *rcdu) int ret;
cmm = of_parse_phandle(np, "renesas,cmms", i); - if (IS_ERR(cmm)) { + if (!cmm) { dev_err(rcdu->dev, "Failed to parse 'renesas,cmms' property\n"); - return PTR_ERR(cmm); + return -EINVAL; }
if (!of_device_is_available(cmm)) { @@ -713,10 +713,10 @@ static int rcar_du_cmm_init(struct rcar_du_device *rcdu) }
pdev = of_find_device_by_node(cmm); - if (IS_ERR(pdev)) { + if (!pdev) { dev_err(rcdu->dev, "No device found for CMM%u\n", i); of_node_put(cmm); - return PTR_ERR(pdev); + return -EINVAL; }
of_node_put(cmm);
From: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
[ Upstream commit 9fa120458da142da0d1d3eaf6f6a3a2c2c91d27b ]
The device references acquired by of_find_device_by_node() are not released by the driver. Fix this by registering a cleanup action.
Fixes: 8de707aeb452 ("drm: rcar-du: kms: Initialize CMM instances") Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com Reviewed-by: Jacopo Mondi jacopo+renesas@jmondi.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 7015e22872bbe..ecc894f0bc430 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -14,6 +14,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_managed.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h>
@@ -726,8 +727,12 @@ static int rcar_du_cmm_init(struct rcar_du_device *rcdu) * disabled: return 0 and let the DU continue probing. */ ret = rcar_cmm_init(pdev); - if (ret) + if (ret) { + platform_device_put(pdev); return ret == -ENODEV ? 0 : ret; + } + + rcdu->cmms[i] = pdev;
/* * Enforce suspend/resume ordering by making the CMM a provider @@ -739,13 +744,20 @@ static int rcar_du_cmm_init(struct rcar_du_device *rcdu) "Failed to create device link to CMM%u\n", i); return -EINVAL; } - - rcdu->cmms[i] = pdev; }
return 0; }
+static void rcar_du_modeset_cleanup(struct drm_device *dev, void *res) +{ + struct rcar_du_device *rcdu = to_rcar_du_device(dev); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i) + platform_device_put(rcdu->cmms[i]); +} + int rcar_du_modeset_init(struct rcar_du_device *rcdu) { static const unsigned int mmio_offsets[] = { @@ -766,6 +778,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) if (ret) return ret;
+ ret = drmm_add_action(&rcdu->ddev, rcar_du_modeset_cleanup, NULL); + if (ret) + return ret; + dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; dev->mode_config.normalize_zpos = true;
From: Chenyang Li lichenyang@loongson.cn
[ Upstream commit 956e20eb0fbb206e5e795539db5469db099715c8 ]
Add an underscore in amdgpu_trace.h line 24 "_AMDGPU_TRACE_H".
Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") Reviewed-by: Guchun Chen guchun.chen@amd.com Reviewed-by: Paul Menzel pmenzel@molgen.mpg.de Signed-off-by: Chenyang Li lichenyang@loongson.cn Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 6752d8b131188..ce8dc995c10cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -21,7 +21,7 @@ * */
-#if !defined(_AMDGPU_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#if !defined(_AMDGPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) #define _AMDGPU_TRACE_H_
#include <linux/stringify.h>
From: Nathan Chancellor natechancellor@gmail.com
[ Upstream commit c58734eee6a2151ba033c0dcb31902c89e310374 ]
When building with clang, the following section mismatch warning occurs:
WARNING: modpost: vmlinux.o(.text+0x24490): Section mismatch in reference from the function r4k_cache_init() to the function .init.text:loongson2_sc_init()
This should have been fixed with commit ad4fddef5f23 ("mips: fix Section mismatch in reference") but it was missed. Remove the improper __init annotation like that commit did.
Fixes: 078a55fc824c ("MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code") Link: https://github.com/ClangBuiltLinux/linux/issues/787 Signed-off-by: Nathan Chancellor natechancellor@gmail.com Reviewed-by: Huacai Chen chenhuacai@kernel.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/mm/c-r4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 4f976d687ab00..f67297b3175fe 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1593,7 +1593,7 @@ static int probe_scache(void) return 1; }
-static void __init loongson2_sc_init(void) +static void loongson2_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data;
From: Nathan Chancellor natechancellor@gmail.com
[ Upstream commit c6f2a9e17b9bef7677caddb1626c2402f3e9d2bd ]
When building xway_defconfig with clang:
arch/mips/lantiq/irq.c:305:48: error: use of logical '&&' with constant operand [-Werror,-Wconstant-logical-operand] if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) ^ ~~~~~~~~~~~~~~~~~ arch/mips/lantiq/irq.c:305:48: note: use '&' for a bitwise operation if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) ^~ & arch/mips/lantiq/irq.c:305:48: note: remove constant to silence this warning if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) ~^~~~~~~~~~~~~~~~~~~~ 1 error generated.
Explicitly compare the constant LTQ_EBU_PCC_ISTAT against 0 to fix the warning. Additionally, remove the unnecessary parentheses as this is a simple conditional statement and shorthand '== 0' to '!'.
Fixes: 3645da0276ae ("OF: MIPS: lantiq: implement irq_domain support") Link: https://github.com/ClangBuiltLinux/linux/issues/807 Reported-by: Dmitry Golovin dima@golovin.in Signed-off-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/lantiq/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index df8eed3875f6d..43c2f271e6ab4 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -302,7 +302,7 @@ static void ltq_hw_irq_handler(struct irq_desc *desc) generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
/* if this is a EBU irq, we need to ack it or get a deadlock */ - if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) + if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10, LTQ_EBU_PCC_ISTAT); }
From: Chia-I Wu olvaffe@gmail.com
[ Upstream commit 8aeef9d4f48917ce85710949b079548974b4a638 ]
The context might still be missing when DRM_IOCTL_PRIME_FD_TO_HANDLE is the first ioctl on the drm_file.
Fixes: 72b48ae800da ("drm/virtio: enqueue virtio_gpu_create_context after the first 3D ioctl") Cc: Gurchetan Singh gurchetansingh@chromium.org Cc: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Chia-I Wu olvaffe@gmail.com Link: http://patchwork.freedesktop.org/patch/msgid/20210107210726.269584-1-olvaffe... Reviewed-by: Gurchetan Singh gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index c30c75ee83fce..8502400b2f9c9 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -39,9 +39,6 @@ static int virtio_gpu_gem_create(struct drm_file *file, int ret; u32 handle;
- if (vgdev->has_virgl_3d) - virtio_gpu_create_context(dev, file); - ret = virtio_gpu_object_create(vgdev, params, &obj, NULL); if (ret < 0) return ret; @@ -119,6 +116,11 @@ int virtio_gpu_gem_object_open(struct drm_gem_object *obj, if (!vgdev->has_virgl_3d) goto out_notify;
+ /* the context might still be missing when the first ioctl is + * DRM_IOCTL_MODE_CREATE_DUMB or DRM_IOCTL_PRIME_FD_TO_HANDLE + */ + virtio_gpu_create_context(obj->dev, file); + objs = virtio_gpu_array_alloc(1); if (!objs) return -ENOMEM;
From: Simon Ser contact@emersion.fr
[ Upstream commit cc3283f8f41f741fbaef63d0503d8fb4a7919100 ]
The comment says the layout and options use 8 bits, and the shift uses 8 bits. However the mask is 0xf, ie. 0b00001111 (4 bits).
This could be surprising when introducing new layouts or options that take more than 4 bits, as this would silently drop the high bits.
Make the masks consistent with the comment and the shift.
Found when writing a drm_info patch [1].
[1]: https://github.com/ascent12/drm_info/pull/67
Signed-off-by: Simon Ser contact@emersion.fr Fixes: d6528ec88309 ("drm/fourcc: Add modifier definitions for describing Amlogic Video Framebuffer Compression") Cc: Neil Armstrong narmstrong@baylibre.com Cc: Sam Ravnborg sam@ravnborg.org Cc: Kevin Hilman khilman@baylibre.com Cc: Daniel Vetter daniel.vetter@ffwll.ch Acked-by: Neil Armstrong narmstrong@baylibre.com Link: https://patchwork.freedesktop.org/patch/msgid/20210110125103.15447-1-contact... Signed-off-by: Sasha Levin sashal@kernel.org --- include/uapi/drm/drm_fourcc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 723c8e23ca87d..5f42a14481bd4 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -1036,9 +1036,9 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) * Not all combinations are valid, and different SoCs may support different * combinations of layout and options. */ -#define __fourcc_mod_amlogic_layout_mask 0xf +#define __fourcc_mod_amlogic_layout_mask 0xff #define __fourcc_mod_amlogic_options_shift 8 -#define __fourcc_mod_amlogic_options_mask 0xf +#define __fourcc_mod_amlogic_options_mask 0xff
#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ fourcc_mod_code(AMLOGIC, \
From: Andy Shevchenko andriy.shevchenko@linux.intel.com
[ Upstream commit 3ef5e42d281ea108f4ccdca186de4ce20a346326 ]
According to the original code in the driver it was never assumed to work with big page sizes: unsigned short type followed by PAGE_SHIFT and PAGE_MASK which may be different on non-x86 architectures.
Recently LKP found an issue on non-x86 architectures due to above mentioned limitations. Since Sakari acknowledges that it's not really useful to be able to compile this elsewhere, mark it x86 only.
Fixes: a31d19f88932 ("media: ipu3: allow building it with COMPILE_TEST on non-x86 archs") Reported-by: kernel test robot lkp@intel.com Suggested-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/pci/intel/ipu3/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig index 82d7f17e6a024..7a805201034b7 100644 --- a/drivers/media/pci/intel/ipu3/Kconfig +++ b/drivers/media/pci/intel/ipu3/Kconfig @@ -2,7 +2,8 @@ config VIDEO_IPU3_CIO2 tristate "Intel ipu3-cio2 driver" depends on VIDEO_V4L2 && PCI - depends on (X86 && ACPI) || COMPILE_TEST + depends on ACPI || COMPILE_TEST + depends on X86 select MEDIA_CONTROLLER select VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE
From: Jacopo Mondi jacopo@jmondi.org
[ Upstream commit dc1eb7c9c290cba52937c9a224b22a400bb0ffd7 ]
The driver currently reports a single supported value for V4L2_CID_PIXEL_RATE and initializes the control's minimum value to 0, which is very risky, as userspace might accidentally use it as divider when calculating the time duration of a line.
Fix this by using as minimum the only supported value when registering the control.
Fixes: 5de35c9b8dcd1 ("media: i2c: Add Omnivision OV5670 5M sensor support") Signed-off-by: Jacopo Mondi jacopo@jmondi.org Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/i2c/ov5670.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 148fd4e05029a..866c8c2e8f59a 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2084,7 +2084,8 @@ static int ov5670_init_controls(struct ov5670 *ov5670)
/* By default, V4L2_CID_PIXEL_RATE is read only */ ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops, - V4L2_CID_PIXEL_RATE, 0, + V4L2_CID_PIXEL_RATE, + link_freq_configs[0].pixel_rate, link_freq_configs[0].pixel_rate, 1, link_freq_configs[0].pixel_rate);
From: Ezequiel Garcia ezequiel@collabora.com
[ Upstream commit bb2216548a2b13cf2942a058b475438a7a6bb028 ]
The csc/scaler device pointer (imxmd->m2m_vdev) is assigned after the imx media device v4l2-async probe completes, therefore we need to check if the device is non-NULL before trying to unregister it.
This can be the case if the non-completed imx media device is unbinded (or the driver is removed), leading to a kernel oops.
Fixes: a8ef0488cc59 ("media: imx: add csc/scaler mem2mem device") Signed-off-by: Ezequiel Garcia ezequiel@collabora.com Reviewed-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/imx/imx-media-dev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 6d2205461e565..338b8bd0bb076 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -53,6 +53,7 @@ static int imx6_media_probe_complete(struct v4l2_async_notifier *notifier) imxmd->m2m_vdev = imx_media_csc_scaler_device_init(imxmd); if (IS_ERR(imxmd->m2m_vdev)) { ret = PTR_ERR(imxmd->m2m_vdev); + imxmd->m2m_vdev = NULL; goto unlock; }
@@ -107,10 +108,14 @@ static int imx_media_remove(struct platform_device *pdev)
v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n");
+ if (imxmd->m2m_vdev) { + imx_media_csc_scaler_device_unregister(imxmd->m2m_vdev); + imxmd->m2m_vdev = NULL; + } + v4l2_async_notifier_unregister(&imxmd->notifier); imx_media_unregister_ipu_internal_subdevs(imxmd); v4l2_async_notifier_cleanup(&imxmd->notifier); - imx_media_csc_scaler_device_unregister(imxmd->m2m_vdev); media_device_unregister(&imxmd->md); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_cleanup(&imxmd->md);
From: Ezequiel Garcia ezequiel@collabora.com
[ Upstream commit 89b14485caa4b7b2eaf70be0064f0978e68ebeee ]
The csc/scaler device private struct is released by ipu_csc_scaler_video_device_release(), which can be called by video_unregister_device() if there are no users of the underlying struct video device.
Therefore, the mutex can't be held when calling video_unregister_device() as its memory may be freed by it, leading to a kernel oops.
Fortunately, the fix is quite simple as no locking is needed when calling video_unregister_device(): v4l2-core already has its own internal locking, and the structures are also properly refcounted.
Fixes: a8ef0488cc59 ("media: imx: add csc/scaler mem2mem device") Signed-off-by: Ezequiel Garcia ezequiel@collabora.com Reviewed-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/imx/imx-media-csc-scaler.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c index fab1155a5958c..63a0204502a8b 100644 --- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -869,11 +869,7 @@ void imx_media_csc_scaler_device_unregister(struct imx_media_video_dev *vdev) struct ipu_csc_scaler_priv *priv = vdev_to_priv(vdev); struct video_device *vfd = priv->vdev.vfd;
- mutex_lock(&priv->mutex); - video_unregister_device(vfd); - - mutex_unlock(&priv->mutex); }
struct imx_media_video_dev *
From: Zhang Changzhong zhangchangzhong@huawei.com
[ Upstream commit 4397efebf039be58e98c81a194a26100eba597bb ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: dea42fb79f4f ("media: mtk-vcodec: reset segment data then trig decoder") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c index 5ea153a685225..d9880210b2ab6 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c @@ -890,7 +890,8 @@ static int vdec_vp9_decode(void *h_vdec, struct mtk_vcodec_mem *bs, memset(inst->seg_id_buf.va, 0, inst->seg_id_buf.size);
if (vsi->show_frame & BIT(2)) { - if (vpu_dec_start(&inst->vpu, NULL, 0)) { + ret = vpu_dec_start(&inst->vpu, NULL, 0); + if (ret) { mtk_vcodec_err(inst, "vpu trig decoder failed"); goto DECODE_ERROR; }
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit b00481bdca2d77fdae5f71517c09fd3b30eba57d ]
This test has a problem because we want to know if "k" is -1 or a positive value less than "f->index". But the "f->index" variable is a u32 so if "k == -1" then -1 gets type promoted to UINT_MAX which is larger than "f->index". I've added an explicit test to check for -1.
Fixes: a3d412d4b9f3 ("media: Revert "media: camss: Make use of V4L2_CAP_IO_MC"") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Robert Foss robert.foss@linaro.org Reviewed-by: Andrey Konovalov andrey.konovalov@linaro.org Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/qcom/camss/camss-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index bd9334af1c734..2fa3214775d58 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -579,7 +579,7 @@ static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) break; }
- if (k < f->index) + if (k == -1 || k < f->index) /* * All the unique pixel formats matching the arguments * have been enumerated (k >= 0 and f->index > 0), or
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 9c67ed2ab299123872be14a3dc2ea44ce7e4538b ]
This error path returns success but it should return -EINVAL.
Fixes: cba3819d1e93 ("media: camss: Format configuration per hardware version") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Robert Foss robert.foss@linaro.org Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/qcom/camss/camss-video.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 2fa3214775d58..97cea7c4d7697 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -961,6 +961,7 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, video->nformats = ARRAY_SIZE(formats_rdi_8x96); } } else { + ret = -EINVAL; goto error_video_register; }
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 7113469dafc2d545fa4fa9bc649c31dc27db492e ]
A previous 'rcar_fcp_get()' call must be undone in the error handling path, as already done in the remove function.
Fixes: 94fcdf829793 ("[media] v4l: vsp1: Add FCP support") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/vsp1/vsp1_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index dc62533cf32ce..aa66e4f5f3f34 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -882,8 +882,10 @@ static int vsp1_probe(struct platform_device *pdev) }
done: - if (ret) + if (ret) { pm_runtime_disable(&pdev->dev); + rcar_fcp_put(vsp1->fcp); + }
return ret; }
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit a26efd1961a18b91ae4cd2e433adbcf865b40fa3 ]
When kzalloc() fails, em28xx_uninit_usb_xfer() will free usb_bufs->buf and set it to NULL. Thus the later access to usb_bufs->buf[i] will lead to null pointer dereference. Also the kfree(usb_bufs->buf) after that is redundant.
Fixes: d571b592c6206 ("media: em28xx: don't use coherent buffer for DMA transfers") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/em28xx/em28xx-core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index e6088b5d1b805..3daa64bb1e1d9 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -956,14 +956,10 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL); if (!usb_bufs->buf[i]) { - em28xx_uninit_usb_xfer(dev, mode); - for (i--; i >= 0; i--) kfree(usb_bufs->buf[i]);
- kfree(usb_bufs->buf); - usb_bufs->buf = NULL; - + em28xx_uninit_usb_xfer(dev, mode); return -ENOMEM; }
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit 15d0c52241ecb1c9d802506bff6f5c3f7872c0df ]
When vb2_queue_init() fails, dev->empress_dev should be released just like other error handling paths.
Fixes: 2ada815fc48bb ("[media] saa7134: convert to vb2") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/pci/saa7134/saa7134-empress.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 39e3c7f8c5b46..76a37fbd84587 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -282,8 +282,11 @@ static int empress_init(struct saa7134_dev *dev) q->lock = &dev->lock; q->dev = &dev->pci->dev; err = vb2_queue_init(q); - if (err) + if (err) { + video_device_release(dev->empress_dev); + dev->empress_dev = NULL; return err; + } dev->empress_dev->queue = q; dev->empress_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit 76aaf8a96771c16365b8510f1fb97738dc88026e ]
When usb_clear_halt() fails, dvb->bulk_urb->transfer_buffer and dvb->bulk_urb should be freed just like when usb_submit_urb() fails.
Fixes: 3169c9b26fffa ("V4L/DVB (12788): tm6000: Add initial DVB-T support") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/tm6000/tm6000-dvb.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c index 19c90fa9e443d..293a460f4616c 100644 --- a/drivers/media/usb/tm6000/tm6000-dvb.c +++ b/drivers/media/usb/tm6000/tm6000-dvb.c @@ -141,6 +141,10 @@ static int tm6000_start_stream(struct tm6000_core *dev) if (ret < 0) { printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n", ret, __func__); + + kfree(dvb->bulk_urb->transfer_buffer); + usb_free_urb(dvb->bulk_urb); + dvb->bulk_urb = NULL; return ret; } else printk(KERN_ERR "tm6000: pipe reset\n");
From: Zhang Changzhong zhangchangzhong@huawei.com
[ Upstream commit d497fcdab02996a4510d5dd0d743447c737c317a ]
Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function.
Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/aspeed-video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index c46a79eace98b..f2c4dadd6a0eb 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -1551,12 +1551,12 @@ static int aspeed_video_setup_video(struct aspeed_video *video) V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask, V4L2_JPEG_CHROMA_SUBSAMPLING_444);
- if (video->ctrl_handler.error) { + rc = video->ctrl_handler.error; + if (rc) { v4l2_ctrl_handler_free(&video->ctrl_handler); v4l2_device_unregister(v4l2_dev);
- dev_err(video->dev, "Failed to init controls: %d\n", - video->ctrl_handler.error); + dev_err(video->dev, "Failed to init controls: %d\n", rc); return rc; }
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 856fe64da84c95a1d415564b981ae3908eea2a76 ]
There are two issues with this code. The first error path forgot to set the error code and instead returns success. The second error path doesn't clean up.
Fixes: 272b5edd3b8f ("ASoC: Add support for CS42L56 CODEC") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/X9NE/9nK9/TuxuL+@mwanda Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/cs42l56.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index bb9599cc832bc..c44a5cdb796ec 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L56 Device ID (%X). Expected %X\n", devid, CS42L56_DEVID); + ret = -EINVAL; goto err_enable; } alpha_rev = reg & CS42L56_AREV_MASK; @@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, ret = devm_snd_soc_register_component(&i2c_client->dev, &soc_component_dev_cs42l56, &cs42l56_dai, 1); if (ret < 0) - return ret; + goto err_enable;
return 0;
From: Stephan Gerhold stephan@gerhold.net
[ Upstream commit 6fd8d2d275f74baa7ac17b2656da1235f56dab99 ]
At the moment it is necessary to set up the DAPM routes between front-end AIF<->DAI explicitly in the device tree, e.g. using
audio-routing = "MM_DL1", "MultiMedia1 Playback", "MM_DL3", "MultiMedia3 Playback", "MM_DL4", "MultiMedia4 Playback", "MultiMedia2 Capture", "MM_UL2";
This is prone to mistakes and (sadly) there is no clear error if one of these routes is missing. :(
Actually, this should not be necessary because the ASoC core normally automatically links AIF<->DAI within snd_soc_dapm_link_dai_widgets(). This is done using the "stname" parameter of SND_SOC_DAPM_AIF_IN/OUT.
For SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), it should create the route from above: MM_DL1 <-> MultiMedia1 Playback.
This does not work at the moment because the AIF widget (MM_DL1) and the DAI widget (MultiMedia1 Playback) belong to different DAPM contexts (q6routing / q6asm-dai).
Fix this by declaring the AIF widgets in the same driver as the DAIs (q6asm-dai). Now the routes above are created automatically and no longer need to be specified in the device tree.
This is also more consistent with the back-end AIFs which are already declared in q6afe-dais instead of q6routing. q6routing should only link the components together using mixers.
Cc: Srinivas Kandagatla srinivas.kandagatla@linaro.org Fixes: 2a9e92d371db ("ASoC: qdsp6: q6asm: Add q6asm dai driver") Signed-off-by: Stephan Gerhold stephan@gerhold.net Link: https://lore.kernel.org/r/20201211203255.148246-1-stephan@gerhold.net Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/qdsp6/q6asm-dai.c | 21 +++++++++++++++++++++ sound/soc/qcom/qdsp6/q6routing.c | 18 ------------------ 2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index c9ac9c1d26c47..9766725c29166 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -1233,6 +1233,25 @@ static void q6asm_dai_pcm_free(struct snd_soc_component *component, } }
+static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + static const struct snd_soc_component_driver q6asm_fe_dai_component = { .name = DRV_NAME, .open = q6asm_dai_open, @@ -1245,6 +1264,8 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .pcm_construct = q6asm_dai_pcm_new, .pcm_destruct = q6asm_dai_pcm_free, .compress_ops = &q6asm_dai_compress_ops, + .dapm_widgets = q6asm_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets), };
static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 53185e26fea17..0a6b9433f6acf 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -713,24 +713,6 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA8) };
static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { - /* Frontend AIF */ - SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0), - /* Mixer definitions */ SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls,
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit ccf11dbaa07b328fa469415c362d33459c140a37 ]
tmp_tfm is allocated, but not freed on subsequent kmalloc failure, which leads to a memory leak. Free tmp_tfm.
Fixes: d46eb3699502b ("evm: crypto hash replaced by shash") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn [zohar@linux.ibm.com: formatted/reworded patch description] Signed-off-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- security/integrity/evm/evm_crypto.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 168c3b78ac47b..a6dd47eb086da 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -73,7 +73,7 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo) { long rc; const char *algo; - struct crypto_shash **tfm, *tmp_tfm; + struct crypto_shash **tfm, *tmp_tfm = NULL; struct shash_desc *desc;
if (type == EVM_XATTR_HMAC) { @@ -118,13 +118,16 @@ unlock: alloc: desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm), GFP_KERNEL); - if (!desc) + if (!desc) { + crypto_free_shash(tmp_tfm); return ERR_PTR(-ENOMEM); + }
desc->tfm = *tfm;
rc = crypto_shash_init(desc); if (rc) { + crypto_free_shash(tmp_tfm); kfree(desc); return ERR_PTR(rc); }
From: Marco Chiappero marco.chiappero@intel.com
[ Upstream commit 4f1a02e75a2eedfddd10222c0fe61d2a04d80099 ]
Use CRYPTO_LIB_AES in place of CRYPTO_AES in the dependences for the QAT common code.
Fixes: c0e583ab2016 ("crypto: qat - add CRYPTO_AES to Kconfig dependencies") Reported-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Marco Chiappero marco.chiappero@intel.com Acked-by: Ard Biesheuvel ardb@kernel.org Reviewed-by: Giovanni Cabiddu giovanni.cabiddu@intel.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/qat/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/qat/Kconfig b/drivers/crypto/qat/Kconfig index 846a3d90b41a3..77783feb62b25 100644 --- a/drivers/crypto/qat/Kconfig +++ b/drivers/crypto/qat/Kconfig @@ -11,7 +11,7 @@ config CRYPTO_DEV_QAT select CRYPTO_SHA1 select CRYPTO_SHA256 select CRYPTO_SHA512 - select CRYPTO_AES + select CRYPTO_LIB_AES select FW_LOADER
config CRYPTO_DEV_QAT_DH895xCC
From: Jiri Olsa jolsa@kernel.org
[ Upstream commit f7f2b43eaf6b4cfe54c75100709be31d5c4b52c8 ]
Renaming 'struct device_private' to 'struct bcm_device_private', because it clashes with 'struct device_private' from 'drivers/base/base.h'.
While it's not a functional problem, it's causing two distinct type hierarchies in BTF data. It also breaks build with options: CONFIG_DEBUG_INFO_BTF=y CONFIG_CRYPTO_DEV_BCM_SPU=y
as reported by Qais Yousef [1].
[1] https://lore.kernel.org/lkml/20201229151352.6hzmjvu3qh6p2qgg@e107158-lin/
Fixes: 9d12ba86f818 ("crypto: brcm - Add Broadcom SPU driver") Signed-off-by: Jiri Olsa jolsa@kernel.org Tested-by: Qais Yousef qais.yousef@arm.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/bcm/cipher.c | 2 +- drivers/crypto/bcm/cipher.h | 4 ++-- drivers/crypto/bcm/util.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 30390a7324b29..0e5537838ef36 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -42,7 +42,7 @@
/* ================= Device Structure ================== */
-struct device_private iproc_priv; +struct bcm_device_private iproc_priv;
/* ==================== Parameters ===================== */
diff --git a/drivers/crypto/bcm/cipher.h b/drivers/crypto/bcm/cipher.h index 0ad5892b445d3..71281a3bdbdc0 100644 --- a/drivers/crypto/bcm/cipher.h +++ b/drivers/crypto/bcm/cipher.h @@ -420,7 +420,7 @@ struct spu_hw { u32 num_chan; };
-struct device_private { +struct bcm_device_private { struct platform_device *pdev;
struct spu_hw spu; @@ -467,6 +467,6 @@ struct device_private { struct mbox_chan **mbox; };
-extern struct device_private iproc_priv; +extern struct bcm_device_private iproc_priv;
#endif diff --git a/drivers/crypto/bcm/util.c b/drivers/crypto/bcm/util.c index 2b304fc780595..77aeedb840555 100644 --- a/drivers/crypto/bcm/util.c +++ b/drivers/crypto/bcm/util.c @@ -348,7 +348,7 @@ char *spu_alg_name(enum spu_cipher_alg alg, enum spu_cipher_mode mode) static ssize_t spu_debugfs_read(struct file *filp, char __user *ubuf, size_t count, loff_t *offp) { - struct device_private *ipriv; + struct bcm_device_private *ipriv; char *buf; ssize_t ret, out_offset, out_count; int i;
From: Xuewen Yan xuewen.yan@unisoc.com
[ Upstream commit 8c1f560c1ea3f19e22ba356f62680d9d449c9ec2 ]
CPU (root cfs_rq) estimated utilization (util_est) is currently used in dequeue_task_fair() to drive frequency selection before it is updated.
with:
CPU_util : rq->cfs.avg.util_avg CPU_util_est : rq->cfs.avg.util_est CPU_utilization : max(CPU_util, CPU_util_est) task_util : p->se.avg.util_avg task_util_est : p->se.avg.util_est
dequeue_task_fair():
/* (1) CPU_util and task_util update + inform schedutil about CPU_utilization changes */ for_each_sched_entity() /* 2 loops */ (dequeue_entity() ->) update_load_avg() -> cfs_rq_util_change() -> cpufreq_update_util() ->...-> sugov_update_[shared|single] -> sugov_get_util() -> cpu_util_cfs()
/* (2) CPU_util_est and task_util_est update */ util_est_dequeue()
cpu_util_cfs() uses CPU_utilization which could lead to a false (too high) utilization value for schedutil in task ramp-down or ramp-up scenarios during task dequeue.
To mitigate the issue split the util_est update (2) into:
(A) CPU_util_est update in util_est_dequeue() (B) task_util_est update in util_est_update()
Place (A) before (1) and keep (B) where (2) is. The latter is necessary since (B) relies on task_util update in (1).
Fixes: 7f65ea42eb00 ("sched/fair: Add util_est on top of PELT") Signed-off-by: Xuewen Yan xuewen.yan@unisoc.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Dietmar Eggemann dietmar.eggemann@arm.com Reviewed-by: Vincent Guittot vincent.guittot@linaro.org Link: https://lkml.kernel.org/r/1608283672-18240-1-git-send-email-xuewen.yan94@gma... Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/fair.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 04a3ce20da671..6918adaf74150 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3943,6 +3943,22 @@ static inline void util_est_enqueue(struct cfs_rq *cfs_rq, trace_sched_util_est_cfs_tp(cfs_rq); }
+static inline void util_est_dequeue(struct cfs_rq *cfs_rq, + struct task_struct *p) +{ + unsigned int enqueued; + + if (!sched_feat(UTIL_EST)) + return; + + /* Update root cfs_rq's estimated utilization */ + enqueued = cfs_rq->avg.util_est.enqueued; + enqueued -= min_t(unsigned int, enqueued, _task_util_est(p)); + WRITE_ONCE(cfs_rq->avg.util_est.enqueued, enqueued); + + trace_sched_util_est_cfs_tp(cfs_rq); +} + /* * Check if a (signed) value is within a specified (unsigned) margin, * based on the observation that: @@ -3956,23 +3972,16 @@ static inline bool within_margin(int value, int margin) return ((unsigned int)(value + margin - 1) < (2 * margin - 1)); }
-static void -util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) +static inline void util_est_update(struct cfs_rq *cfs_rq, + struct task_struct *p, + bool task_sleep) { long last_ewma_diff; struct util_est ue; - int cpu;
if (!sched_feat(UTIL_EST)) return;
- /* Update root cfs_rq's estimated utilization */ - ue.enqueued = cfs_rq->avg.util_est.enqueued; - ue.enqueued -= min_t(unsigned int, ue.enqueued, _task_util_est(p)); - WRITE_ONCE(cfs_rq->avg.util_est.enqueued, ue.enqueued); - - trace_sched_util_est_cfs_tp(cfs_rq); - /* * Skip update of task's estimated utilization when the task has not * yet completed an activation, e.g. being migrated. @@ -4012,8 +4021,7 @@ util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) * To avoid overestimation of actual task utilization, skip updates if * we cannot grant there is idle time in this CPU. */ - cpu = cpu_of(rq_of(cfs_rq)); - if (task_util(p) > capacity_orig_of(cpu)) + if (task_util(p) > capacity_orig_of(cpu_of(rq_of(cfs_rq)))) return;
/* @@ -4096,8 +4104,11 @@ static inline void util_est_enqueue(struct cfs_rq *cfs_rq, struct task_struct *p) {}
static inline void -util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, - bool task_sleep) {} +util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p) {} + +static inline void +util_est_update(struct cfs_rq *cfs_rq, struct task_struct *p, + bool task_sleep) {} static inline void update_misfit_status(struct task_struct *p, struct rq *rq) {}
#endif /* CONFIG_SMP */ @@ -5609,6 +5620,8 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) int idle_h_nr_running = task_has_idle_policy(p); bool was_sched_idle = sched_idle_rq(rq);
+ util_est_dequeue(&rq->cfs, p); + for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); dequeue_entity(cfs_rq, se, flags); @@ -5659,7 +5672,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) rq->next_balance = jiffies;
dequeue_throttle: - util_est_dequeue(&rq->cfs, p, task_sleep); + util_est_update(&rq->cfs, p, task_sleep); hrtick_update(rq); }
From: Giulio Benetti giulio.benetti@micronovasrl.com
[ Upstream commit 67f4aeb2b41a0629abde3794d463547f60b0cbdd ]
During commit 88bc4178568b ("drm: Use new DRM_BUS_FLAG_*_(DRIVE|SAMPLE)_(POS|NEG)EDGE flags") DRM_BUS_FLAG_* macros have been changed to avoid ambiguity but just because of this ambiguity previous DRM_BUS_FLAG_PIXDATA_(POS/NEG)EDGE were used meaning _SAMPLE_ not _DRIVE_. This leads to DLCK inversion and need to fix but instead of swapping phase values, let's adopt an easier approach Maxime suggested: It turned out that bit 26 of SUN4I_TCON0_IO_POL_REG is dedicated to invert DCLK polarity and this makes things really easier than before. So let's handle DCLK polarity by adding SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE as bit 26 and activating according to bus_flags the same way it is done for all the other signals polarity.
Fixes: 88bc4178568b ("drm: Use new DRM_BUS_FLAG_*_(DRIVE|SAMPLE)_(POS|NEG)EDGE flags") Suggested-by: Maxime Ripard maxime@cerno.tech Signed-off-by: Giulio Benetti giulio.benetti@micronovasrl.com Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://patchwork.freedesktop.org/patch/msgid/20210114081732.9386-1-giulio.b... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 ++------------------- drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 + 2 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 1e643bc7e786a..9f06dec0fc61d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -569,30 +569,13 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
- /* - * On A20 and similar SoCs, the only way to achieve Positive Edge - * (Rising Edge), is setting dclk clock phase to 2/3(240°). - * By default TCON works in Negative Edge(Falling Edge), - * this is why phase is set to 0 in that case. - * Unfortunately there's no way to logically invert dclk through - * IO_POL register. - * The only acceptable way to work, triple checked with scope, - * is using clock phase set to 0° for Negative Edge and set to 240° - * for Positive Edge. - * On A33 and similar SoCs there would be a 90° phase option, - * but it divides also dclk by 2. - * Following code is a way to avoid quirks all around TCON - * and DOTCLOCK drivers. - */ - if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) - clk_set_phase(tcon->dclk, 240); - if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) - clk_set_phase(tcon->dclk, 0); + val |= SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE;
regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE | + SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE | SUN4I_TCON0_IO_POL_DE_NEGATIVE, val);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index ee555318e3c2f..e624f6977eb84 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -113,6 +113,7 @@ #define SUN4I_TCON0_IO_POL_REG 0x88 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase) ((phase & 3) << 28) #define SUN4I_TCON0_IO_POL_DE_NEGATIVE BIT(27) +#define SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE BIT(26) #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE BIT(25) #define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE BIT(24)
From: Fabio Estevam festevam@gmail.com
[ Upstream commit 9bac67214fbf4b5f23463f7742ccf69bfe684cbd ]
Commit 86e02d07871c ("media: imx5/6/7: csi: Mark a bound video mux as a CSI mux") made an incorrect assumption that for imx7-media-csi, the bound subdev must always be a CSI mux. On i.MX6UL/i.MX6ULL there is no CSI mux at all, so do not return an error when the entity is not a video mux and assign the IMX_MEDIA_GRP_ID_CSI_MUX group id only when appropriate.
This is the same approach as done in imx-media-csi.c and it fixes the csi probe regression on i.MX6UL.
Tested on a imx6ull-evk board.
Fixes: 86e02d07871c ("media: imx5/6/7: csi: Mark a bound video mux as a CSI mux") Signed-off-by: Fabio Estevam festevam@gmail.com Signed-off-by: Rui Miguel Silva rmfrfs@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/imx/imx7-media-csi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index a3f3df9017046..31e36168f9d0f 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1164,12 +1164,12 @@ static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier, struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); struct media_pad *sink = &csi->sd.entity.pads[IMX7_CSI_PAD_SINK];
- /* The bound subdev must always be the CSI mux */ - if (WARN_ON(sd->entity.function != MEDIA_ENT_F_VID_MUX)) - return -ENXIO; - - /* Mark it as such via its group id */ - sd->grp_id = IMX_MEDIA_GRP_ID_CSI_MUX; + /* + * If the subdev is a video mux, it must be one of the CSI + * muxes. Mark it as such via its group id. + */ + if (sd->entity.function == MEDIA_ENT_F_VID_MUX) + sd->grp_id = IMX_MEDIA_GRP_ID_CSI_MUX;
return v4l2_create_fwnode_links_to_pad(sd, sink); }
From: Rui Miguel Silva rmfrfs@gmail.com
[ Upstream commit f5ffb81f51376eb5a12e8c4cb4871426c65bb2af ]
We can not make the assumption that the bound subdev is always a CSI mux, in i.MX6UL/i.MX6ULL that is not the case. So, just get the entity selected by source directly upstream from the CSI.
Fixes: 86e02d07871c ("media: imx5/6/7: csi: Mark a bound video mux as a CSI mux") Reported-by: Fabio Estevam festevam@gmail.com Signed-off-by: Rui Miguel Silva rmfrfs@gmail.com Tested-by: Fabio Estevam festevam@gmail.com Tested-by: Sébastien Szymanski sebastien.szymanski@armadeus.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/imx/imx7-media-csi.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 31e36168f9d0f..ac52b1daf9914 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -499,6 +499,7 @@ static int imx7_csi_pad_link_validate(struct v4l2_subdev *sd, struct v4l2_subdev_format *sink_fmt) { struct imx7_csi *csi = v4l2_get_subdevdata(sd); + struct media_entity *src; struct media_pad *pad; int ret;
@@ -509,11 +510,21 @@ static int imx7_csi_pad_link_validate(struct v4l2_subdev *sd, if (!csi->src_sd) return -EPIPE;
+ src = &csi->src_sd->entity; + + /* + * if the source is neither a CSI MUX or CSI-2 get the one directly + * upstream from this CSI + */ + if (src->function != MEDIA_ENT_F_VID_IF_BRIDGE && + src->function != MEDIA_ENT_F_VID_MUX) + src = &csi->sd.entity; + /* - * find the entity that is selected by the CSI mux. This is needed + * find the entity that is selected by the source. This is needed * to distinguish between a parallel or CSI-2 pipeline. */ - pad = imx_media_pipeline_pad(&csi->src_sd->entity, 0, 0, true); + pad = imx_media_pipeline_pad(src, 0, 0, true); if (!pad) return -ENODEV;
From: Tomi Valkeinen tomi.valkeinen@ideasonboard.com
[ Upstream commit 5a402af5e19f215689e8bf3cc244c21d94eba3c4 ]
The asd allocated with v4l2_async_notifier_add_fwnode_subdev() must be of size cal_v4l2_async_subdev, otherwise access to cal_v4l2_async_subdev->phy will go to unallocated memory.
Fixes: 8fcb7576ad19 ("media: ti-vpe: cal: Allow multiple contexts per subdev notifier") Signed-off-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/ti-vpe/cal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 59a0266b1f399..2eef245c31a17 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -406,7 +406,7 @@ static irqreturn_t cal_irq(int irq_cal, void *data) */
struct cal_v4l2_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_subdev asd; /* Must be first */ struct cal_camerarx *phy; };
@@ -472,7 +472,7 @@ static int cal_async_notifier_register(struct cal_dev *cal) fwnode = of_fwnode_handle(phy->sensor_node); asd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier, fwnode, - sizeof(*asd)); + sizeof(*casd)); if (IS_ERR(asd)) { phy_err(phy, "Failed to add subdev to notifier\n"); ret = PTR_ERR(asd);
From: Alexander Lobakin alobakin@pm.me
[ Upstream commit 894ef530012fb5078466efdfb2c15d8b2f1565cd ]
Commit 866b6a89c6d1 ("MIPS: Add DWARF unwinding to assembly") added -fno-asynchronous-unwind-tables to KBUILD_CFLAGS to prevent compiler from emitting .eh_frame symbols. However, as MIPS heavily uses CFI, that's not enough. Use the approach taken for x86 (as it also uses CFI) and explicitly put CFI symbols into the .debug_frame section (except for VDSO). This allows us to drop .eh_frame from DISCARDS as it's no longer being generated.
Fixes: 866b6a89c6d1 ("MIPS: Add DWARF unwinding to assembly") Suggested-by: Kees Cook keescook@chromium.org Signed-off-by: Alexander Lobakin alobakin@pm.me Reviewed-by: Kees Cook keescook@chromium.org Reviewed-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/asm.h | 18 ++++++++++++++++++ arch/mips/kernel/vmlinux.lds.S | 1 - 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h index 3682d1a0bb808..ea4b62ece3366 100644 --- a/arch/mips/include/asm/asm.h +++ b/arch/mips/include/asm/asm.h @@ -20,10 +20,27 @@ #include <asm/sgidefs.h> #include <asm/asm-eva.h>
+#ifndef __VDSO__ +/* + * Emit CFI data in .debug_frame sections, not .eh_frame sections. + * We don't do DWARF unwinding at runtime, so only the offline DWARF + * information is useful to anyone. Note we should change this if we + * ever decide to enable DWARF unwinding at runtime. + */ +#define CFI_SECTIONS .cfi_sections .debug_frame +#else + /* + * For the vDSO, emit both runtime unwind information and debug + * symbols for the .dbg file. + */ +#define CFI_SECTIONS +#endif + /* * LEAF - declare leaf routine */ #define LEAF(symbol) \ + CFI_SECTIONS; \ .globl symbol; \ .align 2; \ .type symbol, @function; \ @@ -36,6 +53,7 @@ symbol: .frame sp, 0, ra; \ * NESTED - declare nested routine entry point */ #define NESTED(symbol, framesize, rpc) \ + CFI_SECTIONS; \ .globl symbol; \ .align 2; \ .type symbol, @function; \ diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 83e27a181206a..09fa4705ce8eb 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -224,6 +224,5 @@ SECTIONS *(.options) *(.pdr) *(.reginfo) - *(.eh_frame) } }
From: Nathan Chancellor natechancellor@gmail.com
[ Upstream commit 8790ccf8daf1a8c53b6cb8ce0c9a109274bd3fa8 ]
When building with clang when CONFIG_CPU_LOONGSON3_WORKAROUNDS is enabled:
In file included from lib/errseq.c:4: In file included from ./include/linux/atomic.h:7: ./arch/mips/include/asm/atomic.h:52:1: warning: converting the result of '<<' to a boolean always evaluates to true [-Wtautological-constant-compare] ATOMIC_OPS(atomic64, s64) ^ ./arch/mips/include/asm/atomic.h:40:9: note: expanded from macro 'ATOMIC_OPS' return cmpxchg(&v->counter, o, n); ^ ./arch/mips/include/asm/cmpxchg.h:194:7: note: expanded from macro 'cmpxchg' if (!__SYNC_loongson3_war) ^ ./arch/mips/include/asm/sync.h:147:34: note: expanded from macro '__SYNC_loongson3_war' # define __SYNC_loongson3_war (1 << 31) ^
While it is not wrong that the result of this shift is always true in a boolean context, it is not a problem here. Regardless, the warning is really noisy so rather than making the shift a boolean implicitly, use it in an equality comparison so the shift is used as an integer value.
Fixes: 4d1dbfe6cbec ("MIPS: atomic: Emit Loongson3 sync workarounds within asm") Fixes: a91f2a1dba44 ("MIPS: cmpxchg: Omit redundant barriers for Loongson3") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Nathan Chancellor natechancellor@gmail.com Acked-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/atomic.h | 2 +- arch/mips/include/asm/cmpxchg.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index f904084fcb1fd..27ad767915390 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -248,7 +248,7 @@ static __inline__ int pfx##_sub_if_positive(type i, pfx##_t * v) \ * bltz that can branch to code outside of the LL/SC loop. As \ * such, we don't need to emit another barrier here. \ */ \ - if (!__SYNC_loongson3_war) \ + if (__SYNC_loongson3_war == 0) \ smp_mb__after_atomic(); \ \ return result; \ diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index 5b0b3a6777ea5..ed8f3f3c4304a 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h @@ -99,7 +99,7 @@ unsigned long __xchg(volatile void *ptr, unsigned long x, int size) * contains a completion barrier prior to the LL, so we don't \ * need to emit an extra one here. \ */ \ - if (!__SYNC_loongson3_war) \ + if (__SYNC_loongson3_war == 0) \ smp_mb__before_llsc(); \ \ __res = (__typeof__(*(ptr))) \ @@ -191,7 +191,7 @@ unsigned long __cmpxchg(volatile void *ptr, unsigned long old, * contains a completion barrier prior to the LL, so we don't \ * need to emit an extra one here. \ */ \ - if (!__SYNC_loongson3_war) \ + if (__SYNC_loongson3_war == 0) \ smp_mb__before_llsc(); \ \ __res = cmpxchg_local((ptr), (old), (new)); \ @@ -201,7 +201,7 @@ unsigned long __cmpxchg(volatile void *ptr, unsigned long old, * contains a completion barrier after the SC, so we don't \ * need to emit an extra one here. \ */ \ - if (!__SYNC_loongson3_war) \ + if (__SYNC_loongson3_war == 0) \ smp_llsc_mb(); \ \ __res; \
From: Qinglang Miao miaoqinglang@huawei.com
[ Upstream commit dcdfe2712b68f1e9dbf4f1a96ad59b80e5cc0ef7 ]
The PM reference count is not expected to be incremented on return in these Tegra functions.
However, pm_runtime_get_sync() will increment the PM reference count even on failure. Forgetting to put the reference again will result in a leak.
Replace it with pm_runtime_resume_and_get() to keep the usage counter balanced.
Fixes: fd67e9c6ed5a ("drm/tegra: Do not implement runtime PM") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Qinglang Miao miaoqinglang@huawei.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tegra/dsi.c | 2 +- drivers/gpu/drm/tegra/hdmi.c | 2 +- drivers/gpu/drm/tegra/hub.c | 2 +- drivers/gpu/drm/tegra/sor.c | 2 +- drivers/gpu/drm/tegra/vic.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 85dd7131553af..0ae3a025efe9d 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -2186,7 +2186,7 @@ static int tegra_dc_runtime_resume(struct host1x_client *client) struct device *dev = client->dev; int err;
- err = pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get runtime PM: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 5691ef1b0e586..f46d377f0c304 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -1111,7 +1111,7 @@ static int tegra_dsi_runtime_resume(struct host1x_client *client) struct device *dev = client->dev; int err;
- err = pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get runtime PM: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index d09a24931c87c..e5d2a40260288 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -1510,7 +1510,7 @@ static int tegra_hdmi_runtime_resume(struct host1x_client *client) struct device *dev = client->dev; int err;
- err = pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get runtime PM: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 22a03f7ffdc12..5ce771cba1335 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -789,7 +789,7 @@ static int tegra_display_hub_runtime_resume(struct host1x_client *client) unsigned int i; int err;
- err = pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get runtime PM: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index cc2aa2308a515..f02a035dda453 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -3218,7 +3218,7 @@ static int tegra_sor_runtime_resume(struct host1x_client *client) struct device *dev = client->dev; int err;
- err = pm_runtime_get_sync(dev); + err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get runtime PM: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index ade56b860cf9d..b77f726303d89 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -314,7 +314,7 @@ static int vic_open_channel(struct tegra_drm_client *client, struct vic *vic = to_vic(client); int err;
- err = pm_runtime_get_sync(vic->dev); + err = pm_runtime_resume_and_get(vic->dev); if (err < 0) return err;
From: Guchun Chen guchun.chen@amd.com
[ Upstream commit fe2d9f5abf19f2b3688b3b8da4e42f8d07886847 ]
Fixes: 5c23e9e05e42 ("drm/amdgpu: Update RAS XGMI error inject sequence") Signed-off-by: Guchun Chen guchun.chen@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 82e952696d24f..1fb2a91ad30ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -846,7 +846,7 @@ static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, if (amdgpu_dpm_allow_xgmi_power_down(adev, true)) dev_warn(adev->dev, "Failed to allow XGMI power down");
- if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW)) + if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW)) dev_warn(adev->dev, "Failed to allow df cstate");
return ret;
From: Pan Bian bianpan2016@163.com
[ Upstream commit 0f7b4bc6bb1e57c48ef14f1818df947c1612b206 ]
Free the request rq before returning error code.
Fixes: 972248e9111e ("scsi: bsg-lib: handle bidi requests without block layer help") Signed-off-by: Pan Bian bianpan2016@163.com Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/bsg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/block/bsg.c b/block/bsg.c index d7bae94b64d95..3d78e843a83f6 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -157,8 +157,10 @@ static int bsg_sg_io(struct request_queue *q, fmode_t mode, void __user *uarg) return PTR_ERR(rq);
ret = q->bsg_dev.ops->fill_hdr(rq, &hdr, mode); - if (ret) + if (ret) { + blk_put_request(rq); return ret; + }
rq->timeout = msecs_to_jiffies(hdr.timeout); if (!rq->timeout)
From: Finn Thain fthain@telegraphics.com.au
[ Upstream commit c396dd2ec5bbd1cb80eafe32a72ab6bd6b17cb5a ]
As usual, the available documentation is inadequate and leaves endianness unspecified for message data. However, testing shows that this patch does improve correctness. The mistake should have been detected earlier but it was obscured by other bugs. In testing, this patch reinstated pre-v5.9 behaviour. The old driver bugs remain and ADB input devices may stop working. But that appears to be unrelated.
Cc: Joshua Thompson funaho@jurai.org Fixes: c66da95a39ec ("macintosh/adb-iop: Implement SRQ autopolling") Tested-by: Stan Johnson userm57@yahoo.com Signed-off-by: Finn Thain fthain@telegraphics.com.au Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Link: https://lore.kernel.org/r/20210125074524.3027452-1-geert@linux-m68k.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/macintosh/adb-iop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index 0ee3272491501..2633bc254935c 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -19,6 +19,7 @@ #include <asm/macints.h> #include <asm/mac_iop.h> #include <asm/adb_iop.h> +#include <asm/unaligned.h>
#include <linux/adb.h>
@@ -249,7 +250,7 @@ static void adb_iop_set_ap_complete(struct iop_msg *msg) { struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
- autopoll_devs = (amsg->data[1] << 8) | amsg->data[0]; + autopoll_devs = get_unaligned_be16(amsg->data); if (autopoll_devs & (1 << autopoll_addr)) return; autopoll_addr = autopoll_devs ? (ffs(autopoll_devs) - 1) : 0; @@ -266,8 +267,7 @@ static int adb_iop_autopoll(int devs) amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0); amsg.count = 2; amsg.cmd = 0; - amsg.data[0] = mask & 0xFF; - amsg.data[1] = (mask >> 8) & 0xFF; + put_unaligned_be16(mask, amsg.data);
iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg, adb_iop_set_ap_complete);
From: Mario Kleiner mario.kleiner.de@gmail.com
[ Upstream commit 1916866dfa4aaceba1a70db83fde569387649d93 ]
In set_clamp(), the comments and definitions for the COLOR_DEPTH_101010 and COLOR_DEPTH_121212 cases directly contradict the code comment which explains how this should work, whereas the COLOR_DEPTH_888 case is consistent with the code comments. Comment says the bitmask should be chosen to align to the top-most 10 or 12 MSB's on a 14 bit bus, but the implementation contradicts that: 10 bit case sets a mask for 12 bpc clamping, whereas 12 bit case sets a mask for 14 bpc clamping.
Note that during my limited testing on DCE-8.3 (HDMI deep color) and DCE-11.2 (DP deep color), this didn't have any obvious ill effects, neither did fixing it change anything obvious for the better, so this fix may be inconsequential on DCE, and just reduce the confusion of innocent bystanders when reading the code and trying to investigate problems with 10 bpc+ output.
Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Cc: Harry Wentland harry.wentland@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 130a0a0c83329..68028ec995e74 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -601,12 +601,12 @@ static void set_clamp( clamp_max = 0x3FC0; break; case COLOR_DEPTH_101010: - /* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ - clamp_max = 0x3FFC; + /* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */ + clamp_max = 0x3FF0; break; case COLOR_DEPTH_121212: - /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */ - clamp_max = 0x3FFF; + /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ + clamp_max = 0x3FFC; break; default: clamp_max = 0x3FC0;
From: Mario Kleiner mario.kleiner.de@gmail.com
[ Upstream commit efa18405baa55a864c61d2f3cc6fe4d363818eb3 ]
This fixes corrupted display output in HDMI deep color 10/12 bpc mode at least as observed on AMD Mullins, DCE-8.3.
It will hopefully also provide fixes for other DCE's up to DCE-11, assuming those will need similar fixes, but i could not test that for HDMI due to lack of suitable hw, so viewer discretion is advised.
dce110_stream_encoder_hdmi_set_stream_attribute() is used for HDMI setup on all DCE's and is missing color_depth assignment.
dce110_program_pix_clk() is used for pixel clock setup on HDMI for DCE 6-11, and is missing color_depth assignment.
Additionally some of the underlying Atombios specific encoder and pixelclock setup functions are missing code which is in the classic amdgpu kms modesetting path and the in the radeon kms driver for DCE6/DCE8.
encoder_control_digx_v3() - Was missing setup code wrt. amdgpu and radeon kms classic drivers. Added here, but untested due to lack of suitable test hw.
encoder_control_digx_v4() - Added missing setup code. Successfully tested on AMD mullins / DCE-8.3 with HDMI deep color output at 10 bpc and 12 bpc.
Note that encoder_control_digx_v5() has proper setup code in place and is used, e.g., by DCE-11.2, but this code wasn't used for deep color setup due to the missing cntl.color_depth setup in the calling function for HDMI.
set_pixel_clock_v5() - Missing setup code wrt. classic amdgpu/radeon kms. Added here, but untested due to lack of hw.
set_pixel_clock_v6() - Missing setup code added. Successfully tested on AMD mullins DCE-8.3. This fixes corrupted display output at HDMI deep color output with 10 bpc or 12 bpc.
Fixes: 4562236b3bc0 ("drm/amd/dc: Add dc display driver (v2)")
Reviewed-by: Nicholas Kazlauskas nicholas.kazlauskas@amd.com Signed-off-by: Mario Kleiner mario.kleiner.de@gmail.com Cc: Harry Wentland harry.wentland@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/display/dc/bios/command_table.c | 61 +++++++++++++++++++ .../drm/amd/display/dc/dce/dce_clock_source.c | 14 +++++ .../amd/display/dc/dce/dce_stream_encoder.c | 1 + 3 files changed, 76 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 070459e3e4070..afc10b954ffa7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -245,6 +245,23 @@ static enum bp_result encoder_control_digx_v3( cntl->enable_dp_audio); params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+ switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK;
@@ -274,6 +291,23 @@ static enum bp_result encoder_control_digx_v4( cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+ switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK;
@@ -1057,6 +1091,19 @@ static enum bp_result set_pixel_clock_v5( * driver choose program it itself, i.e. here we program it * to 888 by default. */ + if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) + switch (bp_params->color_depth) { + case TRANSMITTER_COLOR_DEPTH_30: + /* yes this is correct, the atom define is wrong */ + clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP; + break; + case TRANSMITTER_COLOR_DEPTH_36: + /* yes this is correct, the atom define is wrong */ + clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; + break; + default: + break; + }
if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) result = BP_RESULT_OK; @@ -1135,6 +1182,20 @@ static enum bp_result set_pixel_clock_v6( * driver choose program it itself, i.e. here we pass required * target rate that includes deep color. */ + if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) + switch (bp_params->color_depth) { + case TRANSMITTER_COLOR_DEPTH_30: + clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6; + break; + case TRANSMITTER_COLOR_DEPTH_36: + clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6; + break; + case TRANSMITTER_COLOR_DEPTH_48: + clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; + break; + default: + break; + }
if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) result = BP_RESULT_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index fb733f573715e..466f8f5803c9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -871,6 +871,20 @@ static bool dce110_program_pix_clk( bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = pll_settings->use_external_clk;
+ switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_30; + break; + case COLOR_DEPTH_121212: + bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_36; + break; + case COLOR_DEPTH_161616: + bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_48; + break; + default: + break; + } + if (clk_src->bios->funcs->set_pixel_clock( clk_src->bios, &bp_pc_params) != BP_RESULT_OK) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index ada57f745fd76..19e380e0a3301 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -564,6 +564,7 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute( cntl.enable_dp_audio = enable_audio; cntl.pixel_clock = actual_pix_clk_khz; cntl.lanes_number = LANE_COUNT_FOUR; + cntl.color_depth = crtc_timing->display_color_depth;
if (enc110->base.bp->funcs->encoder_control( enc110->base.bp, &cntl) != BP_RESULT_OK)
From: Daniel Scally djrscally@gmail.com
[ Upstream commit fb5ec981adf08b94e6ce27ca16b7765c94f4513c ]
The software_node_get_next_child() function currently does not hold references to the child software_node that it finds or put the ref that is held against the old child - fix that.
Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the firmware node framework") Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Daniel Scally djrscally@gmail.com Reviewed-by: Heikki Krogerus heikki.krogerus@linux.intel.com Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Acked-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/base/swnode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 4a4b2008fbc26..4fcc1a6fb724c 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -443,14 +443,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode, struct swnode *c = to_swnode(child);
if (!p || list_empty(&p->children) || - (c && list_is_last(&c->entry, &p->children))) + (c && list_is_last(&c->entry, &p->children))) { + fwnode_handle_put(child); return NULL; + }
if (c) c = list_next_entry(c, entry); else c = list_first_entry(&p->children, struct swnode, entry); - return &c->fwnode; + + fwnode_handle_put(child); + return fwnode_handle_get(&c->fwnode); }
static struct fwnode_handle *
From: Joe Perches joe@perches.com
[ Upstream commit 59a3e78f8cc33901fe39035c1ab681374bba95ad ]
There's a comma used instead of a semicolon that causes multiple statements to be executed after an if instead of just the intended single statement.
Replace the comma with a semicolon.
Fixes: 15e1ce33182d ("[media] lmedm04: Fix usb_submit_urb BOGUS urb xfer, pipe 1 != type 3 in interrupt urb") Signed-off-by: Joe Perches joe@perches.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/dvb-usb-v2/lmedm04.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 5a7a9522d46da..9ddda8d68ee0f 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -391,7 +391,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe);
if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) - lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa), + lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa);
usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); info("INT Interrupt Service Started");
From: Daniel W. S. Almeida dwlsalmeida@gmail.com
[ Upstream commit 0a933a7f73d6c545dcbecb4f7a92d272aef4417b ]
The PMT write function was refactored and this broke the CRC computation.
Fix it.
Fixes: db9569f67e2e ("media: vidtv: cleanup PMT write table function") Signed-off-by: Daniel W. S. Almeida dwlsalmeida@gmail.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/media/test-drivers/vidtv/vidtv_psi.c b/drivers/media/test-drivers/vidtv/vidtv_psi.c index 4511a2a98405d..1724bb485e670 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_psi.c +++ b/drivers/media/test-drivers/vidtv/vidtv_psi.c @@ -1164,6 +1164,8 @@ u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args) struct vidtv_psi_desc *table_descriptor = args->pmt->descriptor; struct vidtv_psi_table_pmt_stream *stream = args->pmt->stream; struct vidtv_psi_desc *stream_descriptor; + u32 crc = INITIAL_CRC; + u32 nbytes = 0; struct header_write_args h_args = { .dest_buf = args->buf, .dest_offset = args->offset, @@ -1181,6 +1183,7 @@ u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args) .new_psi_section = false, .is_crc = false, .dest_buf_sz = args->buf_sz, + .crc = &crc, }; struct desc_write_args d_args = { .dest_buf = args->buf, @@ -1193,8 +1196,6 @@ u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args) .pid = args->pid, .dest_buf_sz = args->buf_sz, }; - u32 crc = INITIAL_CRC; - u32 nbytes = 0;
vidtv_psi_pmt_table_update_sec_len(args->pmt);
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 625993166b551d633917ca35d4afb7b46d7451b4 ]
The "pad" variable is a user controlled string and we haven't properly clamped it at this point so the debug code could print from beyond the of the array.
Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../media/atomisp/pci/atomisp_subdev.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index b666cb23e5ca1..2ef5f44e4b6b6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -349,12 +349,20 @@ static int isp_subdev_get_selection(struct v4l2_subdev *sd, return 0; }
-static char *atomisp_pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK", - "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE", - "ATOMISP_SUBDEV_PAD_SOURCE_VF", - "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", - "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO" - }; +static const char *atomisp_pad_str(unsigned int pad) +{ + static const char *const pad_str[] = { + "ATOMISP_SUBDEV_PAD_SINK", + "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE", + "ATOMISP_SUBDEV_PAD_SOURCE_VF", + "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", + "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO", + }; + + if (pad >= ARRAY_SIZE(pad_str)) + return "ATOMISP_INVALID_PAD"; + return pad_str[pad]; +}
int atomisp_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, @@ -378,7 +386,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
dev_dbg(isp->dev, "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n", - atomisp_pad_str[pad], target == V4L2_SEL_TGT_CROP + atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE", r->left, r->top, r->width, r->height, which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" @@ -612,7 +620,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, enum atomisp_input_stream_id stream_id;
dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n", - atomisp_pad_str[pad], ffmt->width, ffmt->height, ffmt->code, + atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code, which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY" : "V4L2_SUBDEV_FORMAT_ACTIVE");
From: Luo Meng luomeng12@huawei.com
[ Upstream commit fcf8d018bdca0453b8d6359062e6bc1512d04c38 ]
Fix to return a negative error code from the error handling case instead of 0 in function qm1d1c0042_init(), as done elsewhere in this function.
Fixes: ab4d14528fdf ("[media] em28xx: add support for PLEX PX-BCUD (ISDB-S)") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Luo Meng luomeng12@huawei.com Acked-by: Akihiro Tsukada tskd08@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/tuners/qm1d1c0042.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c index 0e26d22f0b268..53aa2558f71e1 100644 --- a/drivers/media/tuners/qm1d1c0042.c +++ b/drivers/media/tuners/qm1d1c0042.c @@ -343,8 +343,10 @@ static int qm1d1c0042_init(struct dvb_frontend *fe) if (val == reg_initval[reg_index][0x00]) break; } - if (reg_index >= QM1D1C0042_NUM_REG_ROWS) + if (reg_index >= QM1D1C0042_NUM_REG_ROWS) { + ret = -EINVAL; goto failed; + } memcpy(state->regs, reg_initval[reg_index], QM1D1C0042_NUM_REGS); usleep_range(2000, 3000);
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit b2de3643c5024fc4fd128ba7767c7fb8b714bea7 ]
This function looks like a realloc.
However, if 'risc->cpu != NULL', the memory will be freed, but never reallocated with the bigger 'size'. Explicitly set 'risc->cpu' to NULL, so that the reallocation is correctly performed a few lines below.
[hverkuil: NULL != risc->cpu -> risc->cpu]
Fixes: 5ede94c70553 ("[media] cx25821: remove bogus btcx_risc dependency) Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/pci/cx25821/cx25821-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 6f8ffab8840f4..07b6d0c49bbfa 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -976,8 +976,10 @@ int cx25821_riscmem_alloc(struct pci_dev *pci, __le32 *cpu; dma_addr_t dma = 0;
- if (NULL != risc->cpu && risc->size < size) + if (risc->cpu && risc->size < size) { pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); + risc->cpu = NULL; + } if (NULL == risc->cpu) { cpu = pci_zalloc_consistent(pci, size, &dma); if (NULL == cpu)
From: Tom Rix trix@redhat.com
[ Upstream commit a04e187d231086a1313fd635ac42bdbc997137ad ]
When DEBUG is defined this error occurs
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:306:41: error: ‘i’ undeclared (first use in this function) mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[VENC_SYS]);
Reviewing the old line
mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[i]);
All the i's need to be changed to VENC_SYS. Fix a similar error for VENC_LT_SYS.
Fixes: 0dc4b3286125 ("media: mtk-vcodec: venc: support SCP firmware") Signed-off-by: Tom Rix trix@redhat.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index dfb42e19bf813..be3842e6ca475 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -303,7 +303,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) ret = PTR_ERR((__force void *)dev->reg_base[VENC_SYS]); goto err_res; } - mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[VENC_SYS]); + mtk_v4l2_debug(2, "reg[%d] base=0x%p", VENC_SYS, dev->reg_base[VENC_SYS]);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { @@ -332,7 +332,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) ret = PTR_ERR((__force void *)dev->reg_base[VENC_LT_SYS]); goto err_res; } - mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[VENC_LT_SYS]); + mtk_v4l2_debug(2, "reg[%d] base=0x%p", VENC_LT_SYS, dev->reg_base[VENC_LT_SYS]);
dev->enc_lt_irq = platform_get_irq(pdev, 1); irq_set_status_flags(dev->enc_lt_irq, IRQ_NOAUTOEN);
From: yangerkun yangerkun@huawei.com
[ Upstream commit dc2b3e5cbc8087224fcd8698b0dc56131e0bf37d ]
We now support user to set erase page size, and use do_div between len and erase size to determine the reasonableness for the erase size. However, do_div is a macro and will overwrite the value of len. Which results a mtd device with unexcepted size. Fix it by use div_u64_rem.
Fixes: ffad560394de ("mtd: phram: Allow the user to set the erase page size.") Signed-off-by: yangerkun yangerkun@huawei.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20210125124936.651812-1-yangerkun@huawei.c... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mtd/devices/phram.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index cfd170946ba48..5b04ae6c30573 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -222,6 +222,7 @@ static int phram_setup(const char *val) uint64_t start; uint64_t len; uint64_t erasesize = PAGE_SIZE; + uint32_t rem; int i, ret;
if (strnlen(val, sizeof(buf)) >= sizeof(buf)) @@ -263,8 +264,11 @@ static int phram_setup(const char *val) } }
+ if (erasesize) + div_u64_rem(len, (uint32_t)erasesize, &rem); + if (len == 0 || erasesize == 0 || erasesize > len - || erasesize > UINT_MAX || do_div(len, (uint32_t)erasesize) != 0) { + || erasesize > UINT_MAX || rem) { parse_err("illegal erasesize or len\n"); goto error; }
From: Tom Rix trix@redhat.com
[ Upstream commit 031b9212eeee365443aaef013360ea6cded7b2c4 ]
When DEBUG is defined this error occurs
drivers/media/platform/pxa_camera.c:1410:7: error: ‘i’ undeclared (first use in this function) for (i = 0; i < vb->num_planes; i++) ^ The variable 'i' is missing, so declare it.
Fixes: 6f28435d1c15 ("[media] media: platform: pxa_camera: trivial move of functions") Signed-off-by: Tom Rix trix@redhat.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/pxa_camera.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index b664ce7558a1a..75fad9689c901 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -1386,6 +1386,9 @@ static int pxac_vb2_prepare(struct vb2_buffer *vb) struct pxa_camera_dev *pcdev = vb2_get_drv_priv(vb->vb2_queue); struct pxa_buffer *buf = vb2_to_pxa_buffer(vb); int ret = 0; +#ifdef DEBUG + int i; +#endif
switch (pcdev->channels) { case 1:
From: Laurent Pinchart laurent.pinchart@ideasonboard.com
[ Upstream commit dc9455ffae02d7b7fb51ba1e007fffcb9dc5d890 ]
The Renkforce RF AC4K 300 Action Cam 4K reports invalid bFormatIndex and bFrameIndex values when negotiating the video probe and commit controls. The UVC descriptors report a single supported format and frame size, with bFormatIndex and bFrameIndex both equal to 2, but the video probe and commit controls report bFormatIndex and bFrameIndex set to 1.
The device otherwise operates correctly, but the driver rejects the values and fails the format try operation. Fix it by ignoring the invalid indices, and assuming that the format and frame requested by the driver are accepted by the device.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=210767
Fixes: 8a652a17e3c0 ("media: uvcvideo: Ensure all probed info is returned to v4l2") Reported-by: Till Dörges doerges@pre-sense.de Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/uvc/uvc_v4l2.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index fa06bfa174ad3..c7172b8952a96 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -248,7 +248,9 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, goto done;
/* After the probe, update fmt with the values returned from - * negotiation with the device. + * negotiation with the device. Some devices return invalid bFormatIndex + * and bFrameIndex values, in which case we can only assume they have + * accepted the requested format as-is. */ for (i = 0; i < stream->nformats; ++i) { if (probe->bFormatIndex == stream->format[i].index) { @@ -257,11 +259,10 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, } }
- if (i == stream->nformats) { - uvc_trace(UVC_TRACE_FORMAT, "Unknown bFormatIndex %u\n", + if (i == stream->nformats) + uvc_trace(UVC_TRACE_FORMAT, + "Unknown bFormatIndex %u, using default\n", probe->bFormatIndex); - return -EINVAL; - }
for (i = 0; i < format->nframes; ++i) { if (probe->bFrameIndex == format->frame[i].bFrameIndex) { @@ -270,11 +271,10 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, } }
- if (i == format->nframes) { - uvc_trace(UVC_TRACE_FORMAT, "Unknown bFrameIndex %u\n", + if (i == format->nframes) + uvc_trace(UVC_TRACE_FORMAT, + "Unknown bFrameIndex %u, using default\n", probe->bFrameIndex); - return -EINVAL; - }
fmt->fmt.pix.width = frame->wWidth; fmt->fmt.pix.height = frame->wHeight;
From: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com
[ Upstream commit b7cdd6453ca2c2449c5270f2d0ae88b644a1d2fb ]
Fix OV772x build breakage by selecting V4L2_FWNODE config:
ia64-linux-ld: drivers/media/i2c/ov772x.o: in function `ov772x_probe': ov772x.c:(.text+0x1ee2): undefined reference to `v4l2_fwnode_endpoint_alloc_parse' ia64-linux-ld: ov772x.c:(.text+0x1f12): undefined reference to `v4l2_fwnode_endpoint_free' ia64-linux-ld: ov772x.c:(.text+0x2212): undefined reference to `v4l2_fwnode_endpoint_alloc_parse'
Fixes: 8a10b4e3601e ("media: i2c: ov772x: Parse endpoint properties") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Lad Prabhakar prabhakar.mahadev-lad.rj@bp.renesas.com Acked-by: Jacopo Mondi jacopo+renesas@jmondi.org Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/i2c/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 2b9d81e4794a4..6eed3209ee2d3 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1000,6 +1000,7 @@ config VIDEO_OV772X tristate "OmniVision OV772x sensor support" depends on I2C && VIDEO_V4L2 select REGMAP_SCCB + select V4L2_FWNODE help This is a Video4Linux2 sensor driver for the OmniVision OV772x camera.
From: Judy Hsiao judyhsiao@google.com
[ Upstream commit ded055eea679139f11bd808795d9697b430d1c7d ]
The snd_soc_put_volsw in max98373_feedback_get is a typo, change it to snd_soc_get_volsw.
Fixes: 349dd23931d1 ("ASoC: max98373: don't access volatile registers in bias level off") Signed-off-by: Judy Hsiao judyhsiao@google.com Link: https://lore.kernel.org/r/20210127135620.1143942-1-judyhsiao@chromium.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/max98373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 31d571d4fac1c..746c829312b87 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -190,7 +190,7 @@ static int max98373_feedback_get(struct snd_kcontrol *kcontrol, } }
- return snd_soc_put_volsw(kcontrol, ucontrol); + return snd_soc_get_volsw(kcontrol, ucontrol); }
static const struct snd_kcontrol_new max98373_snd_controls[] = {
From: Qais Yousef qais.yousef@arm.com
[ Upstream commit 0ae78eec8aa64e645866e75005162603a77a0f49 ]
If the task is pinned to a cpu, setting the misfit status means that we'll unnecessarily continuously attempt to migrate the task but fail.
This continuous failure will cause the balance_interval to increase to a high value, and eventually cause unnecessary significant delays in balancing the system when real imbalance happens.
Caught while testing uclamp where rt-app calibration loop was pinned to cpu 0, shortly after which we spawn another task with high util_clamp value. The task was failing to migrate after over 40ms of runtime due to balance_interval unnecessary expanded to a very high value from the calibration loop.
Not done here, but it could be useful to extend the check for pinning to verify that the affinity of the task has a cpu that fits. We could end up in a similar situation otherwise.
Fixes: 3b1baa6496e6 ("sched/fair: Add 'group_misfit_task' load-balance type") Signed-off-by: Qais Yousef qais.yousef@arm.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Quentin Perret qperret@google.com Acked-by: Valentin Schneider valentin.schneider@arm.com Link: https://lkml.kernel.org/r/20210119120755.2425264-1-qais.yousef@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6918adaf74150..bbc78794224ac 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4060,7 +4060,7 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq) if (!static_branch_unlikely(&sched_asym_cpucapacity)) return;
- if (!p) { + if (!p || p->nr_cpus_allowed == 1) { rq->misfit_task_load = 0; return; }
From: Daeho Jeong daehojeong@google.com
[ Upstream commit df0736d70c4fa6ed711ba103b61880fe72bb4777 ]
By Colin's static analysis, we found out there is a null page reference under low memory situation in redirty_blocks. I've made the page finding loop stop immediately and return an error not to cause further memory pressure when we run into a failure to find a page under low memory condition.
Signed-off-by: Daeho Jeong daehojeong@google.com Reported-by: Colin Ian King colin.king@canonical.com Fixes: 5fdb322ff2c2 ("f2fs: add F2FS_IOC_DECOMPRESS_FILE and F2FS_IOC_COMPRESS_FILE") Reviewed-by: Colin Ian King colin.king@canonical.com Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/file.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f585545277d77..cd62b0d3369ab 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -4043,8 +4043,10 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
for (i = 0; i < page_len; i++, redirty_idx++) { page = find_lock_page(mapping, redirty_idx); - if (!page) - ret = -ENOENT; + if (!page) { + ret = -ENOMEM; + break; + } set_page_dirty(page); f2fs_put_page(page, 1); f2fs_put_page(page, 0);
From: Chao Yu yuchao0@huawei.com
[ Upstream commit 3afae09ffea5e08f523823be99a784675995d6bb ]
generic/269 reports a hangtask issue, the root cause is ABBA deadlock described as below:
Thread A Thread B - down_write(&sbi->gc_lock) -- A - f2fs_write_data_pages - lock all pages in cluster -- B - f2fs_write_multi_pages - f2fs_write_raw_pages - f2fs_write_single_data_page - f2fs_balance_fs - down_write(&sbi->gc_lock) -- A - f2fs_gc - do_garbage_collect - ra_data_block - pagecache_get_page -- B
To fix this, it needs to avoid calling f2fs_balance_fs() if there is still cluster pages been locked in context of cluster writeback, so instead, let's call f2fs_balance_fs() in the end of f2fs_write_raw_pages() when all cluster pages were unlocked.
Fixes: 4c8ff7095bef ("f2fs: support data compression") Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/compress.c | 5 ++++- fs/f2fs/data.c | 10 ++++++---- fs/f2fs/f2fs.h | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 4bcbacfe33259..7a774c9e4cb89 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1415,7 +1415,7 @@ retry_write:
ret = f2fs_write_single_data_page(cc->rpages[i], &_submitted, NULL, NULL, wbc, io_type, - compr_blocks); + compr_blocks, false); if (ret) { if (ret == AOP_WRITEPAGE_ACTIVATE) { unlock_page(cc->rpages[i]); @@ -1450,6 +1450,9 @@ retry_write:
*submitted += _submitted; } + + f2fs_balance_fs(F2FS_M_SB(mapping), true); + return 0; out_err: for (++i; i < cc->cluster_size; i++) { diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index aa34d620bec98..d72c99d9bd1f4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2743,7 +2743,8 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, sector_t *last_block, struct writeback_control *wbc, enum iostat_type io_type, - int compr_blocks) + int compr_blocks, + bool allow_balance) { struct inode *inode = page->mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -2881,7 +2882,7 @@ out: } unlock_page(page); if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) && - !F2FS_I(inode)->cp_task) + !F2FS_I(inode)->cp_task && allow_balance) f2fs_balance_fs(sbi, need_balance_fs);
if (unlikely(f2fs_cp_error(sbi))) { @@ -2928,7 +2929,7 @@ out: #endif
return f2fs_write_single_data_page(page, NULL, NULL, NULL, - wbc, FS_DATA_IO, 0); + wbc, FS_DATA_IO, 0, true); }
/* @@ -3096,7 +3097,8 @@ continue_unlock: } #endif ret = f2fs_write_single_data_page(page, &submitted, - &bio, &last_block, wbc, io_type, 0); + &bio, &last_block, wbc, io_type, + 0, true); if (ret == AOP_WRITEPAGE_ACTIVATE) unlock_page(page); #ifdef CONFIG_F2FS_FS_COMPRESSION diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index bb11759191dcc..1578402c58444 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3469,7 +3469,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, struct bio **bio, sector_t *last_block, struct writeback_control *wbc, enum iostat_type io_type, - int compr_blocks); + int compr_blocks, bool allow_balance); void f2fs_invalidate_page(struct page *page, unsigned int offset, unsigned int length); int f2fs_release_page(struct page *page, gfp_t wait);
From: Srinivasa Rao Mandadapu srivasam@codeaurora.org
[ Upstream commit 6c28377b7114d04cf82eedffe9dcc8fa66ecec48 ]
No need of BCLK state maintenance from driver side as clock_enable and clk_disable API's maintaing state counter.
One of the major issue was spotted when Headset jack inserted while playback continues, due to same PCM device node opens twice for playaback/capture and closes once for capture and playback continues.
It can resolve the errors in such scenarios.
Fixes: b1824968221c ("ASoC: qcom: Fix enabling BCLK and LRCLK in LPAIF invalid state")
Signed-off-by: Srinivasa Rao Mandadapu srivasam@codeaurora.org Reviewed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210127151824.8929-1-srivasam@codeaurora.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/lpass-cpu.c | 22 ++++++++-------------- sound/soc/qcom/lpass-lpaif-reg.h | 3 --- sound/soc/qcom/lpass.h | 1 - 3 files changed, 8 insertions(+), 18 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 66b834312f330..73ca24c0a08b7 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -286,16 +286,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
- if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_DISABLE) { - ret = clk_enable(drvdata->mi2s_bit_clk[id]); - if (ret) { - dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); - clk_disable(drvdata->mi2s_osr_clk[id]); - return ret; - } - drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_ENABLE; + ret = clk_enable(drvdata->mi2s_bit_clk[id]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + clk_disable(drvdata->mi2s_osr_clk[id]); + return ret; } - break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -310,10 +306,9 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, if (ret) dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_ENABLE) { - clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); - drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_DISABLE; - } + + clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); + break; }
@@ -866,7 +861,6 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); } - drvdata->bit_clk_state[dai_id] = LPAIF_BIT_CLK_DISABLE; }
/* Allocation for i2sctl regmap fields */ diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index baf72f124ea9b..2eb03ad9b7c74 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -60,9 +60,6 @@ #define LPAIF_I2SCTL_BITWIDTH_24 1 #define LPAIF_I2SCTL_BITWIDTH_32 2
-#define LPAIF_BIT_CLK_DISABLE 0 -#define LPAIF_BIT_CLK_ENABLE 1 - #define LPAIF_I2SCTL_RESET_STATE 0x003C0004 #define LPAIF_DMACTL_RESET_STATE 0x00200000
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 2d68af0da34d8..83b2e08ade060 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -68,7 +68,6 @@ struct lpass_data { unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS]; unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS]; int hdmi_port_enable; - int bit_clk_state[LPASS_MAX_MI2S_PORTS];
/* low-power audio interface (LPAIF) registers */ void __iomem *lpaif;
From: Ranjani Sridharan ranjani.sridharan@linux.intel.com
[ Upstream commit 0084364d9678e9d722ee620ed916f2f9954abdbf ]
Cancel the D0i3 work during runtime suspend as no streams are active at this point anyway.
Fixes: 63e51fd33fef ("ASoC: SOF: Intel: cnl: Implement feature to support DSP D0i3 in S0") Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210128092345.1033085-1-kai.vehmanen@linux.intel.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/intel/hda-dsp.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 1c5e05b88a90d..1799fc56a3e41 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -802,11 +802,15 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev)
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_dsp_power_state target_state = { .state = SOF_DSP_PM_D3, }; int ret;
+ /* cancel any attempt for DSP D0I3 */ + cancel_delayed_work_sync(&hda->d0i3_work); + /* stop hda controller and power dsp off */ ret = hda_suspend(sdev, true); if (ret < 0)
From: Robin Murphy robin.murphy@arm.com
[ Upstream commit 79d7c3dca99fa96033695ddf5d495b775a3a137b ]
Although it's neat to avoid the suffix for the typical case of a single PMU, it means systems with multiple CMN instances end up with inconsistent naming. I think it also breaks perf tool's "uncore alias" logic if the common instance prefix is also the full name of one.
Avoid any surprises by not trying to be clever and simply numbering every instance, even when it might technically prove redundant.
Fixes: 0ba64770a2f2 ("perf: Add Arm CMN-600 PMU driver") Signed-off-by: Robin Murphy robin.murphy@arm.com Link: https://lore.kernel.org/r/649a2281233f193d59240b13ed91b57337c77b32.161183956... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- Documentation/admin-guide/perf/arm-cmn.rst | 2 +- drivers/perf/arm-cmn.c | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/Documentation/admin-guide/perf/arm-cmn.rst b/Documentation/admin-guide/perf/arm-cmn.rst index 0e48093460140..796e25b7027b2 100644 --- a/Documentation/admin-guide/perf/arm-cmn.rst +++ b/Documentation/admin-guide/perf/arm-cmn.rst @@ -17,7 +17,7 @@ PMU events ----------
The PMU driver registers a single PMU device for the whole interconnect, -see /sys/bus/event_source/devices/arm_cmn. Multi-chip systems may link +see /sys/bus/event_source/devices/arm_cmn_0. Multi-chip systems may link more than one CMN together via external CCIX links - in this situation, each mesh counts its own events entirely independently, and additional PMU devices will be named arm_cmn_{1..n}. diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index a76ff594f3ca4..f3071b5ddaaef 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -1502,7 +1502,7 @@ static int arm_cmn_probe(struct platform_device *pdev) struct arm_cmn *cmn; const char *name; static atomic_t id; - int err, rootnode, this_id; + int err, rootnode;
cmn = devm_kzalloc(&pdev->dev, sizeof(*cmn), GFP_KERNEL); if (!cmn) @@ -1549,14 +1549,9 @@ static int arm_cmn_probe(struct platform_device *pdev) .cancel_txn = arm_cmn_end_txn, };
- this_id = atomic_fetch_inc(&id); - if (this_id == 0) { - name = "arm_cmn"; - } else { - name = devm_kasprintf(cmn->dev, GFP_KERNEL, "arm_cmn_%d", this_id); - if (!name) - return -ENOMEM; - } + name = devm_kasprintf(cmn->dev, GFP_KERNEL, "arm_cmn_%d", atomic_fetch_inc(&id)); + if (!name) + return -ENOMEM;
err = cpuhp_state_add_instance(arm_cmn_hp_state, &cmn->cpuhp_node); if (err)
From: Robin Murphy robin.murphy@arm.com
[ Upstream commit 1c8147ea89c883d1f4e20f1b1d9c879291430102 ]
If we migrate the PMU context to another CPU, we need to remember to retarget the IRQs as well.
Fixes: 0ba64770a2f2 ("perf: Add Arm CMN-600 PMU driver") Signed-off-by: Robin Murphy robin.murphy@arm.com Link: https://lore.kernel.org/r/e080640aea4ed8dfa870b8549dfb31221803eb6b.161183956... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/perf/arm-cmn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index f3071b5ddaaef..46defb1dcf867 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -1150,7 +1150,7 @@ static int arm_cmn_commit_txn(struct pmu *pmu) static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) { struct arm_cmn *cmn; - unsigned int target; + unsigned int i, target;
cmn = hlist_entry_safe(node, struct arm_cmn, cpuhp_node); if (cpu != cmn->cpu) @@ -1161,6 +1161,8 @@ static int arm_cmn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) return 0;
perf_pmu_migrate_context(&cmn->pmu, cpu, target); + for (i = 0; i < cmn->num_dtcs; i++) + irq_set_affinity_hint(cmn->dtc[i].irq, cpumask_of(target)); cmn->cpu = target; return 0; }
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 12ba8f8ce29fdd277f3100052eddc1afd2f5ea3f ]
If the kstrtouint() calls fail, then this should return a negative error code but it currently returns success.
Fixes: dd84cb022b31 ("mtd: bcm63xxpart: move imagetag parsing to its own parser") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/YBKFtNaFHGYBj+u4@mwanda Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mtd/parsers/parser_imagetag.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/mtd/parsers/parser_imagetag.c b/drivers/mtd/parsers/parser_imagetag.c index d69607b482272..fab0949aabba1 100644 --- a/drivers/mtd/parsers/parser_imagetag.c +++ b/drivers/mtd/parsers/parser_imagetag.c @@ -83,6 +83,7 @@ static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master, pr_err("invalid rootfs address: %*ph\n", (int)sizeof(buf->flash_image_start), buf->flash_image_start); + ret = -EINVAL; goto out; }
@@ -92,6 +93,7 @@ static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master, pr_err("invalid kernel address: %*ph\n", (int)sizeof(buf->kernel_address), buf->kernel_address); + ret = -EINVAL; goto out; }
@@ -100,6 +102,7 @@ static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master, pr_err("invalid kernel length: %*ph\n", (int)sizeof(buf->kernel_length), buf->kernel_length); + ret = -EINVAL; goto out; }
@@ -108,6 +111,7 @@ static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master, pr_err("invalid total length: %*ph\n", (int)sizeof(buf->total_length), buf->total_length); + ret = -EINVAL; goto out; }
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 416b846757bcea20006a9197e67ba3a8b5b2a680 ]
Talitos Security Engine AESU considers any input data size that is not a multiple of 16 bytes to be an error. This is not a problem in general, except for Counter mode that is a stream cipher and can have an input of any size.
Test Manager for ctr(aes) fails on 4th test vector which has a length of 499 while all previous vectors which have a 16 bytes multiple length succeed.
As suggested by Freescale, round up the input data length to the nearest 16 bytes.
Fixes: 5e75ae1b3cef ("crypto: talitos - add new crypto modes") Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/talitos.c | 28 ++++++++++++++++------------ drivers/crypto/talitos.h | 1 + 2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 4fd85f31630ac..b656983c1ef4e 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1093,11 +1093,12 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev, */ static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, unsigned int offset, int datalen, int elen, - struct talitos_ptr *link_tbl_ptr) + struct talitos_ptr *link_tbl_ptr, int align) { int n_sg = elen ? sg_count + 1 : sg_count; int count = 0; int cryptlen = datalen + elen; + int padding = ALIGN(cryptlen, align) - cryptlen;
while (cryptlen && sg && n_sg--) { unsigned int len = sg_dma_len(sg); @@ -1121,7 +1122,7 @@ static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, offset += datalen; } to_talitos_ptr(link_tbl_ptr + count, - sg_dma_address(sg) + offset, len, 0); + sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0); to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); count++; cryptlen -= len; @@ -1144,10 +1145,11 @@ static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, unsigned int len, struct talitos_edesc *edesc, struct talitos_ptr *ptr, int sg_count, unsigned int offset, int tbl_off, int elen, - bool force) + bool force, int align) { struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); + int aligned_len = ALIGN(len, align);
if (!src) { to_talitos_ptr(ptr, 0, 0, is_sec1); @@ -1155,22 +1157,22 @@ static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, } to_talitos_ptr_ext_set(ptr, elen, is_sec1); if (sg_count == 1 && !force) { - to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1); + to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1); return sg_count; } if (is_sec1) { - to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1); + to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1); return sg_count; } sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen, - &edesc->link_tbl[tbl_off]); + &edesc->link_tbl[tbl_off], align); if (sg_count == 1 && !force) { /* Only one segment now, so no link tbl needed*/ copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); return sg_count; } to_talitos_ptr(ptr, edesc->dma_link_tbl + - tbl_off * sizeof(struct talitos_ptr), len, is_sec1); + tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1); to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
return sg_count; @@ -1182,7 +1184,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src, unsigned int offset, int tbl_off) { return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, - tbl_off, 0, false); + tbl_off, 0, false, 1); }
/* @@ -1251,7 +1253,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], sg_count, areq->assoclen, tbl_off, elen, - false); + false, 1);
if (ret > 1) { tbl_off += ret; @@ -1271,7 +1273,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, elen = 0; ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], sg_count, areq->assoclen, tbl_off, elen, - is_ipsec_esp && !encrypt); + is_ipsec_esp && !encrypt, 1); tbl_off += ret;
if (!encrypt && is_ipsec_esp) { @@ -1577,6 +1579,8 @@ static int common_nonsnoop(struct talitos_edesc *edesc, bool sync_needed = false; struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); + bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU && + (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
/* first DWORD empty */
@@ -1597,8 +1601,8 @@ static int common_nonsnoop(struct talitos_edesc *edesc, /* * cipher in */ - sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc, - &desc->ptr[3], sg_count, 0, 0); + sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3], + sg_count, 0, 0, 0, false, is_ctr ? 16 : 1); if (sg_count > 1) sync_needed = true;
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index 1469b956948ab..32825119e8805 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -344,6 +344,7 @@ static inline bool has_ftr_sec1(struct talitos_private *priv)
/* primary execution unit mode (MODE0) and derivatives */ #define DESC_HDR_MODE0_ENCRYPT cpu_to_be32(0x00100000) +#define DESC_HDR_MODE0_AESU_MASK cpu_to_be32(0x00600000) #define DESC_HDR_MODE0_AESU_CBC cpu_to_be32(0x00200000) #define DESC_HDR_MODE0_AESU_CTR cpu_to_be32(0x00600000) #define DESC_HDR_MODE0_DEU_CBC cpu_to_be32(0x00400000)
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 43a942d27eaaf33bca560121cbe42f3637e92880 ]
While ctr(aes) requires the use of a special descriptor on SEC2 (see commit 70d355ccea89 ("crypto: talitos - fix ctr-aes-talitos")), that special descriptor doesn't work on SEC1, see commit e738c5f15562 ("powerpc/8xx: Add DT node for using the SEC engine of the MPC885").
However, the common nonsnoop descriptor works properly on SEC1 for ctr(aes).
Add a second template for ctr(aes) that will be registered only on SEC1.
Fixes: 70d355ccea89 ("crypto: talitos - fix ctr-aes-talitos") Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/talitos.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b656983c1ef4e..25c9f825b8b54 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -2765,6 +2765,22 @@ static struct talitos_alg_template driver_algs[] = { DESC_HDR_SEL0_AESU | DESC_HDR_MODE0_AESU_CTR, }, + { .type = CRYPTO_ALG_TYPE_SKCIPHER, + .alg.skcipher = { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "ctr-aes-talitos", + .base.cra_blocksize = 1, + .base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_ALLOCATES_MEMORY, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = skcipher_aes_setkey, + }, + .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | + DESC_HDR_SEL0_AESU | + DESC_HDR_MODE0_AESU_CTR, + }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .alg.skcipher = { .base.cra_name = "ecb(des)", @@ -3182,6 +3198,12 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, t_alg->algt.alg.skcipher.setkey ?: skcipher_setkey; t_alg->algt.alg.skcipher.encrypt = skcipher_encrypt; t_alg->algt.alg.skcipher.decrypt = skcipher_decrypt; + if (!strcmp(alg->cra_name, "ctr(aes)") && !has_ftr_sec1(priv) && + DESC_TYPE(t_alg->algt.desc_hdr_template) != + DESC_TYPE(DESC_HDR_TYPE_AESU_CTR_NONSNOOP)) { + devm_kfree(dev, t_alg); + return ERR_PTR(-ENOTSUPP); + } break; case CRYPTO_ALG_TYPE_AEAD: alg = &t_alg->algt.alg.aead.base;
From: Frantisek Hrbata frantisek@hrbata.com
[ Upstream commit eaba3b28401f50e22d64351caa8afe8d29509f27 ]
Unprivileged user can crash kernel by using DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC ioctl. This was reported by trinity[1] fuzzer.
[ 71.073906] nouveau 0000:01:00.0: crashme[1329]: channel failed to initialise, -17 [ 71.081730] BUG: kernel NULL pointer dereference, address: 00000000000000a0 [ 71.088928] #PF: supervisor read access in kernel mode [ 71.094059] #PF: error_code(0x0000) - not-present page [ 71.099189] PGD 119590067 P4D 119590067 PUD 1054f5067 PMD 0 [ 71.104842] Oops: 0000 [#1] SMP NOPTI [ 71.108498] CPU: 2 PID: 1329 Comm: crashme Not tainted 5.8.0-rc6+ #2 [ 71.114993] Hardware name: AMD Pike/Pike, BIOS RPK1506A 09/03/2014 [ 71.121213] RIP: 0010:nouveau_abi16_ioctl_channel_alloc+0x108/0x380 [nouveau] [ 71.128339] Code: 48 89 9d f0 00 00 00 41 8b 4c 24 04 41 8b 14 24 45 31 c0 4c 8d 4b 10 48 89 ee 4c 89 f7 e8 10 11 00 00 85 c0 75 78 48 8b 43 10 <8b> 90 a0 00 00 00 41 89 54 24 08 80 7d 3d 05 0f 86 bb 01 00 00 41 [ 71.147074] RSP: 0018:ffffb4a1809cfd38 EFLAGS: 00010246 [ 71.152526] RAX: 0000000000000000 RBX: ffff98cedbaa1d20 RCX: 00000000000003bf [ 71.159651] RDX: 00000000000003be RSI: 0000000000000000 RDI: 0000000000030160 [ 71.166774] RBP: ffff98cee776de00 R08: ffffdc0144198a08 R09: ffff98ceeefd4000 [ 71.173901] R10: ffff98cee7e81780 R11: 0000000000000001 R12: ffffb4a1809cfe08 [ 71.181214] R13: ffff98cee776d000 R14: ffff98cec519e000 R15: ffff98cee776def0 [ 71.188339] FS: 00007fd926250500(0000) GS:ffff98ceeac80000(0000) knlGS:0000000000000000 [ 71.196418] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 71.202155] CR2: 00000000000000a0 CR3: 0000000106622000 CR4: 00000000000406e0 [ 71.209297] Call Trace: [ 71.211777] ? nouveau_abi16_ioctl_getparam+0x1f0/0x1f0 [nouveau] [ 71.218053] drm_ioctl_kernel+0xac/0xf0 [drm] [ 71.222421] drm_ioctl+0x211/0x3c0 [drm] [ 71.226379] ? nouveau_abi16_ioctl_getparam+0x1f0/0x1f0 [nouveau] [ 71.232500] nouveau_drm_ioctl+0x57/0xb0 [nouveau] [ 71.237285] ksys_ioctl+0x86/0xc0 [ 71.240595] __x64_sys_ioctl+0x16/0x20 [ 71.244340] do_syscall_64+0x4c/0x90 [ 71.248110] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 71.253162] RIP: 0033:0x7fd925d4b88b [ 71.256731] Code: Bad RIP value. [ 71.259955] RSP: 002b:00007ffc743592d8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010 [ 71.267514] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fd925d4b88b [ 71.274637] RDX: 0000000000601080 RSI: 00000000c0586442 RDI: 0000000000000003 [ 71.281986] RBP: 00007ffc74359340 R08: 00007fd926016ce0 R09: 00007fd926016ce0 [ 71.289111] R10: 0000000000000003 R11: 0000000000000206 R12: 0000000000400620 [ 71.296235] R13: 00007ffc74359420 R14: 0000000000000000 R15: 0000000000000000 [ 71.303361] Modules linked in: rfkill sunrpc snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hda_core edac_mce_amd snd_hwdep kvm_amd snd_seq ccp snd_seq_device snd_pcm kvm snd_timer snd irqbypass soundcore sp5100_tco pcspkr crct10dif_pclmul crc32_pclmul ghash_clmulni_intel wmi_bmof joydev i2c_piix4 fam15h_power k10temp acpi_cpufreq ip_tables xfs libcrc32c sd_mod t10_pi sg nouveau video mxm_wmi i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm broadcom bcm_phy_lib ata_generic ahci drm e1000 crc32c_intel libahci serio_raw tg3 libata firewire_ohci firewire_core wmi crc_itu_t dm_mirror dm_region_hash dm_log dm_mod [ 71.365269] CR2: 00000000000000a0
simplified reproducer ---------------------------------8<---------------------------------------- /* * gcc -o crashme crashme.c * ./crashme /dev/dri/renderD128 */
struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; uint32_t tt_ctxdma_handle;
int channel; uint32_t pushbuf_domains;
/* Notifier memory */ uint32_t notifier_handle;
/* DRM-enforced subchannel assignments */ struct { uint32_t handle; uint32_t grclass; } subchan[8]; uint32_t nr_subchan; };
static struct drm_nouveau_channel_alloc channel;
int main(int argc, char *argv[]) { int fd; int rv;
if (argc != 2) die("usage: %s <dev>", 0, argv[0]);
if ((fd = open(argv[1], O_RDONLY)) == -1) die("open %s", errno, argv[1]);
if (ioctl(fd, DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC, &channel) == -1 && errno == EACCES) die("ioctl %s", errno, argv[1]);
close(fd);
printf("PASS\n");
return 0; } ---------------------------------8<----------------------------------------
[1] https://github.com/kernelslacker/trinity
Fixes: eeaf06ac1a55 ("drm/nouveau/svm: initial support for shared virtual memory") Signed-off-by: Frantisek Hrbata frantisek@hrbata.com Reviewed-by: Karol Herbst kherbst@redhat.com Signed-off-by: Ben Skeggs bskeggs@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nouveau/nouveau_chan.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 5d191e58edf11..e48f1f7eb3705 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -533,6 +533,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, if (ret) { NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret); nouveau_channel_del(pchan); + goto done; }
ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
From: Biwen Li biwen.li@nxp.com
[ Upstream commit c60767421e102dfd1f4d99ad0cc7f8ba24461eb8 ]
The ls-extirq driver doesn't implement the irq_set_wake() callback, while being wake-up capable. This results in ugly behaviours across suspend/resume cycles.
Advertise this by adding IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Fixes: b16a1caf4686 ("irqchip/ls-extirq: Add LS1043A, LS1088A external interrupt support") Signed-off-by: Biwen Li biwen.li@nxp.com Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210129095034.33821-1-biwen.li@oss.nxp.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-ls-extirq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-ls-extirq.c b/drivers/irqchip/irq-ls-extirq.c index f94f974a87645..853b3972dbe78 100644 --- a/drivers/irqchip/irq-ls-extirq.c +++ b/drivers/irqchip/irq-ls-extirq.c @@ -64,7 +64,7 @@ static struct irq_chip ls_extirq_chip = { .irq_set_type = ls_extirq_set_type, .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_set_affinity = irq_chip_set_affinity_parent, - .flags = IRQCHIP_SET_TYPE_MASKED, + .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE, };
static int
From: Will Deacon will@kernel.org
[ Upstream commit 912efa17e5121693dfbadae29768f4144a3f9e62 ]
Since commit 0758cd830494 ("asm-generic/tlb: avoid potential double flush"), TLB invalidation is elided in tlb_finish_mmu() if no entries were batched via the tlb_remove_*() functions. Consequently, the page-table modifications performed by clear_refs_write() in response to a write to /proc/<pid>/clear_refs do not perform TLB invalidation. Although this is fine when simply aging the ptes, in the case of clearing the "soft-dirty" state we can end up with entries where pte_write() is false, yet a writable mapping remains in the TLB.
Fix this by avoiding the mmu_gather API altogether: managing both the 'tlb_flush_pending' flag on the 'mm_struct' and explicit TLB invalidation for the sort-dirty path, much like mprotect() does already.
Fixes: 0758cd830494 ("asm-generic/tlb: avoid potential double flush”) Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Yu Zhao yuzhao@google.com Acked-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Linus Torvalds torvalds@linux-foundation.org Link: https://lkml.kernel.org/r/20210127235347.1402-2-will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/proc/task_mmu.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 602e3a52884d8..3cec6fbef725e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1210,7 +1210,6 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, struct mm_struct *mm; struct vm_area_struct *vma; enum clear_refs_types type; - struct mmu_gather tlb; int itype; int rv;
@@ -1249,7 +1248,6 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, goto out_unlock; }
- tlb_gather_mmu(&tlb, mm, 0, -1); if (type == CLEAR_REFS_SOFT_DIRTY) { for (vma = mm->mmap; vma; vma = vma->vm_next) { if (!(vma->vm_flags & VM_SOFTDIRTY)) @@ -1258,15 +1256,18 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, vma_set_page_prot(vma); }
+ inc_tlb_flush_pending(mm); mmu_notifier_range_init(&range, MMU_NOTIFY_SOFT_DIRTY, 0, NULL, mm, 0, -1UL); mmu_notifier_invalidate_range_start(&range); } walk_page_range(mm, 0, mm->highest_vm_end, &clear_refs_walk_ops, &cp); - if (type == CLEAR_REFS_SOFT_DIRTY) + if (type == CLEAR_REFS_SOFT_DIRTY) { mmu_notifier_invalidate_range_end(&range); - tlb_finish_mmu(&tlb, 0, -1); + flush_tlb_mm(mm); + dec_tlb_flush_pending(mm); + } out_unlock: mmap_write_unlock(mm); out_mm:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit 10340f8d7b6dd54e616339c8ccb2f397133ebea0 ]
While reworking the resources management and departing from using ahci_platform_enable_resources() which did not allow a proper step separation like we need, we unfortunately lost the ability to control AHCI regulators. This broke some Broadcom STB systems that do expect regulators to be turned on to link up with attached hard drives.
Fixes: c0cdf2ac4b5b ("ata: ahci_brcm: Fix AHCI resources management") Signed-off-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ata/ahci_brcm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 49f7acbfcf01e..5b32df5d33adc 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -377,6 +377,10 @@ static int __maybe_unused brcm_ahci_resume(struct device *dev) if (ret) return ret;
+ ret = ahci_platform_enable_regulators(hpriv); + if (ret) + goto out_disable_clks; + brcm_sata_init(priv); brcm_sata_phys_enable(priv); brcm_sata_alpm_init(hpriv); @@ -406,6 +410,8 @@ out_disable_platform_phys: ahci_platform_disable_phys(hpriv); out_disable_phys: brcm_sata_phys_disable(priv); + ahci_platform_disable_regulators(hpriv); +out_disable_clks: ahci_platform_disable_clks(hpriv); return ret; } @@ -490,6 +496,10 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (ret) goto out_reset;
+ ret = ahci_platform_enable_regulators(hpriv); + if (ret) + goto out_disable_clks; + /* Must be first so as to configure endianness including that * of the standard AHCI register space. */ @@ -499,7 +509,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) priv->port_mask = brcm_ahci_get_portmask(hpriv, priv); if (!priv->port_mask) { ret = -ENODEV; - goto out_disable_clks; + goto out_disable_regulators; }
/* Must be done before ahci_platform_enable_phys() */ @@ -524,6 +534,8 @@ out_disable_platform_phys: ahci_platform_disable_phys(hpriv); out_disable_phys: brcm_sata_phys_disable(priv); +out_disable_regulators: + ahci_platform_disable_regulators(hpriv); out_disable_clks: ahci_platform_disable_clks(hpriv); out_reset:
From: Sebastian Reichel sre@kernel.org
[ Upstream commit de5bfae2fd962a9da99f56382305ec7966a604b9 ]
The correct mask is 0x1f8 (Bit 3-8), but due to missing BIT() 0xf (Bit 0-3) was set instead. This means setting of CPCAP_BIT_MIC1_RX_TIMESLOT0 (Bit 3) still worked (part of both masks). On the other hand the code does not properly clear the other MIC timeslot bits. I think this is not a problem, since they are probably initialized to 0 and not touched by the driver anywhere else. But the mask also contains some wrong bits, that will be cleared. Bit 0 (CPCAP_BIT_SMB_CDC) should be safe, since the driver enforces it to be 0 anyways.
Bit 1-2 are CPCAP_BIT_FS_INV and CPCAP_BIT_CLK_INV. This means enabling audio recording forces the codec into SND_SOC_DAIFMT_NB_NF mode, which is obviously bad.
The bug probably remained undetected, because there are not many use cases for routing microphone to the CPU on platforms using cpcap and user base is small. I do remember having some issues with bad sound quality when testing voice recording back when I wrote the driver. It probably was this bug.
Fixes: f6cdf2d3445d ("ASoC: cpcap: new codec") Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Sebastian Reichel sre@kernel.org Reviewed-by: Tony Lindgren tony@atomide.com Link: https://lore.kernel.org/r/20210123172945.3958622-1-sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/cpcap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index f046987ee4cdb..c0425e3707d9c 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1264,12 +1264,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
if (direction == SNDRV_PCM_STREAM_CAPTURE) { mask = 0x0000; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2; - mask |= CPCAP_BIT_MIC2_TIMESLOT0; - mask |= CPCAP_BIT_MIC2_TIMESLOT1; - mask |= CPCAP_BIT_MIC2_TIMESLOT2; + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2); val = 0x0000; if (channels >= 2) val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org
[ Upstream commit e8820dbddbcad7e91daacf7d42a49d1d04a4e489 ]
For some reason setting max_register was missed from regmap_config. Without this cat /sys/kernel/debug/regmap/sdw:0:217:2010:0:1/range actually throws below Warning.
WARNING: CPU: 7 PID: 540 at drivers/base/regmap/regmap-debugfs.c:160 regmap_debugfs_get_dump_start.part.10+0x1e0/0x220 ... Call trace: regmap_debugfs_get_dump_start.part.10+0x1e0/0x220 regmap_reg_ranges_read_file+0xc0/0x2e0 full_proxy_read+0x64/0x98 vfs_read+0xa8/0x1e0 ksys_read+0x6c/0x100 __arm64_sys_read+0x1c/0x28 el0_svc_common.constprop.3+0x6c/0x190 do_el0_svc+0x24/0x90 el0_svc+0x14/0x20 el0_sync_handler+0x90/0xb8 el0_sync+0x158/0x180 ...
Fixes: a0aab9e1404a ("ASoC: codecs: add wsa881x amplifier support") Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210201161429.28060-1-srinivas.kandagatla@linaro.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/wsa881x.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 4530b74f5921b..db87e07b11c94 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -640,6 +640,7 @@ static struct regmap_config wsa881x_regmap_config = { .val_bits = 8, .cache_type = REGCACHE_RBTREE, .reg_defaults = wsa881x_defaults, + .max_register = WSA881X_SPKR_STATUS3, .num_reg_defaults = ARRAY_SIZE(wsa881x_defaults), .volatile_reg = wsa881x_volatile_register, .readable_reg = wsa881x_readable_register,
From: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
[ Upstream commit 7b844cf445f0a7daa68be0ce71eb2c88d68b0c5d ]
In the case of failure while parsing the partitions, the iterator should be pre decremented by one before starting to free the memory allocated by kstrdup(). Because in the failure case, kstrdup() will not succeed and thus no memory will be allocated for the current iteration.
Fixes: 1fca1f6abb38 ("mtd: afs: simplify partition parsing") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Reviewed-by: Linus Walleij linus.walleij@linaro.org Cc: Linus Walleij linus.walleij@linaro.org Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20210104041137.113075-5-manivannan.sadhasi... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mtd/parsers/afs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/mtd/parsers/afs.c b/drivers/mtd/parsers/afs.c index 980e332bdac48..26116694c821b 100644 --- a/drivers/mtd/parsers/afs.c +++ b/drivers/mtd/parsers/afs.c @@ -370,10 +370,8 @@ static int parse_afs_partitions(struct mtd_info *mtd, return i;
out_free_parts: - while (i >= 0) { + while (--i >= 0) kfree(parts[i].name); - i--; - } kfree(parts); *pparts = NULL; return ret;
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 073abfa7ea9a5b0537d6f92b42baedaf82a04c53 ]
If 'dmaengine_prep_slave_single()' fails, we must undo a previous 'dma_map_single()' call, as already done in all the other error handling paths of this function.
Fixes: 0b1039f016e8 ("mtd: rawnand: Add NAND controller support on Intel LGM SoC") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20210124073955.728797-1-christophe.jaillet... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mtd/nand/raw/intel-nand-controller.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c index a304fda5d1fa5..8b49fd56cf964 100644 --- a/drivers/mtd/nand/raw/intel-nand-controller.c +++ b/drivers/mtd/nand/raw/intel-nand-controller.c @@ -318,8 +318,10 @@ static int ebu_dma_start(struct ebu_nand_controller *ebu_host, u32 dir, }
tx = dmaengine_prep_slave_single(chan, buf_dma, len, dir, flags); - if (!tx) - return -ENXIO; + if (!tx) { + ret = -ENXIO; + goto err_unmap; + }
tx->callback = callback; tx->callback_param = ebu_host;
From: Yi Chen chenyi77@huawei.com
[ Upstream commit 25fb04dbce6a0e165d28fd1fa8a1d7018c637fe8 ]
Occasionally, quota data may be corrupted detected by fsck:
Info: checkpoint state = 45 : crc compacted_summary unmount [QUOTA WARNING] Usage inconsistent for ID 0:actual (1543036928, 762) != expected (1543032832, 762) [ASSERT] (fsck_chk_quota_files:1986) --> Quota file is missing or invalid quota file content found. [QUOTA WARNING] Usage inconsistent for ID 0:actual (1352478720, 344) != expected (1352474624, 344) [ASSERT] (fsck_chk_quota_files:1986) --> Quota file is missing or invalid quota file content found.
[FSCK] Unreachable nat entries [Ok..] [0x0] [FSCK] SIT valid block bitmap checking [Ok..] [FSCK] Hard link checking for regular file [Ok..] [0x0] [FSCK] valid_block_count matching with CP [Ok..] [0xdf299] [FSCK] valid_node_count matcing with CP (de lookup) [Ok..] [0x2b01] [FSCK] valid_node_count matcing with CP (nat lookup) [Ok..] [0x2b01] [FSCK] valid_inode_count matched with CP [Ok..] [0x2665] [FSCK] free segment_count matched with CP [Ok..] [0xcb04] [FSCK] next block offset is free [Ok..] [FSCK] fixing SIT types [FSCK] other corrupted bugs [Fail]
The root cause is: If we open file w/ readonly flag, disk quota info won't be initialized for this file, however, following mmap() will force to convert inline inode via f2fs_convert_inline_inode(), which may increase block usage for this inode w/o updating quota data, it causes inconsistent disk quota info.
The issue will happen in following stack: open(file, O_RDONLY) mmap(file) - f2fs_convert_inline_inode - f2fs_convert_inline_page - f2fs_reserve_block - f2fs_reserve_new_block - f2fs_reserve_new_blocks - f2fs_i_blocks_write - dquot_claim_block inode->i_blocks increase, but the dqb_curspace keep the size for the dquots is NULL.
To fix this issue, let's call dquot_initialize() anyway in both f2fs_truncate() and f2fs_convert_inline_inode() functions to avoid potential inconsistent quota data issue.
Fixes: 0abd675e97e6 ("f2fs: support plain user/group quota") Signed-off-by: Daiyue Zhang zhangdaiyue1@huawei.com Signed-off-by: Dehe Gu gudehe@huawei.com Signed-off-by: Junchao Jiang jiangjunchao1@huawei.com Signed-off-by: Ge Qiu qiuge@huawei.com Signed-off-by: Yi Chen chenyi77@huawei.com Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/file.c | 4 ++++ fs/f2fs/inline.c | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index cd62b0d3369ab..18ea529ef5ea0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -767,6 +767,10 @@ int f2fs_truncate(struct inode *inode) return -EIO; }
+ err = dquot_initialize(inode); + if (err) + return err; + /* we should check inline_data size */ if (!f2fs_may_inline_data(inode)) { err = f2fs_convert_inline_inode(inode); diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 806ebabf58706..993caefcd2bb0 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -192,6 +192,10 @@ int f2fs_convert_inline_inode(struct inode *inode) f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb)) return 0;
+ err = dquot_initialize(inode); + if (err) + return err; + page = f2fs_grab_cache_page(inode->i_mapping, 0, false); if (!page) return -ENOMEM;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit c915ef890d5dc79f483e1ca3b3a5b5f1a170690c ]
If the user passes a "level" value which is higher than 31 then that leads to shift wrapping. The undefined behavior will lead to a syzkaller stack dump.
Fixes: 5632708f4452 ("drm/amd/powerplay: add dpm force multiple levels on cz/tonga/fiji/polaris (v2)") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 7b6ef05a1d35a..0b5be50b2eeeb 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1074,7 +1074,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) { int ret; - long level; + unsigned long level; char *sub_str = NULL; char *tmp; char buf_cpy[AMDGPU_MASK_BUF_MAX + 1]; @@ -1090,8 +1090,8 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) while (tmp[0]) { sub_str = strsep(&tmp, delimiter); if (strlen(sub_str)) { - ret = kstrtol(sub_str, 0, &level); - if (ret) + ret = kstrtoul(sub_str, 0, &level); + if (ret || level > 31) return -EINVAL; *mask |= 1 << level; } else
From: Dehe Gu gudehe@huawei.com
[ Upstream commit 39f71b7e40e21805d6b15fc7750bdd9cab6a5010 ]
We should use !F2FS_IO_ALIGNED() to check and submit_io directly.
Fixes: 8223ecc456d0 ("f2fs: fix to add missing F2FS_IO_ALIGNED() condition") Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Dehe Gu gudehe@huawei.com Signed-off-by: Ge Qiu qiuge@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d72c99d9bd1f4..4d3ebf094f6d7 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -499,7 +499,7 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi, if (f2fs_lfs_mode(sbi) && current->plug) blk_finish_plug(current->plug);
- if (F2FS_IO_ALIGNED(sbi)) + if (!F2FS_IO_ALIGNED(sbi)) goto submit_io;
start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS;
From: Srinivasa Rao Mandadapu srivasam@codeaurora.org
[ Upstream commit e681b1a6d706b4e54c3847bb822531b4660234f3 ]
Had a typo in lpass platform driver that resulted in crash during suspend/resume with an HDMI dongle connected.
The regmap read/write/volatile regesters validation callbacks in lpass-cpu were using MI2S rdma_channels count instead of hdmi_rdma_channels.
This typo error causing to read registers from the regmap beyond the length of the mapping created by ioremap().
This fix avoids the need for reducing number hdmi_rdma_channels, which is done in commit 7dfe20ee92f6 ("ASoC: qcom: Fix number of HDMI RDMA channels on sc7180"). So reverting the same.
Fixes: 7cb37b7bd0d3c ("ASoC: qcom: Add support for lpass hdmi driver") Signed-off-by: Srinivasa Rao Mandadapu srivasam@codeaurora.org Link: https://lore.kernel.org/r/20210202062727.22469-1-srivasam@codeaurora.org Reviewed-by: Stephen Boyd swboyd@chromium.org Tested-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/lpass-cpu.c | 8 ++++---- sound/soc/qcom/lpass-sc7180.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 73ca24c0a08b7..8e5415c9234f1 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -594,7 +594,7 @@ static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg) return true; }
- for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACTL_REG(v, i)) return true; if (reg == LPAIF_HDMI_RDMABASE_REG(v, i)) @@ -640,7 +640,7 @@ static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned int reg) if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v)) return true;
- for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACTL_REG(v, i)) return true; if (reg == LPAIF_HDMI_RDMABASE_REG(v, i)) @@ -667,7 +667,7 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg) if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v)) return true;
- for (i = 0; i < v->rdma_channels; ++i) { + for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACURR_REG(v, i)) return true; } @@ -817,7 +817,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) }
lpass_hdmi_regmap_config.max_register = LPAIF_HDMI_RDMAPER_REG(variant, - variant->hdmi_rdma_channels); + variant->hdmi_rdma_channels - 1); drvdata->hdmiif_map = devm_regmap_init_mmio(dev, drvdata->hdmiif, &lpass_hdmi_regmap_config); if (IS_ERR(drvdata->hdmiif_map)) { diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c index 735c9dac28f26..8c168d3c589e9 100644 --- a/sound/soc/qcom/lpass-sc7180.c +++ b/sound/soc/qcom/lpass-sc7180.c @@ -171,7 +171,7 @@ static struct lpass_variant sc7180_data = { .rdma_channels = 5, .hdmi_rdma_reg_base = 0x64000, .hdmi_rdma_reg_stride = 0x1000, - .hdmi_rdma_channels = 3, + .hdmi_rdma_channels = 4, .dmactl_audif_start = 1, .wrdma_reg_base = 0x18000, .wrdma_reg_stride = 0x1000,
From: Sean Christopherson seanjc@google.com
[ Upstream commit 2732be90235347a3be4babdc9f88a1ea93970b0b ]
Don't clear the SME C-bit when reading a guest PDPTR, as the GPA (CR3) is in the guest domain.
Barring a bizarre paravirtual use case, this is likely a benign bug. SME is not emulated by KVM, loading SEV guest PDPTRs is doomed as KVM can't use the correct key to read guest memory, and setting guest MAXPHYADDR higher than the host, i.e. overlapping the C-bit, would cause faults in the guest.
Note, for SEV guests, stripping the C-bit is technically aligned with CPU behavior, but for KVM it's the greater of two evils. Because KVM doesn't have access to the guest's encryption key, ignoring the C-bit would at best result in KVM reading garbage. By keeping the C-bit, KVM will fail its read (unless userspace creates a memslot with the C-bit set). The guest will still undoubtedly die, as KVM will use '0' for the PDPTR value, but that's preferable to interpreting encrypted data as a PDPTR.
Fixes: d0ec49d4de90 ("kvm/x86/svm: Support Secure Memory Encryption within KVM") Cc: Tom Lendacky thomas.lendacky@amd.com Cc: Brijesh Singh brijesh.singh@amd.com Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210204000117.3303214-3-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/svm/nested.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index db30670dd8c4a..8ded795a18151 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -58,7 +58,7 @@ static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index) u64 pdpte; int ret;
- ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(__sme_clr(cr3)), &pdpte, + ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(cr3), &pdpte, offset_in_page(cr3) + index * 8, 8); if (ret) return 0;
From: Yongqiang Niu yongqiang.niu@mediatek.com
[ Upstream commit b1d685b6467ac0d98fc63989f71b4ca9186be5d4 ]
It's possible that state->base.fb is null. Add a check before access its format.
Fixes: b6b1bb980ec4 ("drm/mediatek: Turn off Alpha bit when plane format has no alpha") Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com Signed-off-by: Chun-Kuang Hu chunkuang.hu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 74ef6fc0528b6..523716e3c278a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -267,7 +267,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, }
con = ovl_fmt_convert(ovl, fmt); - if (state->base.fb->format->has_alpha) + if (state->base.fb && state->base.fb->format->has_alpha) con |= OVL_CON_AEN | OVL_CON_ALPHA;
if (pending->rotation & DRM_MODE_REFLECT_Y) {
[ Upstream commit 71dcadba34203d8dd35152e368720f977e9cdb81 ]
The orginal setting is not correct, fix it to follow hardware data sheet. If keep this error setting, mt8173/mt8183 display ok but mt8192 display abnormal.
Fixes: 0664d1392c26 ("drm/mediatek: Add AAL engine basic function")
Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com Signed-off-by: Chun-Kuang Hu chunkuang.hu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 3064eac1a7507..7fcb717f256c9 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -180,7 +180,9 @@ static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_AAL_SIZE); + struct mtk_ddp_comp_dev *priv = dev_get_drvdata(comp->dev); + + mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE); }
static void mtk_aal_start(struct mtk_ddp_comp *comp)
From: Andrea Parri (Microsoft) parri.andrea@gmail.com
[ Upstream commit e3fa4b747f085d2cda09bba0533b86fa76038635 ]
When channel->device_obj is non-NULL, vmbus_onoffer_rescind() could invoke put_device(), that will eventually release the device and free the channel object (cf. vmbus_device_release()). However, a pointer to the object is dereferenced again later to load the primary_channel. The use-after-free can be avoided by noticing that this load/check is redundant if device_obj is non-NULL: primary_channel must be NULL if device_obj is non-NULL, cf. vmbus_add_channel_work().
Fixes: 54a66265d6754b ("Drivers: hv: vmbus: Fix rescind handling") Reported-by: Juan Vazquez juvazq@microsoft.com Signed-off-by: Andrea Parri (Microsoft) parri.andrea@gmail.com Reviewed-by: Michael Kelley mikelley@microsoft.com Link: https://lore.kernel.org/r/20201209070827.29335-5-parri.andrea@gmail.com Signed-off-by: Wei Liu wei.liu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hv/channel_mgmt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 1d44bb635bb84..6be9f56cb6270 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -1102,8 +1102,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) vmbus_device_unregister(channel->device_obj); put_device(dev); } - } - if (channel->primary_channel != NULL) { + } else if (channel->primary_channel != NULL) { /* * Sub-channel is being rescinded. Following is the channel * close sequence when initiated from the driveri (refer to
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit f12bbc50f3b14c9b8ed902c6d1da980dd5addcce ]
We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies.
Fixes: 9ad9bc59dde10 ('ASoC: Intel: sof_sdw: set proper flags for Dell TGL-H SKU 0A5E') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210204203312.27112-3-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6d0d6ef711e0f..29b6bba3d4257 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -73,7 +73,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), },
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 45c92ec32b43c6cb42341ebf07577eefed9d87ec ]
We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies.
Fixes: 488cdbd8931fe ('ASoC: Intel: sof_sdw: add quirk for new TigerLake-SDCA device') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210204203312.27112-4-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 29b6bba3d4257..afdc336ec9bf5 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -54,7 +54,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), },
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 5ab3ff4d66960be766a544886667e7c002f17fd6 ]
We missed adding the TGL_HDMI quirk which is very much needed to expose the 4 display pipelines and will be required on TGL topologies.
Fixes: e787f5b5b1406 ('ASoC: Intel: add support for new SoundWire hardware layout on TGL') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210204203312.27112-2-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index afdc336ec9bf5..152ea166eeaef 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -65,7 +65,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | SOF_RT715_DAI_ID_FIX), }, {
From: Peter Zijlstra peterz@infradead.org
[ Upstream commit 7f82e631d236cafd28518b998c6d4d8dc2ef68f6 ]
Commit f6f48e180404 ("lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions") overlooked that print_usage_bug() releases the graph_lock and called it without the graph lock held.
Fixes: f6f48e180404 ("lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions") Reported-by: Dmitry Vyukov dvyukov@google.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Acked-by: Waiman Long longman@redhat.com Link: https://lkml.kernel.org/r/YBfkuyIfB1+VRxXP@hirez.programming.kicks-ass.net Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/locking/lockdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index bdaf4829098c0..780012eb2f3fe 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -3707,7 +3707,7 @@ static void print_usage_bug(struct task_struct *curr, struct held_lock *this, enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit) { - if (!debug_locks_off_graph_unlock() || debug_locks_silent) + if (!debug_locks_off() || debug_locks_silent) return;
pr_warn("\n"); @@ -3748,6 +3748,7 @@ valid_state(struct task_struct *curr, struct held_lock *this, enum lock_usage_bit new_bit, enum lock_usage_bit bad_bit) { if (unlikely(hlock_class(this)->usage_mask & (1 << bad_bit))) { + graph_unlock(); print_usage_bug(curr, this, bad_bit, new_bit); return 0; }
From: Jun Nie jun.nie@linaro.org
[ Upstream commit 5e3277ab3baff6db96ae44adf6f85d6f0f6502cc ]
Fix bitwidth mapping in i2s ctl register per APQ8016 document.
Fixes: b5022a36d28f ("ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers") Reviewed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Reviewed-by: Stephan Gerhold stephan@gerhold.net Signed-off-by: Jun Nie jun.nie@linaro.org Link: https://lore.kernel.org/r/20210201132941.460360-1-jun.nie@linaro.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/lpass-apq8016.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index 8507ef8f6679b..3efa133d1c641 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -250,7 +250,7 @@ static struct lpass_variant apq8016_data = { .micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000), .micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000), .wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000), - .bitwidth = REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000), + .bitwidth = REG_FIELD_ID(0x1000, 0, 1, 4, 0x1000),
.rdma_dyncclk = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000), .rdma_bursten = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000),
From: Sathyanarayana Nujella sathyanarayana.nujella@intel.com
[ Upstream commit 45a2702ce10993eda7a5b12690294782d565519c ]
During Coldboot stress tests, system encountered the following panic. Panic logs depicts rt5682_i2c_shutdown() happened first and then later jack detect handler workqueue function triggered. This situation causes panic as rt5682_i2c_shutdown() resets codec. Fix this panic by cancelling all jack detection delayed work.
Panic log: [ 20.936124] sof_pci_shutdown [ 20.940248] snd_sof_device_shutdown [ 20.945023] snd_sof_shutdown [ 21.126849] rt5682_i2c_shutdown [ 21.286053] rt5682_jack_detect_handler [ 21.291235] BUG: kernel NULL pointer dereference, address: 000000000000037c [ 21.299302] #PF: supervisor read access in kernel mode [ 21.305254] #PF: error_code(0x0000) - not-present page [ 21.311218] PGD 0 P4D 0 [ 21.314155] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 21.319206] CPU: 2 PID: 123 Comm: kworker/2:3 Tainted: G U 5.4.68 #10 [ 21.333687] ACPI: Preparing to enter system sleep state S5 [ 21.337669] Workqueue: events_power_efficient rt5682_jack_detect_handler [snd_soc_rt5682] [ 21.337671] RIP: 0010:rt5682_jack_detect_handler+0x6c/0x279 [snd_soc_rt5682]
Fixes: a50067d4f3c1d ('ASoC: rt5682: split i2c driver into separate module') Signed-off-by: Jairaj Arava jairaj.arava@intel.com Signed-off-by: Sathyanarayana Nujella sathyanarayana.nujella@intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@intel.com Reviewed-by: Shuming Fan shumingf@realtek.com Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Link: https://lore.kernel.org/r/20210205171428.2344210-1-ranjani.sridharan@linux.i... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/rt5682-i2c.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 37d13120f5ba8..93c1603b42f10 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -273,6 +273,9 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
+ cancel_delayed_work_sync(&rt5682->jack_detect_work); + cancel_delayed_work_sync(&rt5682->jd_check_work); + rt5682_reset(rt5682); }
From: Hui Wang hui.wang@canonical.com
[ Upstream commit 9037c3bde65d339017ef41d81cb58069ffc321d4 ]
The function simple_write_to_buffer() doesn't add string termination at the end of buf, we need to handle it on our own. This change refers to the function tokenize_input() in debug.c and the function sof_dfsentry_trace_filter_write() in trace.c.
Fixes: 091c12e1f50c ("ASoC: SOF: debug: add new debugfs entries for IPC flood test") Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Signed-off-by: Hui Wang hui.wang@canonical.com Link: https://lore.kernel.org/r/20210208103857.75705-1-hui.wang@canonical.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 30213a1beaaa2..715a374b33cfb 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -352,7 +352,7 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, char *string; int ret;
- string = kzalloc(count, GFP_KERNEL); + string = kzalloc(count+1, GFP_KERNEL); if (!string) return -ENOMEM;
From: Zhihao Cheng chengzhihao1@huawei.com
[ Upstream commit 3cc64e7ebfb0d7faaba2438334c43466955a96e8 ]
Return value in __load_free_space_cache is not properly set after (unlikely) memory allocation failures and 0 is returned instead. This is not a problem for the caller load_free_space_cache because only value 1 is considered as 'cache loaded' but for clarity it's better to set the errors accordingly.
Fixes: a67509c30079 ("Btrfs: add a io_ctl struct and helpers for dealing with the space cache") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zhihao Cheng chengzhihao1@huawei.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/btrfs/free-space-cache.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 4d8897879c9cb..71d0d14bc18b3 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -775,8 +775,10 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, while (num_entries) { e = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); - if (!e) + if (!e) { + ret = -ENOMEM; goto free_cache; + }
ret = io_ctl_read_entry(&io_ctl, e, &type); if (ret) { @@ -785,6 +787,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, }
if (!e->bytes) { + ret = -1; kmem_cache_free(btrfs_free_space_cachep, e); goto free_cache; } @@ -805,6 +808,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, e->bitmap = kmem_cache_zalloc( btrfs_free_space_bitmap_cachep, GFP_NOFS); if (!e->bitmap) { + ret = -ENOMEM; kmem_cache_free( btrfs_free_space_cachep, e); goto free_cache;
From: Qu Wenruo wqu@suse.com
[ Upstream commit 951c80f83d61bd4b21794c8aba829c3c1a45c2d0 ]
Commit dbfdb6d1b369 ("Btrfs: Search for all ordered extents that could span across a page") make btrfs_invalidapage() to search all ordered extents.
The offending code looks like this:
again: start = page_start; ordered = btrfs_lookup_ordered_range(inode, start, page_end - start + 1); if (ordred) { end = min(page_end, ordered->file_offset + ordered->num_bytes - 1);
/* Do the cleanup */
start = end + 1; if (start < page_end) goto again; }
The behavior is indeed necessary for the incoming subpage support, but when it iterates through all the ordered extents, it also resets the search range @start.
This means, for the following cases, we can double account the ordered extents, causing its bytes_left underflow:
Page offset 0 16K 32K |<--- OE 1 --->|<--- OE 2 ---->|
As the first iteration will find ordered extent (OE) 1, which doesn't cover the full page, thus after cleanup code, we need to retry again. But again label will reset start to page_start, and we got OE 1 again, which causes double accounting on OE 1, and cause OE 1's byte_left to underflow.
This problem can only happen for subpage case, as for regular sectorsize == PAGE_SIZE case, we will always find a OE ends at or after page end, thus no way to trigger the problem.
Move the again label after start = page_start. There will be more comprehensive rework to convert the open coded loop to a proper while loop for subpage support.
Fixes: dbfdb6d1b369 ("Btrfs: Search for all ordered extents that could span across a page") 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/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a8e0a6b038d3e..ad34c5a09befc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8186,8 +8186,9 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
if (!inode_evicting) lock_extent_bits(tree, page_start, page_end, &cached_state); -again: + start = page_start; +again: ordered = btrfs_lookup_ordered_range(inode, start, page_end - start + 1); if (ordered) { found_ordered = true;
From: Jinyang He hejinyang@loongson.cn
[ Upstream commit d4d3ef8b347b73aa60f60f4be06acf1643e79f34 ]
Provide kaslr_offset() to get the kernel offset when KASLR is enabled. Error may occur before update_kaslr_offset(), so put it at the end of the offset branch.
Fixes: a307a4ce9ecd ("MIPS: Loongson64: Add KASLR support") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Jinyang He hejinyang@loongson.cn Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/page.h | 6 ++++++ arch/mips/kernel/relocate.c | 10 ++++++++++ arch/mips/kernel/setup.c | 3 +++ 3 files changed, 19 insertions(+)
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 6a77bc4a6eec4..74082e35d57c8 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -255,6 +255,12 @@ extern bool __virt_addr_valid(const volatile void *kaddr);
#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC
+extern unsigned long __kaslr_offset; +static inline unsigned long kaslr_offset(void) +{ + return __kaslr_offset; +} + #include <asm-generic/memory_model.h> #include <asm-generic/getorder.h>
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index 0e365b7c742d9..ac16cf2716df5 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -300,6 +300,13 @@ static inline int __init relocation_addr_valid(void *loc_new) return 1; }
+static inline void __init update_kaslr_offset(unsigned long *addr, long offset) +{ + unsigned long *new_addr = (unsigned long *)RELOCATED(addr); + + *new_addr = (unsigned long)offset; +} + #if defined(CONFIG_USE_OF) void __weak *plat_get_fdt(void) { @@ -410,6 +417,9 @@ void *__init relocate_kernel(void)
/* Return the new kernel's entry point */ kernel_entry = RELOCATED(start_kernel); + + /* Error may occur before, so keep it at last */ + update_kaslr_offset(&__kaslr_offset, offset); } out: return kernel_entry; diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 7e1f8e2774373..83ec0d5a0918b 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -84,6 +84,9 @@ static struct resource code_resource = { .name = "Kernel code", }; static struct resource data_resource = { .name = "Kernel data", }; static struct resource bss_resource = { .name = "Kernel bss", };
+unsigned long __kaslr_offset __ro_after_init; +EXPORT_SYMBOL(__kaslr_offset); + static void *detect_magic __initdata = detect_memory_region;
#ifdef CONFIG_MIPS_AUTO_PFN_OFFSET
From: Sean Christopherson seanjc@google.com
[ Upstream commit 2644312052d54e2e7543c7d186899a36ed22f0bf ]
Restore the full 64-bit values of DR6 and DR7 when emulating RSM on x86-64, as defined by both Intel's SDM and AMD's APM.
Note, bits 63:32 of DR6 and DR7 are reserved, so this is a glorified nop unless the SMM handler is poking into SMRAM, which it most definitely shouldn't be doing since both Intel and AMD list the DR6 and DR7 fields as read-only.
Fixes: 660a5d517aaa ("KVM: x86: save/load state on SMM switch") Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210205012458.3872687-3-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/emulate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 66a08322988f2..1453b9b794425 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2564,12 +2564,12 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, ctxt->_eip = GET_SMSTATE(u64, smstate, 0x7f78); ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7f70) | X86_EFLAGS_FIXED;
- val = GET_SMSTATE(u32, smstate, 0x7f68); + val = GET_SMSTATE(u64, smstate, 0x7f68);
if (ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1)) return X86EMUL_UNHANDLEABLE;
- val = GET_SMSTATE(u32, smstate, 0x7f60); + val = GET_SMSTATE(u64, smstate, 0x7f60);
if (ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1)) return X86EMUL_UNHANDLEABLE;
From: Harald Freudenberger freude@linux.ibm.com
[ Upstream commit d39fae45c97c67b1b4da04773f2bb5a2f29088c4 ]
When a msg is retried because the lower ap layer returns -EAGAIN there is a retry limit (currently 10). When this limit is reached the last return code from the lower layer is returned, causing the userspace to get -1 on the ioctl with errno EAGAIN.
This EAGAIN is misleading here. After 10 retry attempts the userspace should receive a clear failure indication like EINVAL or EIO or ENODEV. However, the reason why these retries all fail is unclear. On an invalid message EINVAL would be returned by the lower layer, and if devices go away or are not available an ENODEV is seen. So this patch now reworks the retry loops to return EIO to userspace when the retry limit is reached.
Fixes: 91ffc519c199 ("s390/zcrypt: introduce msg tracking in zcrypt functions") Signed-off-by: Harald Freudenberger freude@linux.ibm.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/s390/crypto/zcrypt_api.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 10206e4498d07..52eaf51c9bb64 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -1438,6 +1438,8 @@ static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg) if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) { ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc); return rc; @@ -1481,6 +1483,8 @@ static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg) if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) { ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc); return rc; @@ -1524,6 +1528,8 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg) if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n", rc, xcRB.status); @@ -1568,6 +1574,8 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg) if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc); if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) @@ -1744,6 +1752,8 @@ static long trans_modexpo32(struct ap_perms *perms, struct file *filp, if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) return rc; return put_user(mex64.outputdatalength, @@ -1795,6 +1805,8 @@ static long trans_modexpo_crt32(struct ap_perms *perms, struct file *filp, if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; if (rc) return rc; return put_user(crt64.outputdatalength, @@ -1865,6 +1877,8 @@ static long trans_xcRB32(struct ap_perms *perms, struct file *filp, if (rc == -EAGAIN) tr.again_counter++; } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX); + if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX) + rc = -EIO; xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; xcRB32.reply_data_length = xcRB64.reply_data_length; xcRB32.status = xcRB64.status;
From: Dom Cobley popcornmix@gmail.com
[ Upstream commit 902dc5c19a8fecd3113dd41cc601b34557bdede9 ]
The hdmi reset got moved to a later point in the commit 9045e91a476b ("drm/vc4: hdmi: Add reset callback").
However, the reset now occurs after vc4_hdmi_cec_init and so tramples the setup of registers like HDMI_CEC_CNTRL_1
This only affects pi0-3 as on pi4 the cec registers are in a separate block
Fixes: 9045e91a476b ("drm/vc4: hdmi: Add reset callback") Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Dom Cobley popcornmix@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-3-maxime... (cherry picked from commit 7155334f15f360f5c98391c5c7e12af4c13395c4) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 2013f83ef50b6..ea50ecf985d1c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -660,9 +660,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) return; }
- if (vc4_hdmi->variant->reset) - vc4_hdmi->variant->reset(vc4_hdmi); - if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
@@ -1743,6 +1740,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->disable_wifi_frequencies = of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
+ if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); + pm_runtime_enable(dev);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
From: Dom Cobley popcornmix@gmail.com
[ Upstream commit 4a59ed546c0511f01a4bf6b886fe34b6cce2513f ]
The code prior to 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") was relying on the fact that the register offset was incremented by 4 for each readl call. That worked since the register width is 4 bytes.
However, since that commit the HDMI_READ macro is now taking an enum, and the offset doesn't increment by 4 but 1 now. Divide the index by 4 to fix this.
Fixes: 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Dom Cobley popcornmix@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-4-maxime... (cherry picked from commit e9c9481f373eb7344f9e973eb28fc6e9d0f46485) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ea50ecf985d1c..3d473638dbe18 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1312,13 +1312,20 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) { + struct drm_device *dev = vc4_hdmi->connector.dev; struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; unsigned int i;
msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); + + if (msg->len > 16) { + drm_err(dev, "Attempting to read too much data (%d)\n", msg->len); + return; + } + for (i = 0; i < msg->len; i += 4) { - u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i); + u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + (i >> 2));
msg->msg[i] = val & 0xff; msg->msg[i + 1] = (val >> 8) & 0xff; @@ -1411,11 +1418,17 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *dev = vc4_hdmi->connector.dev; u32 val; unsigned int i;
+ if (msg->len > 16) { + drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); + return -ENOMEM; + } + for (i = 0; i < msg->len; i += 4) - HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i, + HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2), (msg->msg[i]) | (msg->msg[i + 1] << 8) | (msg->msg[i + 2] << 16) |
From: Dom Cobley popcornmix@gmail.com
[ Upstream commit 5a32bfd563e8b5766e57475c2c81c769e5a13f5d ]
The commit 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") forgot one CEC register, and made a copy and paste mistake for another one. Fix those mistakes.
Fixes: 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Dom Cobley popcornmix@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-5-maxime... (cherry picked from commit 303085bc11bb7aebeeaaf09213f99fd7aa539a34) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index 96d764ebfe675..5379c36f09923 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -29,6 +29,7 @@ enum vc4_hdmi_field { HDMI_CEC_CPU_MASK_SET, HDMI_CEC_CPU_MASK_STATUS, HDMI_CEC_CPU_STATUS, + HDMI_CEC_CPU_SET,
/* * Transmit data, first byte is low byte of the 32-bit reg. @@ -196,9 +197,10 @@ static const struct vc4_hdmi_register __maybe_unused vc4_hdmi_fields[] = { VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0), VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4), VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340), + VC4_HDMI_REG(HDMI_CEC_CPU_SET, 0x0344), VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348), VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c), - VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c), + VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x0350), VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354), VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400), };
From: Dom Cobley popcornmix@gmail.com
[ Upstream commit 4d8602b8ec16f5721a4d1339c610a81f95df1856 ]
Currently we call cec_phys_addr_invalidate on a hotplug deassert. That may be due to a TV power cycling, or an AVR being switched on (and switching edid).
This makes CEC unusable since our controller wouldn't have a physical address anymore.
Set it back up again on the hotplug assert.
Fixes: 15b4511a4af6 ("drm/vc4: add HDMI CEC support") Signed-off-by: Dom Cobley popcornmix@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Dave Stevenson dave.stevenson@raspberrypi.com Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-6-maxime... (cherry picked from commit b06eecb5158e5f3eb47b9d05aea8c259985cc5f7) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 3d473638dbe18..a9a6552bdae93 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -123,20 +123,32 @@ static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + bool connected = false;
if (vc4_hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ vc4_hdmi->hpd_active_low) - return connector_status_connected; - cec_phys_addr_invalidate(vc4_hdmi->cec_adap); - return connector_status_disconnected; + connected = true; + } else if (drm_probe_ddc(vc4_hdmi->ddc)) { + connected = true; + } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { + connected = true; }
- if (drm_probe_ddc(vc4_hdmi->ddc)) - return connector_status_connected; + if (connected) { + if (connector->status != connector_status_connected) { + struct edid *edid = drm_get_edid(connector, vc4_hdmi->ddc); + + if (edid) { + cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); + vc4_hdmi->encoder.hdmi_monitor = drm_detect_hdmi_monitor(edid); + kfree(edid); + } + }
- if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) return connector_status_connected; + } + cec_phys_addr_invalidate(vc4_hdmi->cec_adap); return connector_status_disconnected; }
From: Maxime Ripard maxime@cerno.tech
[ Upstream commit 163a3ef681e5e9d5df558e855d86ccd4708d6200 ]
The CEC clock divider needs to output a frequency of 40kHz from the HSM rate on the BCM2835. The driver used to have a fixed frequency for it, but that changed for the BCM2711 and we now need to compute it dynamically to maintain the proper rate.
Fixes: cd4cb49dc5bb ("drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate") Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-7-maxime... (cherry picked from commit f1ceb9d10043683b89e5e5e5848fb4e855295762) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a9a6552bdae93..eff9014750e2d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1467,6 +1467,7 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { struct cec_connector_info conn_info; struct platform_device *pdev = vc4_hdmi->pdev; + u16 clk_cnt; u32 value; int ret;
@@ -1492,8 +1493,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) * divider: the hsm_clock rate and this divider setting will * give a 40 kHz CEC clock. */ + clk_cnt = clk_get_rate(vc4_hdmi->hsm_clock) / CEC_CLOCK_FREQ; value |= VC4_HDMI_CEC_ADDR_MASK | - (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); + (clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); HDMI_WRITE(HDMI_CEC_CNTRL_1, value); ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), vc4_cec_irq_handler,
From: Maxime Ripard maxime@cerno.tech
[ Upstream commit 47fa9a80270e20a0c4ddaffca1f144d22cc59620 ]
As part of the enable sequence we might change the HSM clock rate if the pixel rate is different than the one we were already dealing with.
On the BCM2835 however, the CEC clock derives from the HSM clock so any rate change will need to be reflected in the CEC clock divider to output 40kHz.
Fixes: cd4cb49dc5bb ("drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate") Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Tested-by: Hans Verkuil hverkuil-cisco@xs4all.nl Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-8-maxime... (cherry picked from commit a9dd0b9a5c3e11c79e6ff9c7fdf07c471732dcb6) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index eff9014750e2d..a9f494590c578 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -119,6 +119,27 @@ static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); }
+#ifdef CONFIG_DRM_VC4_HDMI_CEC +static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) +{ + u16 clk_cnt; + u32 value; + + value = HDMI_READ(HDMI_CEC_CNTRL_1); + value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; + + /* + * Set the clock divider: the hsm_clock rate and this divider + * setting will give a 40 kHz CEC clock. + */ + clk_cnt = clk_get_rate(vc4_hdmi->hsm_clock) / CEC_CLOCK_FREQ; + value |= clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT; + HDMI_WRITE(HDMI_CEC_CNTRL_1, value); +} +#else +static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} +#endif + static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { @@ -651,6 +672,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) return; }
+ vc4_hdmi_cec_update_clk_div(vc4_hdmi); + /* * FIXME: When the pixel freq is 594MHz (4k60), this needs to be setup * at 300MHz. @@ -1467,7 +1490,6 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { struct cec_connector_info conn_info; struct platform_device *pdev = vc4_hdmi->pdev; - u16 clk_cnt; u32 value; int ret;
@@ -1486,17 +1508,14 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); + value = HDMI_READ(HDMI_CEC_CNTRL_1); - value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; - /* - * Set the logical address to Unregistered and set the clock - * divider: the hsm_clock rate and this divider setting will - * give a 40 kHz CEC clock. - */ - clk_cnt = clk_get_rate(vc4_hdmi->hsm_clock) / CEC_CLOCK_FREQ; - value |= VC4_HDMI_CEC_ADDR_MASK | - (clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); + /* Set the logical address to Unregistered */ + value |= VC4_HDMI_CEC_ADDR_MASK; HDMI_WRITE(HDMI_CEC_CNTRL_1, value); + + vc4_hdmi_cec_update_clk_div(vc4_hdmi); + ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), vc4_cec_irq_handler, vc4_cec_irq_handler_thread, 0,
From: Qinglang Miao miaoqinglang@huawei.com
[ Upstream commit de4248b744e8394f239c0dd0af34088399d27d94 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in a reference leak here.
A new function pm_runtime_resume_and_get is introduced in [0] to keep usage counter balanced. So We fix the reference leak by replacing it with new function.
[0] commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter")
Fixes: 50de2e9ebbc0 ("drm/lima: enable runtime pm") Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Qinglang Miao miaoqinglang@huawei.com Signed-off-by: Qiang Yu yuq825@gmail.com Link: https://patchwork.freedesktop.org/patch/msgid/20201127094438.121003-1-miaoqi... (cherry picked from commit de499781c97d96703af8a32d2b5e37fdb5b51568) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/lima/lima_sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index 63b4c5643f9cd..5cc20b403a252 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -201,7 +201,7 @@ static int lima_pm_busy(struct lima_device *ldev) int ret;
/* resume GPU if it has been suspended by runtime PM */ - ret = pm_runtime_get_sync(ldev->dev); + ret = pm_runtime_resume_and_get(ldev->dev); if (ret < 0) return ret;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 8d0cb8860a4551fa5998acd67ca6d9ce3015b1e2 ]
If devm_request_mem_region() fails this code currently returns success but it should return -EBUSY.
Fixes: 6076a9711dc5 ("drm/virtio: implement blob resources: probe for host visible region") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: http://patchwork.freedesktop.org/patch/msgid/YBpy0GS7GfmafMfe@mwanda Signed-off-by: Gerd Hoffmann kraxel@redhat.com (cherry picked from commit eb988a2ee500d3297a1de048dc3c77b6c354e650) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/virtio/virtgpu_kms.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index b4ec479c32cda..b375394193be8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -163,6 +163,7 @@ int virtio_gpu_init(struct drm_device *dev) vgdev->host_visible_region.len, dev_name(&vgdev->vdev->dev))) { DRM_ERROR("Could not reserve host visible region\n"); + ret = -EBUSY; goto err_vqs; }
From: Imre Deak imre.deak@intel.com
[ Upstream commit 4b8878eefa0a3b65e2e016db49014ea66fb9fd45 ]
Caching EDIDs for physical ports prevents updating the EDID if a port gets reconnected via a Connection Status Notification message, fix this.
Fixes: db1a07956968 ("drm/dp_mst: Handle SST-only branch device case") Cc: Wayne Lin Wayne.Lin@amd.com Cc: Lyude Paul lyude@redhat.com Signed-off-by: Imre Deak imre.deak@intel.com Reviewed-by: Lyude Paul lyude@redhat.com Link: https://patchwork.freedesktop.org/patch/msgid/20210201120145.350258-2-imre.d... (cherry picked from commit 468091531c2e5c49f55d8c6f1d036ce997d24e13) Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_dp_mst_topology.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b11c0522a4410..405501c74e400 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2302,7 +2302,8 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb, }
if (port->pdt != DP_PEER_DEVICE_NONE && - drm_dp_mst_is_end_device(port->pdt, port->mcs)) { + drm_dp_mst_is_end_device(port->pdt, port->mcs) && + port->port_num >= DP_MST_LOGICAL_PORT_0) { port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc); drm_connector_set_tile_property(port->connector);
From: Jan Henrik Weinstock jan.weinstock@rwth-aachen.de
[ Upstream commit e145f5565dc48ccaf4cb50b7cfc48777bed8c100 ]
Ensure cooldown period tolerance of 1% is actually accounted for.
Fixes: ca3bff70ab32 ("hwrng: timeriomem - Improve performance...") Signed-off-by: Jan Henrik Weinstock jan.weinstock@rwth-aachen.de Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/char/hw_random/timeriomem-rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index e262445fed5f5..f35f0f31f52ad 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -69,7 +69,7 @@ static int timeriomem_rng_read(struct hwrng *hwrng, void *data, */ if (retval > 0) usleep_range(period_us, - period_us + min(1, period_us / 100)); + period_us + max(1, period_us / 100));
*(u32 *)data = readl(priv->io_base); retval += sizeof(u32);
From: Daniele Alessandrelli daniele.alessandrelli@intel.com
[ Upstream commit a53ab94eb6850c3657392e2d2ce9b38c387a2633 ]
The length ('len' parameter) passed to crypto_ecdh_decode_key() is never checked against the length encoded in the passed buffer ('buf' parameter). This could lead to an out-of-bounds access when the passed length is less than the encoded length.
Add a check to prevent that.
Fixes: 3c4b23901a0c7 ("crypto: ecdh - Add ECDH software support") Signed-off-by: Daniele Alessandrelli daniele.alessandrelli@intel.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- crypto/ecdh_helper.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/crypto/ecdh_helper.c b/crypto/ecdh_helper.c index 66fcb2ea81544..fca63b559f655 100644 --- a/crypto/ecdh_helper.c +++ b/crypto/ecdh_helper.c @@ -67,6 +67,9 @@ int crypto_ecdh_decode_key(const char *buf, unsigned int len, if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH) return -EINVAL;
+ if (unlikely(len < secret.len)) + return -EINVAL; + ptr = ecdh_unpack_data(¶ms->curve_id, ptr, sizeof(params->curve_id)); ptr = ecdh_unpack_data(¶ms->key_size, ptr, sizeof(params->key_size)); if (secret.len != crypto_ecdh_key_len(params))
From: Hao Xu haoxu@linux.alibaba.com
[ Upstream commit ed670c3f90a67d9e16ab6d8893be6f072d79cd4c ]
Abaci reported follow issue:
[ 30.615891] ====================================================== [ 30.616648] WARNING: possible circular locking dependency detected [ 30.617423] 5.11.0-rc3-next-20210115 #1 Not tainted [ 30.618035] ------------------------------------------------------ [ 30.618914] a.out/1128 is trying to acquire lock: [ 30.619520] ffff88810b063868 (&ep->mtx){+.+.}-{3:3}, at: __ep_eventpoll_poll+0x9f/0x220 [ 30.620505] [ 30.620505] but task is already holding lock: [ 30.621218] ffff88810e952be8 (&ctx->uring_lock){+.+.}-{3:3}, at: __x64_sys_io_uring_enter+0x3f0/0x5b0 [ 30.622349] [ 30.622349] which lock already depends on the new lock. [ 30.622349] [ 30.623289] [ 30.623289] the existing dependency chain (in reverse order) is: [ 30.624243] [ 30.624243] -> #1 (&ctx->uring_lock){+.+.}-{3:3}: [ 30.625263] lock_acquire+0x2c7/0x390 [ 30.625868] __mutex_lock+0xae/0x9f0 [ 30.626451] io_cqring_overflow_flush.part.95+0x6d/0x70 [ 30.627278] io_uring_poll+0xcb/0xd0 [ 30.627890] ep_item_poll.isra.14+0x4e/0x90 [ 30.628531] do_epoll_ctl+0xb7e/0x1120 [ 30.629122] __x64_sys_epoll_ctl+0x70/0xb0 [ 30.629770] do_syscall_64+0x2d/0x40 [ 30.630332] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 30.631187] [ 30.631187] -> #0 (&ep->mtx){+.+.}-{3:3}: [ 30.631985] check_prevs_add+0x226/0xb00 [ 30.632584] __lock_acquire+0x1237/0x13a0 [ 30.633207] lock_acquire+0x2c7/0x390 [ 30.633740] __mutex_lock+0xae/0x9f0 [ 30.634258] __ep_eventpoll_poll+0x9f/0x220 [ 30.634879] __io_arm_poll_handler+0xbf/0x220 [ 30.635462] io_issue_sqe+0xa6b/0x13e0 [ 30.635982] __io_queue_sqe+0x10b/0x550 [ 30.636648] io_queue_sqe+0x235/0x470 [ 30.637281] io_submit_sqes+0xcce/0xf10 [ 30.637839] __x64_sys_io_uring_enter+0x3fb/0x5b0 [ 30.638465] do_syscall_64+0x2d/0x40 [ 30.638999] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 30.639643] [ 30.639643] other info that might help us debug this: [ 30.639643] [ 30.640618] Possible unsafe locking scenario: [ 30.640618] [ 30.641402] CPU0 CPU1 [ 30.641938] ---- ---- [ 30.642664] lock(&ctx->uring_lock); [ 30.643425] lock(&ep->mtx); [ 30.644498] lock(&ctx->uring_lock); [ 30.645668] lock(&ep->mtx); [ 30.646321] [ 30.646321] *** DEADLOCK *** [ 30.646321] [ 30.647642] 1 lock held by a.out/1128: [ 30.648424] #0: ffff88810e952be8 (&ctx->uring_lock){+.+.}-{3:3}, at: __x64_sys_io_uring_enter+0x3f0/0x5b0 [ 30.649954] [ 30.649954] stack backtrace: [ 30.650592] CPU: 1 PID: 1128 Comm: a.out Not tainted 5.11.0-rc3-next-20210115 #1 [ 30.651554] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 [ 30.652290] Call Trace: [ 30.652688] dump_stack+0xac/0xe3 [ 30.653164] check_noncircular+0x11e/0x130 [ 30.653747] ? check_prevs_add+0x226/0xb00 [ 30.654303] check_prevs_add+0x226/0xb00 [ 30.654845] ? add_lock_to_list.constprop.49+0xac/0x1d0 [ 30.655564] __lock_acquire+0x1237/0x13a0 [ 30.656262] lock_acquire+0x2c7/0x390 [ 30.656788] ? __ep_eventpoll_poll+0x9f/0x220 [ 30.657379] ? __io_queue_proc.isra.88+0x180/0x180 [ 30.658014] __mutex_lock+0xae/0x9f0 [ 30.658524] ? __ep_eventpoll_poll+0x9f/0x220 [ 30.659112] ? mark_held_locks+0x5a/0x80 [ 30.659648] ? __ep_eventpoll_poll+0x9f/0x220 [ 30.660229] ? _raw_spin_unlock_irqrestore+0x2d/0x40 [ 30.660885] ? trace_hardirqs_on+0x46/0x110 [ 30.661471] ? __io_queue_proc.isra.88+0x180/0x180 [ 30.662102] ? __ep_eventpoll_poll+0x9f/0x220 [ 30.662696] __ep_eventpoll_poll+0x9f/0x220 [ 30.663273] ? __ep_eventpoll_poll+0x220/0x220 [ 30.663875] __io_arm_poll_handler+0xbf/0x220 [ 30.664463] io_issue_sqe+0xa6b/0x13e0 [ 30.664984] ? __lock_acquire+0x782/0x13a0 [ 30.665544] ? __io_queue_proc.isra.88+0x180/0x180 [ 30.666170] ? __io_queue_sqe+0x10b/0x550 [ 30.666725] __io_queue_sqe+0x10b/0x550 [ 30.667252] ? __fget_files+0x131/0x260 [ 30.667791] ? io_req_prep+0xd8/0x1090 [ 30.668316] ? io_queue_sqe+0x235/0x470 [ 30.668868] io_queue_sqe+0x235/0x470 [ 30.669398] io_submit_sqes+0xcce/0xf10 [ 30.669931] ? xa_load+0xe4/0x1c0 [ 30.670425] __x64_sys_io_uring_enter+0x3fb/0x5b0 [ 30.671051] ? lockdep_hardirqs_on_prepare+0xde/0x180 [ 30.671719] ? syscall_enter_from_user_mode+0x2b/0x80 [ 30.672380] do_syscall_64+0x2d/0x40 [ 30.672901] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 30.673503] RIP: 0033:0x7fd89c813239 [ 30.673962] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 3d 01 f0 ff ff 73 01 c3 48 8b 0d 27 ec 2c 00 f7 d8 64 89 01 48 [ 30.675920] RSP: 002b:00007ffc65a7c628 EFLAGS: 00000217 ORIG_RAX: 00000000000001aa [ 30.676791] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fd89c813239 [ 30.677594] RDX: 0000000000000000 RSI: 0000000000000014 RDI: 0000000000000003 [ 30.678678] RBP: 00007ffc65a7c720 R08: 0000000000000000 R09: 0000000003000000 [ 30.679492] R10: 0000000000000000 R11: 0000000000000217 R12: 0000000000400ff0 [ 30.680282] R13: 00007ffc65a7c840 R14: 0000000000000000 R15: 0000000000000000
This might happen if we do epoll_wait on a uring fd while reading/writing the former epoll fd in a sqe in the former uring instance. So let's don't flush cqring overflow list, just do a simple check.
Reported-by: Abaci abaci@linux.alibaba.com Fixes: 6c503150ae33 ("io_uring: patch up IOPOLL overflow_flush sync") Signed-off-by: Hao Xu haoxu@linux.alibaba.com Reviewed-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/io_uring.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c index 931671082e615..4d0ede0418571 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8723,8 +8723,21 @@ static __poll_t io_uring_poll(struct file *file, poll_table *wait) smp_rmb(); if (!io_sqring_full(ctx)) mask |= EPOLLOUT | EPOLLWRNORM; - io_cqring_overflow_flush(ctx, false, NULL, NULL); - if (io_cqring_events(ctx)) + + /* + * Don't flush cqring overflow list here, just do a simple check. + * Otherwise there could possible be ABBA deadlock: + * CPU0 CPU1 + * ---- ---- + * lock(&ctx->uring_lock); + * lock(&ep->mtx); + * lock(&ctx->uring_lock); + * lock(&ep->mtx); + * + * Users may get EPOLLIN meanwhile seeing nothing in cqring, this + * pushs them to do the flush. + */ + if (io_cqring_events(ctx) || test_bit(0, &ctx->cq_check_overflow)) mask |= EPOLLIN | EPOLLRDNORM;
return mask;
From: Sagi Grimberg sagi@grimberg.me
[ Upstream commit fda871c0ba5d2eed2cd1c881573168129da70058 ]
When a host sends multiple h2cdata PDUs for a single command, we should verify the data digest calculation per PDU and not per command.
Fixes: 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver") Reported-by: Narayan Ayalasomayajula Narayan.Ayalasomayajula@wdc.com Tested-by: Narayan Ayalasomayajula Narayan.Ayalasomayajula@wdc.com Signed-off-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/tcp.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index aacf06f0b4312..577ce7d403ae9 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -379,7 +379,7 @@ err: return NVME_SC_INTERNAL; }
-static void nvmet_tcp_ddgst(struct ahash_request *hash, +static void nvmet_tcp_send_ddgst(struct ahash_request *hash, struct nvmet_tcp_cmd *cmd) { ahash_request_set_crypt(hash, cmd->req.sg, @@ -387,6 +387,23 @@ static void nvmet_tcp_ddgst(struct ahash_request *hash, crypto_ahash_digest(hash); }
+static void nvmet_tcp_recv_ddgst(struct ahash_request *hash, + struct nvmet_tcp_cmd *cmd) +{ + struct scatterlist sg; + struct kvec *iov; + int i; + + crypto_ahash_init(hash); + for (i = 0, iov = cmd->iov; i < cmd->nr_mapped; i++, iov++) { + sg_init_one(&sg, iov->iov_base, iov->iov_len); + ahash_request_set_crypt(hash, &sg, NULL, iov->iov_len); + crypto_ahash_update(hash); + } + ahash_request_set_crypt(hash, NULL, (void *)&cmd->exp_ddgst, 0); + crypto_ahash_final(hash); +} + static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd) { struct nvme_tcp_data_pdu *pdu = cmd->data_pdu; @@ -411,7 +428,7 @@ static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
if (queue->data_digest) { pdu->hdr.flags |= NVME_TCP_F_DDGST; - nvmet_tcp_ddgst(queue->snd_hash, cmd); + nvmet_tcp_send_ddgst(queue->snd_hash, cmd); }
if (cmd->queue->hdr_digest) { @@ -1060,7 +1077,7 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd) { struct nvmet_tcp_queue *queue = cmd->queue;
- nvmet_tcp_ddgst(queue->rcv_hash, cmd); + nvmet_tcp_recv_ddgst(queue->rcv_hash, cmd); queue->offset = 0; queue->left = NVME_TCP_DIGEST_LENGTH; queue->rcv_state = NVMET_TCP_RECV_DDGST; @@ -1081,14 +1098,14 @@ static int nvmet_tcp_try_recv_data(struct nvmet_tcp_queue *queue) cmd->rbytes_done += ret; }
+ if (queue->data_digest) { + nvmet_tcp_prep_recv_ddgst(cmd); + return 0; + } nvmet_tcp_unmap_pdu_iovec(cmd);
if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED) && cmd->rbytes_done == cmd->req.transfer_len) { - if (queue->data_digest) { - nvmet_tcp_prep_recv_ddgst(cmd); - return 0; - } cmd->req.execute(&cmd->req); }
From: Sagi Grimberg sagi@grimberg.me
[ Upstream commit 0fbcfb089a3f2f2a731d01f0aec8f7697a849c28 ]
When we accept a TCP connection and allocate an nvmet-tcp queue we should make sure not to fully establish it or reference it as the connection may be already closing, which triggers queue release work, which does not fence against queue establishment.
In order to address such a race, we make sure to check the sk_state and contain the queue reference to be done underneath the sk_callback_lock such that the queue release work correctly fences against it.
Fixes: 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver") Reported-by: Elad Grupi elad.grupi@dell.com Signed-off-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/tcp.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 577ce7d403ae9..8b0485ada315b 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1485,17 +1485,27 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue) if (inet->rcv_tos > 0) ip_sock_set_tos(sock->sk, inet->rcv_tos);
+ ret = 0; write_lock_bh(&sock->sk->sk_callback_lock); - sock->sk->sk_user_data = queue; - queue->data_ready = sock->sk->sk_data_ready; - sock->sk->sk_data_ready = nvmet_tcp_data_ready; - queue->state_change = sock->sk->sk_state_change; - sock->sk->sk_state_change = nvmet_tcp_state_change; - queue->write_space = sock->sk->sk_write_space; - sock->sk->sk_write_space = nvmet_tcp_write_space; + if (sock->sk->sk_state != TCP_ESTABLISHED) { + /* + * If the socket is already closing, don't even start + * consuming it + */ + ret = -ENOTCONN; + } else { + sock->sk->sk_user_data = queue; + queue->data_ready = sock->sk->sk_data_ready; + sock->sk->sk_data_ready = nvmet_tcp_data_ready; + queue->state_change = sock->sk->sk_state_change; + sock->sk->sk_state_change = nvmet_tcp_state_change; + queue->write_space = sock->sk->sk_write_space; + sock->sk->sk_write_space = nvmet_tcp_write_space; + queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work); + } write_unlock_bh(&sock->sk->sk_callback_lock);
- return 0; + return ret; }
static int nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, @@ -1543,8 +1553,6 @@ static int nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, if (ret) goto out_destroy_sq;
- queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work); - return 0; out_destroy_sq: mutex_lock(&nvmet_tcp_queue_mutex);
From: Keith Busch kbusch@kernel.org
[ Upstream commit 73a1a2298f3e9df24cea7a9aab412ba9470f6159 ]
The bio based drivers only require the request_queue's nr_zones is set, so set this field in the head if the namespace path is zoned.
Fixes: 240e6ee272c07 ("nvme: support for zoned namespaces") Reported-by: Minwoo Im minwoo.im.dev@gmail.com Cc: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Keith Busch kbusch@kernel.org Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/multipath.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 282b7a4ea9a9a..fdfc18a222cc3 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -677,6 +677,10 @@ void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id) if (blk_queue_stable_writes(ns->queue) && ns->head->disk) blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->head->disk->queue); +#ifdef CONFIG_BLK_DEV_ZONED + if (blk_queue_is_zoned(ns->queue) && ns->head->disk) + ns->head->disk->queue->nr_zones = ns->queue->nr_zones; +#endif }
void nvme_mpath_remove_disk(struct nvme_ns_head *head)
From: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com
[ Upstream commit 3c7b224f1956ed232b24ed2eb2c54e4476c6acb2 ]
We remove the extra local variable struct nvmet_ns in nvmet_execute_identify_ns() since req already has ns member that can be reused, this also eliminates the explicit call to nvmet_put_namespace() which is already present in the request completion path.
Signed-off-by: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com Reviewed-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/admin-cmd.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index dc1ea468b182b..de6aaa4c96e53 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -469,7 +469,6 @@ out: static void nvmet_execute_identify_ns(struct nvmet_req *req) { struct nvmet_ctrl *ctrl = req->sq->ctrl; - struct nvmet_ns *ns; struct nvme_id_ns *id; u16 status = 0;
@@ -486,20 +485,21 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req) }
/* return an all zeroed buffer if we can't find an active namespace */ - ns = nvmet_find_namespace(ctrl, req->cmd->identify.nsid); - if (!ns) { + req->ns = nvmet_find_namespace(ctrl, req->cmd->identify.nsid); + if (!req->ns) { status = NVME_SC_INVALID_NS; goto done; }
- nvmet_ns_revalidate(ns); + nvmet_ns_revalidate(req->ns);
/* * nuse = ncap = nsze isn't always true, but we have no way to find * that out from the underlying device. */ - id->ncap = id->nsze = cpu_to_le64(ns->size >> ns->blksize_shift); - switch (req->port->ana_state[ns->anagrpid]) { + id->ncap = id->nsze = + cpu_to_le64(req->ns->size >> req->ns->blksize_shift); + switch (req->port->ana_state[req->ns->anagrpid]) { case NVME_ANA_INACCESSIBLE: case NVME_ANA_PERSISTENT_LOSS: break; @@ -508,8 +508,8 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req) break; }
- if (ns->bdev) - nvmet_bdev_set_limits(ns->bdev, id); + if (req->ns->bdev) + nvmet_bdev_set_limits(req->ns->bdev, id);
/* * We just provide a single LBA format that matches what the @@ -523,25 +523,24 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req) * controllers, but also with any other user of the block device. */ id->nmic = (1 << 0); - id->anagrpid = cpu_to_le32(ns->anagrpid); + id->anagrpid = cpu_to_le32(req->ns->anagrpid);
- memcpy(&id->nguid, &ns->nguid, sizeof(id->nguid)); + memcpy(&id->nguid, &req->ns->nguid, sizeof(id->nguid));
- id->lbaf[0].ds = ns->blksize_shift; + id->lbaf[0].ds = req->ns->blksize_shift;
- if (ctrl->pi_support && nvmet_ns_has_pi(ns)) { + if (ctrl->pi_support && nvmet_ns_has_pi(req->ns)) { id->dpc = NVME_NS_DPC_PI_FIRST | NVME_NS_DPC_PI_LAST | NVME_NS_DPC_PI_TYPE1 | NVME_NS_DPC_PI_TYPE2 | NVME_NS_DPC_PI_TYPE3; id->mc = NVME_MC_EXTENDED_LBA; - id->dps = ns->pi_type; + id->dps = req->ns->pi_type; id->flbas = NVME_NS_FLBAS_META_EXT; - id->lbaf[0].ms = cpu_to_le16(ns->metadata_size); + id->lbaf[0].ms = cpu_to_le16(req->ns->metadata_size); }
- if (ns->readonly) + if (req->ns->readonly) id->nsattr |= (1 << 0); - nvmet_put_namespace(ns); done: if (!status) status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
From: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com
[ Upstream commit 40244ad36bcfb796a6bb9e95bdcbf8ddf3134509 ]
For unallocated namespace in nvmet_execute_identify_ns() don't set the status to NVME_SC_INVALID_NS, set it to zero.
Fixes: bffcd507780e ("nvmet: set right status on error in id-ns handler") Signed-off-by: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/target/admin-cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c index de6aaa4c96e53..1827d8d8f3b00 100644 --- a/drivers/nvme/target/admin-cmd.c +++ b/drivers/nvme/target/admin-cmd.c @@ -487,7 +487,7 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req) /* return an all zeroed buffer if we can't find an active namespace */ req->ns = nvmet_find_namespace(ctrl, req->cmd->identify.nsid); if (!req->ns) { - status = NVME_SC_INVALID_NS; + status = 0; goto done; }
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit bd8036eb15263a720b8f846861c180b27d050a09 ]
The UpExtreme board supports the community key and was missed in previous contributions. Add it to make sure the open firmware is picked by default without needing a symlink on the target.
Fixes: 46207ca24545 ('ASoC: SOF: pci: change the default firmware path when the community key is used') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Bard Liao bard.liao@intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Link: https://lore.kernel.org/r/20210208231853.58761-1-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/sof-pci-dev.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 215711ac74509..9adf50b20a735 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -65,6 +65,13 @@ static const struct dmi_system_id community_key_platforms[] = { DMI_MATCH(DMI_BOARD_NAME, "UP-APL01"), } }, + { + .ident = "Up Extreme", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_BOARD_NAME, "UP-WHL01"), + } + }, { .ident = "Google Chromebooks", .matches = {
From: Lakshmi Ramasubramanian nramas@linux.microsoft.com
[ Upstream commit 6d14c6517885fa68524238787420511b87d671df ]
IMA allocates kernel virtual memory to carry forward the measurement list, from the current kernel to the next kernel on kexec system call, in ima_add_kexec_buffer() function. In error code paths this memory is not freed resulting in memory leak.
Free the memory allocated for the IMA measurement list in the error code paths in ima_add_kexec_buffer() function.
Signed-off-by: Lakshmi Ramasubramanian nramas@linux.microsoft.com Suggested-by: Tyler Hicks tyhicks@linux.microsoft.com Fixes: 7b8589cc29e7 ("ima: on soft reboot, save the measurement list") Signed-off-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- security/integrity/ima/ima_kexec.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 121de3e04af23..206ddcaa5c67a 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -119,6 +119,7 @@ void ima_add_kexec_buffer(struct kimage *image) ret = kexec_add_buffer(&kbuf); if (ret) { pr_err("Error passing over kexec measurement buffer.\n"); + vfree(kexec_buffer); return; }
From: Lakshmi Ramasubramanian nramas@linux.microsoft.com
[ Upstream commit f31e3386a4e92ba6eda7328cb508462956c94c64 ]
IMA allocates kernel virtual memory to carry forward the measurement list, from the current kernel to the next kernel on kexec system call, in ima_add_kexec_buffer() function. This buffer is not freed before completing the kexec system call resulting in memory leak.
Add ima_buffer field in "struct kimage" to store the virtual address of the buffer allocated for the IMA measurement list. Free the memory allocated for the IMA measurement list in kimage_file_post_load_cleanup() function.
Signed-off-by: Lakshmi Ramasubramanian nramas@linux.microsoft.com Suggested-by: Tyler Hicks tyhicks@linux.microsoft.com Reviewed-by: Thiago Jung Bauermann bauerman@linux.ibm.com Reviewed-by: Tyler Hicks tyhicks@linux.microsoft.com Fixes: 7b8589cc29e7 ("ima: on soft reboot, save the measurement list") Signed-off-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/kexec.h | 5 +++++ kernel/kexec_file.c | 5 +++++ security/integrity/ima/ima_kexec.c | 2 ++ 3 files changed, 12 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 9e93bef529680..5f61389f5f361 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -300,6 +300,11 @@ struct kimage { /* Information for loading purgatory */ struct purgatory_info purgatory_info; #endif + +#ifdef CONFIG_IMA_KEXEC + /* Virtual address of IMA measurement buffer for kexec syscall */ + void *ima_buffer; +#endif };
/* kexec interface functions */ diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index b02086d704923..5c3447cf7ad58 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -166,6 +166,11 @@ void kimage_file_post_load_cleanup(struct kimage *image) vfree(pi->sechdrs); pi->sechdrs = NULL;
+#ifdef CONFIG_IMA_KEXEC + vfree(image->ima_buffer); + image->ima_buffer = NULL; +#endif /* CONFIG_IMA_KEXEC */ + /* See if architecture has anything to cleanup post load */ arch_kimage_file_post_load_cleanup(image);
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 206ddcaa5c67a..e29bea3dd4ccd 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -129,6 +129,8 @@ void ima_add_kexec_buffer(struct kimage *image) return; }
+ image->ima_buffer = kexec_buffer; + pr_debug("kexec measurement buffer for the loaded kernel at 0x%lx.\n", kbuf.mem); }
From: Sameer Pujar spujar@nvidia.com
[ Upstream commit 1e30f642cf2939bbdac82ea0dd3071232670b5ab ]
If "clocks = <&xxx>" is specified from the CPU or Codec component device node, the clock is not getting enabled. Thus audio playback or capture fails.
Fix this by populating "simple_dai->clk" field when clocks property is specified from device node as well. Also tidy up by re-organising conditional statements of parsing logic.
Fixes: bb6fc620c2ed ("ASoC: simple-card-utils: add asoc_simple_card_parse_clk()") Cc: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Sameer Pujar spujar@nvidia.com Link: https://lore.kernel.org/r/1612939421-19900-2-git-send-email-spujar@nvidia.co... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/generic/simple-card-utils.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 6cada4c1e283b..ab31045cfc952 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -172,16 +172,15 @@ int asoc_simple_parse_clk(struct device *dev, * or device's module clock. */ clk = devm_get_clk_from_child(dev, node, NULL); - if (!IS_ERR(clk)) { - simple_dai->sysclk = clk_get_rate(clk); + if (IS_ERR(clk)) + clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
+ if (!IS_ERR(clk)) { simple_dai->clk = clk; - } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { + simple_dai->sysclk = clk_get_rate(clk); + } else if (!of_property_read_u32(node, "system-clock-frequency", + &val)) { simple_dai->sysclk = val; - } else { - clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); - if (!IS_ERR(clk)) - simple_dai->sysclk = clk_get_rate(clk); }
if (of_property_read_bool(node, "system-clock-direction-out"))
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 4208c398aae4c2290864ba15c3dab7111f32bec1 ]
The left shift of int 32 bit integer constant 1 is evaluated using 32 bit arithmetic and then assigned to a signed 64 bit integer. In the case where l2nb is 32 or more this can lead to an overflow. Avoid this by shifting the value 1LL instead.
Addresses-Coverity: ("Uninitentional integer overflow") Fixes: b40c2e665cd5 ("fs/jfs: TRIM support for JFS Filesystem") Signed-off-by: Colin Ian King colin.king@canonical.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jfs/jfs_dmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 94b7c1cb5ceb3..7aee156086198 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -1656,7 +1656,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) } else if (rc == -ENOSPC) { /* search for next smaller log2 block */ l2nb = BLKSTOL2(nblocks) - 1; - nblocks = 1 << l2nb; + nblocks = 1LL << l2nb; } else { /* Trim any already allocated blocks */ jfs_error(bmp->db_ipbmap->i_sb, "-EIO\n");
From: Tom Rix trix@redhat.com
[ Upstream commit 19646447ad3a680d2ab08c097585b7d96a66126b ]
clang static analysis reports this problem
fs/jffs2/summary.c:794:31: warning: Use of memory after it is freed c->summary->sum_list_head = temp->u.next; ^~~~~~~~~~~~
In jffs2_sum_write_data(), in a loop summary data is handles a node at a time. When it has written out the node it is removed the summary list, and the node is deleted. In the corner case when a JFFS2_FEATURE_RWCOMPAT_COPY is seen, a call is made to jffs2_sum_disable_collecting(). jffs2_sum_disable_collecting() deletes the whole list which conflicts with the loop's deleting the list by parts.
To preserve the old behavior of stopping the write midway, bail out of the loop after disabling summary collection.
Fixes: 6171586a7ae5 ("[JFFS2] Correct handling of JFFS2_FEATURE_RWCOMPAT_COPY nodes.") Signed-off-by: Tom Rix trix@redhat.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jffs2/summary.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index be7c8a6a57480..4fe64519870f1 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -783,6 +783,8 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n", je16_to_cpu(temp->u.nodetype)); jffs2_sum_disable_collecting(c->summary); + /* The above call removes the list, nothing more to do */ + goto bail_rwcompat; } else { BUG(); /* unknown node in summary information */ } @@ -794,6 +796,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
c->summary->sum_num--; } + bail_rwcompat:
jffs2_sum_reset_collected(c->summary);
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit 11b8ab3836454a2600e396f34731e491b661f9d5 ]
When crypto_shash_digestsize() fails, c->hmac_tfm has not been freed before returning, which leads to memleak.
Fixes: 49525e5eecca5 ("ubifs: Add helper functions for authentication support") Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Reviewed-by: Zhihao Cheng chengzhihao1@huawei.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ubifs/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c index 51a7c8c2c3f0a..e564d5ff87816 100644 --- a/fs/ubifs/auth.c +++ b/fs/ubifs/auth.c @@ -327,7 +327,7 @@ int ubifs_init_authentication(struct ubifs_info *c) ubifs_err(c, "hmac %s is bigger than maximum allowed hmac size (%d > %d)", hmac_name, c->hmac_desc_len, UBIFS_HMAC_ARR_SZ); err = -EINVAL; - goto out_free_hash; + goto out_free_hmac; }
err = crypto_shash_setkey(c->hmac_tfm, ukp->data, ukp->datalen);
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 410b6de702ef84fea6e7abcb6620ef8bfc112fae ]
An earlier commit moved out some functions to not be inlined by gcc, but after some other rework to remove one of those, clang started inlining the other one and ran into the same problem as gcc did before:
fs/ubifs/replay.c:1174:5: error: stack frame size of 1152 bytes in function 'ubifs_replay_journal' [-Werror,-Wframe-larger-than=]
Mark the function as noinline_for_stack to ensure it doesn't happen again.
Fixes: f80df3851246 ("ubifs: use crypto_shash_tfm_digest()") Fixes: eb66eff6636d ("ubifs: replay: Fix high stack usage") Signed-off-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Nathan Chancellor natechancellor@gmail.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ubifs/replay.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 79801c9a5b874..0f8a6a16421b4 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -559,7 +559,9 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud) }
/* authenticate_sleb_hash is split out for stack usage */ -static int authenticate_sleb_hash(struct ubifs_info *c, struct shash_desc *log_hash, u8 *hash) +static int noinline_for_stack +authenticate_sleb_hash(struct ubifs_info *c, + struct shash_desc *log_hash, u8 *hash) { SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
From: Wang ShaoBo bobo.shaobowang@huawei.com
[ Upstream commit 42119dbe571eb419dae99b81dd20fa42f47464e1 ]
Fix to return PTR_ERR() error code from the error handling case instead fo 0 in function alloc_wbufs(), as done elsewhere in this function.
Fixes: 6a98bc4614de ("ubifs: Add authentication nodes to journal") Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Reviewed-by: Sascha Hauer s.hauer@pengutronix.de Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ubifs/super.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 138b9426c6c18..ddb2ca636c93d 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -838,8 +838,10 @@ static int alloc_wbufs(struct ubifs_info *c) c->jheads[i].wbuf.jhead = i; c->jheads[i].grouped = 1; c->jheads[i].log_hash = ubifs_hash_get_desc(c); - if (IS_ERR(c->jheads[i].log_hash)) + if (IS_ERR(c->jheads[i].log_hash)) { + err = PTR_ERR(c->jheads[i].log_hash); goto out; + } }
/*
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit a890caeb2ba40ca183969230e204ab144f258357 ]
Merely enabling CONFIG_COMPILE_TEST should not enable additional code. To fix this, restrict the automatic enabling of IMX_INTMUX to ARCH_MXC, and ask the user in case of compile-testing.
Fixes: 66968d7dfc3f5451 ("irqchip: Add COMPILE_TEST support for IMX_INTMUX") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210208145605.422943-1-geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b147f22a78f48..d7d1a0fab2c1a 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -457,7 +457,8 @@ config IMX_IRQSTEER Support for the i.MX IRQSTEER interrupt multiplexer/remapper.
config IMX_INTMUX - def_bool y if ARCH_MXC || COMPILE_TEST + bool "i.MX INTMUX support" if COMPILE_TEST + default y if ARCH_MXC select IRQ_DOMAIN help Support for the i.MX INTMUX interrupt multiplexer.
From: Sebastian Andrzej Siewior bigeasy@linutronix.de
[ Upstream commit f9d34595ae4feed38856b88769e2ba5af22d2548 ]
send_call_function_single_ipi() may wake an idle CPU without sending an IPI. The woken up CPU will process the SMP-functions in flush_smp_call_function_from_idle(). Any raised softirq from within the SMP-function call will not be processed. Should the CPU have no tasks assigned, then it will go back to idle with pending softirqs and the NOHZ will rightfully complain.
Process pending softirqs on return from flush_smp_call_function_queue().
Fixes: b2a02fc43a1f4 ("smp: Optimize send_call_function_single_ipi()") Reported-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sebastian Andrzej Siewior bigeasy@linutronix.de Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Link: https://lkml.kernel.org/r/20210123201027.3262800-2-bigeasy@linutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/smp.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/kernel/smp.c b/kernel/smp.c index 1b6070bf97bb0..aeb0adfa06063 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -14,6 +14,7 @@ #include <linux/export.h> #include <linux/percpu.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/gfp.h> #include <linux/smp.h> #include <linux/cpu.h> @@ -449,6 +450,9 @@ void flush_smp_call_function_from_idle(void)
local_irq_save(flags); flush_smp_call_function_queue(true); + if (local_softirq_pending()) + do_softirq(); + local_irq_restore(flags); }
From: Nirmoy Das nirmoy.das@amd.com
[ Upstream commit e96b1b2974989c6a25507b527843ede7594efc85 ]
Fixes: 9037246bb2da5 ("drm/amd/display: Add sysfs interface for set/get srm")
Signed-off-by: Nirmoy Das nirmoy.das@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 ++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 961abf1cf040c..6a336cce6b7c6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1131,7 +1131,7 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
#ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->dm.hdcp_workqueue) { - hdcp_destroy(adev->dm.hdcp_workqueue); + hdcp_destroy(&adev->dev->kobj, adev->dm.hdcp_workqueue); adev->dm.hdcp_workqueue = NULL; }
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index c2cd184f0bbd4..79de68ac03f20 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -376,7 +376,7 @@ static void event_cpirq(struct work_struct *work) }
-void hdcp_destroy(struct hdcp_workqueue *hdcp_work) +void hdcp_destroy(struct kobject *kobj, struct hdcp_workqueue *hdcp_work) { int i = 0;
@@ -385,6 +385,7 @@ void hdcp_destroy(struct hdcp_workqueue *hdcp_work) cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork); }
+ sysfs_remove_bin_file(kobj, &hdcp_work[0].attr); kfree(hdcp_work->srm); kfree(hdcp_work->srm_temp); kfree(hdcp_work); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h index 5159b3a5e5b03..09294ff122fea 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h @@ -69,7 +69,7 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
void hdcp_reset_display(struct hdcp_workqueue *work, unsigned int link_index); void hdcp_handle_cpirq(struct hdcp_workqueue *work, unsigned int link_index); -void hdcp_destroy(struct hdcp_workqueue *work); +void hdcp_destroy(struct kobject *kobj, struct hdcp_workqueue *work);
struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct cp_psp *cp_psp, struct dc *dc);
From: Dmitry Torokhov dmitry.torokhov@gmail.com
[ Upstream commit 1e2020aa0da00051d94c4690c023c45d8f3834bd ]
An "if" testing for error condition has accidentally been dropped from the code.
Reported-by: kernel test robot lkp@intel.com Fixes: cd3f609823a5 ("Input: new da7280 haptic driver") Reviewed-by: Roy Im Roy.Im.Opensource@diasemi.com Link: https://lore.kernel.org/r/X9j8lGFgijzHyYZZ@google.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/misc/da7280.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c index 37568b00873d4..2f698a8c1d650 100644 --- a/drivers/input/misc/da7280.c +++ b/drivers/input/misc/da7280.c @@ -863,6 +863,7 @@ static void da7280_parse_properties(struct device *dev, gpi_str3[7] = '0' + i; haptics->gpi_ctl[i].polarity = 0; error = device_property_read_string(dev, gpi_str3, &str); + if (!error) haptics->gpi_ctl[i].polarity = da7280_haptic_of_gpi_pol_str(dev, str); }
From: Dmitry Torokhov dmitry.torokhov@gmail.com
[ Upstream commit 6d2ad82fece2f5adcafe77252614fcf7211dec28 ]
The OF match table is only used when OF is enabled.
Fixes: cd3f609823a5 ("Input: new da7280 haptic driver") Reported-by: kernel test robot lkp@intel.com Acked-by: Roy Im roy.im.opensource@diasemi.com Link: https://lore.kernel.org/r/X9xRLVPt9eBi0CT6@google.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/misc/da7280.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c index 2f698a8c1d650..b08610d6e575e 100644 --- a/drivers/input/misc/da7280.c +++ b/drivers/input/misc/da7280.c @@ -1300,11 +1300,13 @@ static int __maybe_unused da7280_resume(struct device *dev) return retval; }
+#ifdef CONFIG_OF static const struct of_device_id da7280_of_match[] = { { .compatible = "dlg,da7280", }, { } }; MODULE_DEVICE_TABLE(of, da7280_of_match); +#endif
static const struct i2c_device_id da7280_i2c_id[] = { { "da7280", },
From: Dmitry Torokhov dmitry.torokhov@gmail.com
[ Upstream commit f5cace4b93d736cef348211ae0814cabdd26d86a ]
devm_platform_ioremap_resource() depends on CONFIG_HAS_IOMEM, so let's add it to the dependencies when COMPILE_TEST is enabled.
Reported-by: kernel test robot lkp@intel.com Fixes: c8834032ffe2 ("Input: imx_keypad - add COMPILE_TEST support") Link: https://lore.kernel.org/r/X9llpA3w1zlZCHXU@google.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2b321c17054ad..94eab82086b27 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -446,7 +446,7 @@ config KEYBOARD_MPR121
config KEYBOARD_SNVS_PWRKEY tristate "IMX SNVS Power Key Driver" - depends on ARCH_MXC || COMPILE_TEST + depends on ARCH_MXC || (COMPILE_TEST && HAS_IOMEM) depends on OF help This is the snvs powerkey driver for the Freescale i.MX application
From: Eric W. Biederman ebiederm@xmission.com
[ Upstream commit 95ebabde382c371572297915b104e55403674e73 ]
The v3 file capabilities have a uid field that records the filesystem uid of the root user of the user namespace the file capabilities are valid in.
When someone is silly enough to have the same underlying uid as the root uid of multiple nested containers a v3 filesystem capability can be ambiguous.
In the spirit of don't do that then, forbid writing a v3 filesystem capability if it is ambiguous.
Fixes: 8db6c34f1dbc ("Introduce v3 namespaced file capabilities") Reviewed-by: Andrew G. Morgan morgan@kernel.org Reviewed-by: Serge Hallyn serge@hallyn.com Signed-off-by: Eric W. Biederman ebiederm@xmission.com Signed-off-by: Sasha Levin sashal@kernel.org --- security/commoncap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/security/commoncap.c b/security/commoncap.c index 26c1cb725dcbe..78598be45f101 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -500,7 +500,8 @@ int cap_convert_nscap(struct dentry *dentry, const void **ivalue, size_t size) __u32 magic, nsmagic; struct inode *inode = d_backing_inode(dentry); struct user_namespace *task_ns = current_user_ns(), - *fs_ns = inode->i_sb->s_user_ns; + *fs_ns = inode->i_sb->s_user_ns, + *ancestor; kuid_t rootid; size_t newsize;
@@ -523,6 +524,15 @@ int cap_convert_nscap(struct dentry *dentry, const void **ivalue, size_t size) if (nsrootid == -1) return -EINVAL;
+ /* + * Do not allow allow adding a v3 filesystem capability xattr + * if the rootid field is ambiguous. + */ + for (ancestor = task_ns->parent; ancestor; ancestor = ancestor->parent) { + if (from_kuid(ancestor, rootid) == 0) + return -EINVAL; + } + newsize = sizeof(struct vfs_ns_cap_data); nscap = kmalloc(newsize, GFP_ATOMIC); if (!nscap)
From: Zhang Qilong zhangqilong3@huawei.com
[ Upstream commit aa57e77b3d28f0df07149d88c47bc0f3aa77330b ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. We fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Fixes: b209e047bc743 ("HSI: Introduce OMAP SSI driver") Signed-off-by: Zhang Qilong zhangqilong3@huawei.com Signed-off-by: Sebastian Reichel sre@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hsi/controllers/omap_ssi_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 7596dc1646484..44a3f5660c109 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c @@ -424,7 +424,7 @@ static int ssi_hw_init(struct hsi_controller *ssi) struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi); int err;
- err = pm_runtime_get_sync(ssi->device.parent); + err = pm_runtime_resume_and_get(ssi->device.parent); if (err < 0) { dev_err(&ssi->device, "runtime PM failed %d\n", err); return err;
From: Tony Lindgren tony@atomide.com
[ Upstream commit e62333e26be649bfc3c167b9f2bbca38b92332c5 ]
Commit 25d76fed7ffe ("phy: cpcap-usb: Use IRQF_ONESHOT") started causing errors loading phy-cpcap-usb driver:
cpcap_battery cpcap_battery.0: failed to register power supply genirq: Flags mismatch irq 211. 00002080 (se0conn) vs. 00000080 (se0conn) cpcap-usb-phy cpcap-usb-phy.0: could not get irq se0conn: -16
Let's fix this by adding the missing IRQF_ONESHOT to also cpcap-battery and cpcap-charger drivers.
Fixes: 25d76fed7ffe ("phy: cpcap-usb: Use IRQF_ONESHOT") Reported-by: Merlijn Wajer merlijn@wizzup.org Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/cpcap-battery.c | 2 +- drivers/power/supply/cpcap-charger.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index 295611b3b15e9..7a974b5bd9dd1 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -666,7 +666,7 @@ static int cpcap_battery_init_irq(struct platform_device *pdev,
error = devm_request_threaded_irq(ddata->dev, irq, NULL, cpcap_battery_irq_thread, - IRQF_SHARED, + IRQF_SHARED | IRQF_ONESHOT, name, ddata); if (error) { dev_err(ddata->dev, "could not get irq %s: %i\n", diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index c0d452e3dc8b0..804ac7f84c301 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -708,7 +708,7 @@ static int cpcap_usb_init_irq(struct platform_device *pdev,
error = devm_request_threaded_irq(ddata->dev, irq, NULL, cpcap_charger_irq_thread, - IRQF_SHARED, + IRQF_SHARED | IRQF_ONESHOT, name, ddata); if (error) { dev_err(ddata->dev, "could not get irq %s: %i\n",
From: Martin Blumenstingl martin.blumenstingl@googlemail.com
[ Upstream commit 2f290b7c67adf6459a17a4c978102af35cd62e4a ]
The "rate" parameter in meson_clk_pll_set_rate() contains the new rate. Retrieve the old rate with clk_hw_get_rate() so we don't inifinitely try to switch from the new rate to the same rate again.
Fixes: 7a29a869434e8b ("clk: meson: Add support for Meson clock controller") Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20201226121556.975418-2-martin.blumenstingl@google... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/meson/clk-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index b17a13e9337c4..9404609b5ebfa 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -371,7 +371,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (parent_rate == 0 || rate == 0) return -EINVAL;
- old_rate = rate; + old_rate = clk_hw_get_rate(hw);
ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll); if (ret)
From: Martin Blumenstingl martin.blumenstingl@googlemail.com
[ Upstream commit 9e717285f0bd591d716fa0e7418f2cdaf756dd25 ]
The error codes returned by meson_clk_get_pll_settings() are all negative. Make "ret" a signed integer in meson_clk_pll_set_rate() to make it match with the clk_ops.set_rate API as well as the data type returned by meson_clk_get_pll_settings().
Fixes: 8eed1db1adec6a ("clk: meson: pll: update driver for the g12a") Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20201226121556.975418-3-martin.blumenstingl@google... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/meson/clk-pll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 9404609b5ebfa..5b932976483fd 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -365,8 +365,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - unsigned int enabled, m, n, frac = 0, ret; + unsigned int enabled, m, n, frac = 0; unsigned long old_rate; + int ret;
if (parent_rate == 0 || rate == 0) return -EINVAL;
From: Martin Blumenstingl martin.blumenstingl@googlemail.com
[ Upstream commit ccdc1f0836f8e37b558a424f1e491f929b2e7ede ]
Popagate the error code from meson_clk_pll_set_rate() when the PLL does not lock with the new settings.
Fixes: 722825dcd54b2e ("clk: meson: migrate plls clocks to clk_regmap") Signed-off-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20201226121556.975418-4-martin.blumenstingl@google... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/meson/clk-pll.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 5b932976483fd..49f27fe532139 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -394,7 +394,8 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (!enabled) return 0;
- if (meson_clk_pll_enable(hw)) { + ret = meson_clk_pll_enable(hw); + if (ret) { pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", __func__, old_rate); /* @@ -406,7 +407,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, meson_clk_pll_set_rate(hw, old_rate, parent_rate); }
- return 0; + return ret; }
/*
From: Po-Hsu Lin po-hsu.lin@canonical.com
[ Upstream commit 3db380570af7052620ace20c29e244938610ca71 ]
The == operand is a bash extension, thus this will fail on Ubuntu with: ./eeh-basic.sh: 89: test: 2: unexpected operator
As the /bin/sh on Ubuntu is pointed to DASH.
Use -eq to fix this posix compatibility issue.
Fixes: 996f9e0f93f162 ("selftests/powerpc: Fix eeh-basic.sh exit codes") Signed-off-by: Po-Hsu Lin po-hsu.lin@canonical.com Reviewed-by: Frederic Barrat fbarrat@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20201228043459.14281-1-po-hsu.lin@canonical.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/powerpc/eeh/eeh-basic.sh b/tools/testing/selftests/powerpc/eeh/eeh-basic.sh index 0d783e1065c86..64779f073e177 100755 --- a/tools/testing/selftests/powerpc/eeh/eeh-basic.sh +++ b/tools/testing/selftests/powerpc/eeh/eeh-basic.sh @@ -86,5 +86,5 @@ echo "$failed devices failed to recover ($dev_count tested)" lspci | diff -u $pre_lspci - rm -f $pre_lspci
-test "$failed" == 0 +test "$failed" -eq 0 exit $?
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
[ Upstream commit 951384cabc5dfb09251d440dbc26058eba86f97e ]
PM8009 has special revision (P=1), which is to be used for sm8250 platform. The major difference is the S2 regulator which supplies 0.95 V instead of 2.848V. Declare regulators data to be used for this chip revision. The datasheet calls the chip just pm8009-1, so use the same name.
Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Fixes: 06369bcc15a1 ("regulator: qcom-rpmh: Add support for SM8150") Reviewed-by: Vinod Koul vkoul@kernel.org Link: https://lore.kernel.org/r/20201231122348.637917-4-dmitry.baryshkov@linaro.or... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/qcom-rpmh-regulator.c | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index c395a8dda6f7c..98320e1d8bf66 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -732,6 +732,15 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, };
+static const struct rpmh_vreg_hw_data pmic5_hfsmps515_1 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(900000, 0, 4, 16000), + .n_voltages = 5, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + static const struct rpmh_vreg_hw_data pmic5_bob = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_bypass_ops, @@ -932,6 +941,19 @@ static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { {}, };
+static const struct rpmh_vreg_init_data pm8009_1_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515_1, "vdd-s2"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), + {}, +}; + static const struct rpmh_vreg_init_data pm6150_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), @@ -1057,6 +1079,10 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .compatible = "qcom,pm8009-rpmh-regulators", .data = pm8009_vreg_data, }, + { + .compatible = "qcom,pm8009-1-rpmh-regulators", + .data = pm8009_1_vreg_data, + }, { .compatible = "qcom,pm8150-rpmh-regulators", .data = pm8150_vreg_data,
From: Dmitry Baryshkov dmitry.baryshkov@linaro.org
[ Upstream commit c3da02421230639bf6ee5462b70b58f5b7f3b7c6 ]
Fix pm8009 compatibility string to reference pm8009 revision specific to sm8250 platform. Also add S2 regulator to be used for qca639x.
Signed-off-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Fixes: b1d2674e6121 ("arm64: dts: qcom: Add basic devicetree support for QRB5165 RB5") Reviewed-by: Vinod Koul vkoul@kernel.org Link: https://lore.kernel.org/r/20201231122348.637917-5-dmitry.baryshkov@linaro.or... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index f86cc5140d3b9..f13a63ca8efd6 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -122,7 +122,7 @@
&apps_rsc { pm8009-rpmh-regulators { - compatible = "qcom,pm8009-rpmh-regulators"; + compatible = "qcom,pm8009-1-rpmh-regulators"; qcom,pmic-id = "f";
vdd-s1-supply = <&vph_pwr>; @@ -131,6 +131,13 @@ vdd-l5-l6-supply = <&vreg_bob>; vdd-l7-supply = <&vreg_s4a_1p8>;
+ vreg_s2f_0p95: smps2 { + regulator-name = "vreg_s2f_0p95"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <952000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>; + }; + vreg_l1f_1p1: ldo1 { regulator-name = "vreg_l1f_1p1"; regulator-min-microvolt = <1104000>;
From: Jan Kara jack@suse.cz
[ Upstream commit a4db1072e1a3bd7a8d9c356e1902b13ac5deb8ef ]
When checking corrupted quota file we can bail out and leak allocated info structure. Properly free info structure on error return.
Reported-by: syzbot+77779c9b52ab78154b08@syzkaller.appspotmail.com Fixes: 11c514a99bb9 ("quota: Sanity-check quota file headers on load") Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/quota/quota_v2.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index c21106557a37e..b1467f3921c28 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -164,19 +164,24 @@ static int v2_read_file_info(struct super_block *sb, int type) quota_error(sb, "Number of blocks too big for quota file size (%llu > %llu).", (loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits, i_size_read(sb_dqopt(sb)->files[type])); - goto out; + goto out_free; } if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { quota_error(sb, "Free block number too big (%u >= %u).", qinfo->dqi_free_blk, qinfo->dqi_blocks); - goto out; + goto out_free; } if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { quota_error(sb, "Block with free entry too big (%u >= %u).", qinfo->dqi_free_entry, qinfo->dqi_blocks); - goto out; + goto out_free; } ret = 0; +out_free: + if (ret) { + kfree(info->dqi_priv); + info->dqi_priv = NULL; + } out: up_read(&dqopt->dqio_sem); return ret;
From: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com
[ Upstream commit 545f4011e156554d704d6278245d54543f6680d1 ]
Handle only slave interrupts which are enabled.
The IS_OFFSET register contains the interrupt status bits which will be set regardless of the enabling of the corresponding interrupt condition. One must therefore look at both IS_OFFSET and IE_OFFSET to determine whether an interrupt condition is set and enabled.
Fixes: c245d94ed106 ("i2c: iproc: Add multi byte read-write support for slave mode") Signed-off-by: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com Acked-by: Ray Jui ray.jui@broadcom.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-bcm-iproc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index d8295b1c379d1..b98433c04d184 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -505,12 +505,17 @@ static void bcm_iproc_i2c_process_m_event(struct bcm_iproc_i2c_dev *iproc_i2c, static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data) { struct bcm_iproc_i2c_dev *iproc_i2c = data; - u32 status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET); + u32 slave_status; + u32 status; bool ret; - u32 sl_status = status & ISR_MASK_SLAVE;
- if (sl_status) { - ret = bcm_iproc_i2c_slave_isr(iproc_i2c, sl_status); + status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET); + /* process only slave interrupt which are enabled */ + slave_status = status & iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET) & + ISR_MASK_SLAVE; + + if (slave_status) { + ret = bcm_iproc_i2c_slave_isr(iproc_i2c, slave_status); if (ret) return IRQ_HANDLED; else
From: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com
[ Upstream commit 603e77af7b0704bdb057de0368f1f2b04fc9552c ]
Update slave isr mask (ISR_MASK_SLAVE) to include remaining two slave interrupts.
Fixes: c245d94ed106 ("i2c: iproc: Add multi byte read-write support for slave mode") Signed-off-by: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com Acked-by: Ray Jui ray.jui@broadcom.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-bcm-iproc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index b98433c04d184..68db2068f38b0 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -215,7 +215,8 @@ struct bcm_iproc_i2c_dev {
#define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\ | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\ - | BIT(IS_S_TX_UNDERRUN_SHIFT)) + | BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT)\ + | BIT(IS_S_RX_THLD_SHIFT))
static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave); static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave);
From: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com
[ Upstream commit e21d79778768e4e187b2892d662c6aaa01e1d399 ]
Handle single or multi byte master read request with or without repeated start.
Fixes: c245d94ed106 ("i2c: iproc: Add multi byte read-write support for slave mode") Signed-off-by: Rayagonda Kokatanur rayagonda.kokatanur@broadcom.com Acked-by: Ray Jui ray.jui@broadcom.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-bcm-iproc.c | 215 +++++++++++++++++++++++------ 1 file changed, 170 insertions(+), 45 deletions(-)
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 68db2068f38b0..35baca2f62c4e 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -159,6 +159,11 @@
#define IE_S_ALL_INTERRUPT_SHIFT 21 #define IE_S_ALL_INTERRUPT_MASK 0x3f +/* + * It takes ~18us to reading 10bytes of data, hence to keep tasklet + * running for less time, max slave read per tasklet is set to 10 bytes. + */ +#define MAX_SLAVE_RX_PER_INT 10
enum i2c_slave_read_status { I2C_SLAVE_RX_FIFO_EMPTY = 0, @@ -205,8 +210,18 @@ struct bcm_iproc_i2c_dev { /* bytes that have been read */ unsigned int rx_bytes; unsigned int thld_bytes; + + bool slave_rx_only; + bool rx_start_rcvd; + bool slave_read_complete; + u32 tx_underrun; + u32 slave_int_mask; + struct tasklet_struct slave_rx_tasklet; };
+/* tasklet to process slave rx data */ +static void slave_rx_tasklet_fn(unsigned long); + /* * Can be expanded in the future if more interrupt status bits are utilized */ @@ -260,6 +275,7 @@ static void bcm_iproc_i2c_slave_init( { u32 val;
+ iproc_i2c->tx_underrun = 0; if (need_reset) { /* put controller in reset */ val = iproc_i2c_rd_reg(iproc_i2c, CFG_OFFSET); @@ -296,8 +312,11 @@ static void bcm_iproc_i2c_slave_init(
/* Enable interrupt register to indicate a valid byte in receive fifo */ val = BIT(IE_S_RX_EVENT_SHIFT); + /* Enable interrupt register to indicate a Master read transaction */ + val |= BIT(IE_S_RD_EVENT_SHIFT); /* Enable interrupt register for the Slave BUSY command */ val |= BIT(IE_S_START_BUSY_SHIFT); + iproc_i2c->slave_int_mask = val; iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); }
@@ -322,76 +341,176 @@ static void bcm_iproc_i2c_check_slave_status( } }
-static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, - u32 status) +static void bcm_iproc_i2c_slave_read(struct bcm_iproc_i2c_dev *iproc_i2c) { + u8 rx_data, rx_status; + u32 rx_bytes = 0; u32 val; - u8 value, rx_status;
- /* Slave RX byte receive */ - if (status & BIT(IS_S_RX_EVENT_SHIFT)) { + while (rx_bytes < MAX_SLAVE_RX_PER_INT) { val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; - if (rx_status == I2C_SLAVE_RX_START) { - /* Start of SMBUS for Master write */ - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_REQUESTED, &value); + rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
- val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); - value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + if (rx_status == I2C_SLAVE_RX_START) { + /* Start of SMBUS Master write */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_RECEIVED, &value); - } else if (status & BIT(IS_S_RD_EVENT_SHIFT)) { - /* Start of SMBUS for Master Read */ + I2C_SLAVE_WRITE_REQUESTED, &rx_data); + iproc_i2c->rx_start_rcvd = true; + iproc_i2c->slave_read_complete = false; + } else if (rx_status == I2C_SLAVE_RX_DATA && + iproc_i2c->rx_start_rcvd) { + /* Middle of SMBUS Master write */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_REQUESTED, &value); - iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + I2C_SLAVE_WRITE_RECEIVED, &rx_data); + } else if (rx_status == I2C_SLAVE_RX_END && + iproc_i2c->rx_start_rcvd) { + /* End of SMBUS Master write */ + if (iproc_i2c->slave_rx_only) + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_WRITE_RECEIVED, + &rx_data); + + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, + &rx_data); + } else if (rx_status == I2C_SLAVE_RX_FIFO_EMPTY) { + iproc_i2c->rx_start_rcvd = false; + iproc_i2c->slave_read_complete = true; + break; + }
- val = BIT(S_CMD_START_BUSY_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + rx_bytes++; + } +}
- /* - * Enable interrupt for TX FIFO becomes empty and - * less than PKT_LENGTH bytes were output on the SMBUS - */ - val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); - val |= BIT(IE_S_TX_UNDERRUN_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); - } else { - /* Master write other than start */ - value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); +static void slave_rx_tasklet_fn(unsigned long data) +{ + struct bcm_iproc_i2c_dev *iproc_i2c = (struct bcm_iproc_i2c_dev *)data; + u32 int_clr; + + bcm_iproc_i2c_slave_read(iproc_i2c); + + /* clear pending IS_S_RX_EVENT_SHIFT interrupt */ + int_clr = BIT(IS_S_RX_EVENT_SHIFT); + + if (!iproc_i2c->slave_rx_only && iproc_i2c->slave_read_complete) { + /* + * In case of single byte master-read request, + * IS_S_TX_UNDERRUN_SHIFT event is generated before + * IS_S_START_BUSY_SHIFT event. Hence start slave data send + * from first IS_S_TX_UNDERRUN_SHIFT event. + * + * This means don't send any data from slave when + * IS_S_RD_EVENT_SHIFT event is generated else it will increment + * eeprom or other backend slave driver read pointer twice. + */ + iproc_i2c->tx_underrun = 0; + iproc_i2c->slave_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT); + + /* clear IS_S_RD_EVENT_SHIFT interrupt */ + int_clr |= BIT(IS_S_RD_EVENT_SHIFT); + } + + /* clear slave interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, int_clr); + /* enable slave interrupts */ + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, iproc_i2c->slave_int_mask); +} + +static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, + u32 status) +{ + u32 val; + u8 value; + + /* + * Slave events in case of master-write, master-write-read and, + * master-read + * + * Master-write : only IS_S_RX_EVENT_SHIFT event + * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT + * events + * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT + * events or only IS_S_RD_EVENT_SHIFT + */ + if (status & BIT(IS_S_RX_EVENT_SHIFT) || + status & BIT(IS_S_RD_EVENT_SHIFT)) { + /* disable slave interrupts */ + val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); + val &= ~iproc_i2c->slave_int_mask; + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); + + if (status & BIT(IS_S_RD_EVENT_SHIFT)) + /* Master-write-read request */ + iproc_i2c->slave_rx_only = false; + else + /* Master-write request only */ + iproc_i2c->slave_rx_only = true; + + /* schedule tasklet to read data later */ + tasklet_schedule(&iproc_i2c->slave_rx_tasklet); + + /* clear only IS_S_RX_EVENT_SHIFT interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, + BIT(IS_S_RX_EVENT_SHIFT)); + } + + if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { + iproc_i2c->tx_underrun++; + if (iproc_i2c->tx_underrun == 1) + /* Start of SMBUS for Master Read */ i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_WRITE_RECEIVED, &value); - if (rx_status == I2C_SLAVE_RX_END) - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_STOP, &value); - } - } else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { - /* Master read other than start */ - i2c_slave_event(iproc_i2c->slave, - I2C_SLAVE_READ_PROCESSED, &value); + I2C_SLAVE_READ_REQUESTED, + &value); + else + /* Master read other than start */ + i2c_slave_event(iproc_i2c->slave, + I2C_SLAVE_READ_PROCESSED, + &value);
iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); + /* start transfer */ val = BIT(S_CMD_START_BUSY_SHIFT); iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + + /* clear interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, + BIT(IS_S_TX_UNDERRUN_SHIFT)); }
- /* Stop */ + /* Stop received from master in case of master read transaction */ if (status & BIT(IS_S_START_BUSY_SHIFT)) { - i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); /* * Enable interrupt for TX FIFO becomes empty and * less than PKT_LENGTH bytes were output on the SMBUS */ - val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); - val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); - iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); + iproc_i2c->slave_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, + iproc_i2c->slave_int_mask); + + /* End of SMBUS for Master Read */ + val = BIT(S_TX_WR_STATUS_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, val); + + val = BIT(S_CMD_START_BUSY_SHIFT); + iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); + + /* flush TX FIFOs */ + val = iproc_i2c_rd_reg(iproc_i2c, S_FIFO_CTRL_OFFSET); + val |= (BIT(S_FIFO_TX_FLUSH_SHIFT)); + iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, val); + + i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); + + /* clear interrupt */ + iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, + BIT(IS_S_START_BUSY_SHIFT)); }
- /* clear interrupt status */ - iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, status); + /* check slave transmit status only if slave is transmitting */ + if (!iproc_i2c->slave_rx_only) + bcm_iproc_i2c_check_slave_status(iproc_i2c);
- bcm_iproc_i2c_check_slave_status(iproc_i2c); return true; }
@@ -1072,6 +1191,10 @@ static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave) return -EAFNOSUPPORT;
iproc_i2c->slave = slave; + + tasklet_init(&iproc_i2c->slave_rx_tasklet, slave_rx_tasklet_fn, + (unsigned long)iproc_i2c); + bcm_iproc_i2c_slave_init(iproc_i2c, false); return 0; } @@ -1092,6 +1215,8 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave) IE_S_ALL_INTERRUPT_SHIFT); iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp);
+ tasklet_kill(&iproc_i2c->slave_rx_tasklet); + /* Erase the slave address programmed */ tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET); tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
From: Pratyush Yadav p.yadav@ti.com
[ Upstream commit ceeda328edeeeeac7579e9dbf0610785a3b83d39 ]
The controller can only support up to 31 dummy cycles. If the command requires more it falls back to using 31. This command is likely to fail because the correct number of cycles are not waited upon. Rather than silently issuing an incorrect command, fail loudly so the caller can get a chance to find out the command can't be supported by the controller.
Fixes: 140623410536 ("mtd: spi-nor: Add driver for Cadence Quad SPI Flash Controller") Signed-off-by: Pratyush Yadav p.yadav@ti.com Link: https://lore.kernel.org/r/20201222184425.7028-3-p.yadav@ti.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-cadence-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index ba7d40c2922f7..826b01f346246 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -461,7 +461,7 @@ static int cqspi_read_setup(struct cqspi_flash_pdata *f_pdata, /* Setup dummy clock cycles */ dummy_clk = op->dummy.nbytes * 8; if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) - dummy_clk = CQSPI_DUMMY_CLKS_MAX; + return -EOPNOTSUPP;
if (dummy_clk) reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK)
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit 756650820abd4770c4200763505b634a3c04e05e ]
The CEC clock on the H6 SoC is a bit special, since it uses a fixed pre-dividier for one source clock (the PLL), but conveys the other clock (32K OSC) directly. We are using a fixed predivider array for that, but fail to use the right flag to actually activate that.
Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU") Reported-by: Jernej Skrabec jernej.skrabec@siol.net Signed-off-by: Andre Przywara andre.przywara@arm.com Acked-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210106143246.11255-1-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index f2497d0a4683a..a26dbbdff80d1 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -682,7 +682,7 @@ static struct ccu_mux hdmi_cec_clk = {
.common = { .reg = 0xb10, - .features = CCU_FEATURE_VARIABLE_PREDIV, + .features = CCU_FEATURE_FIXED_PREDIV, .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", hdmi_cec_parents, &ccu_mux_ops,
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 5b30be15ca262d9cb2c36b173bb488e8d1952ea0 ]
The S2 internal core clock does not exist on R-Car V3U. Remove it.
Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Tested-by: Wolfram Sang wsa+renesas@sang-engineering.com Link: https://lore.kernel.org/r/20201019120614.22149-2-geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index aa5389b04d742..9ccefc36b7ca8 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -69,7 +69,6 @@ enum clk_ids { CLK_PLL5_DIV2, CLK_PLL5_DIV4, CLK_S1, - CLK_S2, CLK_S3, CLK_SDSRC, CLK_RPCSRC,
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 80d3e07ec509c5098d44e4f1416cc9f133fd436f ]
According to Figure 8.1.1 ("Block Diagram of CPG (R-Car V3U-AD)") in the R-Car V3U Series User's Manual Rev. 0.5, the parent of the CBFUSA clock is EXTAL.
Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Tested-by: Wolfram Sang wsa+renesas@sang-engineering.com Link: https://lore.kernel.org/r/20201019120614.22149-3-geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 9ccefc36b7ca8..7b2c640c3de0c 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -136,7 +136,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1), DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1), DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1), - DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_MAIN, 2, 1), + DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878),
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit a0312af1f94d13800e63a7d0a66e563582e39aec ]
Prevent invalid (0, 0) inputs to hid-core's snto32() function.
Maybe it is just the dummy device here that is causing this, but there are hundreds of calls to snto32(0, 0). Having n (bits count) of 0 is causing the current UBSAN trap with a shift value of 0xffffffff (-1, or n - 1 in this function).
Either of the value to shift being 0 or the bits count being 0 can be handled by just returning 0 to the caller, avoiding the following complex shift + OR operations:
return value & (1 << (n - 1)) ? value | (~0U << n) : value;
Fixes: dde5845a529f ("[PATCH] Generic HID layer - code split") Signed-off-by: Randy Dunlap rdunlap@infradead.org Reported-by: syzbot+1e911ad71dd4ea72e04a@syzkaller.appspotmail.com Cc: Jiri Kosina jikos@kernel.org Cc: Benjamin Tissoires benjamin.tissoires@redhat.com Cc: linux-input@vger.kernel.org Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-core.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8a8b2b982f83c..097cb1ee31268 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1307,6 +1307,9 @@ EXPORT_SYMBOL_GPL(hid_open_report);
static s32 snto32(__u32 value, unsigned n) { + if (!value || !n) + return 0; + switch (n) { case 8: return ((__s8)value); case 16: return ((__s16)value);
From: Bernard Metzler bmt@zurich.ibm.com
[ Upstream commit 661f385961f06f36da24cf408d461f988d0c39ad ]
During connection setup, the application may choose to zero-size inbound and outbound READ queues, as well as the Receive queue. This patch fixes handling of zero-sized queues, but not prevents it.
Kamal Heib says in an initial error report:
When running the blktests over siw the following shift-out-of-bounds is reported, this is happening because the passed IRD or ORD from the ulp could be zero which will lead to unexpected behavior when calling roundup_pow_of_two(), fix that by blocking zero values of ORD or IRD.
UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 shift exponent 64 is too large for 64-bit type 'long unsigned int' CPU: 20 PID: 3957 Comm: kworker/u64:13 Tainted: G S 5.10.0-rc6 #2 Hardware name: Dell Inc. PowerEdge R630/02C2CP, BIOS 2.1.5 04/11/2016 Workqueue: iw_cm_wq cm_work_handler [iw_cm] Call Trace: dump_stack+0x99/0xcb ubsan_epilogue+0x5/0x40 __ubsan_handle_shift_out_of_bounds.cold.11+0xb4/0xf3 ? down_write+0x183/0x3d0 siw_qp_modify.cold.8+0x2d/0x32 [siw] ? __local_bh_enable_ip+0xa5/0xf0 siw_accept+0x906/0x1b60 [siw] ? xa_load+0x147/0x1f0 ? siw_connect+0x17a0/0x17a0 [siw] ? lock_downgrade+0x700/0x700 ? siw_get_base_qp+0x1c2/0x340 [siw] ? _raw_spin_unlock_irqrestore+0x39/0x40 iw_cm_accept+0x1f4/0x430 [iw_cm] rdma_accept+0x3fa/0xb10 [rdma_cm] ? check_flush_dependency+0x410/0x410 ? cma_rep_recv+0x570/0x570 [rdma_cm] nvmet_rdma_queue_connect+0x1a62/0x2680 [nvmet_rdma] ? nvmet_rdma_alloc_cmds+0xce0/0xce0 [nvmet_rdma] ? lock_release+0x56e/0xcc0 ? lock_downgrade+0x700/0x700 ? lock_downgrade+0x700/0x700 ? __xa_alloc_cyclic+0xef/0x350 ? __xa_alloc+0x2d0/0x2d0 ? rdma_restrack_add+0xbe/0x2c0 [ib_core] ? __ww_mutex_die+0x190/0x190 cma_cm_event_handler+0xf2/0x500 [rdma_cm] iw_conn_req_handler+0x910/0xcb0 [rdma_cm] ? _raw_spin_unlock_irqrestore+0x39/0x40 ? trace_hardirqs_on+0x1c/0x150 ? cma_ib_handler+0x8a0/0x8a0 [rdma_cm] ? __kasan_kmalloc.constprop.7+0xc1/0xd0 cm_work_handler+0x121c/0x17a0 [iw_cm] ? iw_cm_reject+0x190/0x190 [iw_cm] ? trace_hardirqs_on+0x1c/0x150 process_one_work+0x8fb/0x16c0 ? pwq_dec_nr_in_flight+0x320/0x320 worker_thread+0x87/0xb40 ? __kthread_parkme+0xd1/0x1a0 ? process_one_work+0x16c0/0x16c0 kthread+0x35f/0x430 ? kthread_mod_delayed_work+0x180/0x180 ret_from_fork+0x22/0x30
Fixes: a531975279f3 ("rdma/siw: main include file") Fixes: f29dd55b0236 ("rdma/siw: queue pair methods") Fixes: 8b6a361b8c48 ("rdma/siw: receive path") Fixes: b9be6f18cf9e ("rdma/siw: transmit path") Fixes: 303ae1cdfdf7 ("rdma/siw: application interface") Link: https://lore.kernel.org/r/20210108125845.1803-1-bmt@zurich.ibm.com Reported-by: Kamal Heib kamalheib1@gmail.com Reported-by: Yi Zhang yi.zhang@redhat.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: Bernard Metzler bmt@zurich.ibm.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/siw/siw.h | 2 +- drivers/infiniband/sw/siw/siw_qp.c | 271 ++++++++++++++------------ drivers/infiniband/sw/siw/siw_qp_rx.c | 26 ++- drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +- drivers/infiniband/sw/siw/siw_verbs.c | 20 +- 5 files changed, 177 insertions(+), 146 deletions(-)
diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h index adda789962196..368959ae9a8cc 100644 --- a/drivers/infiniband/sw/siw/siw.h +++ b/drivers/infiniband/sw/siw/siw.h @@ -653,7 +653,7 @@ static inline struct siw_sqe *orq_get_free(struct siw_qp *qp) { struct siw_sqe *orq_e = orq_get_tail(qp);
- if (orq_e && READ_ONCE(orq_e->flags) == 0) + if (READ_ONCE(orq_e->flags) == 0) return orq_e;
return NULL; diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c index 875d36d4b1c61..ddb2e66f9f133 100644 --- a/drivers/infiniband/sw/siw/siw_qp.c +++ b/drivers/infiniband/sw/siw/siw_qp.c @@ -199,26 +199,26 @@ void siw_qp_llp_write_space(struct sock *sk)
static int siw_qp_readq_init(struct siw_qp *qp, int irq_size, int orq_size) { - irq_size = roundup_pow_of_two(irq_size); - orq_size = roundup_pow_of_two(orq_size); - - qp->attrs.irq_size = irq_size; - qp->attrs.orq_size = orq_size; - - qp->irq = vzalloc(irq_size * sizeof(struct siw_sqe)); - if (!qp->irq) { - siw_dbg_qp(qp, "irq malloc for %d failed\n", irq_size); - qp->attrs.irq_size = 0; - return -ENOMEM; + if (irq_size) { + irq_size = roundup_pow_of_two(irq_size); + qp->irq = vzalloc(irq_size * sizeof(struct siw_sqe)); + if (!qp->irq) { + qp->attrs.irq_size = 0; + return -ENOMEM; + } } - qp->orq = vzalloc(orq_size * sizeof(struct siw_sqe)); - if (!qp->orq) { - siw_dbg_qp(qp, "orq malloc for %d failed\n", orq_size); - qp->attrs.orq_size = 0; - qp->attrs.irq_size = 0; - vfree(qp->irq); - return -ENOMEM; + if (orq_size) { + orq_size = roundup_pow_of_two(orq_size); + qp->orq = vzalloc(orq_size * sizeof(struct siw_sqe)); + if (!qp->orq) { + qp->attrs.orq_size = 0; + qp->attrs.irq_size = 0; + vfree(qp->irq); + return -ENOMEM; + } } + qp->attrs.irq_size = irq_size; + qp->attrs.orq_size = orq_size; siw_dbg_qp(qp, "ORD %d, IRD %d\n", orq_size, irq_size); return 0; } @@ -288,13 +288,14 @@ int siw_qp_mpa_rts(struct siw_qp *qp, enum mpa_v2_ctrl ctrl) if (ctrl & MPA_V2_RDMA_WRITE_RTR) wqe->sqe.opcode = SIW_OP_WRITE; else if (ctrl & MPA_V2_RDMA_READ_RTR) { - struct siw_sqe *rreq; + struct siw_sqe *rreq = NULL;
wqe->sqe.opcode = SIW_OP_READ;
spin_lock(&qp->orq_lock);
- rreq = orq_get_free(qp); + if (qp->attrs.orq_size) + rreq = orq_get_free(qp); if (rreq) { siw_read_to_orq(rreq, &wqe->sqe); qp->orq_put++; @@ -877,135 +878,88 @@ void siw_read_to_orq(struct siw_sqe *rreq, struct siw_sqe *sqe) rreq->num_sge = 1; }
-/* - * Must be called with SQ locked. - * To avoid complete SQ starvation by constant inbound READ requests, - * the active IRQ will not be served after qp->irq_burst, if the - * SQ has pending work. - */ -int siw_activate_tx(struct siw_qp *qp) +static int siw_activate_tx_from_sq(struct siw_qp *qp) { - struct siw_sqe *irqe, *sqe; + struct siw_sqe *sqe; struct siw_wqe *wqe = tx_wqe(qp); int rv = 1;
- irqe = &qp->irq[qp->irq_get % qp->attrs.irq_size]; - - if (irqe->flags & SIW_WQE_VALID) { - sqe = sq_get_next(qp); - - /* - * Avoid local WQE processing starvation in case - * of constant inbound READ request stream - */ - if (sqe && ++qp->irq_burst >= SIW_IRQ_MAXBURST_SQ_ACTIVE) { - qp->irq_burst = 0; - goto skip_irq; - } - memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE); - wqe->wr_status = SIW_WR_QUEUED; - - /* start READ RESPONSE */ - wqe->sqe.opcode = SIW_OP_READ_RESPONSE; - wqe->sqe.flags = 0; - if (irqe->num_sge) { - wqe->sqe.num_sge = 1; - wqe->sqe.sge[0].length = irqe->sge[0].length; - wqe->sqe.sge[0].laddr = irqe->sge[0].laddr; - wqe->sqe.sge[0].lkey = irqe->sge[0].lkey; - } else { - wqe->sqe.num_sge = 0; - } - - /* Retain original RREQ's message sequence number for - * potential error reporting cases. - */ - wqe->sqe.sge[1].length = irqe->sge[1].length; - - wqe->sqe.rkey = irqe->rkey; - wqe->sqe.raddr = irqe->raddr; + sqe = sq_get_next(qp); + if (!sqe) + return 0;
- wqe->processed = 0; - qp->irq_get++; + memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE); + wqe->wr_status = SIW_WR_QUEUED;
- /* mark current IRQ entry free */ - smp_store_mb(irqe->flags, 0); + /* First copy SQE to kernel private memory */ + memcpy(&wqe->sqe, sqe, sizeof(*sqe));
+ if (wqe->sqe.opcode >= SIW_NUM_OPCODES) { + rv = -EINVAL; goto out; } - sqe = sq_get_next(qp); - if (sqe) { -skip_irq: - memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE); - wqe->wr_status = SIW_WR_QUEUED; - - /* First copy SQE to kernel private memory */ - memcpy(&wqe->sqe, sqe, sizeof(*sqe)); - - if (wqe->sqe.opcode >= SIW_NUM_OPCODES) { + if (wqe->sqe.flags & SIW_WQE_INLINE) { + if (wqe->sqe.opcode != SIW_OP_SEND && + wqe->sqe.opcode != SIW_OP_WRITE) { rv = -EINVAL; goto out; } - if (wqe->sqe.flags & SIW_WQE_INLINE) { - if (wqe->sqe.opcode != SIW_OP_SEND && - wqe->sqe.opcode != SIW_OP_WRITE) { - rv = -EINVAL; - goto out; - } - if (wqe->sqe.sge[0].length > SIW_MAX_INLINE) { - rv = -EINVAL; - goto out; - } - wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1]; - wqe->sqe.sge[0].lkey = 0; - wqe->sqe.num_sge = 1; + if (wqe->sqe.sge[0].length > SIW_MAX_INLINE) { + rv = -EINVAL; + goto out; } - if (wqe->sqe.flags & SIW_WQE_READ_FENCE) { - /* A READ cannot be fenced */ - if (unlikely(wqe->sqe.opcode == SIW_OP_READ || - wqe->sqe.opcode == - SIW_OP_READ_LOCAL_INV)) { - siw_dbg_qp(qp, "cannot fence read\n"); - rv = -EINVAL; - goto out; - } - spin_lock(&qp->orq_lock); + wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1]; + wqe->sqe.sge[0].lkey = 0; + wqe->sqe.num_sge = 1; + } + if (wqe->sqe.flags & SIW_WQE_READ_FENCE) { + /* A READ cannot be fenced */ + if (unlikely(wqe->sqe.opcode == SIW_OP_READ || + wqe->sqe.opcode == + SIW_OP_READ_LOCAL_INV)) { + siw_dbg_qp(qp, "cannot fence read\n"); + rv = -EINVAL; + goto out; + } + spin_lock(&qp->orq_lock);
- if (!siw_orq_empty(qp)) { - qp->tx_ctx.orq_fence = 1; - rv = 0; - } - spin_unlock(&qp->orq_lock); + if (qp->attrs.orq_size && !siw_orq_empty(qp)) { + qp->tx_ctx.orq_fence = 1; + rv = 0; + } + spin_unlock(&qp->orq_lock);
- } else if (wqe->sqe.opcode == SIW_OP_READ || - wqe->sqe.opcode == SIW_OP_READ_LOCAL_INV) { - struct siw_sqe *rreq; + } else if (wqe->sqe.opcode == SIW_OP_READ || + wqe->sqe.opcode == SIW_OP_READ_LOCAL_INV) { + struct siw_sqe *rreq;
- wqe->sqe.num_sge = 1; + if (unlikely(!qp->attrs.orq_size)) { + /* We negotiated not to send READ req's */ + rv = -EINVAL; + goto out; + } + wqe->sqe.num_sge = 1;
- spin_lock(&qp->orq_lock); + spin_lock(&qp->orq_lock);
- rreq = orq_get_free(qp); - if (rreq) { - /* - * Make an immediate copy in ORQ to be ready - * to process loopback READ reply - */ - siw_read_to_orq(rreq, &wqe->sqe); - qp->orq_put++; - } else { - qp->tx_ctx.orq_fence = 1; - rv = 0; - } - spin_unlock(&qp->orq_lock); + rreq = orq_get_free(qp); + if (rreq) { + /* + * Make an immediate copy in ORQ to be ready + * to process loopback READ reply + */ + siw_read_to_orq(rreq, &wqe->sqe); + qp->orq_put++; + } else { + qp->tx_ctx.orq_fence = 1; + rv = 0; } - - /* Clear SQE, can be re-used by application */ - smp_store_mb(sqe->flags, 0); - qp->sq_get++; - } else { - rv = 0; + spin_unlock(&qp->orq_lock); } + + /* Clear SQE, can be re-used by application */ + smp_store_mb(sqe->flags, 0); + qp->sq_get++; out: if (unlikely(rv < 0)) { siw_dbg_qp(qp, "error %d\n", rv); @@ -1014,6 +968,65 @@ out: return rv; }
+/* + * Must be called with SQ locked. + * To avoid complete SQ starvation by constant inbound READ requests, + * the active IRQ will not be served after qp->irq_burst, if the + * SQ has pending work. + */ +int siw_activate_tx(struct siw_qp *qp) +{ + struct siw_sqe *irqe; + struct siw_wqe *wqe = tx_wqe(qp); + + if (!qp->attrs.irq_size) + return siw_activate_tx_from_sq(qp); + + irqe = &qp->irq[qp->irq_get % qp->attrs.irq_size]; + + if (!(irqe->flags & SIW_WQE_VALID)) + return siw_activate_tx_from_sq(qp); + + /* + * Avoid local WQE processing starvation in case + * of constant inbound READ request stream + */ + if (sq_get_next(qp) && ++qp->irq_burst >= SIW_IRQ_MAXBURST_SQ_ACTIVE) { + qp->irq_burst = 0; + return siw_activate_tx_from_sq(qp); + } + memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE); + wqe->wr_status = SIW_WR_QUEUED; + + /* start READ RESPONSE */ + wqe->sqe.opcode = SIW_OP_READ_RESPONSE; + wqe->sqe.flags = 0; + if (irqe->num_sge) { + wqe->sqe.num_sge = 1; + wqe->sqe.sge[0].length = irqe->sge[0].length; + wqe->sqe.sge[0].laddr = irqe->sge[0].laddr; + wqe->sqe.sge[0].lkey = irqe->sge[0].lkey; + } else { + wqe->sqe.num_sge = 0; + } + + /* Retain original RREQ's message sequence number for + * potential error reporting cases. + */ + wqe->sqe.sge[1].length = irqe->sge[1].length; + + wqe->sqe.rkey = irqe->rkey; + wqe->sqe.raddr = irqe->raddr; + + wqe->processed = 0; + qp->irq_get++; + + /* mark current IRQ entry free */ + smp_store_mb(irqe->flags, 0); + + return 1; +} + /* * Check if current CQ state qualifies for calling CQ completion * handler. Must be called with CQ lock held. diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c index 4bd1f1f84057b..60116f20653c7 100644 --- a/drivers/infiniband/sw/siw/siw_qp_rx.c +++ b/drivers/infiniband/sw/siw/siw_qp_rx.c @@ -680,6 +680,10 @@ static int siw_init_rresp(struct siw_qp *qp, struct siw_rx_stream *srx) } spin_lock_irqsave(&qp->sq_lock, flags);
+ if (unlikely(!qp->attrs.irq_size)) { + run_sq = 0; + goto error_irq; + } if (tx_work->wr_status == SIW_WR_IDLE) { /* * immediately schedule READ response w/o @@ -712,8 +716,9 @@ static int siw_init_rresp(struct siw_qp *qp, struct siw_rx_stream *srx) /* RRESP now valid as current TX wqe or placed into IRQ */ smp_store_mb(resp->flags, SIW_WQE_VALID); } else { - pr_warn("siw: [QP %u]: irq %d exceeded %d\n", qp_id(qp), - qp->irq_put % qp->attrs.irq_size, qp->attrs.irq_size); +error_irq: + pr_warn("siw: [QP %u]: IRQ exceeded or null, size %d\n", + qp_id(qp), qp->attrs.irq_size);
siw_init_terminate(qp, TERM_ERROR_LAYER_RDMAP, RDMAP_ETYPE_REMOTE_OPERATION, @@ -740,6 +745,9 @@ static int siw_orqe_start_rx(struct siw_qp *qp) struct siw_sqe *orqe; struct siw_wqe *wqe = NULL;
+ if (unlikely(!qp->attrs.orq_size)) + return -EPROTO; + /* make sure ORQ indices are current */ smp_mb();
@@ -796,8 +804,8 @@ int siw_proc_rresp(struct siw_qp *qp) */ rv = siw_orqe_start_rx(qp); if (rv) { - pr_warn("siw: [QP %u]: ORQ empty at idx %d\n", - qp_id(qp), qp->orq_get % qp->attrs.orq_size); + pr_warn("siw: [QP %u]: ORQ empty, size %d\n", + qp_id(qp), qp->attrs.orq_size); goto error_term; } rv = siw_rresp_check_ntoh(srx, frx); @@ -1290,11 +1298,13 @@ static int siw_rdmap_complete(struct siw_qp *qp, int error) wc_status); siw_wqe_put_mem(wqe, SIW_OP_READ);
- if (!error) + if (!error) { rv = siw_check_tx_fence(qp); - else - /* Disable current ORQ eleement */ - WRITE_ONCE(orq_get_current(qp)->flags, 0); + } else { + /* Disable current ORQ element */ + if (qp->attrs.orq_size) + WRITE_ONCE(orq_get_current(qp)->flags, 0); + } break;
case RDMAP_RDMA_READ_REQ: diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c index d19d8325588b5..7989c4043db4e 100644 --- a/drivers/infiniband/sw/siw/siw_qp_tx.c +++ b/drivers/infiniband/sw/siw/siw_qp_tx.c @@ -1107,8 +1107,8 @@ next_wqe: /* * RREQ may have already been completed by inbound RRESP! */ - if (tx_type == SIW_OP_READ || - tx_type == SIW_OP_READ_LOCAL_INV) { + if ((tx_type == SIW_OP_READ || + tx_type == SIW_OP_READ_LOCAL_INV) && qp->attrs.orq_size) { /* Cleanup pending entry in ORQ */ qp->orq_put--; qp->orq[qp->orq_put % qp->attrs.orq_size].flags = 0; diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c index 68fd053fc7748..e389d44e5591d 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.c +++ b/drivers/infiniband/sw/siw/siw_verbs.c @@ -365,13 +365,23 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, if (rv) goto err_out;
+ num_sqe = attrs->cap.max_send_wr; + num_rqe = attrs->cap.max_recv_wr; + /* All queue indices are derived from modulo operations * on a free running 'get' (consumer) and 'put' (producer) * unsigned counter. Having queue sizes at power of two * avoids handling counter wrap around. */ - num_sqe = roundup_pow_of_two(attrs->cap.max_send_wr); - num_rqe = roundup_pow_of_two(attrs->cap.max_recv_wr); + if (num_sqe) + num_sqe = roundup_pow_of_two(num_sqe); + else { + /* Zero sized SQ is not supported */ + rv = -EINVAL; + goto err_out; + } + if (num_rqe) + num_rqe = roundup_pow_of_two(num_rqe);
if (udata) qp->sendq = vmalloc_user(num_sqe * sizeof(struct siw_sqe)); @@ -379,7 +389,6 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, qp->sendq = vzalloc(num_sqe * sizeof(struct siw_sqe));
if (qp->sendq == NULL) { - siw_dbg(base_dev, "SQ size %d alloc failed\n", num_sqe); rv = -ENOMEM; goto err_out_xa; } @@ -413,7 +422,6 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, qp->recvq = vzalloc(num_rqe * sizeof(struct siw_rqe));
if (qp->recvq == NULL) { - siw_dbg(base_dev, "RQ size %d alloc failed\n", num_rqe); rv = -ENOMEM; goto err_out_xa; } @@ -966,9 +974,9 @@ int siw_post_receive(struct ib_qp *base_qp, const struct ib_recv_wr *wr, unsigned long flags; int rv = 0;
- if (qp->srq) { + if (qp->srq || qp->attrs.rq_size == 0) { *bad_wr = wr; - return -EOPNOTSUPP; /* what else from errno.h? */ + return -EINVAL; } if (!rdma_is_kernel_res(&qp->base_qp.res)) { siw_dbg_qp(qp, "no kernel post_recv for user mapped rq\n");
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit cbc0ad004c03ad7971726a5db3ec84dba3dcb857 ]
A 'irq_dispose_mapping()' call is missing in the remove function. Add it.
This is needed to undo the 'irq_of_parse_and_map() call from the probe function and already part of the error handling path of the probe function.
It was added in the probe function only in commit d3f620b2c4fe ("fsldma: simplify IRQ probing and handling")
Fixes: 77cd62e8082b ("fsldma: allow Freescale Elo DMA driver to be compiled as a module") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/20201212160516.92515-1-christophe.jaillet@wanadoo.... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/fsldma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 0feb323bae1e3..554f70a0c18c0 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1314,6 +1314,7 @@ static int fsldma_of_remove(struct platform_device *op) if (fdev->chan[i]) fsl_dma_chan_remove(fdev->chan[i]); } + irq_dispose_mapping(fdev->irq);
iounmap(fdev->regs); kfree(fdev);
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit b202d4e82531a62a33a6b14d321dd2aad491578e ]
In case of error, the previous 'fsl_dma_chan_probe()' calls must be undone by some 'fsl_dma_chan_remove()', as already done in the remove function.
It was added in the remove function in commit 77cd62e8082b ("fsldma: allow Freescale Elo DMA driver to be compiled as a module")
Fixes: d3f620b2c4fe ("fsldma: simplify IRQ probing and handling") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/20201212160614.92576-1-christophe.jaillet@wanadoo.... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/fsldma.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 554f70a0c18c0..f8459cc5315df 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1214,6 +1214,7 @@ static int fsldma_of_probe(struct platform_device *op) { struct fsldma_device *fdev; struct device_node *child; + unsigned int i; int err;
fdev = kzalloc(sizeof(*fdev), GFP_KERNEL); @@ -1292,6 +1293,10 @@ static int fsldma_of_probe(struct platform_device *op) return 0;
out_free_fdev: + for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (fdev->chan[i]) + fsl_dma_chan_remove(fdev->chan[i]); + } irq_dispose_mapping(fdev->irq); iounmap(fdev->regs); out_free:
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 1f0a16f04113f9f0ab0c8e6d3abe661edab549e6 ]
A 'dma_pool_destroy()' call is missing in the remove function. Add it.
This call is already made in the error handling path of the probe function.
Fixes: 47e20577c24d ("dmaengine: Add Actions Semi Owl family S900 DMA driver") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/20201212162535.95727-1-christophe.jaillet@wanadoo.... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/owl-dma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 9fede32641e9e..04202d75f4eed 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -1245,6 +1245,7 @@ static int owl_dma_remove(struct platform_device *pdev) owl_dma_free(od);
clk_disable_unprepare(od->clk); + dma_pool_destroy(od->lli_pool);
return 0; }
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit def8550f543e6c9101f3e1a03160b2aab8c02e8a ]
With CONFIG_I2C=m, the #ifdef section is disabled, as shown by this warning:
drivers/rtc/rtc-rx6110.c:314:12: error: unused function 'rx6110_probe' [-Werror,-Wunused-function]
Change the driver to use IS_ENABLED() instead, which works for both module and built-in subsystems.
Fixes: afa819c2c6bf ("rtc: rx6110: add i2c support") Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20201230145938.3254459-1-arnd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/rtc-rx6110.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c index a7b671a210223..79161d4c6ce4d 100644 --- a/drivers/rtc/rtc-rx6110.c +++ b/drivers/rtc/rtc-rx6110.c @@ -331,7 +331,7 @@ static int rx6110_probe(struct rx6110_data *rx6110, struct device *dev) return 0; }
-#ifdef CONFIG_SPI_MASTER +#if IS_ENABLED(CONFIG_SPI_MASTER) static struct regmap_config regmap_spi_config = { .reg_bits = 8, .val_bits = 8, @@ -411,7 +411,7 @@ static void rx6110_spi_unregister(void) } #endif /* CONFIG_SPI_MASTER */
-#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static struct regmap_config regmap_i2c_config = { .reg_bits = 8, .val_bits = 8,
From: Nathan Chancellor natechancellor@gmail.com
[ Upstream commit 0a6d3038d914b51d6860f23ea2b508590e8340de ]
When building with CONFIG_UBSAN_UNSIGNED_OVERFLOW, clang decides not to inline gpi_update_reg, which causes a linkage failure around __bad_mask:
ld.lld: error: undefined symbol: __bad_mask
referenced by bitfield.h:119 (include/linux/bitfield.h:119) dma/qcom/gpi.o:(gpi_update_reg) in archive drivers/built-in.a referenced by bitfield.h:119 (include/linux/bitfield.h:119) dma/qcom/gpi.o:(gpi_update_reg) in archive drivers/built-in.a
If gpi_update_reg is not inlined, the mask value will not be known at compile time so the check in field_multiplier stays in the final object file, causing the above linkage failure. Always inline gpi_update_reg so that this check can never fail.
Fixes: 5d0c3533a19f ("dmaengine: qcom: Add GPI dma driver") Link: https://github.com/ClangBuiltLinux/linux/issues/1243 Signed-off-by: Nathan Chancellor natechancellor@gmail.com Link: https://lore.kernel.org/r/20210112191214.1264793-1-natechancellor@gmail.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/qcom/gpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 1a0bf6b0567a5..e48eb397f433d 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -584,7 +584,7 @@ static inline void gpi_write_reg_field(struct gpii *gpii, void __iomem *addr, gpi_write_reg(gpii, addr, val); }
-static inline void +static __always_inline void gpi_update_reg(struct gpii *gpii, u32 offset, u32 mask, u32 val) { void __iomem *addr = gpii->regs + offset;
From: Vignesh Raghavendra vigneshr@ti.com
[ Upstream commit aecf9d38361090857aa58708e500ee79bed1e273 ]
BCDMA RX channels have one flow per channel, therefore set the rflow_cnt to rchan_cnt.
Without this patch, request for BCDMA RX channel allocation fails as rflow_cnt is 0 thus fails to reserve a rflow for the channel.
Fixes: 8844898028d4 ("dmaengine: ti: k3-udma: Add support for BCDMA channel TPL handling") Signed-off-by: Vignesh Raghavendra vigneshr@ti.com Acked-by: Peter Ujfalusi peter.ujfalusi@gmail.com Link: https://lore.kernel.org/r/20210112141403.30286-1-vigneshr@ti.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/ti/k3-udma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index f474a12323354..46bc1a419bdfb 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -4306,6 +4306,7 @@ static int udma_get_mmrs(struct platform_device *pdev, struct udma_dev *ud) ud->bchan_cnt = BCDMA_CAP2_BCHAN_CNT(cap2); ud->tchan_cnt = BCDMA_CAP2_TCHAN_CNT(cap2); ud->rchan_cnt = BCDMA_CAP2_RCHAN_CNT(cap2); + ud->rflow_cnt = ud->rchan_cnt; break; case DMA_TYPE_PKTDMA: cap4 = udma_read(ud->mmrs[MMR_GCFG], 0x30);
From: Ferry Toth ftoth@exalondelft.nl
[ Upstream commit 035b73b2b3b2e074a56489a7bf84b6a8012c0e0d ]
On Intel Tangier B0 and Anniedale the interrupt line, disregarding to have different numbers, is shared between HSU DMA and UART IPs. Thus on such SoCs we are expecting that IRQ handler is called in UART driver only. hsu_pci_irq was handling the spurious interrupt from HSU DMA by returning immediately. This wastes CPU time and since HSU DMA and HSU UART interrupt occur simultaneously they race to be handled causing delay to the HSU UART interrupt handling. Fix this by disabling the interrupt entirely.
Fixes: 4831e0d9054c ("serial: 8250_mid: handle interrupt correctly in DMA case") Signed-off-by: Ferry Toth ftoth@exalondelft.nl Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Link: https://lore.kernel.org/r/20210112223749.97036-1-ftoth@exalondelft.nl Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/hsu/pci.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c index 07cc7320a614f..9045a6f7f5893 100644 --- a/drivers/dma/hsu/pci.c +++ b/drivers/dma/hsu/pci.c @@ -26,22 +26,12 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) { struct hsu_dma_chip *chip = dev; - struct pci_dev *pdev = to_pci_dev(chip->dev); u32 dmaisr; u32 status; unsigned short i; int ret = 0; int err;
- /* - * On Intel Tangier B0 and Anniedale the interrupt line, disregarding - * to have different numbers, is shared between HSU DMA and UART IPs. - * Thus on such SoCs we are expecting that IRQ handler is called in - * UART driver only. - */ - if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA) - return IRQ_HANDLED; - dmaisr = readl(chip->regs + HSU_PCI_DMAISR); for (i = 0; i < chip->hsu->nr_channels; i++) { if (dmaisr & 0x1) { @@ -105,6 +95,17 @@ static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_register_irq;
+ /* + * On Intel Tangier B0 and Anniedale the interrupt line, disregarding + * to have different numbers, is shared between HSU DMA and UART IPs. + * Thus on such SoCs we are expecting that IRQ handler is called in + * UART driver only. Instead of handling the spurious interrupt + * from HSU DMA here and waste CPU time and delay HSU UART interrupt + * handling, disable the interrupt entirely. + */ + if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA) + disable_irq_nosync(chip->irq); + pci_set_drvdata(pdev, chip);
return 0;
From: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com
[ Upstream commit c58ad0f2b052b5675d6394e03713ee41e721b44c ]
To remove mfd devices when unload this driver, should use devm_mfd_add_devices() instead.
Fixes: d3ea21272094 ("mfd: Add ROHM BD9571MWV-M MFD PMIC driver") Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Acked-for-MFD-by: Lee Jones lee.jones@linaro.org Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Matti Vaittinen matti.vaittinen@fi.rohmeurope.com Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mfd/bd9571mwv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index fab3cdc27ed64..19d57a45134c6 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -185,9 +185,9 @@ static int bd9571mwv_probe(struct i2c_client *client, return ret; }
- ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells, - ARRAY_SIZE(bd9571mwv_cells), NULL, 0, - regmap_irq_get_domain(bd->irq_data)); + ret = devm_mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, + bd9571mwv_cells, ARRAY_SIZE(bd9571mwv_cells), + NULL, 0, regmap_irq_get_domain(bd->irq_data)); if (ret) { regmap_del_irq_chip(bd->irq, bd->irq_data); return ret;
From: Tony Lindgren tony@atomide.com
[ Upstream commit 4bff91bb3231882b530af794c92ac3a5fe199481 ]
Fix missing power_supply_put().
Cc: Arthur Demchenkov spinal.by@gmail.com Cc: Carl Philipp Klemm philipp@uvos.xyz Cc: Merlijn Wajer merlijn@wizzup.org Cc: Pavel Machek pavel@ucw.cz Fixes: 5688ea049233 ("power: supply: cpcap-charger: Allow changing constant charge voltage") Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/cpcap-charger.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index 804ac7f84c301..2c5f2246c6eaa 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -302,6 +302,7 @@ cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata) if (!error) voltage = prop.intval; } + power_supply_put(battery);
return voltage; }
From: Tony Lindgren tony@atomide.com
[ Upstream commit 97456a24acb41b74ab6910f40fb8f09b206fd3b5 ]
Fix missing power_supply_put().
Cc: Arthur Demchenkov spinal.by@gmail.com Cc: Carl Philipp Klemm philipp@uvos.xyz Cc: Merlijn Wajer merlijn@wizzup.org Cc: Pavel Machek pavel@ucw.cz Fixes: 8b0134cc14b9 ("power: supply: cpcap-battery: Fix handling of lowered charger voltage") Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/cpcap-battery.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index 7a974b5bd9dd1..cebc5c8fda1b5 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -561,17 +561,21 @@ static int cpcap_battery_update_charger(struct cpcap_battery_ddata *ddata, POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, &prop); if (error) - return error; + goto out_put;
/* Allow charger const voltage lower than battery const voltage */ if (const_charge_voltage > prop.intval) - return 0; + goto out_put;
val.intval = const_charge_voltage;
- return power_supply_set_property(charger, + error = power_supply_set_property(charger, POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, &val); +out_put: + power_supply_put(charger); + + return error; }
static int cpcap_battery_set_property(struct power_supply *psy,
From: Can Guo cang@codeaurora.org
[ Upstream commit fb7afe24ba1b7e27483be7d2ac3ed002e67eecd5 ]
During system resume/suspend, hba could be NULL. In this case, do not touch eh_sem.
Fixes: 88a92d6ae4fe ("scsi: ufs: Serialize eh_work with system PM events and async scan") Link: https://lore.kernel.org/r/1610594010-7254-2-git-send-email-cang@codeaurora.o... Acked-by: Stanley Chu stanley.chu@mediatek.com Signed-off-by: Can Guo cang@codeaurora.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index fb32d122f2e38..728168cd18f55 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -94,6 +94,8 @@ 16, 4, buf, __len, false); \ } while (0)
+static bool early_suspend; + int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, const char *prefix) { @@ -8939,8 +8941,14 @@ int ufshcd_system_suspend(struct ufs_hba *hba) int ret = 0; ktime_t start = ktime_get();
+ if (!hba) { + early_suspend = true; + return 0; + } + down(&hba->eh_sem); - if (!hba || !hba->is_powered) + + if (!hba->is_powered) return 0;
if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) == @@ -8989,9 +8997,12 @@ int ufshcd_system_resume(struct ufs_hba *hba) int ret = 0; ktime_t start = ktime_get();
- if (!hba) { - up(&hba->eh_sem); + if (!hba) return -EINVAL; + + if (unlikely(early_suspend)) { + early_suspend = false; + down(&hba->eh_sem); }
if (!hba->is_powered || pm_runtime_suspended(hba->dev))
From: Colin Ian King colin.king@canonical.com
[ Upstream commit 39196cfe10dd2b46ee28b44abbc0db4f4cb7822f ]
Currently if the pointer battery is null there is a null pointer dereference on the call to power_supply_put. Fix this by only performing the put if battery is not null.
Addresses-Coverity: ("Dereference after null check") Fixes: 4bff91bb3231 ("power: supply: cpcap-charger: Fix missing power_supply_put()") Signed-off-by: Colin Ian King colin.king@canonical.com Acked-by: Tony Lindgren tony@atomide.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/cpcap-charger.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index 2c5f2246c6eaa..22fff01425d63 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -301,8 +301,9 @@ cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata) &prop); if (!error) voltage = prop.intval; + + power_supply_put(battery); } - power_supply_put(battery);
return voltage; }
From: KarimAllah Ahmed karahmed@amazon.de
[ Upstream commit 86588296acbfb1591e92ba60221e95677ecadb43 ]
Mark the memory region with NOMAP flag instead of completely removing it from the memory blocks. That makes the FDT handling consistent with the EFI memory map handling.
Cc: Rob Herring robh+dt@kernel.org Cc: Frank Rowand frowand.list@gmail.com Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: KarimAllah Ahmed karahmed@amazon.de Signed-off-by: Quentin Perret qperret@google.com Link: https://lore.kernel.org/r/20210115114544.1830068-2-qperret@google.com Signed-off-by: Rob Herring robh@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/of/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index feb0f2d67fc5f..427b534d60d2d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1147,7 +1147,7 @@ int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { if (nomap) - return memblock_remove(base, size); + return memblock_mark_nomap(base, size); return memblock_reserve(base, size); }
From: Nicolas Boichat drinkcat@chromium.org
[ Upstream commit 8a5a75e5e9e55de1cef5d83ca3589cb4899193ef ]
If the device tree is incorrectly configured, and attempts to define a "no-map" reserved memory that overlaps with the kernel data/code, the kernel would crash quickly after boot, with no obvious clue about the nature of the issue.
For example, this would happen if we have the kernel mapped at these addresses (from /proc/iomem): 40000000-41ffffff : System RAM 40080000-40dfffff : Kernel code 40e00000-411fffff : reserved 41200000-413e0fff : Kernel data
And we declare a no-map shared-dma-pool region at a fixed address within that range: mem_reserved: mem_region { compatible = "shared-dma-pool"; reg = <0 0x40000000 0 0x01A00000>; no-map; };
To fix this, when removing memory regions at early boot (which is what "no-map" regions do), we need to make sure that the memory is not already reserved. If we do, __reserved_mem_reserve_reg will throw an error: [ 0.000000] OF: fdt: Reserved memory: failed to reserve memory for node 'mem_region': base 0x0000000040000000, size 26 MiB and the code that will try to use the region should also fail, later on.
We do not do anything for non-"no-map" regions, as memblock explicitly allows reserved regions to overlap, and the commit that this fixes removed the check for that precise reason.
[ qperret: fixed conflicts caused by the usage of memblock_mark_nomap ]
Fixes: 094cb98179f19b7 ("of/fdt: memblock_reserve /memreserve/ regions in the case of partial overlap") Signed-off-by: Nicolas Boichat drinkcat@chromium.org Reviewed-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Quentin Perret qperret@google.com Link: https://lore.kernel.org/r/20210115114544.1830068-3-qperret@google.com Signed-off-by: Rob Herring robh@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/of/fdt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 427b534d60d2d..dcc1dd96911a9 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1146,8 +1146,16 @@ int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { - if (nomap) + if (nomap) { + /* + * If the memory is already reserved (by another region), we + * should not allow it to be marked nomap. + */ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + return memblock_mark_nomap(base, size); + } return memblock_reserve(base, size); }
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit 7490fd1fe836ba3c7eda7a4b1cfd9e44389ffda5 ]
rtrs does not have same limit for both max_send_wr and max_recv_wr, To allow client and server set different values, export in a separate parameter for rtrs_cq_qp_create.
Also fix the type accordingly, u32 should be used instead of u16.
Fixes: c0894b3ea69d ("RDMA/rtrs: core: lib functions shared between client and server modules") Link: https://lore.kernel.org/r/20201217141915.56989-2-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 4 ++-- drivers/infiniband/ulp/rtrs/rtrs-pri.h | 5 +++-- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 5 +++-- drivers/infiniband/ulp/rtrs/rtrs.c | 14 ++++++++------ 4 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 67f86c405a265..719254fc83a1c 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -1511,7 +1511,7 @@ static void destroy_con(struct rtrs_clt_con *con) static int create_con_cq_qp(struct rtrs_clt_con *con) { struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); - u16 wr_queue_size; + u32 wr_queue_size; int err, cq_vector; struct rtrs_msg_rkey_rsp *rsp;
@@ -1573,7 +1573,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) cq_vector = con->cpu % sess->s.dev->ib_dev->num_comp_vectors; err = rtrs_cq_qp_create(&sess->s, &con->c, sess->max_send_sge, cq_vector, wr_queue_size, wr_queue_size, - IB_POLL_SOFTIRQ); + wr_queue_size, IB_POLL_SOFTIRQ); /* * In case of error we do not bother to clean previous allocations, * since destroy_con_cq_qp() must be called. diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h index 3f2918671dbed..d5621e6fad1b1 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h +++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h @@ -303,8 +303,9 @@ int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con, struct ib_cqe *cqe, struct ib_send_wr *head);
int rtrs_cq_qp_create(struct rtrs_sess *rtrs_sess, struct rtrs_con *con, - u32 max_send_sge, int cq_vector, u16 cq_size, - u16 wr_queue_size, enum ib_poll_context poll_ctx); + u32 max_send_sge, int cq_vector, int cq_size, + u32 max_send_wr, u32 max_recv_wr, + enum ib_poll_context poll_ctx); void rtrs_cq_qp_destroy(struct rtrs_con *con);
void rtrs_init_hb(struct rtrs_sess *sess, struct ib_cqe *cqe, diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index c42fd470c4eb4..ed4628f032bb6 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1586,7 +1586,7 @@ static int create_con(struct rtrs_srv_sess *sess, struct rtrs_sess *s = &sess->s; struct rtrs_srv_con *con;
- u16 cq_size, wr_queue_size; + u32 cq_size, wr_queue_size; int err, cq_vector;
con = kzalloc(sizeof(*con), GFP_KERNEL); @@ -1630,7 +1630,8 @@ static int create_con(struct rtrs_srv_sess *sess,
/* TODO: SOFTIRQ can be faster, but be careful with softirq context */ err = rtrs_cq_qp_create(&sess->s, &con->c, 1, cq_vector, cq_size, - wr_queue_size, IB_POLL_WORKQUEUE); + wr_queue_size, wr_queue_size, + IB_POLL_WORKQUEUE); if (err) { rtrs_err(s, "rtrs_cq_qp_create(), err: %d\n", err); goto free_con; diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c index 2e3a849e0a77c..df52427f17106 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs.c @@ -231,14 +231,14 @@ static int create_cq(struct rtrs_con *con, int cq_vector, u16 cq_size, }
static int create_qp(struct rtrs_con *con, struct ib_pd *pd, - u16 wr_queue_size, u32 max_sge) + u32 max_send_wr, u32 max_recv_wr, u32 max_sge) { struct ib_qp_init_attr init_attr = {NULL}; struct rdma_cm_id *cm_id = con->cm_id; int ret;
- init_attr.cap.max_send_wr = wr_queue_size; - init_attr.cap.max_recv_wr = wr_queue_size; + init_attr.cap.max_send_wr = max_send_wr; + init_attr.cap.max_recv_wr = max_recv_wr; init_attr.cap.max_recv_sge = 1; init_attr.event_handler = qp_event_handler; init_attr.qp_context = con; @@ -260,8 +260,9 @@ static int create_qp(struct rtrs_con *con, struct ib_pd *pd, }
int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con, - u32 max_send_sge, int cq_vector, u16 cq_size, - u16 wr_queue_size, enum ib_poll_context poll_ctx) + u32 max_send_sge, int cq_vector, int cq_size, + u32 max_send_wr, u32 max_recv_wr, + enum ib_poll_context poll_ctx) { int err;
@@ -269,7 +270,8 @@ int rtrs_cq_qp_create(struct rtrs_sess *sess, struct rtrs_con *con, if (err) return err;
- err = create_qp(con, sess->dev->ib_pd, wr_queue_size, max_send_sge); + err = create_qp(con, sess->dev->ib_pd, max_send_wr, max_recv_wr, + max_send_sge); if (err) { ib_free_cq(con->cq); con->cq = NULL;
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit 99f0c3807973359bba8f37d9198eea59fe38c32a ]
In this error case, we don't need hold mutex to call close_sess.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-4-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Tested-by: Lutz Pogrell lutz.pogrell@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index ed4628f032bb6..341661f42add0 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1863,8 +1863,8 @@ reject_w_econnreset: return rtrs_rdma_do_reject(cm_id, -ECONNRESET);
close_and_return_err: - close_sess(sess); mutex_unlock(&srv->paths_mutex); + close_sess(sess);
return err; }
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit f991fdac813f1598a9bb17b602ce04812ba9148c ]
Remove self first to avoid deadlock, we don't want to use close_work to remove sess sysfs.
Fixes: 91b11610af8d ("RDMA/rtrs: server: sysfs interface functions") Link: https://lore.kernel.org/r/20201217141915.56989-5-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Tested-by: Lutz Pogrell lutz.pogrell@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c index d2edff3b8f0df..cca3a0acbabc5 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c @@ -51,6 +51,8 @@ static ssize_t rtrs_srv_disconnect_store(struct kobject *kobj, sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, str, sizeof(str));
rtrs_info(s, "disconnect for path %s requested\n", str); + /* first remove sysfs itself to avoid deadlock */ + sysfs_remove_file_self(&sess->kobj, &attr->attr); close_sess(sess);
return count;
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit f47e4e3e71724f625958b0059f6c8ac5d44d27ef ]
Currently rtrs when create_qp use a coarse numbers (bigger in general), which leads to hardware create more resources which only waste memory with no benefits.
- SERVICE con, For max_send_wr/max_recv_wr, it's 2 times SERVICE_CON_QUEUE_DEPTH + 2
- IO con For max_send_wr/max_recv_wr, it's sess->queue_depth * 3 + 1
Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-6-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 719254fc83a1c..b3fb5fb93815f 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -1511,7 +1511,7 @@ static void destroy_con(struct rtrs_clt_con *con) static int create_con_cq_qp(struct rtrs_clt_con *con) { struct rtrs_clt_sess *sess = to_clt_sess(con->c.sess); - u32 wr_queue_size; + u32 max_send_wr, max_recv_wr, cq_size; int err, cq_vector; struct rtrs_msg_rkey_rsp *rsp;
@@ -1523,7 +1523,8 @@ static int create_con_cq_qp(struct rtrs_clt_con *con) * + 2 for drain and heartbeat * in case qp gets into error state */ - wr_queue_size = SERVICE_CON_QUEUE_DEPTH * 3 + 2; + max_send_wr = SERVICE_CON_QUEUE_DEPTH * 2 + 2; + max_recv_wr = SERVICE_CON_QUEUE_DEPTH * 2 + 2; /* We must be the first here */ if (WARN_ON(sess->s.dev)) return -EINVAL; @@ -1555,25 +1556,29 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
/* Shared between connections */ sess->s.dev_ref++; - wr_queue_size = + max_send_wr = min_t(int, sess->s.dev->ib_dev->attrs.max_qp_wr, /* QD * (REQ + RSP + FR REGS or INVS) + drain */ sess->queue_depth * 3 + 1); + max_recv_wr = + min_t(int, sess->s.dev->ib_dev->attrs.max_qp_wr, + sess->queue_depth * 3 + 1); } /* alloc iu to recv new rkey reply when server reports flags set */ if (sess->flags == RTRS_MSG_NEW_RKEY_F || con->c.cid == 0) { - con->rsp_ius = rtrs_iu_alloc(wr_queue_size, sizeof(*rsp), + con->rsp_ius = rtrs_iu_alloc(max_recv_wr, sizeof(*rsp), GFP_KERNEL, sess->s.dev->ib_dev, DMA_FROM_DEVICE, rtrs_clt_rdma_done); if (!con->rsp_ius) return -ENOMEM; - con->queue_size = wr_queue_size; + con->queue_size = max_recv_wr; } + cq_size = max_send_wr + max_recv_wr; cq_vector = con->cpu % sess->s.dev->ib_dev->num_comp_vectors; err = rtrs_cq_qp_create(&sess->s, &con->c, sess->max_send_sge, - cq_vector, wr_queue_size, wr_queue_size, - wr_queue_size, IB_POLL_SOFTIRQ); + cq_vector, cq_size, max_send_wr, + max_recv_wr, IB_POLL_SOFTIRQ); /* * In case of error we do not bother to clean previous allocations, * since destroy_con_cq_qp() must be called.
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
[ Upstream commit f77c4839ee8f4612dcb6601602329096030bd813 ]
The rtrs_iu_free is called in rtrs_iu_alloc if memory is limited, so we don't need to free the same iu again.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-7-jinpu.wang@cloud.ionos.com Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Reviewed-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 341661f42add0..92a216ddd9fd3 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -651,7 +651,7 @@ static int map_cont_bufs(struct rtrs_srv_sess *sess) if (!srv_mr->iu) { err = -ENOMEM; rtrs_err(ss, "rtrs_iu_alloc(), err: %d\n", err); - goto free_iu; + goto dereg_mr; } } /* Eventually dma addr for each chunk can be cached */ @@ -667,7 +667,6 @@ err: srv_mr = &sess->mrs[mri]; sgt = &srv_mr->sgt; mr = srv_mr->mr; -free_iu: rtrs_iu_free(srv_mr->iu, sess->s.dev->ib_dev, 1); dereg_mr: ib_dereg_mr(mr);
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
[ Upstream commit 424774c9f3fa100ef7d9cfb9ee211e2ba1cd5119 ]
Per the comment of kobject_init_and_add, we need to free the memory by call kobject_put.
Fixes: 215378b838df ("RDMA/rtrs: client: sysfs interface functions") Fixes: 91b11610af8d ("RDMA/rtrs: server: sysfs interface functions") Link: https://lore.kernel.org/r/20201217141915.56989-8-jinpu.wang@cloud.ionos.com Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Reviewed-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Reviewed-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 ++ drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c index ba00f0de14caa..ad77659800cd2 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c @@ -408,6 +408,7 @@ int rtrs_clt_create_sess_files(struct rtrs_clt_sess *sess) "%s", str); if (err) { pr_err("kobject_init_and_add: %d\n", err); + kobject_put(&sess->kobj); return err; } err = sysfs_create_group(&sess->kobj, &rtrs_clt_sess_attr_group); @@ -419,6 +420,7 @@ int rtrs_clt_create_sess_files(struct rtrs_clt_sess *sess) &sess->kobj, "stats"); if (err) { pr_err("kobject_init_and_add: %d\n", err); + kobject_put(&sess->stats->kobj_stats); goto remove_group; }
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c index cca3a0acbabc5..0a3886629cae8 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c @@ -236,6 +236,7 @@ static int rtrs_srv_create_stats_files(struct rtrs_srv_sess *sess) &sess->kobj, "stats"); if (err) { rtrs_err(s, "kobject_init_and_add(): %d\n", err); + kobject_put(&sess->stats->kobj_stats); return err; } err = sysfs_create_group(&sess->stats->kobj_stats, @@ -292,8 +293,8 @@ remove_group: sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group); put_kobj: kobject_del(&sess->kobj); - kobject_put(&sess->kobj); destroy_root: + kobject_put(&sess->kobj); rtrs_srv_destroy_once_sysfs_root_folders(sess);
return err;
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit 8537f2de6519945890a2b0f3739b23f32b5c0a89 ]
We had a few places wr_cqe is not set, which could lead to NULL pointer deref or GPF in error case.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-14-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 92a216ddd9fd3..f59731c5a96a3 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -267,6 +267,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) WARN_ON_ONCE(rkey != wr->rkey);
wr->wr.opcode = IB_WR_RDMA_WRITE; + wr->wr.wr_cqe = &io_comp_cqe; wr->wr.ex.imm_data = 0; wr->wr.send_flags = 0;
@@ -294,6 +295,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) inv_wr.sg_list = NULL; inv_wr.num_sge = 0; inv_wr.opcode = IB_WR_SEND_WITH_INV; + inv_wr.wr_cqe = &io_comp_cqe; inv_wr.send_flags = 0; inv_wr.ex.invalidate_rkey = rkey; } @@ -304,6 +306,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id)
srv_mr = &sess->mrs[id->msg_id]; rwr.wr.opcode = IB_WR_REG_MR; + rwr.wr.wr_cqe = &local_reg_cqe; rwr.wr.num_sge = 0; rwr.mr = srv_mr->mr; rwr.wr.send_flags = 0; @@ -379,6 +382,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
if (need_inval) { if (likely(sg_cnt)) { + inv_wr.wr_cqe = &io_comp_cqe; inv_wr.sg_list = NULL; inv_wr.num_sge = 0; inv_wr.opcode = IB_WR_SEND_WITH_INV; @@ -421,6 +425,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, srv_mr = &sess->mrs[id->msg_id]; rwr.wr.next = &imm_wr; rwr.wr.opcode = IB_WR_REG_MR; + rwr.wr.wr_cqe = &local_reg_cqe; rwr.wr.num_sge = 0; rwr.wr.send_flags = 0; rwr.mr = srv_mr->mr;
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
[ Upstream commit eab098246625e91c1cbd6e8f75b09e4c9c28a9fc ]
Make all failure cases go to the common path to avoid duplicate code. And some issued existed before.
1. clt need to be freed to avoid memory leak.
2. return ERR_PTR(-ENOMEM) if kobject_create_and_add fails, because rtrs_clt_open checks the return value of by call "IS_ERR(clt)".
Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-15-jinpu.wang@cloud.ionos.com Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Reviewed-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index b3fb5fb93815f..172bf7f221ff0 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -2570,11 +2570,8 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num, clt->dev.class = rtrs_clt_dev_class; clt->dev.release = rtrs_clt_dev_release; err = dev_set_name(&clt->dev, "%s", sessname); - if (err) { - free_percpu(clt->pcpu_path); - kfree(clt); - return ERR_PTR(err); - } + if (err) + goto err; /* * Suppress user space notification until * sysfs files are created @@ -2582,29 +2579,31 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num, dev_set_uevent_suppress(&clt->dev, true); err = device_register(&clt->dev); if (err) { - free_percpu(clt->pcpu_path); put_device(&clt->dev); - return ERR_PTR(err); + goto err; }
clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj); if (!clt->kobj_paths) { - free_percpu(clt->pcpu_path); - device_unregister(&clt->dev); - return NULL; + err = -ENOMEM; + goto err_dev; } err = rtrs_clt_create_sysfs_root_files(clt); if (err) { - free_percpu(clt->pcpu_path); kobject_del(clt->kobj_paths); kobject_put(clt->kobj_paths); - device_unregister(&clt->dev); - return ERR_PTR(err); + goto err_dev; } dev_set_uevent_suppress(&clt->dev, false); kobject_uevent(&clt->dev.kobj, KOBJ_ADD);
return clt; +err_dev: + device_unregister(&clt->dev); +err: + free_percpu(clt->pcpu_path); + kfree(clt); + return ERR_PTR(err); }
static void wait_for_inflight_permits(struct rtrs_clt *clt)
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit 6f5d1b3016d650f351e65c645a5eee5394547dd0 ]
Fix up wr_avail accounting. if wr_cnt is 0, then we do SIGNAL for first wr, in completion we add queue_depth back, which is not right in the sense of tracking for available wr.
So fix it by init wr_cnt to 1.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20201217141915.56989-19-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index f59731c5a96a3..d017ede304b76 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1604,7 +1604,7 @@ static int create_con(struct rtrs_srv_sess *sess, con->c.cm_id = cm_id; con->c.sess = &sess->s; con->c.cid = cid; - atomic_set(&con->wr_cnt, 0); + atomic_set(&con->wr_cnt, 1);
if (con->c.cid == 0) { /*
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit 7fbc3c373eefc291ff96d48496106c106b7f81c6 ]
When KASAN is enabled, we notice warning below: [ 483.436975] ================================================================== [ 483.437234] BUG: KASAN: stack-out-of-bounds in _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.437430] Read of size 4 at addr ffff88a195fd7d30 by task kworker/1:3/6954
[ 483.437731] CPU: 1 PID: 6954 Comm: kworker/1:3 Kdump: loaded Tainted: G O 5.4.82-pserver #5.4.82-1+feature+linux+5.4.y+dbg+20201210.1532+987e7a6~deb10 [ 483.437976] Hardware name: Supermicro Super Server/X11DDW-L, BIOS 3.3 02/21/2020 [ 483.438168] Workqueue: rtrs_server_wq hb_work [rtrs_core] [ 483.438323] Call Trace: [ 483.438486] dump_stack+0x96/0xe0 [ 483.438646] ? _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.438802] print_address_description.constprop.6+0x1b/0x220 [ 483.438966] ? _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.439133] ? _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.439285] __kasan_report.cold.9+0x1a/0x32 [ 483.439444] ? _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.439597] kasan_report+0x10/0x20 [ 483.439752] _mlx5_ib_post_send+0x188a/0x2560 [mlx5_ib] [ 483.439910] ? update_sd_lb_stats+0xfb1/0xfc0 [ 483.440073] ? set_reg_wr+0x520/0x520 [mlx5_ib] [ 483.440222] ? update_group_capacity+0x340/0x340 [ 483.440377] ? find_busiest_group+0x314/0x870 [ 483.440526] ? update_sd_lb_stats+0xfc0/0xfc0 [ 483.440683] ? __bitmap_and+0x6f/0x100 [ 483.440832] ? __lock_acquire+0xa2/0x2150 [ 483.440979] ? __lock_acquire+0xa2/0x2150 [ 483.441128] ? __lock_acquire+0xa2/0x2150 [ 483.441279] ? debug_lockdep_rcu_enabled+0x23/0x60 [ 483.441430] ? lock_downgrade+0x390/0x390 [ 483.441582] ? __lock_acquire+0xa2/0x2150 [ 483.441729] ? __lock_acquire+0xa2/0x2150 [ 483.441876] ? newidle_balance+0x425/0x8f0 [ 483.442024] ? __lock_acquire+0xa2/0x2150 [ 483.442172] ? debug_lockdep_rcu_enabled+0x23/0x60 [ 483.442330] hb_work+0x15d/0x1d0 [rtrs_core] [ 483.442479] ? schedule_hb+0x50/0x50 [rtrs_core] [ 483.442627] ? lock_downgrade+0x390/0x390 [ 483.442781] ? process_one_work+0x40d/0xa50 [ 483.442931] process_one_work+0x4ee/0xa50 [ 483.443082] ? pwq_dec_nr_in_flight+0x110/0x110 [ 483.443231] ? do_raw_spin_lock+0x119/0x1d0 [ 483.443383] worker_thread+0x65/0x5c0 [ 483.443532] ? process_one_work+0xa50/0xa50 [ 483.451839] kthread+0x1e2/0x200 [ 483.451983] ? kthread_create_on_node+0xc0/0xc0 [ 483.452139] ret_from_fork+0x3a/0x50
The problem is we use wrong type when send wr, hw driver expect the type of IB_WR_RDMA_WRITE_WITH_IMM wr should be ib_rdma_wr, and doing container_of to access member. The fix is simple use ib_rdma_wr instread of ib_send_wr.
Fixes: c0894b3ea69d ("RDMA/rtrs: core: lib functions shared between client and server modules") Link: https://lore.kernel.org/r/20201217141915.56989-20-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c index df52427f17106..da4ff764dd3f0 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs.c @@ -182,16 +182,16 @@ int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con, struct ib_cqe *cqe, u32 imm_data, enum ib_send_flags flags, struct ib_send_wr *head) { - struct ib_send_wr wr; + struct ib_rdma_wr wr;
- wr = (struct ib_send_wr) { - .wr_cqe = cqe, - .send_flags = flags, - .opcode = IB_WR_RDMA_WRITE_WITH_IMM, - .ex.imm_data = cpu_to_be32(imm_data), + wr = (struct ib_rdma_wr) { + .wr.wr_cqe = cqe, + .wr.send_flags = flags, + .wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM, + .wr.ex.imm_data = cpu_to_be32(imm_data), };
- return rtrs_post_send(con->qp, head, &wr); + return rtrs_post_send(con->qp, head, &wr.wr); } EXPORT_SYMBOL_GPL(rtrs_post_rdma_write_imm_empty);
From: Claudiu Beznea claudiu.beznea@microchip.com
[ Upstream commit 95aa21a3f1183260db1b0395e03df5bebc5ed641 ]
According to datasheet WKUPDBC mask is b/w bits 26..24.
Fixes: f80cb48843987 ("power: reset: at91-shdwc: add new shutdown controller driver") Signed-off-by: Claudiu Beznea claudiu.beznea@microchip.com Reviewed-by: Alexandre Belloni alexandre.belloni@bootlin.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/reset/at91-sama5d2_shdwc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c index 2fe3a627cb535..d9cf91e5b06d0 100644 --- a/drivers/power/reset/at91-sama5d2_shdwc.c +++ b/drivers/power/reset/at91-sama5d2_shdwc.c @@ -37,7 +37,7 @@
#define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */ #define AT91_SHDW_WKUPDBC_SHIFT 24 -#define AT91_SHDW_WKUPDBC_MASK GENMASK(31, 16) +#define AT91_SHDW_WKUPDBC_MASK GENMASK(26, 24) #define AT91_SHDW_WKUPDBC(x) (((x) << AT91_SHDW_WKUPDBC_SHIFT) \ & AT91_SHDW_WKUPDBC_MASK)
From: Bartosz Golaszewski bgolaszewski@baylibre.com
[ Upstream commit 1f0cbda3b452b520c5f3794f8f0e410e8bc7386a ]
The rtc-s5m uses the I2C regmap but doesn't select it in Kconfig so depending on the configuration the build may fail. Fix it.
Fixes: 959df7778bbd ("rtc: Enable compile testing for Maxim and Samsung drivers") Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Reviewed-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210114102219.23682-2-brgl@bgdev.pl Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6123f9f4fbc90..e4bef40831c75 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -692,6 +692,7 @@ config RTC_DRV_S5M tristate "Samsung S2M/S5M series" depends on MFD_SEC_CORE || COMPILE_TEST select REGMAP_IRQ + select REGMAP_I2C help If you say yes here you will get support for the RTC of Samsung S2MPS14 and S5M PMIC series.
From: Dave Jiang dave.jiang@intel.com
[ Upstream commit c06e424be5f5184468c5f761c0d2cf1ed0a4e0fc ]
Add DMA_PRIVATE attribute flag to idxd DMA channels. The dedicated WQs are expected to be used by a single client and not shared. While doing NTB testing this mistake was discovered, which prevented ntb_transport from requesting DSA wqs as DMA channels via dma_request_channel().
Reported-by: Srinijia Kambham srinija.kambham@intel.com Signed-off-by: Dave Jiang dave.jiang@intel.com Tested-by: Srinijia Kambham srinija.kambham@intel.com Fixes: 8f47d1a5e545 ("dmaengine: idxd: connect idxd to dmaengine subsystem") Link: https://lore.kernel.org/r/161074758743.2184057.3388557138816350980.stgit@dji... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/idxd/dma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c index 71fd6e4c42cd7..a15e50126434e 100644 --- a/drivers/dma/idxd/dma.c +++ b/drivers/dma/idxd/dma.c @@ -165,6 +165,7 @@ int idxd_register_dma_device(struct idxd_device *idxd) INIT_LIST_HEAD(&dma->channels); dma->dev = &idxd->pdev->dev;
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask); dma_cap_set(DMA_COMPLETION_NO_ORDER, dma->cap_mask); dma->device_release = idxd_dma_release;
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit a4bdea2004b28f47ab48ea99172eda8628f6fb44 ]
CHARGER_SBS should select REGMAP_I2C since it uses API(s) that are provided by that Kconfig symbol.
Fixes these errors:
../drivers/power/supply/sbs-charger.c:149:21: error: variable ‘sbs_regmap’ has initializer but incomplete type static const struct regmap_config sbs_regmap = { ../drivers/power/supply/sbs-charger.c:150:3: error: ‘const struct regmap_config’ has no member named ‘reg_bits’ .reg_bits = 8, ../drivers/power/supply/sbs-charger.c:155:23: error: ‘REGMAP_ENDIAN_LITTLE’ undeclared here (not in a function) .val_format_endian = REGMAP_ENDIAN_LITTLE, /* since based on SMBus */ ../drivers/power/supply/sbs-charger.c: In function ‘sbs_probe’: ../drivers/power/supply/sbs-charger.c:183:17: error: implicit declaration of function ‘devm_regmap_init_i2c’; did you mean ‘devm_request_irq’? [-Werror=implicit-function-declaration] chip->regmap = devm_regmap_init_i2c(client, &sbs_regmap); ../drivers/power/supply/sbs-charger.c: At top level: ../drivers/power/supply/sbs-charger.c:149:35: error: storage size of ‘sbs_regmap’ isn’t known static const struct regmap_config sbs_regmap = {
Fixes: feb583e37f8a ("power: supply: add sbs-charger driver") Reported-by: Martin Mokrejs mmokrejs@fold.natur.cuni.cz Signed-off-by: Randy Dunlap rdunlap@infradead.org Tested-by: Martin Mokrejs mmokrejs@fold.natur.cuni.cz Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index eec646c568b7b..1699b9269a78e 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -229,6 +229,7 @@ config BATTERY_SBS config CHARGER_SBS tristate "SBS Compliant charger" depends on I2C + select REGMAP_I2C help Say Y to include support for SBS compliant battery chargers.
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 7a3b8758bd6e45f7b671723b5c9fa2b69d0787ae ]
Compile-testing the ixp4xx timer with CONFIG_OF enabled but CONFIG_TIMER_OF disabled leads to a harmless warning:
arm-linux-gnueabi-ld: warning: orphan section `__timer_of_table' from `drivers/clocksource/timer-ixp4xx.o' being placed in section `__timer_of_table'
Move the select statement from the platform code into the driver so it always gets enabled in configurations that rely on it.
Fixes: 40df14cc5cc0 ("clocksource/drivers/ixp4xx: Add OF initialization support") Signed-off-by: Arnd Bergmann arnd@arndb.de Reviewed-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210103135955.3808976-1-arnd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/mach-ixp4xx/Kconfig | 1 - drivers/clocksource/Kconfig | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index f7211b57b1e78..165c184801e19 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -13,7 +13,6 @@ config MACH_IXP4XX_OF select I2C select I2C_IOP3XX select PCI - select TIMER_OF select USE_OF help Say 'Y' here to support Device Tree-based IXP4xx platforms. diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 14c7c47124787..66be9ea69e332 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -79,6 +79,7 @@ config IXP4XX_TIMER bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST depends on HAS_IOMEM select CLKSRC_MMIO + select TIMER_OF if OF help Enables support for the Intel XScale IXP4xx SoC timer.
From: Tom Rix trix@redhat.com
[ Upstream commit 7da390694afbaed8e0f05717a541dfaf1077ba51 ]
When DEBUG is defined this error occurs
drivers/clocksource/mxs_timer.c:138:1: error: expected ‘;’ before ‘}’ token
The preceding statement needs a semicolon. Replace pr_info() with pr_debug() and remove the unneeded ifdef.
Fixes: eb8703e2ef7c ("clockevents/drivers/mxs: Migrate to new 'set-state' interface") Signed-off-by: Tom Rix trix@redhat.com Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/20210118211955.763609-1-trix@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clocksource/mxs_timer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index bc96a4cbf26c6..e52e12d27d2aa 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -131,10 +131,7 @@ static void mxs_irq_clear(char *state)
/* Clear pending interrupt */ timrot_irq_acknowledge(); - -#ifdef DEBUG - pr_info("%s: changing mode to %s\n", __func__, state) -#endif /* DEBUG */ + pr_debug("%s: changing mode to %s\n", __func__, state); }
static int mxs_shutdown(struct clock_event_device *evt)
From: Frank van der Linden fllinden@amazon.com
[ Upstream commit ec2a29593c83ed71a7f16e3243941ebfcf75fdf6 ]
5fdc7db644 ("module: setup load info before module_sig_check()") moved the ELF setup, so that it was done before the signature check. This made the module name available to signature error messages.
However, the checks for ELF correctness in setup_load_info are not sufficient to prevent bad memory references due to corrupted offset fields, indices, etc.
So, there's a regression in behavior here: a corrupt and unsigned (or badly signed) module, which might previously have been rejected immediately, can now cause an oops/crash.
Harden ELF handling for module loading by doing the following:
- Move the signature check back up so that it comes before ELF initialization. It's best to do the signature check to see if we can trust the module, before using the ELF structures inside it. This also makes checks against info->len more accurate again, as this field will be reduced by the length of the signature in mod_check_sig().
The module name is now once again not available for error messages during the signature check, but that seems like a fair tradeoff.
- Check if sections have offset / size fields that at least don't exceed the length of the module.
- Check if sections have section name offsets that don't fall outside the section name table.
- Add a few other sanity checks against invalid section indices, etc.
This is not an exhaustive consistency check, but the idea is to at least get through the signature and blacklist checks without crashing because of corrupted ELF info, and to error out gracefully for most issues that would have caused problems later on.
Fixes: 5fdc7db6448a ("module: setup load info before module_sig_check()") Signed-off-by: Frank van der Linden fllinden@amazon.com Signed-off-by: Jessica Yu jeyu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/module.c | 143 +++++++++++++++++++++++++++++++++----- kernel/module_signature.c | 2 +- kernel/module_signing.c | 2 +- 3 files changed, 126 insertions(+), 21 deletions(-)
diff --git a/kernel/module.c b/kernel/module.c index 4bf30e4b3eaaa..fda42c0064db9 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2964,7 +2964,7 @@ static int module_sig_check(struct load_info *info, int flags) }
if (is_module_sig_enforced()) { - pr_notice("%s: loading of %s is rejected\n", info->name, reason); + pr_notice("Loading of %s is rejected\n", reason); return -EKEYREJECTED; }
@@ -2977,9 +2977,33 @@ static int module_sig_check(struct load_info *info, int flags) } #endif /* !CONFIG_MODULE_SIG */
-/* Sanity checks against invalid binaries, wrong arch, weird elf version. */ -static int elf_header_check(struct load_info *info) +static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr) { + unsigned long secend; + + /* + * Check for both overflow and offset/size being + * too large. + */ + secend = shdr->sh_offset + shdr->sh_size; + if (secend < shdr->sh_offset || secend > info->len) + return -ENOEXEC; + + return 0; +} + +/* + * Sanity checks against invalid binaries, wrong arch, weird elf version. + * + * Also do basic validity checks against section offsets and sizes, the + * section name string table, and the indices used for it (sh_name). + */ +static int elf_validity_check(struct load_info *info) +{ + unsigned int i; + Elf_Shdr *shdr, *strhdr; + int err; + if (info->len < sizeof(*(info->hdr))) return -ENOEXEC;
@@ -2989,11 +3013,78 @@ static int elf_header_check(struct load_info *info) || info->hdr->e_shentsize != sizeof(Elf_Shdr)) return -ENOEXEC;
+ /* + * e_shnum is 16 bits, and sizeof(Elf_Shdr) is + * known and small. So e_shnum * sizeof(Elf_Shdr) + * will not overflow unsigned long on any platform. + */ if (info->hdr->e_shoff >= info->len || (info->hdr->e_shnum * sizeof(Elf_Shdr) > info->len - info->hdr->e_shoff)) return -ENOEXEC;
+ info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; + + /* + * Verify if the section name table index is valid. + */ + if (info->hdr->e_shstrndx == SHN_UNDEF + || info->hdr->e_shstrndx >= info->hdr->e_shnum) + return -ENOEXEC; + + strhdr = &info->sechdrs[info->hdr->e_shstrndx]; + err = validate_section_offset(info, strhdr); + if (err < 0) + return err; + + /* + * The section name table must be NUL-terminated, as required + * by the spec. This makes strcmp and pr_* calls that access + * strings in the section safe. + */ + info->secstrings = (void *)info->hdr + strhdr->sh_offset; + if (info->secstrings[strhdr->sh_size - 1] != '\0') + return -ENOEXEC; + + /* + * The code assumes that section 0 has a length of zero and + * an addr of zero, so check for it. + */ + if (info->sechdrs[0].sh_type != SHT_NULL + || info->sechdrs[0].sh_size != 0 + || info->sechdrs[0].sh_addr != 0) + return -ENOEXEC; + + for (i = 1; i < info->hdr->e_shnum; i++) { + shdr = &info->sechdrs[i]; + switch (shdr->sh_type) { + case SHT_NULL: + case SHT_NOBITS: + continue; + case SHT_SYMTAB: + if (shdr->sh_link == SHN_UNDEF + || shdr->sh_link >= info->hdr->e_shnum) + return -ENOEXEC; + fallthrough; + default: + err = validate_section_offset(info, shdr); + if (err < 0) { + pr_err("Invalid ELF section in module (section %u type %u)\n", + i, shdr->sh_type); + return err; + } + + if (shdr->sh_flags & SHF_ALLOC) { + if (shdr->sh_name >= strhdr->sh_size) { + pr_err("Invalid ELF section name in module (section %u type %u)\n", + i, shdr->sh_type); + return -ENOEXEC; + } + } + break; + } + } + return 0; }
@@ -3095,11 +3186,6 @@ static int rewrite_section_headers(struct load_info *info, int flags)
for (i = 1; i < info->hdr->e_shnum; i++) { Elf_Shdr *shdr = &info->sechdrs[i]; - if (shdr->sh_type != SHT_NOBITS - && info->len < shdr->sh_offset + shdr->sh_size) { - pr_err("Module len %lu truncated\n", info->len); - return -ENOEXEC; - }
/* * Mark all sections sh_addr with their address in the @@ -3133,11 +3219,6 @@ static int setup_load_info(struct load_info *info, int flags) { unsigned int i;
- /* Set up the convenience variables */ - info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; - info->secstrings = (void *)info->hdr - + info->sechdrs[info->hdr->e_shstrndx].sh_offset; - /* Try to find a name early so we can log errors with a module name */ info->index.info = find_sec(info, ".modinfo"); if (info->index.info) @@ -3894,26 +3975,50 @@ static int load_module(struct load_info *info, const char __user *uargs, long err = 0; char *after_dashes;
- err = elf_header_check(info); + /* + * Do the signature check (if any) first. All that + * the signature check needs is info->len, it does + * not need any of the section info. That can be + * set up later. This will minimize the chances + * of a corrupt module causing problems before + * we even get to the signature check. + * + * The check will also adjust info->len by stripping + * off the sig length at the end of the module, making + * checks against info->len more correct. + */ + err = module_sig_check(info, flags); + if (err) + goto free_copy; + + /* + * Do basic sanity checks against the ELF header and + * sections. + */ + err = elf_validity_check(info); if (err) { - pr_err("Module has invalid ELF header\n"); + pr_err("Module has invalid ELF structures\n"); goto free_copy; }
+ /* + * Everything checks out, so set up the section info + * in the info structure. + */ err = setup_load_info(info, flags); if (err) goto free_copy;
+ /* + * Now that we know we have the correct module name, check + * if it's blacklisted. + */ if (blacklisted(info->name)) { err = -EPERM; pr_err("Module %s is blacklisted\n", info->name); goto free_copy; }
- err = module_sig_check(info, flags); - if (err) - goto free_copy; - err = rewrite_section_headers(info, flags); if (err) goto free_copy; diff --git a/kernel/module_signature.c b/kernel/module_signature.c index 4224a1086b7d8..00132d12487cd 100644 --- a/kernel/module_signature.c +++ b/kernel/module_signature.c @@ -25,7 +25,7 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len, return -EBADMSG;
if (ms->id_type != PKEY_ID_PKCS7) { - pr_err("%s: Module is not signed with expected PKCS#7 message\n", + pr_err("%s: not signed with expected PKCS#7 message\n", name); return -ENOPKG; } diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 9d9fc678c91d6..8723ae70ea1fe 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -30,7 +30,7 @@ int mod_verify_sig(const void *mod, struct load_info *info)
memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
- ret = mod_check_sig(&ms, modlen, info->name); + ret = mod_check_sig(&ms, modlen, "module"); if (ret) return ret;
From: Guido Günther agx@sigxcpu.org
[ Upstream commit 8346633f2c87713a1852d802305e03555e9a9fce ]
This avoids
[ 0.962538] spi_imx 30820000.spi: bitbang start failed with -517
durig driver probe.
Fixes: 8197f489f4c4 ("spi: imx: Fix failure path leak on GPIO request error correctly") Signed-off-by: Guido Günther agx@sigxcpu.org Reviewed-by: Fabio Estevam festevam@gmail.com Link: https://lore.kernel.org/r/0f51ab42e7c7a3452f2f8652794d81584303ea0d.161098741... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 73ca821763d69..5dc4ea4b4450e 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1685,7 +1685,7 @@ static int spi_imx_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; ret = spi_bitbang_start(&spi_imx->bitbang); if (ret) { - dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); + dev_err_probe(&pdev->dev, ret, "bitbang start failed\n"); goto out_bitbang_start; }
From: Yishai Hadas yishaih@nvidia.com
[ Upstream commit 8798e4ad0abe0ba1221928a46561981c510be0c6 ]
Use the correct obj_id upon DEVX TIR creation by strictly taking the tirn 24 bits and not the general obj_id which is 32 bits.
Fixes: 7efce3691d33 ("IB/mlx5: Add obj create and destroy functionality") Link: https://lore.kernel.org/r/20201230130121.180350-2-leon@kernel.org Signed-off-by: Yishai Hadas yishaih@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mlx5/devx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c index 819c142857d65..ff8e17d7f7ca8 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -1064,7 +1064,9 @@ static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT); break; case MLX5_CMD_OP_CREATE_TIR: - MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR); + *obj_id = MLX5_GET(create_tir_out, out, tirn); + MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR); + MLX5_SET(destroy_tir_in, din, tirn, *obj_id); break; case MLX5_CMD_OP_CREATE_TIS: MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
From: Parav Pandit parav@nvidia.com
[ Upstream commit ab40530a2e0a7aca9a5187824c4fb072f3916e85 ]
mutex_destroy() call for device's cap_mask_mutex mutex is missing, let's add it to annotate destruction.
Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") Link: https://lore.kernel.org/r/20210113121703.559778-4-leon@kernel.org Signed-off-by: Parav Pandit parav@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mlx5/main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index aabdc07e47537..9b772457286f2 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -3927,7 +3927,7 @@ static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev) mlx5_ib_cleanup_multiport_master(dev); WARN_ON(!xa_empty(&dev->odp_mkeys)); cleanup_srcu_struct(&dev->odp_srcu); - + mutex_destroy(&dev->cap_mask_mutex); WARN_ON(!xa_empty(&dev->sig_mrs)); WARN_ON(!bitmap_empty(dev->dm.memic_alloc_pages, MLX5_MAX_MEMIC_PAGES)); } @@ -3978,6 +3978,10 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev) dev->ib_dev.dev.parent = mdev->device; dev->ib_dev.lag_flags = RDMA_LAG_FLAGS_HASH_ALL_SLAVES;
+ err = init_srcu_struct(&dev->odp_srcu); + if (err) + goto err_mp; + mutex_init(&dev->cap_mask_mutex); INIT_LIST_HEAD(&dev->qp_list); spin_lock_init(&dev->reset_flow_resource_lock); @@ -3987,11 +3991,6 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
spin_lock_init(&dev->dm.lock); dev->dm.dev = mdev; - - err = init_srcu_struct(&dev->odp_srcu); - if (err) - goto err_mp; - return 0;
err_mp:
From: Andre Przywara andre.przywara@arm.com
[ Upstream commit 04ef679591c76571a9e7d5ca48316cc86fa0ef12 ]
While comparing clocks between the H6 and H616, some of the M factor ranges were found to be wrong: the manual says they are only covering two bits [1:0], but our code had "5" in the number-of-bits field.
By writing 0xff into that register in U-Boot and via FEL, it could be confirmed that bits [4:2] are indeed masked off, so the manual is right.
Change to number of bits in the affected clock's description.
Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU") Signed-off-by: Andre Przywara andre.przywara@arm.com Reviewed-by: Jernej Skrabec jernej.skrabec@siol.net Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://lore.kernel.org/r/20210118000912.28116-1-andre.przywara@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index a26dbbdff80d1..bff446b782907 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -237,7 +237,7 @@ static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", psi_ahb1_ahb2_parents, 0x510, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -246,19 +246,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", "psi-ahb1-ahb2", "pll-periph0" }; static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0);
static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0);
static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0);
From: Evan Benn evanbenn@chromium.org
[ Upstream commit 0944ea07baa748741563c8842122010fa9017d16 ]
The host_event_code enum is 1-based, use EC_HOST_EVENT_MASK not BIT to generate the intended mask. This patch changes the behaviour of the mask, a following patch will restore the intended behaviour: 'Add LID and BATTERY to default mask'
Fixes: c214e564acb2 ("platform/chrome: cros_ec_proto: ignore unnecessary wakeups on old ECs") Signed-off-by: Evan Benn evanbenn@chromium.org Reviewed-by: Brian Norris briannorris@chromium.org Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Link: https://lore.kernel.org/r/20201209220306.1.I6133572c0ab3c6b95426f804bac2d383... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/chrome/cros_ec_proto.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 7c92a6e22d75d..3ad60190e11c6 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -526,11 +526,11 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) * power), not wake up. */ ec_dev->host_event_wake_mask = U32_MAX & - ~(BIT(EC_HOST_EVENT_AC_DISCONNECTED) | - BIT(EC_HOST_EVENT_BATTERY_LOW) | - BIT(EC_HOST_EVENT_BATTERY_CRITICAL) | - BIT(EC_HOST_EVENT_PD_MCU) | - BIT(EC_HOST_EVENT_BATTERY_STATUS)); + ~(EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS)); /* * Old ECs may not support this command. Complain about all * other errors.
From: Evan Benn evanbenn@chromium.org
[ Upstream commit 852405d8efcbca0e02f14592fb1d1dcd0d3fb508 ]
After 'platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT' some of the flags are not quite correct. LID_CLOSED is used to suspend the device, so it makes sense to ignore that. BATTERY events are also frequent and causing spurious wakes on elm/hana mt8173 devices.
Fixes: c214e564acb2 ("platform/chrome: cros_ec_proto: ignore unnecessary wakeups on old ECs") Signed-off-by: Evan Benn evanbenn@chromium.org Reviewed-by: Brian Norris briannorris@chromium.org Signed-off-by: Enric Balletbo i Serra enric.balletbo@collabora.com Link: https://lore.kernel.org/r/20201209220306.2.I3291bf83e4884c206b097ede34780e01... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/chrome/cros_ec_proto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index 3ad60190e11c6..aa7f7aa772971 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -526,9 +526,11 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) * power), not wake up. */ ec_dev->host_event_wake_mask = U32_MAX & - ~(EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | + ~(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) | EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) | + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) | EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) | EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS)); /*
From: Pan Bian bianpan2016@163.com
[ Upstream commit e78bf6be7edaacb39778f3a89416caddfc6c6d70 ]
Decrements the reference count of device node and its child node.
Fixes: dfe7a1b058bb ("regulator: AXP20x: Add support for regulators subsystem") Signed-off-by: Pan Bian bianpan2016@163.com Link: https://lore.kernel.org/r/20210120123313.107640-1-bianpan2016@163.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/axp20x-regulator.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 90cb8445f7216..d260c442b788d 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -1070,7 +1070,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) static int axp20x_regulator_parse_dt(struct platform_device *pdev) { struct device_node *np, *regulators; - int ret; + int ret = 0; u32 dcdcfreq = 0;
np = of_node_get(pdev->dev.parent->of_node); @@ -1085,13 +1085,12 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev) ret = axp20x_set_dcdc_freq(pdev, dcdcfreq); if (ret < 0) { dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret); - return ret; } - of_node_put(regulators); }
- return 0; + of_node_put(np); + return ret; }
static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
From: Gabriel Krisman Bertazi krisman@collabora.com
[ Upstream commit 8fe62e0c0e2efa5437f3ee81b65d69e70a45ecd2 ]
The merged API doesn't use a watch_queue device, but instead relies on pipes, so let the documentation reflect that.
Fixes: f7e47677e39a ("watch_queue: Add a key/keyring notification facility") Signed-off-by: Gabriel Krisman Bertazi krisman@collabora.com Signed-off-by: David Howells dhowells@redhat.com Acked-by: Jarkko Sakkinen jarkko@kernel.org Reviewed-by: Ben Boeckel mathstuf@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- Documentation/security/keys/core.rst | 4 ++-- samples/Kconfig | 2 +- samples/watch_queue/watch_test.c | 2 +- security/keys/Kconfig | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst index aa0081685ee11..b3ed5c581034c 100644 --- a/Documentation/security/keys/core.rst +++ b/Documentation/security/keys/core.rst @@ -1040,8 +1040,8 @@ The keyctl syscall functions are:
"key" is the ID of the key to be watched.
- "queue_fd" is a file descriptor referring to an open "/dev/watch_queue" - which manages the buffer into which notifications will be delivered. + "queue_fd" is a file descriptor referring to an open pipe which + manages the buffer into which notifications will be delivered.
"filter" is either NULL to remove a watch or a filter specification to indicate what events are required from the key. diff --git a/samples/Kconfig b/samples/Kconfig index 0ed6e4d71d87b..e76cdfc50e257 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -210,7 +210,7 @@ config SAMPLE_WATCHDOG depends on CC_CAN_LINK
config SAMPLE_WATCH_QUEUE - bool "Build example /dev/watch_queue notification consumer" + bool "Build example watch_queue notification API consumer" depends on CC_CAN_LINK && HEADERS_INSTALL help Build example userspace program to use the new mount_notify(), diff --git a/samples/watch_queue/watch_test.c b/samples/watch_queue/watch_test.c index 46e618a897fef..8c6cb57d5cfc5 100644 --- a/samples/watch_queue/watch_test.c +++ b/samples/watch_queue/watch_test.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Use /dev/watch_queue to watch for notifications. +/* Use watch_queue API to watch for notifications. * * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 83bc23409164a..c161642a84841 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -119,7 +119,7 @@ config KEY_NOTIFICATIONS bool "Provide key/keyring change notifications" depends on KEYS && WATCH_QUEUE help - This option provides support for getting change notifications on keys - and keyrings on which the caller has View permission. This makes use - of the /dev/watch_queue misc device to handle the notification - buffer and provides KEYCTL_WATCH_KEY to enable/disable watches. + This option provides support for getting change notifications + on keys and keyrings on which the caller has View permission. + This makes use of pipes to handle the notification buffer and + provides KEYCTL_WATCH_KEY to enable/disable watches.
From: David Howells dhowells@redhat.com
[ Upstream commit 4993e1f9479a4161fd7d93e2b8b30b438f00cb0f ]
KEY_FLAG_KEEP is not meant to be passed to keyring_alloc() or key_alloc(), as these only take KEY_ALLOC_* flags. KEY_FLAG_KEEP has the same value as KEY_ALLOC_BYPASS_RESTRICTION, but fortunately only key_create_or_update() uses it. LSMs using the key_alloc hook don't check that flag.
KEY_FLAG_KEEP is then ignored but fortunately (again) the root user cannot write to the blacklist keyring, so it is not possible to remove a key/hash from it.
Fix this by adding a KEY_ALLOC_SET_KEEP flag that tells key_alloc() to set KEY_FLAG_KEEP on the new key. blacklist_init() can then, correctly, pass this to keyring_alloc().
We can also use this in ima_mok_init() rather than setting the flag manually.
Note that this doesn't fix an observable bug with the current implementation but it is required to allow addition of new hashes to the blacklist in the future without making it possible for them to be removed.
Fixes: 734114f8782f ("KEYS: Add a system blacklist keyring") Reported-by: Mickaël Salaün mic@linux.microsoft.com Signed-off-by: David Howells dhowells@redhat.com cc: Mickaël Salaün mic@linux.microsoft.com cc: Mimi Zohar zohar@linux.vnet.ibm.com Cc: David Woodhouse dwmw2@infradead.org Signed-off-by: Sasha Levin sashal@kernel.org --- certs/blacklist.c | 2 +- include/linux/key.h | 1 + security/integrity/ima/ima_mok.c | 5 ++--- security/keys/key.c | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/certs/blacklist.c b/certs/blacklist.c index 6514f9ebc943f..f1c434b04b5e4 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -162,7 +162,7 @@ static int __init blacklist_init(void) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH, KEY_ALLOC_NOT_IN_QUOTA | - KEY_FLAG_KEEP, + KEY_ALLOC_SET_KEEP, NULL, NULL); if (IS_ERR(blacklist_keyring)) panic("Can't allocate system blacklist keyring\n"); diff --git a/include/linux/key.h b/include/linux/key.h index 0f2e24f13c2bd..eed3ce139a32e 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -289,6 +289,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_BUILT_IN 0x0004 /* Key is built into kernel */ #define KEY_ALLOC_BYPASS_RESTRICTION 0x0008 /* Override the check on restricted keyrings */ #define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ +#define KEY_ALLOC_SET_KEEP 0x0020 /* Set the KEEP flag on the key/keyring */
extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 36cadadbfba47..1e5c019161738 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c @@ -38,13 +38,12 @@ __init int ima_mok_init(void) (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, - KEY_ALLOC_NOT_IN_QUOTA, + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_SET_KEEP, restriction, NULL);
if (IS_ERR(ima_blacklist_keyring)) panic("Can't allocate IMA blacklist keyring."); - - set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); return 0; } device_initcall(ima_mok_init); diff --git a/security/keys/key.c b/security/keys/key.c index ebe752b137aa1..c45afdd1dfbb4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -303,6 +303,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->flags |= 1 << KEY_FLAG_BUILTIN; if (flags & KEY_ALLOC_UID_KEYRING) key->flags |= 1 << KEY_FLAG_UID_KEYRING; + if (flags & KEY_ALLOC_SET_KEEP) + key->flags |= 1 << KEY_FLAG_KEEP;
#ifdef KEY_DEBUGGING key->magic = KEY_DEBUG_MAGIC;
From: Pan Bian bianpan2016@163.com
[ Upstream commit dea6dd2ba63f8c8532addb8f32daf7b89a368a42 ]
Call of_node_put() to drop references of regulators_np and reg_np before returning error code.
Fixes: 9ae5cc75ceaa ("regulator: s5m8767: Pass descriptor instead of GPIO number") Signed-off-by: Pan Bian bianpan2016@163.com Reviewed-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20210121032756.49501-1-bianpan2016@163.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/s5m8767.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 3fa472127e9a1..48dd95b3ff45a 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -573,10 +573,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, "s5m8767,pmic-ext-control", GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "s5m8767"); - if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) + if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) { rdata->ext_control_gpiod = NULL; - else if (IS_ERR(rdata->ext_control_gpiod)) + } else if (IS_ERR(rdata->ext_control_gpiod)) { + of_node_put(reg_np); + of_node_put(regulators_np); return PTR_ERR(rdata->ext_control_gpiod); + }
rdata->id = i; rdata->initdata = of_get_regulator_init_data(
From: Pan Bian bianpan2016@163.com
[ Upstream commit 21ea2743f015dbacec1831bdc8afc848db9c2b8c ]
The allocated master is not released. Goto error handling label rather than directly return.
Fixes: 5e9af37e46bc ("spi: atmel: introduce probe deferring") Signed-off-by: Pan Bian bianpan2016@163.com Fixes: 5e9af37e46bc ("spi: atmel: introduce probe deferring") Reviewed-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20210120050025.25426-1-bianpan2016@163.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-atmel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 948396b382d73..f429436082afa 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1590,7 +1590,7 @@ static int atmel_spi_probe(struct platform_device *pdev) if (ret == 0) { as->use_dma = true; } else if (ret == -EPROBE_DEFER) { - return ret; + goto out_unmap_regs; } } else if (as->caps.has_pdc_support) { as->use_pdc = true;
From: Krzysztof Kozlowski krzk@kernel.org
[ Upstream commit a5872bd3398d0ff2ce4c77794bc7837899c69024 ]
The device node reference obtained with of_get_child_by_name() should be dropped on error paths.
Fixes: 26aec009f6b6 ("regulator: add device tree support for s5m8767") Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Link: https://lore.kernel.org/r/20210121155914.48034-1-krzk@kernel.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/s5m8767.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 48dd95b3ff45a..7c111bbdc2afa 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -544,14 +544,18 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, rdata = devm_kcalloc(&pdev->dev, pdata->num_regulators, sizeof(*rdata), GFP_KERNEL); - if (!rdata) + if (!rdata) { + of_node_put(regulators_np); return -ENOMEM; + }
rmode = devm_kcalloc(&pdev->dev, pdata->num_regulators, sizeof(*rmode), GFP_KERNEL); - if (!rmode) + if (!rmode) { + of_node_put(regulators_np); return -ENOMEM; + }
pdata->regulators = rdata; pdata->opmode = rmode;
From: John Garry john.garry@huawei.com
[ Upstream commit 121181f3f839c29d8dd9fdc3cc9babbdc74227f8 ]
LLDDs report events to libsas with .notify_port_event and .notify_phy_event callbacks.
These callbacks are fixed and so there is no reason why the functions cannot be called directly, so do that.
This neatens the code slightly, makes it more obvious, and reduces function pointer usage, which is generally a good thing. Downside is that there are 2x more symbol exports.
[a.darwish@linutronix.de: Remove the now unused "sas_ha" local variables]
Link: https://lore.kernel.org/r/20210118100955.1761652-3-a.darwish@linutronix.de Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- Documentation/scsi/libsas.rst | 9 ++---- drivers/scsi/aic94xx/aic94xx_scb.c | 20 ++++++------- drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +++----- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +- drivers/scsi/isci/port.c | 7 ++--- drivers/scsi/libsas/sas_event.c | 13 +++------ drivers/scsi/libsas/sas_init.c | 6 ---- drivers/scsi/libsas/sas_internal.h | 1 - drivers/scsi/mvsas/mv_sas.c | 14 ++++----- drivers/scsi/pm8001/pm8001_hwi.c | 40 ++++++++++++-------------- drivers/scsi/pm8001/pm8001_sas.c | 7 ++--- drivers/scsi/pm8001/pm80xx_hwi.c | 35 ++++++++++------------ include/scsi/libsas.h | 7 ++--- 15 files changed, 70 insertions(+), 110 deletions(-)
diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst index f9b77c7879dbb..210df1aba1409 100644 --- a/Documentation/scsi/libsas.rst +++ b/Documentation/scsi/libsas.rst @@ -189,12 +189,9 @@ num_phys The event interface::
/* LLDD calls these to notify the class of an event. */ - void (*notify_port_event)(struct sas_phy *, enum port_event); - void (*notify_phy_event)(struct sas_phy *, enum phy_event); - -When sas_register_ha() returns, those are set and can be -called by the LLDD to notify the SAS layer of such events -the SAS layer. + void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); + void sas_notify_port_event(struct sas_phy *, enum port_event); + void sas_notify_phy_event(struct sas_phy *, enum phy_event);
The port notification::
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 13677973da5cf..770546177ca46 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -68,7 +68,6 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, struct done_list_struct *dl) { struct asd_ha_struct *asd_ha = ascb->ha; - struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; int phy_id = dl->status_block[0] & DL_PHY_MASK; struct asd_phy *phy = &asd_ha->phys[phy_id];
@@ -81,7 +80,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, ASD_DPRINTK("phy%d: device unplugged\n", phy_id); asd_turn_led(asd_ha, phy_id, 0); sas_phy_disconnected(&phy->sas_phy); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); break; case CURRENT_OOB_DONE: /* hot plugged device */ @@ -89,12 +88,12 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, get_lrate_mode(phy, oob_mode); ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n", phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); break; case CURRENT_SPINUP_HOLD: /* hot plug SATA, no COMWAKE sent */ asd_turn_led(asd_ha, phy_id, 1); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); + sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); break; case CURRENT_GTO_TIMEOUT: case CURRENT_OOB_ERROR: @@ -102,7 +101,7 @@ static void asd_phy_event_tasklet(struct asd_ascb *ascb, dl->status_block[1]); asd_turn_led(asd_ha, phy_id, 0); sas_phy_disconnected(&phy->sas_phy); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); break; } } @@ -222,7 +221,6 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, int edb_el = edb_id + ascb->edb_index; struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el]; struct asd_phy *phy = &ascb->ha->phys[phy_id]; - struct sas_ha_struct *sas_ha = phy->sas_phy.ha; u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
size = min(size, (u16) sizeof(phy->frame_rcvd)); @@ -234,7 +232,7 @@ static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); asd_dump_frame_rcvd(phy, dl); asd_form_port(ascb->ha, phy); - sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); + sas_notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); }
static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, @@ -270,7 +268,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb *ascb, asd_turn_led(asd_ha, phy_id, 0); sas_phy_disconnected(sas_phy); asd_deform_port(asd_ha, phy); - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
if (retries_left == 0) { int num = 1; @@ -315,7 +313,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = ffs(cont); spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy,PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break;
case LmUNKNOWNP: @@ -336,7 +334,7 @@ static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, /* The sequencer disables all phys on that port. * We have to re-enable the phys ourselves. */ asd_deform_port(asd_ha, phy); - sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); + sas_notify_port_event(sas_phy, PORTE_HARD_RESET); break;
default: @@ -567,7 +565,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, /* the device is gone */ sas_phy_disconnected(sas_phy); asd_deform_port(asd_ha, phy); - sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); + sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT); break; default: ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__, diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index cf0bfac920a81..76f8fc3fad599 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -616,7 +616,6 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) { struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sas_ha;
if (!phy->phy_attached) return; @@ -627,8 +626,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) return; }
- sas_ha = &hisi_hba->sha; - sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
if (sas_phy->phy) { struct sas_phy *sphy = sas_phy->phy; @@ -656,7 +654,7 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no) }
sas_phy->frame_rcvd_size = phy->frame_rcvd_size; - sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED); + sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED); }
static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) @@ -1411,7 +1409,6 @@ static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) { - struct sas_ha_struct *sas_ha = &hisi_hba->sha; struct asd_sas_port *_sas_port = NULL; int phy_no;
@@ -1432,7 +1429,7 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) _sas_port = sas_port;
if (dev_is_expander(dev->dev_type)) - sas_ha->notify_port_event(sas_phy, + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); } } else { @@ -2194,7 +2191,6 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) { struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sas_ha = &hisi_hba->sha; struct device *dev = hisi_hba->dev;
if (rdy) { @@ -2210,7 +2206,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) return; } /* Phy down and not ready */ - sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); + sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); sas_phy_disconnected(sas_phy);
if (port) { diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 45e866cb9164d..22eecc89d41bd 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1408,7 +1408,6 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) struct hisi_sas_phy *phy = p; struct hisi_hba *hisi_hba = phy->hisi_hba; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sha = &hisi_hba->sha; struct device *dev = hisi_hba->dev; int phy_no = sas_phy->id; u32 irq_value; @@ -1424,7 +1423,7 @@ static irqreturn_t int_bcast_v1_hw(int irq, void *p) }
if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) - sha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
end: hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 9adfdefef9cad..10ba0680da04b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2818,14 +2818,13 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba) { struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sas_ha = &hisi_hba->sha; u32 bcast_status;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1); bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); if ((bcast_status & RX_BCAST_CHG_MSK) && !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_RX_BCST_ACK_MSK); hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 7c12804b4e1d1..9d9dcc11a866b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1600,14 +1600,13 @@ static irqreturn_t phy_bcast_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sas_ha = &hisi_hba->sha; u32 bcast_status;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1); bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS); if ((bcast_status & RX_BCAST_CHG_MSK) && !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_SL_RX_BCST_ACK_MSK); hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0); diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 1df45f028ea75..8d93497380674 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -164,7 +164,7 @@ static void isci_port_bc_change_received(struct isci_host *ihost, "%s: isci_phy = %p, sas_phy = %p\n", __func__, iphy, &iphy->sas_phy);
- ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); sci_port_bcn_enable(iport); }
@@ -223,8 +223,7 @@ static void isci_port_link_up(struct isci_host *isci_host, /* Notify libsas that we have an address frame, if indeed * we've found an SSP, SMP, or STP target */ if (success) - isci_host->sas_ha.notify_port_event(&iphy->sas_phy, - PORTE_BYTES_DMAED); + sas_notify_port_event(&iphy->sas_phy, PORTE_BYTES_DMAED); }
@@ -270,7 +269,7 @@ static void isci_port_link_down(struct isci_host *isci_host, * isci_port_deformed and isci_dev_gone functions. */ sas_phy_disconnected(&isci_phy->sas_phy); - isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, + sas_notify_phy_event(&isci_phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
dev_dbg(&isci_host->pdev->dev, diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index a1852f6c042b9..112a1b76f63b1 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -109,7 +109,7 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy, port_phy_el); - ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); } mutex_unlock(&ha->disco_mutex); } @@ -131,7 +131,7 @@ static void sas_phy_event_worker(struct work_struct *work) sas_free_event(ev); }
-static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) +int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) { struct asd_sas_event *ev; struct sas_ha_struct *ha = phy->ha; @@ -151,6 +151,7 @@ static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
return ret; } +EXPORT_SYMBOL_GPL(sas_notify_port_event);
int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) { @@ -172,11 +173,5 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
return ret; } +EXPORT_SYMBOL_GPL(sas_notify_phy_event);
-int sas_init_events(struct sas_ha_struct *sas_ha) -{ - sas_ha->notify_port_event = sas_notify_port_event; - sas_ha->notify_phy_event = sas_notify_phy_event; - - return 0; -} diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 21c43b18d5d5b..6dc2505d36af7 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -123,12 +123,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) goto Undo_phys; }
- error = sas_init_events(sas_ha); - if (error) { - pr_notice("couldn't start event thread:%d\n", error); - goto Undo_ports; - } - error = -ENOMEM; snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev)); sas_ha->event_q = create_singlethread_workqueue(name); diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 1f1d01901978c..53ea32ed17a75 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -54,7 +54,6 @@ void sas_free_event(struct asd_sas_event *event); int sas_register_ports(struct sas_ha_struct *sas_ha); void sas_unregister_ports(struct sas_ha_struct *sas_ha);
-int sas_init_events(struct sas_ha_struct *sas_ha); void sas_disable_revalidation(struct sas_ha_struct *ha); void sas_enable_revalidation(struct sas_ha_struct *ha); void __sas_drain_work(struct sas_ha_struct *ha); diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index a920eced92ecc..e5e3e95f78b0c 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -220,7 +220,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) { struct mvs_phy *phy = &mvi->phy[i]; struct asd_sas_phy *sas_phy = &phy->sas_phy; - struct sas_ha_struct *sas_ha; + if (!phy->phy_attached) return;
@@ -229,8 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) return; }
- sas_ha = mvi->sas; - sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
if (sas_phy->phy) { struct sas_phy *sphy = sas_phy->phy; @@ -262,8 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
- mvi->sas->notify_port_event(sas_phy, - PORTE_BYTES_DMAED); + sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED); }
void mvs_scan_start(struct Scsi_Host *shost) @@ -1880,7 +1878,6 @@ static void mvs_work_queue(struct work_struct *work) struct mvs_info *mvi = mwq->mvi; unsigned long flags; u32 phy_no = (unsigned long) mwq->data; - struct sas_ha_struct *sas_ha = mvi->sas; struct mvs_phy *phy = &mvi->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -1895,7 +1892,7 @@ static void mvs_work_queue(struct work_struct *work) if (!(tmp & PHY_READY_MASK)) { sas_phy_disconnected(sas_phy); mvs_phy_disconnected(phy); - sas_ha->notify_phy_event(sas_phy, + sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); mv_dprintk("phy%d Removed Device\n", phy_no); } else { @@ -1908,8 +1905,7 @@ static void mvs_work_queue(struct work_struct *work) } } else if (mwq->handler & EXP_BRCT_CHG) { phy->phy_event &= ~EXP_BRCT_CHG; - sas_ha->notify_port_event(sas_phy, - PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); mv_dprintk("phy%d Got Broadcast Change\n", phy_no); } list_del(&mwq->entry); diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index c8d4d87c54737..dd15246d5b037 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -3179,7 +3179,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
sas_phy->frame_rcvd_size = phy->frame_rcvd_size; - pm8001_ha->sas->notify_port_event(sas_phy, PORTE_BYTES_DMAED); + sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED); }
/* Get the link rate speed */ @@ -3293,7 +3293,6 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate); u8 portstate = (u8)(npip_portstate & 0x0000000F); struct pm8001_port *port = &pm8001_ha->port[port_id]; - struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; u8 deviceType = pPayload->sas_identify.dev_type; @@ -3337,7 +3336,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) else if (phy->identify.device_type != SAS_PHY_UNUSED) phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; phy->sas_phy.oob_mode = SAS_OOB_MODE; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); memcpy(phy->frame_rcvd, &pPayload->sas_identify, sizeof(struct sas_identify_frame)-4); @@ -3369,7 +3368,6 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate); u8 portstate = (u8)(npip_portstate & 0x0000000F); struct pm8001_port *port = &pm8001_ha->port[port_id]; - struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; pm8001_dbg(pm8001_ha, DEVIO, "HW_EVENT_SATA_PHY_UP port id = %d, phy id = %d\n", @@ -3381,7 +3379,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) phy->phy_type |= PORT_TYPE_SATA; phy->phy_attached = 1; phy->sas_phy.oob_mode = SATA_OOB_MODE; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), sizeof(struct dev_to_host_fis)); @@ -3728,11 +3726,11 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) break; case HW_EVENT_SATA_SPINUP_HOLD: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); + sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); break; case HW_EVENT_PHY_DOWN: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); phy->phy_attached = 0; phy->phy_state = 0; hw_event_phy_down(pm8001_ha, piomb); @@ -3741,7 +3739,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; /* the broadcast change primitive received, tell the LIBSAS this event to revalidate the sas domain*/ @@ -3752,20 +3750,20 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_PHY_ERROR: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); break; case HW_EVENT_BROADCAST_EXP: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: pm8001_dbg(pm8001_ha, MSG, @@ -3774,7 +3772,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: pm8001_dbg(pm8001_ha, MSG, @@ -3784,7 +3782,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: pm8001_dbg(pm8001_ha, MSG, @@ -3794,7 +3792,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: pm8001_dbg(pm8001_ha, MSG, @@ -3804,7 +3802,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_MALFUNCTION: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n"); @@ -3814,7 +3812,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_INBOUND_CRC_ERROR: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); @@ -3824,13 +3822,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) break; case HW_EVENT_HARD_RESET_RECEIVED: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); - sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); + sas_notify_port_event(sas_phy, PORTE_HARD_RESET); break; case HW_EVENT_ID_FRAME_TIMEOUT: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: pm8001_dbg(pm8001_ha, MSG, @@ -3840,20 +3838,20 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RESET_TIMER_TMO: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RECOVERY_TIMER_TMO: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RECOVER: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n"); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index d1e9dba2ef193..e21c6cfff4cbd 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -158,7 +158,6 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, int rc = 0, phy_id = sas_phy->id; struct pm8001_hba_info *pm8001_ha = NULL; struct sas_phy_linkrates *rates; - struct sas_ha_struct *sas_ha; struct pm8001_phy *phy; DECLARE_COMPLETION_ONSTACK(completion); unsigned long flags; @@ -207,18 +206,16 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, if (pm8001_ha->chip_id != chip_8001) { if (pm8001_ha->phy[phy_id].phy_state == PHY_STATE_LINK_UP_SPCV) { - sas_ha = pm8001_ha->sas; sas_phy_disconnected(&phy->sas_phy); - sas_ha->notify_phy_event(&phy->sas_phy, + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); phy->phy_attached = 0; } } else { if (pm8001_ha->phy[phy_id].phy_state == PHY_STATE_LINK_UP_SPC) { - sas_ha = pm8001_ha->sas; sas_phy_disconnected(&phy->sas_phy); - sas_ha->notify_phy_event(&phy->sas_phy, + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); phy->phy_attached = 0; } diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 6772b0924dac8..f617177b7bb33 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3243,7 +3243,6 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id]; - struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; u8 deviceType = pPayload->sas_identify.dev_type; @@ -3288,7 +3287,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) else if (phy->identify.device_type != SAS_PHY_UNUSED) phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; phy->sas_phy.oob_mode = SAS_OOB_MODE; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); memcpy(phy->frame_rcvd, &pPayload->sas_identify, sizeof(struct sas_identify_frame)-4); @@ -3322,7 +3321,6 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id]; - struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; pm8001_dbg(pm8001_ha, DEVIO, @@ -3336,7 +3334,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) phy->phy_type |= PORT_TYPE_SATA; phy->phy_attached = 1; phy->sas_phy.oob_mode = SATA_OOB_MODE; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), sizeof(struct dev_to_host_fis)); @@ -3418,11 +3416,8 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break;
} - if (port_sata && (portstate != PORT_IN_RESET)) { - struct sas_ha_struct *sas_ha = pm8001_ha->sas; - - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); - } + if (port_sata && (portstate != PORT_IN_RESET)) + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); }
static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) @@ -3520,7 +3515,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) break; case HW_EVENT_SATA_SPINUP_HOLD: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); + sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); break; case HW_EVENT_PHY_DOWN: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); @@ -3536,7 +3531,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; /* the broadcast change primitive received, tell the LIBSAS this event to revalidate the sas domain*/ @@ -3547,20 +3542,20 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_PHY_ERROR: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; - sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); + sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); break; case HW_EVENT_BROADCAST_EXP: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: pm8001_dbg(pm8001_ha, MSG, @@ -3597,7 +3592,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); - sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_INBOUND_CRC_ERROR: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); @@ -3607,13 +3602,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) break; case HW_EVENT_HARD_RESET_RECEIVED: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); - sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); + sas_notify_port_event(sas_phy, PORTE_HARD_RESET); break; case HW_EVENT_ID_FRAME_TIMEOUT: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: pm8001_dbg(pm8001_ha, MSG, @@ -3623,7 +3618,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RESET_TIMER_TMO: pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); @@ -3631,7 +3626,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; - sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); + sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); if (pm8001_ha->phy[phy_id].reset_completion) { pm8001_ha->phy[phy_id].port_reset_status = PORT_RESET_TMO; @@ -3648,7 +3643,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) for (i = 0; i < pm8001_ha->chip->n_phy; i++) { if (port->wide_port_phymap & (1 << i)) { phy = &pm8001_ha->phy[i]; - sas_ha->notify_phy_event(&phy->sas_phy, + sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); port->wide_port_phymap &= ~(1 << i); } diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 4e2d61e8fb1ed..3387149502e9a 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -391,10 +391,6 @@ struct sas_ha_struct { int strict_wide_ports; /* both sas_addr and attached_sas_addr must match * their siblings when forming wide ports */
- /* LLDD calls these to notify the class of an event. */ - int (*notify_port_event)(struct asd_sas_phy *, enum port_event); - int (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); - void *lldd_ha; /* not touched by sas class code */
struct list_head eh_done_q; /* complete via scsi_eh_flush_done_q */ @@ -706,4 +702,7 @@ struct sas_phy *sas_get_local_phy(struct domain_device *dev);
int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event); +int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); + #endif /* _SASLIB_H_ */
From: Ahmed S. Darwish a.darwish@linutronix.de
[ Upstream commit c2d0f1a65ab9fbabebb463bf36f50ea8f4633386 ]
sas_alloc_event() uses in_interrupt() to decide which allocation should be used.
The usage of in_interrupt() in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated or the context be conveyed in an argument passed by the caller, which usually knows the context.
The in_interrupt() check is also only partially correct, because it fails to choose the correct code path when just preemption or interrupts are disabled. For example, as in the following call chain:
mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation
Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and sas_notify_phy_event_gfp(), which all behave like the non _gfp() variants but use a caller-passed GFP mask for allocations.
For bisectability, all callers will be modified first to pass GFP context, then the non _gfp() libsas API variants will be modified to take a gfp_t by default.
Link: https://lore.kernel.org/r/20210118100955.1761652-4-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan yanaijie@huawei.com Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- Documentation/scsi/libsas.rst | 2 + drivers/scsi/libsas/sas_event.c | 65 ++++++++++++++++++++++++------ drivers/scsi/libsas/sas_init.c | 21 +++++++--- drivers/scsi/libsas/sas_internal.h | 4 ++ include/scsi/libsas.h | 4 ++ 5 files changed, 79 insertions(+), 17 deletions(-)
diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst index 210df1aba1409..de422253b0ab7 100644 --- a/Documentation/scsi/libsas.rst +++ b/Documentation/scsi/libsas.rst @@ -192,6 +192,8 @@ The event interface:: void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); void sas_notify_port_event(struct sas_phy *, enum port_event); void sas_notify_phy_event(struct sas_phy *, enum phy_event); + void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t); + void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
The port notification::
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 112a1b76f63b1..ba266a17250ae 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -131,18 +131,15 @@ static void sas_phy_event_worker(struct work_struct *work) sas_free_event(ev); }
-int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) +static int __sas_notify_port_event(struct asd_sas_phy *phy, + enum port_event event, + struct asd_sas_event *ev) { - struct asd_sas_event *ev; struct sas_ha_struct *ha = phy->ha; int ret;
BUG_ON(event >= PORT_NUM_EVENTS);
- ev = sas_alloc_event(phy); - if (!ev) - return -ENOMEM; - INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
ret = sas_queue_event(event, &ev->work, ha); @@ -151,20 +148,41 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
return ret; } -EXPORT_SYMBOL_GPL(sas_notify_port_event);
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) +int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags) { struct asd_sas_event *ev; - struct sas_ha_struct *ha = phy->ha; - int ret;
- BUG_ON(event >= PHY_NUM_EVENTS); + ev = sas_alloc_event_gfp(phy, gfp_flags); + if (!ev) + return -ENOMEM; + + return __sas_notify_port_event(phy, event, ev); +} +EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp); + +int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) +{ + struct asd_sas_event *ev;
ev = sas_alloc_event(phy); if (!ev) return -ENOMEM;
+ return __sas_notify_port_event(phy, event, ev); +} +EXPORT_SYMBOL_GPL(sas_notify_port_event); + +static inline int __sas_notify_phy_event(struct asd_sas_phy *phy, + enum phy_event event, + struct asd_sas_event *ev) +{ + struct sas_ha_struct *ha = phy->ha; + int ret; + + BUG_ON(event >= PHY_NUM_EVENTS); + INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
ret = sas_queue_event(event, &ev->work, ha); @@ -173,5 +191,28 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
return ret; } -EXPORT_SYMBOL_GPL(sas_notify_phy_event);
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags) +{ + struct asd_sas_event *ev; + + ev = sas_alloc_event_gfp(phy, gfp_flags); + if (!ev) + return -ENOMEM; + + return __sas_notify_phy_event(phy, event, ev); +} +EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp); + +int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) +{ + struct asd_sas_event *ev; + + ev = sas_alloc_event(phy); + if (!ev) + return -ENOMEM; + + return __sas_notify_phy_event(phy, event, ev); +} +EXPORT_SYMBOL_GPL(sas_notify_phy_event); diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 6dc2505d36af7..f8ae1f0f17d36 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -584,16 +584,15 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft) } EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
- -struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) +static struct asd_sas_event *__sas_alloc_event(struct asd_sas_phy *phy, + gfp_t gfp_flags) { struct asd_sas_event *event; - gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; struct sas_ha_struct *sas_ha = phy->ha; struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt);
- event = kmem_cache_zalloc(sas_event_cache, flags); + event = kmem_cache_zalloc(sas_event_cache, gfp_flags); if (!event) return NULL;
@@ -604,7 +603,8 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) { pr_notice("The phy%d bursting events, shut it down.\n", phy->id); - sas_notify_phy_event(phy, PHYE_SHUTDOWN); + sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN, + gfp_flags); } } else { /* Do not support PHY control, stop allocating events */ @@ -618,6 +618,17 @@ struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) return event; }
+struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) +{ + return __sas_alloc_event(phy, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); +} + +struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, + gfp_t gfp_flags) +{ + return __sas_alloc_event(phy, gfp_flags); +} + void sas_free_event(struct asd_sas_event *event) { struct asd_sas_phy *phy = event->phy; diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 53ea32ed17a75..52e09c3e2b50d 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -49,6 +49,8 @@ int sas_register_phys(struct sas_ha_struct *sas_ha); void sas_unregister_phys(struct sas_ha_struct *sas_ha);
struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy); +struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy, + gfp_t gfp_flags); void sas_free_event(struct asd_sas_event *event);
int sas_register_ports(struct sas_ha_struct *sas_ha); @@ -77,6 +79,8 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id, int sas_smp_get_phy_events(struct sas_phy *phy);
int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); +int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, + gfp_t flags); void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 3387149502e9a..e6a43163ab5b7 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -704,5 +704,9 @@ int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event); int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event); +int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags); +int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags);
#endif /* _SASLIB_H_ */
From: Ahmed S. Darwish a.darwish@linutronix.de
[ Upstream commit feb18e900f0048001ff375dca639eaa327ab3c1b ]
mvsas calls the non _gfp version of the libsas event notifiers API, leading to the buggy call chains below:
mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation
Use the new event notifiers API instead, which requires callers to explicitly pass the gfp_t memory allocation flags.
Below are context analysis for the modified functions:
=> mvs_bytes_dmaed():
Since it is invoked from both process and atomic contexts, let its callers pass the gfp_t flags. Call chains:
scsi_scan.c: do_scsi_scan_host() [has msleep()] -> shost->hostt->scan_start() -> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = mvs_scan_start()] -> mvsas/mv_sas.c: mvs_scan_start() -> mvs_bytes_dmaed(..., GFP_KERNEL)
mvsas/mv_sas.c: mvs_work_queue() spin_lock_irqsave(mvs_info::lock,) -> mvs_bytes_dmaed(..., GFP_ATOMIC)
mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr() -> mvsas/mv_chips.h: mvs_int_full() -> mvsas/mv_sas.c: mvs_int_port() -> mvs_bytes_dmaed(..., GFP_ATOMIC);
=> mvs_work_queue():
Invoked from process context, but it calls all the libsas event notifier APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC.
Link: https://lore.kernel.org/r/20210118100955.1761652-5-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan yanaijie@huawei.com Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/mvsas/mv_sas.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index e5e3e95f78b0c..484e01428da28 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -216,7 +216,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo, MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi); }
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) +static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags) { struct mvs_phy *phy = &mvi->phy[i]; struct asd_sas_phy *sas_phy = &phy->sas_phy; @@ -229,7 +229,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) return; }
- sas_notify_phy_event(sas_phy, PHYE_OOB_DONE); + sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
if (sas_phy->phy) { struct sas_phy *sphy = sas_phy->phy; @@ -261,7 +261,7 @@ static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
- sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED); + sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags); }
void mvs_scan_start(struct Scsi_Host *shost) @@ -277,7 +277,7 @@ void mvs_scan_start(struct Scsi_Host *shost) for (j = 0; j < core_nr; j++) { mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j]; for (i = 0; i < mvi->chip->n_phy; ++i) - mvs_bytes_dmaed(mvi, i); + mvs_bytes_dmaed(mvi, i, GFP_KERNEL); } mvs_prv->scan_finished = 1; } @@ -1892,20 +1892,21 @@ static void mvs_work_queue(struct work_struct *work) if (!(tmp & PHY_READY_MASK)) { sas_phy_disconnected(sas_phy); mvs_phy_disconnected(phy); - sas_notify_phy_event(sas_phy, - PHYE_LOSS_OF_SIGNAL); + sas_notify_phy_event_gfp(sas_phy, + PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC); mv_dprintk("phy%d Removed Device\n", phy_no); } else { MVS_CHIP_DISP->detect_porttype(mvi, phy_no); mvs_update_phyinfo(mvi, phy_no, 1); - mvs_bytes_dmaed(mvi, phy_no); + mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC); mvs_port_notify_formed(sas_phy, 0); mv_dprintk("phy%d Attached Device\n", phy_no); } } } else if (mwq->handler & EXP_BRCT_CHG) { phy->phy_event &= ~EXP_BRCT_CHG; - sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event_gfp(sas_phy, + PORTE_BROADCAST_RCVD, GFP_ATOMIC); mv_dprintk("phy%d Got Broadcast Change\n", phy_no); } list_del(&mwq->entry); @@ -2022,7 +2023,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) mdelay(10); }
- mvs_bytes_dmaed(mvi, phy_no); + mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC); /* whether driver is going to handle hot plug */ if (phy->phy_event & PHY_PLUG_OUT) { mvs_port_notify_formed(&phy->sas_phy, 0);
From: Ahmed S. Darwish a.darwish@linutronix.de
[ Upstream commit 885ab3b8926fdf9cdd7163dfad99deb9b0662b39 ]
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags.
sas_notify_phy_event() is exclusively called by isci_port_link_down(). Below is the context analysis for all of its call chains:
port.c: port_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> port_state_machine_change(..., SCI_PORT_FAILED) -> enter SCI port state: *SCI_PORT_FAILED* -> sci_port_failed_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down()
port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> port.c: sci_port_deactivate_phy() -> isci_port_link_down()
port.c: enter SCI port state: *SCI_PORT_READY* # Cont. from [1] -> sci_port_ready_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down()
phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [2] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_deactivate_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down()
phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [3] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down()
[1] Call chains for 'enter SCI port state: *SCI_PORT_READY*' ------------------------------------------------------------
host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY*
host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> host.c: sci_controller_start(), atomic (*) -> host.c: sci_port_start() -> port.c: port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY*
port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY*
port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port.c: sci_apc_agent_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY*
phy.c: enter SCI state: SCI_PHY_SUB_FINAL # Cont. from [1A] -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> port_agent.link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY*
[1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------
host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)
host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL)
[2] Call chains for entering state: *SCI_PHY_STOPPED* -----------------------------------------------------
host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED)
init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED)
phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED)
[3] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------
phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING)
host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances
phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed (*) -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING)
As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas phy event notifier.
Note, The now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above.
Link: https://lore.kernel.org/r/20210118100955.1761652-6-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz artur.paszkiewicz@intel.com Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/isci/port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 8d93497380674..a3c58718c2600 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -269,8 +269,8 @@ static void isci_port_link_down(struct isci_host *isci_host, * isci_port_deformed and isci_dev_gone functions. */ sas_phy_disconnected(&isci_phy->sas_phy); - sas_notify_phy_event(&isci_phy->sas_phy, - PHYE_LOSS_OF_SIGNAL); + sas_notify_phy_event_gfp(&isci_phy->sas_phy, + PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
dev_dbg(&isci_host->pdev->dev, "%s: isci_port = %p - Done\n", __func__, isci_port);
From: Ahmed S. Darwish a.darwish@linutronix.de
[ Upstream commit 5ce7902902adb8d154d67ba494f06daa29360ef0 ]
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags.
libsas sas_notify_port_event() is called from isci_port_link_up(). Below is the context analysis for all of its call chains:
host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up()
port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up()
phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1] -> phy.c: sci_phy_starting_final_substate_enter() -> phy.c: sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> phy.c: sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> .link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A])
port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A])
[A] port.c: sci_port_link_up() -> sci_port_activate_phy() -> isci_port_link_up() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up()
[1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* -----------------------------------------------------------
host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)
host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL)
As can be seen from the "(*)" markers above, all the call-chains are atomic. Pass GFP_ATOMIC to libsas port event notifier.
Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above.
Link: https://lore.kernel.org/r/20210118100955.1761652-7-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz artur.paszkiewicz@intel.com Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/isci/port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index a3c58718c2600..10136ae466e20 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -223,7 +223,8 @@ static void isci_port_link_up(struct isci_host *isci_host, /* Notify libsas that we have an address frame, if indeed * we've found an SSP, SMP, or STP target */ if (success) - sas_notify_port_event(&iphy->sas_phy, PORTE_BYTES_DMAED); + sas_notify_port_event_gfp(&iphy->sas_phy, + PORTE_BYTES_DMAED, GFP_ATOMIC); }
From: Ahmed S. Darwish a.darwish@linutronix.de
[ Upstream commit 71dca5539fcf977aead0c9ea1962e70e78484b8e ]
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags.
libsas sas_notify_port_event() is called from isci_port_bc_change_received(). Below is the context analysis for all of its call chains:
host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received()
host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received()
port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received()
phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [1] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received()
phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [2] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received()
[1] Call chains for entering state: *SCI_PHY_STOPPED* -----------------------------------------------------
host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED)
init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED)
phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED)
[2] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------
phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING)
host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
phy.c: Enter SCI state *SCI_PHY_SUB_FINAL* # Cont. from [2A] -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING)
phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances
port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING)
[2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------
host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL)
host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL)
As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas port event notifier.
Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above.
Link: https://lore.kernel.org/r/20210118100955.1761652-8-a.darwish@linutronix.de Fixes: 1c393b970e0f ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz artur.paszkiewicz@intel.com Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Ahmed S. Darwish a.darwish@linutronix.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/isci/port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 10136ae466e20..e50c3b0deeb30 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -164,7 +164,8 @@ static void isci_port_bc_change_received(struct isci_host *ihost, "%s: isci_phy = %p, sas_phy = %p\n", __func__, iphy, &iphy->sas_phy);
- sas_notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD); + sas_notify_port_event_gfp(&iphy->sas_phy, + PORTE_BROADCAST_RCVD, GFP_ATOMIC); sci_port_bcn_enable(iport); }
From: Samuel Holland samuel@sholland.org
[ Upstream commit b5e8642ed95ff6ecc20cc6038fe831affa9d098c ]
The IRQ handler calls mod_delayed_work() on power->vbus_detect. However, that work item is not initialized until after the IRQs are enabled. If an IRQ is already pending when the driver is probed, the driver calls mod_delayed_work() on an uninitialized work item, which causes an oops.
Fixes: bcfb7ae3f50b ("power: supply: axp20x_usb_power: Only poll while offline") Signed-off-by: Samuel Holland samuel@sholland.org Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/axp20x_usb_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index 70b28b699a80c..8933ae26c3d69 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -593,6 +593,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) power->axp20x_id = axp_data->axp20x_id; power->regmap = axp20x->regmap; power->num_irqs = axp_data->num_irq_names; + INIT_DELAYED_WORK(&power->vbus_detect, axp20x_usb_power_poll_vbus);
if (power->axp20x_id == AXP202_ID) { /* Enable vbus valid checking */ @@ -645,7 +646,6 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) } }
- INIT_DELAYED_WORK(&power->vbus_detect, axp20x_usb_power_poll_vbus); if (axp20x_usb_vbus_needs_polling(power)) queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0);
From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit 6996312642d2dad3070c3d276c7621f35e721f30 ]
The IRQ=0 could be a valid interrupt number in kernel because interrupt numbers are virtual in a modern kernel. Hence fix the interrupt usage in a case if interrupt is unavailable by not overriding the interrupt number which is used by the driver.
Note that currently Nexus 7 is the only know device which uses SMB347 kernel diver and it has a properly working interrupt, hence this patch doesn't fix any real problems, it's a minor cleanup/improvement.
Fixes: 99298de5df92 ("power: supply: smb347-charger: Replace mutex with IRQ disable/enable") Signed-off-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/power/supply/smb347-charger.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index d3bf35ed12cee..8cfbd8d6b4786 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -137,6 +137,7 @@ * @mains_online: is AC/DC input connected * @usb_online: is USB input connected * @charging_enabled: is charging enabled + * @irq_unsupported: is interrupt unsupported by SMB hardware * @max_charge_current: maximum current (in uA) the battery can be charged * @max_charge_voltage: maximum voltage (in uV) the battery can be charged * @pre_charge_current: current (in uA) to use in pre-charging phase @@ -193,6 +194,7 @@ struct smb347_charger { bool mains_online; bool usb_online; bool charging_enabled; + bool irq_unsupported;
unsigned int max_charge_current; unsigned int max_charge_voltage; @@ -862,6 +864,9 @@ static int smb347_irq_set(struct smb347_charger *smb, bool enable) { int ret;
+ if (smb->irq_unsupported) + return 0; + ret = smb347_set_writable(smb, true); if (ret < 0) return ret; @@ -923,8 +928,6 @@ static int smb347_irq_init(struct smb347_charger *smb, ret = regmap_update_bits(smb->regmap, CFG_STAT, CFG_STAT_ACTIVE_HIGH | CFG_STAT_DISABLED, CFG_STAT_DISABLED); - if (ret < 0) - client->irq = 0;
smb347_set_writable(smb, false);
@@ -1345,6 +1348,7 @@ static int smb347_probe(struct i2c_client *client, if (ret < 0) { dev_warn(dev, "failed to initialize IRQ: %d\n", ret); dev_warn(dev, "disabling IRQ support\n"); + smb->irq_unsupported = true; } else { smb347_irq_enable(smb); } @@ -1357,8 +1361,8 @@ static int smb347_remove(struct i2c_client *client) { struct smb347_charger *smb = i2c_get_clientdata(client);
- if (client->irq) - smb347_irq_disable(smb); + smb347_irq_disable(smb); + return 0; }
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit dbe954d8f1635f949a1d9a5d6e6fb749ae022b47 ]
Sometimes regulator_get() gets called twice for the same supply on the same device. This may happen e.g. when a framework / library is used which uses the regulator; and the driver itself also needs to enable the regulator in some cases where the framework will not enable it.
Commit ff268b56ce8c ("regulator: core: Don't spew backtraces on duplicate sysfs") already takes care of the backtrace which would trigger when creating a duplicate consumer symlink under /sys/class/regulator/regulator.%d in this scenario.
Commit c33d442328f5 ("debugfs: make error message a bit more verbose") causes a new error to get logged in this scenario:
[ 26.938425] debugfs: Directory 'wm5102-codec-MICVDD' with parent 'spi-WM510204:00-MICVDD' already present!
There is no _nowarn variant of debugfs_create_dir(), but we can detect and avoid this problem by checking the return value of the earlier sysfs_create_link_nowarn() call.
Add a check for the earlier sysfs_create_link_nowarn() failing with -EEXIST and skip the debugfs_create_dir() call in that case, avoiding this error getting logged.
Fixes: c33d442328f5 ("debugfs: make error message a bit more verbose") Cc: Charles Keepax ckeepax@opensource.cirrus.com Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Charles Keepax ckeepax@opensource.cirrus.com Link: https://lore.kernel.org/r/20210122183250.370571-1-hdegoede@redhat.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 67a768fe5b2a3..2e6c6af9d1c3a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1617,7 +1617,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, const char *supply_name) { struct regulator *regulator; - int err; + int err = 0;
if (dev) { char buf[REG_STR_SIZE]; @@ -1663,8 +1663,8 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, } }
- regulator->debugfs = debugfs_create_dir(supply_name, - rdev->debugfs); + if (err != -EEXIST) + regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); if (!regulator->debugfs) { rdev_dbg(rdev, "Failed to create debugfs directory\n"); } else {
From: Pan Bian bianpan2016@163.com
[ Upstream commit 0a6dc67a6aa45f19bd4ff89b4f468fc50c4b8daa ]
Release the buffer_head before returning error code in do_isofs_readdir() and isofs_find_entry().
Fixes: 2deb1acc653c ("isofs: fix access to unallocated memory when reading corrupted filesystem") Link: https://lore.kernel.org/r/20210118120455.118955-1-bianpan2016@163.com Signed-off-by: Pan Bian bianpan2016@163.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/isofs/dir.c | 1 + fs/isofs/namei.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index f0fe641893a5e..b9e6a7ec78be4 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -152,6 +152,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *file, printk(KERN_NOTICE "iso9660: Corrupted directory entry" " in block %lu of inode %lu\n", block, inode->i_ino); + brelse(bh); return -EIO; }
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 402769881c32b..58f80e1b3ac0d 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -102,6 +102,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, printk(KERN_NOTICE "iso9660: Corrupted directory entry" " in block %lu of inode %lu\n", block, dir->i_ino); + brelse(bh); return 0; }
From: Andy Shevchenko andriy.shevchenko@linux.intel.com
[ Upstream commit f285c9532b5bd3de7e37a6203318437cab79bd9a ]
When SCU is not ready and CONFIG_DEBUG_SHIRQ=y we got deferred probe followed by fired test IRQ which immediately makes kernel panic. Fix this by delaying IRQ handler registration till SCU is ready.
Fixes: 80ae679b8f86 ("watchdog: intel-mid_wdt: Convert to use new SCU IPC API") Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Reviewed-by: Guenter Roeck linux@roeck-us.net Acked-by: Linus Walleij linus.walleij@linaro.org Reviewed-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/watchdog/intel-mid_wdt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 1ae03b64ef8bf..9b2173f765c8c 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -154,6 +154,10 @@ static int mid_wdt_probe(struct platform_device *pdev) watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT); watchdog_set_drvdata(wdt_dev, mid);
+ mid->scu = devm_intel_scu_ipc_dev_get(dev); + if (!mid->scu) + return -EPROBE_DEFER; + ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog", wdt_dev); @@ -162,10 +166,6 @@ static int mid_wdt_probe(struct platform_device *pdev) return ret; }
- mid->scu = devm_intel_scu_ipc_dev_get(dev); - if (!mid->scu) - return -EPROBE_DEFER; - /* * The firmware followed by U-Boot leaves the watchdog running * with the default threshold which may vary. When we get here
From: Geert Uytterhoeven geert@linux-m68k.org
[ Upstream commit e89b0a426721a8ca5971bc8d70aa5ea35c020f90 ]
Drop the call to msecs_to_jiffies(), as "HZ / fbdev->refresh_rate" is already the number of jiffies to wait.
Fixes: 8992da44c6805d53 ("auxdisplay: ht16k33: Driver for LED controller") Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Miguel Ojeda ojeda@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/auxdisplay/ht16k33.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index d951d54b26f52..d8602843e8a53 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -117,8 +117,7 @@ static void ht16k33_fb_queue(struct ht16k33_priv *priv) { struct ht16k33_fbdev *fbdev = &priv->fbdev;
- schedule_delayed_work(&fbdev->work, - msecs_to_jiffies(HZ / fbdev->refresh_rate)); + schedule_delayed_work(&fbdev->work, HZ / fbdev->refresh_rate); }
/*
From: Geert Uytterhoeven geert@linux-m68k.org
[ Upstream commit b45616445a6e346daf8a173a0c51413aec067ebb ]
A second CHARLCD config symbol was added instead of moving the existing one. Fix this by removing the old one.
Fixes: 718e05ed92ecac0d ("auxdisplay: Introduce hd44780_common.[ch]") Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Miguel Ojeda ojeda@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/auxdisplay/Kconfig | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index a2b59b84bb881..1509cb74705a3 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -507,6 +507,3 @@ config PANEL depends on PARPORT select AUXDISPLAY select PARPORT_PANEL - -config CHARLCD - tristate "Character LCD core support" if COMPILE_TEST
From: Josh Poimboeuf jpoimboe@redhat.com
[ Upstream commit 6f567c9300a5ebd7b18c26dda1c8d6ffbdd0debd ]
Actually return an error (and display a backtrace, if requested) for directional bit warnings.
Fixes: 2f0f9e9ad7b3 ("objtool: Add Direction Flag validation") Signed-off-by: Josh Poimboeuf jpoimboe@redhat.com Link: https://lore.kernel.org/r/dc70f2adbc72f09526f7cab5b6feb8bf7f6c5ad4.161126346... Signed-off-by: Sasha Levin sashal@kernel.org --- tools/objtool/check.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 4bd30315eb62b..2e154f00ccec2 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2592,15 +2592,19 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, break;
case INSN_STD: - if (state.df) + if (state.df) { WARN_FUNC("recursive STD", sec, insn->offset); + return 1; + }
state.df = true; break;
case INSN_CLD: - if (!state.df && func) + if (!state.df && func) { WARN_FUNC("redundant CLD", sec, insn->offset); + return 1; + }
state.df = false; break;
From: Josh Poimboeuf jpoimboe@redhat.com
[ Upstream commit 1f9a1b74942485a0a29e7c4a9a9f2fe8aea17766 ]
The JMP_NOSPEC macro branches to __x86_retpoline_*() rather than the __x86_indirect_thunk_*() wrappers used by C code. Detect jumps to __x86_retpoline_*() as retpoline dynamic jumps.
Presumably this doesn't trigger a user-visible bug. I only found it when testing vmlinux.o validation.
Fixes: 39b735332cb8 ("objtool: Detect jumps to retpoline thunks") Signed-off-by: Josh Poimboeuf jpoimboe@redhat.com Link: https://lore.kernel.org/r/31f5833e2e4f01e3d755889ac77e3661e906c09f.161126346... Signed-off-by: Sasha Levin sashal@kernel.org --- tools/objtool/arch/x86/special.c | 2 +- tools/objtool/check.c | 3 ++- tools/objtool/check.h | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c index fd4af88c0ea52..151b13d0a2676 100644 --- a/tools/objtool/arch/x86/special.c +++ b/tools/objtool/arch/x86/special.c @@ -48,7 +48,7 @@ bool arch_support_alt_relocation(struct special_alt *special_alt, * replacement group. */ return insn->offset == special_alt->new_off && - (insn->type == INSN_CALL || is_static_jump(insn)); + (insn->type == INSN_CALL || is_jump(insn)); }
/* diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 2e154f00ccec2..48e22e3c6f186 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -789,7 +789,8 @@ static int add_jump_destinations(struct objtool_file *file) dest_sec = reloc->sym->sec; dest_off = reloc->sym->sym.st_value + arch_dest_reloc_offset(reloc->addend); - } else if (strstr(reloc->sym->name, "_indirect_thunk_")) { + } else if (!strncmp(reloc->sym->name, "__x86_indirect_thunk_", 21) || + !strncmp(reloc->sym->name, "__x86_retpoline_", 16)) { /* * Retpoline jumps are really dynamic jumps in * disguise, so convert them accordingly. diff --git a/tools/objtool/check.h b/tools/objtool/check.h index 5ec00a4b891b6..2804848e628e3 100644 --- a/tools/objtool/check.h +++ b/tools/objtool/check.h @@ -54,6 +54,17 @@ static inline bool is_static_jump(struct instruction *insn) insn->type == INSN_JUMP_UNCONDITIONAL; }
+static inline bool is_dynamic_jump(struct instruction *insn) +{ + return insn->type == INSN_JUMP_DYNAMIC || + insn->type == INSN_JUMP_DYNAMIC_CONDITIONAL; +} + +static inline bool is_jump(struct instruction *insn) +{ + return is_static_jump(insn) || is_dynamic_jump(insn); +} + struct instruction *find_insn(struct objtool_file *file, struct section *sec, unsigned long offset);
From: Josh Poimboeuf jpoimboe@redhat.com
[ Upstream commit 34ca59e109bdf69704c33b8eeffaa4c9f71076e5 ]
With my version of GCC 9.3.1 the ".cold" subfunctions no longer have a numbered suffix, so the trailing period is no longer there.
Presumably this doesn't yet trigger a user-visible bug since most of the subfunction detection logic is duplicated. I only found it when testing vmlinux.o validation.
Fixes: 54262aa28301 ("objtool: Fix sibling call detection") Signed-off-by: Josh Poimboeuf jpoimboe@redhat.com Link: https://lore.kernel.org/r/ca0b5a57f08a2fbb48538dd915cc253b5edabb40.161126346... Signed-off-by: Sasha Levin sashal@kernel.org --- tools/objtool/check.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 48e22e3c6f186..dc24aac08edd6 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -850,8 +850,8 @@ static int add_jump_destinations(struct objtool_file *file) * case where the parent function's only reference to a * subfunction is through a jump table. */ - if (!strstr(insn->func->name, ".cold.") && - strstr(insn->jump_dest->func->name, ".cold.")) { + if (!strstr(insn->func->name, ".cold") && + strstr(insn->jump_dest->func->name, ".cold")) { insn->func->cfunc = insn->jump_dest->func; insn->jump_dest->func->pfunc = insn->func;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 0be310979e5e1272d4c5b557642df4da4ce7eba4 ]
The "pmb" pointer is freed at the start of the function and then freed again in the error handling code.
Link: https://lore.kernel.org/r/YA6E8rO51hE56SVw@mwanda Fixes: 92d7f7b0cde3 ("[SCSI] lpfc: NPIV: add NPIV support on top of SLI-3") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 2b6b5fc671feb..e5ace4a4f432a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1145,13 +1145,14 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_vport *vport = pmb->vport; LPFC_MBOXQ_t *sparam_mb; struct lpfc_dmabuf *sparam_mp; + u16 status = pmb->u.mb.mbxStatus; int rc;
- if (pmb->u.mb.mbxStatus) - goto out; - mempool_free(pmb, phba->mbox_mem_pool);
+ if (status) + goto out; + /* don't perform discovery for SLI4 loopback diagnostic test */ if ((phba->sli_rev == LPFC_SLI_REV4) && !(phba->hba_flag & HBA_FCOE_MODE) && @@ -1214,12 +1215,10 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
out: lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "0306 CONFIG_LINK mbxStatus error x%x " - "HBA state x%x\n", - pmb->u.mb.mbxStatus, vport->port_state); -sparam_out: - mempool_free(pmb, phba->mbox_mem_pool); + "0306 CONFIG_LINK mbxStatus error x%x HBA state x%x\n", + status, vport->port_state);
+sparam_out: lpfc_linkdown(phba);
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
From: Yong Wu yong.wu@mediatek.com
[ Upstream commit 862c3715de8f3e5350489240c951d697f04bd8c9 ]
Currently gather->end is "unsigned long" which may be overflow in arch32 in the corner case: 0xfff00000 + 0x100000(iova + size). Although it doesn't affect the size(end - start), it affects the checking "gather->end < end"
This patch changes this "end" to the real end address (end = start + size - 1). Correspondingly, update the length to "end - start + 1".
Fixes: a7d20dc19d9e ("iommu: Introduce struct iommu_iotlb_gather for batching TLB flushes") Signed-off-by: Yong Wu yong.wu@mediatek.com Reviewed-by: Robin Murphy robin.murphy@arm.com Acked-by: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20210107122909.16317-5-yong.wu@mediatek.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- drivers/iommu/mtk_iommu.c | 2 +- include/linux/iommu.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 8ca7415d785d9..c70d6e79f5346 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2280,7 +2280,7 @@ static void arm_smmu_iotlb_sync(struct iommu_domain *domain, { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
- arm_smmu_tlb_inv_range(gather->start, gather->end - gather->start, + arm_smmu_tlb_inv_range(gather->start, gather->end - gather->start + 1, gather->pgsize, true, smmu_domain); }
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 8e56cec532e71..bfe6ec329f8d5 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -444,7 +444,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, struct iommu_iotlb_gather *gather) { struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); - size_t length = gather->end - gather->start; + size_t length = gather->end - gather->start + 1;
if (gather->start == ULONG_MAX) return; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index efa96263b81b3..d63d3e9cc7b67 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -170,7 +170,7 @@ enum iommu_dev_features { * struct iommu_iotlb_gather - Range information for a pending IOTLB flush * * @start: IOVA representing the start of the range to be flushed - * @end: IOVA representing the end of the range to be flushed (exclusive) + * @end: IOVA representing the end of the range to be flushed (inclusive) * @pgsize: The interval at which to perform the flush * * This structure is intended to be updated by multiple calls to the @@ -538,7 +538,7 @@ static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, struct iommu_iotlb_gather *gather, unsigned long iova, size_t size) { - unsigned long start = iova, end = start + size; + unsigned long start = iova, end = start + size - 1;
/* * If the new page is disjoint from the current range or is mapped at
From: Maor Gottlieb maorg@nvidia.com
[ Upstream commit 96667052149da3855c4361925324b690c687152f ]
Because SCATTERLIST_MAX_SEGMENT was removed and replaced with UINT_MAX, the test overflows the max_sgement variable. Remove this case.
Fixes: 7a60c2dd0f57 ("drm: Remove SCATTERLIST_MAX_SEGMENT") Link: https://lore.kernel.org/r/20210125120527.836363-1-leon@kernel.org Signed-off-by: Maor Gottlieb maorg@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/scatterlist/main.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/tools/testing/scatterlist/main.c b/tools/testing/scatterlist/main.c index 71c960dcd8a42..652254754b4cb 100644 --- a/tools/testing/scatterlist/main.c +++ b/tools/testing/scatterlist/main.c @@ -55,7 +55,6 @@ int main(void) struct test *test, tests[] = { { -EINVAL, 1, pfn(0), NULL, PAGE_SIZE, 0, 1 }, { 0, 1, pfn(0), NULL, PAGE_SIZE, PAGE_SIZE + 1, 1 }, - { 0, 1, pfn(0), NULL, PAGE_SIZE, sgmax + 1, 1 }, { 0, 1, pfn(0), NULL, PAGE_SIZE, sgmax, 1 }, { 0, 1, pfn(0), NULL, 1, sgmax, 1 }, { 0, 2, pfn(0, 1), NULL, 2 * PAGE_SIZE, sgmax, 1 },
From: Mark Bloch mbloch@nvidia.com
[ Upstream commit 2614488d1f3cd5989375042286b11424208e20c8 ]
The cited commit disallowed creating any QP which isn't raw ethernet, reg umr or the special UD qp for testing WC, this proved too strict.
While modify can't be done (no GIDS/GID table for example) just creating a QP is okay.
This patch partially reverts the bellow mentioned commit and places the restriction at the modify QP stage and not at the creation. DEVX commands should be used to manipulate such QPs.
Fixes: 42caf9cb5937 ("RDMA/mlx5: Allow only raw Ethernet QPs when RoCE isn't enabled") Link: https://lore.kernel.org/r/20210125120709.836718-1-leon@kernel.org Signed-off-by: Mark Bloch mbloch@nvidia.com Reviewed-by: Maor Gottlieb maorg@mellanox.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mlx5/qp.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 0cb7cc642d87d..bab40ad527dae 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -2432,9 +2432,6 @@ static int check_qp_type(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, case MLX5_IB_QPT_HW_GSI: case IB_QPT_DRIVER: case IB_QPT_GSI: - if (dev->profile == &raw_eth_profile) - goto out; - fallthrough; case IB_QPT_RAW_PACKET: case IB_QPT_UD: case MLX5_IB_QPT_REG_UMR: @@ -2629,10 +2626,6 @@ static int process_create_flags(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, int create_flags = attr->create_flags; bool cond;
- if (qp->type == IB_QPT_UD && dev->profile == &raw_eth_profile) - if (create_flags & ~MLX5_IB_QP_CREATE_WC_TEST) - return -EINVAL; - if (qp_type == MLX5_IB_QPT_DCT) return (create_flags) ? -EINVAL : 0;
@@ -4211,6 +4204,23 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, return 0; }
+static bool mlx5_ib_modify_qp_allowed(struct mlx5_ib_dev *dev, + struct mlx5_ib_qp *qp, + enum ib_qp_type qp_type) +{ + if (dev->profile != &raw_eth_profile) + return true; + + if (qp_type == IB_QPT_RAW_PACKET || qp_type == MLX5_IB_QPT_REG_UMR) + return true; + + /* Internal QP used for wc testing, with NOPs in wq */ + if (qp->flags & MLX5_IB_QP_CREATE_WC_TEST) + return true; + + return false; +} + int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_udata *udata) { @@ -4223,6 +4233,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int err = -EINVAL; int port;
+ if (!mlx5_ib_modify_qp_allowed(dev, qp, ibqp->qp_type)) + return -EOPNOTSUPP; + if (attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT)) return -EOPNOTSUPP;
From: Shay Drory shayd@nvidia.com
[ Upstream commit 4fc5461823c9cad547a9bdfbf17d13f0da0d6bb5 ]
MAD message received by the user has EINVAL error in all flows including when the device is disassociated. That makes it impossible for the applications to treat such flow differently.
Change it to return EIO, so the applications will be able to perform disassociation recovery.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/r/20210125121339.837518-2-leon@kernel.org Signed-off-by: Shay Drory shayd@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/user_mad.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 19104a6756915..7ec1918431f70 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -379,6 +379,11 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
mutex_lock(&file->mutex);
+ if (file->agents_dead) { + mutex_unlock(&file->mutex); + return -EIO; + } + while (list_empty(&file->recv_list)) { mutex_unlock(&file->mutex);
@@ -524,7 +529,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
agent = __get_agent(file, packet->mad.hdr.id); if (!agent) { - ret = -EINVAL; + ret = -EIO; goto err_up; }
From: Shay Drory shayd@nvidia.com
[ Upstream commit def4cd43f522253645b72c97181399c241b54536 ]
Currently, polling a umad device will always works, even if the device was disassociated. A disassociated device should immediately return EPOLLERR from poll(). Otherwise userspace is endlessly hung on poll() with no idea that the device has been removed from the system.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/r/20210125121339.837518-3-leon@kernel.org Signed-off-by: Shay Drory shayd@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/user_mad.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 7ec1918431f70..dd7f3b437c6be 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -397,6 +397,11 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, mutex_lock(&file->mutex); }
+ if (file->agents_dead) { + mutex_unlock(&file->mutex); + return -EIO; + } + packet = list_entry(file->recv_list.next, struct ib_umad_packet, list); list_del(&packet->list);
@@ -658,10 +663,14 @@ static __poll_t ib_umad_poll(struct file *filp, struct poll_table_struct *wait) /* we will always be able to post a MAD send */ __poll_t mask = EPOLLOUT | EPOLLWRNORM;
+ mutex_lock(&file->mutex); poll_wait(filp, &file->recv_wait, wait);
if (!list_empty(&file->recv_list)) mask |= EPOLLIN | EPOLLRDNORM; + if (file->agents_dead) + mask = EPOLLERR; + mutex_unlock(&file->mutex);
return mask; } @@ -1341,6 +1350,7 @@ static void ib_umad_kill_port(struct ib_umad_port *port) list_for_each_entry(file, &port->file_list, port_list) { mutex_lock(&file->mutex); file->agents_dead = 1; + wake_up_interruptible(&file->recv_wait); mutex_unlock(&file->mutex);
for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
From: Cédric Le Goater clg@kaod.org
[ Upstream commit 9236f57a9e51c72ce426ccd2e53e123de7196a0f ]
These are only used locally. It fixes these W=1 compile errors :
../arch/powerpc/kvm/powerpc.c:1521:5: error: no previous prototype for ‘kvmppc_get_vmx_dword’ [-Werror=missing-prototypes] 1521 | int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) | ^~~~~~~~~~~~~~~~~~~~ ../arch/powerpc/kvm/powerpc.c:1539:5: error: no previous prototype for ‘kvmppc_get_vmx_word’ [-Werror=missing-prototypes] 1539 | int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) | ^~~~~~~~~~~~~~~~~~~ ../arch/powerpc/kvm/powerpc.c:1557:5: error: no previous prototype for ‘kvmppc_get_vmx_hword’ [-Werror=missing-prototypes] 1557 | int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) | ^~~~~~~~~~~~~~~~~~~~ ../arch/powerpc/kvm/powerpc.c:1575:5: error: no previous prototype for ‘kvmppc_get_vmx_byte’ [-Werror=missing-prototypes] 1575 | int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) | ^~~~~~~~~~~~~~~~~~~
Fixes: acc9eb9305fe ("KVM: PPC: Reimplement LOAD_VMX/STORE_VMX instruction mmio emulation with analyse_instr() input") Signed-off-by: Cédric Le Goater clg@kaod.org Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210104143206.695198-19-clg@kaod.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kvm/powerpc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index cf52d26f49cd7..25966ae3271ef 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -1518,7 +1518,7 @@ int kvmppc_handle_vmx_load(struct kvm_vcpu *vcpu, return emulated; }
-int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1536,7 +1536,7 @@ int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) return result; }
-int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1554,7 +1554,7 @@ int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) return result; }
-int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1572,7 +1572,7 @@ int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) return result; }
-int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0;
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 27f699579b64dbf27caf31e5c0eac567ec0aa8b8 ]
book3s/32 kvm is designed with the assumption that an FPU is always present.
Force selection of FPU support in the kernel when build KVM.
Fixes: 7d68c8916950 ("powerpc/32s: Allow deselecting CONFIG_PPC_FPU on mpc832x") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/74461a99fa1466f361532ca794ca0753be3d9f86.161103804... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kvm/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 549591d9aaa2c..e45644657d49d 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -54,6 +54,7 @@ config KVM_BOOK3S_32 select KVM select KVM_BOOK3S_32_HANDLER select KVM_BOOK3S_PR_POSSIBLE + select PPC_FPU help Support running unmodified book3s_32 guest kernels in virtual machines on book3s_32 host processors.
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 910a0cb6d259736a0c86e795d4c2f42af8d0d775 ]
PPC47x_TLBE_SIZE isn't defined for 256k pages, leading to a build break if 256k pages is selected.
So change the kconfig so that 256k pages can't be selected for 47x.
Fixes: e7f75ad01d59 ("powerpc/47x: Base ppc476 support") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu [mpe: Expand change log to mention build break] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/2fed79b1154c872194f98bac4422c23918325e61.161112893... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 107bb4319e0e0..a685e42d39932 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -772,7 +772,7 @@ config PPC_64K_PAGES
config PPC_256K_PAGES bool "256k page size" - depends on 44x && !STDBINUTILS + depends on 44x && !STDBINUTILS && !PPC_47x help Make the page size 256k.
From: Ananth N Mavinakayanahalli ananth@linux.ibm.com
[ Upstream commit 8813ff49607eab3caaf40fe8929b0ce7dc68e85f ]
We currently unconditionally try to emulate newer instructions on older Power versions that could cause issues. Gate it.
Fixes: 350779a29f11 ("powerpc: Handle most loads and stores in instruction emulation code") Signed-off-by: Ananth N Mavinakayanahalli ananth@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/161157995977.64773.13794501093457185080.stgit@thin... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/lib/sstep.c | 78 +++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index ede093e962347..5e725ed24d772 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1306,9 +1306,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, if ((word & 0xfe2) == 2) op->type = SYSCALL; else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && - (word & 0xfe3) == 1) + (word & 0xfe3) == 1) { /* scv */ op->type = SYSCALL_VECTORED_0; - else + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; + } else op->type = UNKNOWN; return 0; #endif @@ -1412,7 +1414,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #ifdef __powerpc64__ case 1: if (!cpu_has_feature(CPU_FTR_ARCH_31)) - return -1; + goto unknown_opcode;
prefix_r = GET_PREFIX_R(word); ra = GET_PREFIX_RA(suffix); @@ -1446,7 +1448,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #ifdef __powerpc64__ case 4: if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode;
switch (word & 0x3f) { case 48: /* maddhd */ @@ -1532,6 +1534,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, case 19: if (((word >> 1) & 0x1f) == 2) { /* addpcis */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; imm = (short) (word & 0xffc1); /* d0 + d2 fields */ imm |= (word >> 15) & 0x3e; /* d1 field */ op->val = regs->nip + (imm << 16) + 4; @@ -1844,7 +1848,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #ifdef __powerpc64__ case 265: /* modud */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; op->val = regs->gpr[ra] % regs->gpr[rb]; goto compute_done; #endif @@ -1854,7 +1858,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 267: /* moduw */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; op->val = (unsigned int) regs->gpr[ra] % (unsigned int) regs->gpr[rb]; goto compute_done; @@ -1891,7 +1895,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #endif case 755: /* darn */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; switch (ra & 0x3) { case 0: /* 32-bit conditioned */ @@ -1913,14 +1917,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #ifdef __powerpc64__ case 777: /* modsd */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; op->val = (long int) regs->gpr[ra] % (long int) regs->gpr[rb]; goto compute_done; #endif case 779: /* modsw */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; op->val = (int) regs->gpr[ra] % (int) regs->gpr[rb]; goto compute_done; @@ -1997,14 +2001,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #endif case 538: /* cnttzw */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; val = (unsigned int) regs->gpr[rd]; op->val = (val ? __builtin_ctz(val) : 32); goto logical_done; #ifdef __powerpc64__ case 570: /* cnttzd */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; val = regs->gpr[rd]; op->val = (val ? __builtin_ctzl(val) : 64); goto logical_done; @@ -2114,7 +2118,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, case 890: /* extswsli with sh_5 = 0 */ case 891: /* extswsli with sh_5 = 1 */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) - return -1; + goto unknown_opcode; op->type = COMPUTE + SETREG; sh = rb | ((word & 2) << 4); val = (signed int) regs->gpr[rd]; @@ -2441,6 +2445,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 268: /* lxvx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 16); op->element_size = 16; @@ -2450,6 +2456,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, case 269: /* lxvl */ case 301: { /* lxvll */ int nb; + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->ea = ra ? regs->gpr[ra] : 0; nb = regs->gpr[rb] & 0xff; @@ -2470,13 +2478,15 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 333: /* lxvpx */ if (!cpu_has_feature(CPU_FTR_ARCH_31)) - return -1; + goto unknown_opcode; op->reg = VSX_REGISTER_XTP(rd); op->type = MKOP(LOAD_VSX, 0, 32); op->element_size = 32; break;
case 364: /* lxvwsx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 4); op->element_size = 4; @@ -2484,6 +2494,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 396: /* stxvx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(STORE_VSX, 0, 16); op->element_size = 16; @@ -2493,6 +2505,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, case 397: /* stxvl */ case 429: { /* stxvll */ int nb; + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->ea = ra ? regs->gpr[ra] : 0; nb = regs->gpr[rb] & 0xff; @@ -2506,7 +2520,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, } case 461: /* stxvpx */ if (!cpu_has_feature(CPU_FTR_ARCH_31)) - return -1; + goto unknown_opcode; op->reg = VSX_REGISTER_XTP(rd); op->type = MKOP(STORE_VSX, 0, 32); op->element_size = 32; @@ -2544,6 +2558,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 781: /* lxsibzx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 1); op->element_size = 8; @@ -2551,6 +2567,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 812: /* lxvh8x */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 16); op->element_size = 2; @@ -2558,6 +2576,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 813: /* lxsihzx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 2); op->element_size = 8; @@ -2571,6 +2591,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 876: /* lxvb16x */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(LOAD_VSX, 0, 16); op->element_size = 1; @@ -2584,6 +2606,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 909: /* stxsibx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(STORE_VSX, 0, 1); op->element_size = 8; @@ -2591,6 +2615,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 940: /* stxvh8x */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(STORE_VSX, 0, 16); op->element_size = 2; @@ -2598,6 +2624,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 941: /* stxsihx */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(STORE_VSX, 0, 2); op->element_size = 8; @@ -2611,6 +2639,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 1004: /* stxvb16x */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd | ((word & 1) << 5); op->type = MKOP(STORE_VSX, 0, 16); op->element_size = 1; @@ -2719,12 +2749,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, op->type = MKOP(LOAD_FP, 0, 16); break; case 2: /* lxsd */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd + 32; op->type = MKOP(LOAD_VSX, 0, 8); op->element_size = 8; op->vsx_flags = VSX_CHECK_VEC; break; case 3: /* lxssp */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->reg = rd + 32; op->type = MKOP(LOAD_VSX, 0, 4); op->element_size = 8; @@ -2754,7 +2788,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, #ifdef CONFIG_VSX case 6: if (!cpu_has_feature(CPU_FTR_ARCH_31)) - return -1; + goto unknown_opcode; op->ea = dqform_ea(word, regs); op->reg = VSX_REGISTER_XTP(rd); op->element_size = 32; @@ -2777,6 +2811,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 1: /* lxv */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->ea = dqform_ea(word, regs); if (word & 8) op->reg = rd + 32; @@ -2787,6 +2823,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 2: /* stxsd with LSB of DS field = 0 */ case 6: /* stxsd with LSB of DS field = 1 */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->ea = dsform_ea(word, regs); op->reg = rd + 32; op->type = MKOP(STORE_VSX, 0, 8); @@ -2796,6 +2834,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 3: /* stxssp with LSB of DS field = 0 */ case 7: /* stxssp with LSB of DS field = 1 */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->ea = dsform_ea(word, regs); op->reg = rd + 32; op->type = MKOP(STORE_VSX, 0, 4); @@ -2804,6 +2844,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break;
case 5: /* stxv */ + if (!cpu_has_feature(CPU_FTR_ARCH_300)) + goto unknown_opcode; op->ea = dqform_ea(word, regs); if (word & 8) op->reg = rd + 32; @@ -2833,7 +2875,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, break; case 1: /* Prefixed instructions */ if (!cpu_has_feature(CPU_FTR_ARCH_31)) - return -1; + goto unknown_opcode;
prefix_r = GET_PREFIX_R(word); ra = GET_PREFIX_RA(suffix); @@ -2982,6 +3024,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0;
+ unknown_opcode: + op->type = UNKNOWN; + return 0; + logical_done: if (word & 1) set_cr0(regs, op);
From: Ananth N Mavinakayanahalli ananth@linux.ibm.com
[ Upstream commit 718aae916fa6619c57c348beaedd675835cf1aa1 ]
We currently just percolate the return value from analyze_instr() to the caller of emulate_step(), especially if it is a -1.
For one particular case (opcode = 4) for instructions that aren't currently emulated, we are returning 'should not be single-stepped' while we should have returned 0 which says 'did not emulate, may have to single-step'.
Fixes: 930d6288a26787 ("powerpc: sstep: Add support for maddhd, maddhdu, maddld instructions") Signed-off-by: Ananth N Mavinakayanahalli ananth@linux.ibm.com Suggested-by: Michael Ellerman mpe@ellerman.id.au Tested-by: Naveen N. Rao naveen.n.rao@linux.vnet.ibm.com Reviewed-by: Sandipan Das sandipan@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/161157999039.64773.14950289716779364766.stgit@thin... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/lib/sstep.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 5e725ed24d772..33935869e4976 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1447,6 +1447,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#ifdef __powerpc64__ case 4: + /* + * There are very many instructions with this primary opcode + * introduced in the ISA as early as v2.03. However, the ones + * we currently emulate were all introduced with ISA 3.0 + */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) goto unknown_opcode;
@@ -1474,7 +1479,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, * There are other instructions from ISA 3.0 with the same * primary opcode which do not have emulation support yet. */ - return -1; + goto unknown_opcode; #endif
case 7: /* mulli */
From: Pingfan Liu kernelfans@gmail.com
[ Upstream commit b709e32ef570b8b91dfbcb63cffac4324c87799f ]
When CONFIG_IRQ_TIME_ACCOUNTING and CONFIG_VIRT_CPU_ACCOUNTING_GEN, powerpc does not enable "sched_clock_irqtime" and can not utilize irq time accounting.
Like x86, powerpc does not use the sched_clock_register() interface. So it needs an dedicated call to enable_sched_clock_irqtime() to enable irq time accounting.
Fixes: 518470fe962e ("powerpc: Add HAVE_IRQ_TIME_ACCOUNTING") Signed-off-by: Pingfan Liu kernelfans@gmail.com [mpe: Add fixes tag] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/1603349479-26185-1-git-send-email-kernelfans@gmail... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 67feb35244606..83633a24ce788 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -53,6 +53,7 @@ #include <linux/of_clk.h> #include <linux/suspend.h> #include <linux/sched/cputime.h> +#include <linux/sched/clock.h> #include <linux/processor.h> #include <asm/trace.h>
@@ -1030,6 +1031,7 @@ void __init time_init(void) tick_setup_hrtimer_broadcast();
of_clk_init(NULL); + enable_sched_clock_irqtime(); }
/*
From: Michal Suchanek msuchanek@suse.de
[ Upstream commit 9899a56f1eca964cd0de21008a9fa1523a571231 ]
./arch/powerpc/include/asm/paravirt.h:83:44: error: implicit declaration of function 'smp_processor_id'; did you mean 'raw_smp_processor_id'?
smp_processor_id is defined in linux/smp.h but it is not included.
The build error happens only when the patch is applied to 5.3 kernel but it only works by chance in mainline.
Fixes: ca3f969dcb11 ("powerpc/paravirt: Use is_kvm_guest() in vcpu_is_preempted()") Signed-off-by: Michal Suchanek msuchanek@suse.de Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210120132838.15589-1-msuchanek@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/paravirt.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h index edc08f04aef77..5d1726bb28e79 100644 --- a/arch/powerpc/include/asm/paravirt.h +++ b/arch/powerpc/include/asm/paravirt.h @@ -10,6 +10,7 @@ #endif
#ifdef CONFIG_PPC_SPLPAR +#include <linux/smp.h> #include <asm/kvm_guest.h> #include <asm/cputhreads.h>
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 5d15cbf63515c6183d2ed7c9dd0586b4db23ffb1 ]
'dma_request_chan()' calls should be balanced by a corresponding 'dma_release_channel()' call.
Add the missing call both in the error handling path of the probe function and in the remove function.
Fixes: ff65ffe46d28 ("mmc: Add Actions Semi Owl SoCs SD/MMC driver") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/20201209194202.54099-1-christophe.jaillet@wanadoo.... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/owl-mmc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 53b81582f1afe..5490962dc8e53 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -640,7 +640,7 @@ static int owl_mmc_probe(struct platform_device *pdev) owl_host->irq = platform_get_irq(pdev, 0); if (owl_host->irq < 0) { ret = -EINVAL; - goto err_free_host; + goto err_release_channel; }
ret = devm_request_irq(&pdev->dev, owl_host->irq, owl_irq_handler, @@ -648,19 +648,21 @@ static int owl_mmc_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request irq %d\n", owl_host->irq); - goto err_free_host; + goto err_release_channel; }
ret = mmc_add_host(mmc); if (ret) { dev_err(&pdev->dev, "Failed to add host\n"); - goto err_free_host; + goto err_release_channel; }
dev_dbg(&pdev->dev, "Owl MMC Controller Initialized\n");
return 0;
+err_release_channel: + dma_release_channel(owl_host->dma); err_free_host: mmc_free_host(mmc);
@@ -674,6 +676,7 @@ static int owl_mmc_remove(struct platform_device *pdev)
mmc_remove_host(mmc); disable_irq(owl_host->irq); + dma_release_channel(owl_host->dma); mmc_free_host(mmc);
return 0;
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit c9c256a8b0dc09c305c409d6264cc016af2ba38d ]
'sdhci_remove_host()' and 'sdhci_pltfm_free()' should be used in place of 'mmc_remove_host()' and 'mmc_free_host()'.
This avoids some resource leaks, is more in line with the error handling path of the probe function, and is more consistent with other drivers.
Fixes: fb8bd90f83c4 ("mmc: sdhci-sprd: Add Spreadtrum's initial host controller") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Acked-by: Orson Zhai orson.zhai@gmail.com Acked-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/20201217204236.163446-1-christophe.jaillet@wanadoo... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/sdhci-sprd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index f85171edabeb9..5dc36efff47ff 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -708,14 +708,14 @@ static int sdhci_sprd_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); - struct mmc_host *mmc = host->mmc;
- mmc_remove_host(mmc); + sdhci_remove_host(host, 0); + clk_disable_unprepare(sprd_host->clk_sdio); clk_disable_unprepare(sprd_host->clk_enable); clk_disable_unprepare(sprd_host->clk_2x_enable);
- mmc_free_host(mmc); + sdhci_pltfm_free(pdev);
return 0; }
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 6052b3c370fb82dec28bcfff6d7ec0da84ac087a ]
A call to 'ausdhi6_dma_release()' to undo a previous call to 'usdhi6_dma_request()' is missing in the error handling path of the probe function.
It is already present in the remove function.
Fixes: 75fa9ea6e3c0 ("mmc: add a driver for the Renesas usdhi6rol0 SD/SDIO host controller") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/20201217210922.165340-1-christophe.jaillet@wanadoo... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/usdhi6rol0.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index e2d5112d809dc..615f3d008af1e 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1858,10 +1858,12 @@ static int usdhi6_probe(struct platform_device *pdev)
ret = mmc_add_host(mmc); if (ret < 0) - goto e_clk_off; + goto e_release_dma;
return 0;
+e_release_dma: + usdhi6_dma_release(host); e_clk_off: clk_disable_unprepare(host->clk); e_free_mmc:
From: Takeshi Saito takeshi.saito.xv@renesas.com
[ Upstream commit d7aefb2887601cf1fc3f86f55d43b2c9aece5e8f ]
According to the latest datasheet, the internal DMAC buffer alignment R-Car Gen3 SDHI HW should be 128-bytes. So, fix it.
Signed-off-by: Takeshi Saito takeshi.saito.xv@renesas.com [shimoda: revise commit description, rebase] Fixes: 2a68ea7896e3 ("mmc: renesas-sdhi: add support for R-Car Gen3 SDHI DMAC") Signed-off-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Reviewed-by: Wolfram Sang wsa+renesas@sang-engineering.com Tested-by: Wolfram Sang wsa+renesas@sang-engineering.com Link: https://lore.kernel.org/r/1608114572-1892-2-git-send-email-yoshihiro.shimoda... Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index fe13e1ea22dcc..f3e76d6b3e3fe 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -186,8 +186,8 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, mmc_get_dma_dir(data))) goto force_pio;
- /* This DMAC cannot handle if buffer is not 8-bytes alignment */ - if (!IS_ALIGNED(sg_dma_address(sg), 8)) + /* This DMAC cannot handle if buffer is not 128-bytes alignment */ + if (!IS_ALIGNED(sg_dma_address(sg), 128)) goto force_pio_with_unmap;
if (data->flags & MMC_DATA_READ) {
From: Vladimir Murzin vladimir.murzin@arm.com
[ Upstream commit 2acb909750431030b65a0a2a17fd8afcbd813a84 ]
It was observed that decompressor running on hardware implementing ARM v8.2 Load/Store Multiple Atomicity and Ordering Control (LSMAOC), say, as guest, would stuck just after:
Uncompressing Linux... done, booting the kernel.
The reason is that it clears nTLSMD bit when disabling caches:
nTLSMD, bit [3]
When ARMv8.2-LSMAOC is implemented:
No Trap Load Multiple and Store Multiple to Device-nGRE/Device-nGnRE/Device-nGnRnE memory.
0b0 All memory accesses by A32 and T32 Load Multiple and Store Multiple at EL1 or EL0 that are marked at stage 1 as Device-nGRE/Device-nGnRE/Device-nGnRnE memory are trapped and generate a stage 1 Alignment fault.
0b1 All memory accesses by A32 and T32 Load Multiple and Store Multiple at EL1 or EL0 that are marked at stage 1 as Device-nGRE/Device-nGnRE/Device-nGnRnE memory are not trapped.
This bit is permitted to be cached in a TLB.
This field resets to 1.
Otherwise:
Reserved, RES1
So as effect we start getting traps we are not quite ready for.
Looking into history it seems that mask used for SCTLR clear came from the similar code for ARMv4, where bit[3] is the enable/disable bit for the write buffer. That not applicable to ARMv7 and onwards, so retire that bit from the masks.
Fixes: 7d09e85448dfa78e3e58186c934449aaf6d49b50 ("[ARM] 4393/2: ARMv7: Add uncompressing code for the new CPU Id format") Signed-off-by: Vladimir Murzin vladimir.murzin@arm.com Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/boot/compressed/head.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index d9cce7238a365..73eee41826e2d 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -1164,9 +1164,9 @@ __armv4_mmu_cache_off: __armv7_mmu_cache_off: mrc p15, 0, r0, c1, c0 #ifdef CONFIG_MMU - bic r0, r0, #0x000d + bic r0, r0, #0x0005 #else - bic r0, r0, #0x000c + bic r0, r0, #0x0004 #endif mcr p15, 0, r0, c1, c0 @ turn MMU and cache off mov r0, #0
From: Roja Rani Yarubandi rojay@codeaurora.org
[ Upstream commit 357ee8841d0b7bd822f25fc768afbc0c2ab7e47b ]
Store DMA mapping data in geni_i2c_dev struct to enhance DMA mapping data scope. For example during shutdown callback to unmap DMA mapping, this stored DMA mapping data can be used to call geni_se_tx_dma_unprep and geni_se_rx_dma_unprep functions.
Add two helper functions geni_i2c_rx_msg_cleanup and geni_i2c_tx_msg_cleanup to unwrap the things after rx/tx FIFO/DMA transfers, so that the same can be used in geni_i2c_stop_xfer() function during shutdown callback.
Signed-off-by: Roja Rani Yarubandi rojay@codeaurora.org Reviewed-by: Akash Asthana akashast@codeaurora.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-qcom-geni.c | 59 ++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 16 deletions(-)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 046d241183c58..214b4c913a139 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -86,6 +86,9 @@ struct geni_i2c_dev { u32 clk_freq_out; const struct geni_i2c_clk_fld *clk_fld; int suspended; + void *dma_buf; + size_t xfer_len; + dma_addr_t dma_addr; };
struct geni_i2c_err_log { @@ -348,14 +351,39 @@ static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c) dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n"); }
+static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c, + struct i2c_msg *cur) +{ + gi2c->cur_rd = 0; + if (gi2c->dma_buf) { + if (gi2c->err) + geni_i2c_rx_fsm_rst(gi2c); + geni_se_rx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len); + i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err); + } +} + +static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c, + struct i2c_msg *cur) +{ + gi2c->cur_wr = 0; + if (gi2c->dma_buf) { + if (gi2c->err) + geni_i2c_tx_fsm_rst(gi2c); + geni_se_tx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len); + i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err); + } +} + static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, u32 m_param) { - dma_addr_t rx_dma; + dma_addr_t rx_dma = 0; unsigned long time_left; void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur;
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) @@ -370,19 +398,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); i2c_put_dma_safe_msg_buf(dma_buf, msg, false); dma_buf = NULL; + } else { + gi2c->xfer_len = len; + gi2c->dma_addr = rx_dma; + gi2c->dma_buf = dma_buf; }
+ cur = gi2c->cur; time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c);
- gi2c->cur_rd = 0; - if (dma_buf) { - if (gi2c->err) - geni_i2c_rx_fsm_rst(gi2c); - geni_se_rx_dma_unprep(se, rx_dma, len); - i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err); - } + geni_i2c_rx_msg_cleanup(gi2c, cur);
return gi2c->err; } @@ -390,11 +417,12 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, u32 m_param) { - dma_addr_t tx_dma; + dma_addr_t tx_dma = 0; unsigned long time_left; void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur;
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) @@ -409,22 +437,21 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); i2c_put_dma_safe_msg_buf(dma_buf, msg, false); dma_buf = NULL; + } else { + gi2c->xfer_len = len; + gi2c->dma_addr = tx_dma; + gi2c->dma_buf = dma_buf; }
if (!dma_buf) /* Get FIFO IRQ */ writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);
+ cur = gi2c->cur; time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c);
- gi2c->cur_wr = 0; - if (dma_buf) { - if (gi2c->err) - geni_i2c_tx_fsm_rst(gi2c); - geni_se_tx_dma_unprep(se, tx_dma, len); - i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err); - } + geni_i2c_tx_msg_cleanup(gi2c, cur);
return gi2c->err; }
From: Roja Rani Yarubandi rojay@codeaurora.org
[ Upstream commit e0371298ddc51761be257698554ea507ac8bf831 ]
If the hardware is still accessing memory after SMMU translation is disabled (as part of smmu shutdown callback), then the IOVAs (I/O virtual address) which it was using will go on the bus as the physical addresses which will result in unknown crashes like NoC/interconnect errors.
So, implement shutdown callback to i2c driver to stop on-going transfer and unmap DMA mappings during system "reboot" or "shutdown".
Fixes: 37692de5d523 ("i2c: i2c-qcom-geni: Add bus driver for the Qualcomm GENI I2C controller") Signed-off-by: Roja Rani Yarubandi rojay@codeaurora.org Reviewed-by: Akash Asthana akashast@codeaurora.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-qcom-geni.c | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 214b4c913a139..c3f5847959116 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -375,6 +375,32 @@ static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c, } }
+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c) +{ + int ret; + u32 geni_status; + struct i2c_msg *cur; + + /* Resume device, as runtime suspend can happen anytime during transfer */ + ret = pm_runtime_get_sync(gi2c->se.dev); + if (ret < 0) { + dev_err(gi2c->se.dev, "Failed to resume device: %d\n", ret); + return; + } + + geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS); + if (geni_status & M_GENI_CMD_ACTIVE) { + cur = gi2c->cur; + geni_i2c_abort_xfer(gi2c); + if (cur->flags & I2C_M_RD) + geni_i2c_rx_msg_cleanup(gi2c, cur); + else + geni_i2c_tx_msg_cleanup(gi2c, cur); + } + + pm_runtime_put_sync_suspend(gi2c->se.dev); +} + static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, u32 m_param) { @@ -650,6 +676,13 @@ static int geni_i2c_remove(struct platform_device *pdev) return 0; }
+static void geni_i2c_shutdown(struct platform_device *pdev) +{ + struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); + + geni_i2c_stop_xfer(gi2c); +} + static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev) { int ret; @@ -714,6 +747,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match); static struct platform_driver geni_i2c_driver = { .probe = geni_i2c_probe, .remove = geni_i2c_remove, + .shutdown = geni_i2c_shutdown, .driver = { .name = "geni_i2c", .pm = &geni_i2c_pm_ops,
From: David Gow davidgow@google.com
[ Upstream commit 9d909f1b1e91b4aa7d016ed14b7b76dbf2675414 ]
The MIPI i3c HCI driver makes use of IOMEM functions like devm_platform_ioremap_resource(), which are only available if CONFIG_HAS_IOMEM is defined.
This causes the driver to be enabled under make ARCH=um allyesconfig, even though it won't build.
By adding a dependency on HAS_IOMEM, the driver will not be enabled on architectures which don't support it.
Fixes: 9ad9a52cce28 ("i3c/master: introduce the mipi-i3c-hci driver") Signed-off-by: David Gow davidgow@google.com Acked-by: Nicolas Pitre npitre@baylibre.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210127040636.1535722-1-davidgow@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i3c/master/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig index e68f15f4b4d0c..afff0e2320f74 100644 --- a/drivers/i3c/master/Kconfig +++ b/drivers/i3c/master/Kconfig @@ -25,6 +25,7 @@ config DW_I3C_MASTER config MIPI_I3C_HCI tristate "MIPI I3C Host Controller Interface driver (EXPERIMENTAL)" depends on I3C + depends on HAS_IOMEM help Support for hardware following the MIPI Aliance's I3C Host Controller Interface specification.
From: Uwe Kleine-König u.kleine-koenig@pengutronix.de
[ Upstream commit de5d7adb89367bbc87b4e5ce7afe7ae9bd86dc12 ]
Consider an amba driver with a .probe but without a .remove callback (e.g. pl061_gpio_driver). The function amba_probe() is called to bind a device and so dev_pm_domain_attach() and others are called. As there is no remove callback amba_remove() isn't called at unbind time however and so calling dev_pm_domain_detach() is missed and the pm domain keeps active.
To fix this always use the core driver callbacks and handle missing amba callbacks there. For probe refuse registration as a driver without probe doesn't make sense.
Fixes: 7cfe249475fd ("ARM: AMBA: Add pclk support to AMBA bus infrastructure") Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Reviewed-by: Arnd Bergmann arnd@arndb.de Link: https://lore.kernel.org/r/20210126165835.687514-2-u.kleine-koenig@pengutroni... Signed-off-by: Uwe Kleine-König u.kleine-koenig@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/amba/bus.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index ecc304149067c..b5f5ca4e3f343 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -299,10 +299,11 @@ static int amba_remove(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *drv = to_amba_driver(dev->driver); - int ret; + int ret = 0;
pm_runtime_get_sync(dev); - ret = drv->remove(pcdev); + if (drv->remove) + ret = drv->remove(pcdev); pm_runtime_put_noidle(dev);
/* Undo the runtime PM settings in amba_probe() */ @@ -319,7 +320,9 @@ static int amba_remove(struct device *dev) static void amba_shutdown(struct device *dev) { struct amba_driver *drv = to_amba_driver(dev->driver); - drv->shutdown(to_amba_device(dev)); + + if (drv->shutdown) + drv->shutdown(to_amba_device(dev)); }
/** @@ -332,12 +335,13 @@ static void amba_shutdown(struct device *dev) */ int amba_driver_register(struct amba_driver *drv) { - drv->drv.bus = &amba_bustype; + if (!drv->probe) + return -EINVAL;
-#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn - SETFN(probe); - SETFN(remove); - SETFN(shutdown); + drv->drv.bus = &amba_bustype; + drv->drv.probe = amba_probe; + drv->drv.remove = amba_remove; + drv->drv.shutdown = amba_shutdown;
return driver_register(&drv->drv); }
From: Yong Wu yong.wu@mediatek.com
[ Upstream commit d8c1df02ac7f2c802a9b2afc0f5c888c4217f1d5 ]
In the end of __iommu_map, It alway call iotlb_sync_map.
This patch moves iotlb_sync_map out from __iommu_map since it is unnecessary to call this for each sg segment especially iotlb_sync_map is flush tlb all currently. Add a little helper _iommu_map for this.
Signed-off-by: Yong Wu yong.wu@mediatek.com Reviewed-by: Robin Murphy robin.murphy@arm.com Acked-by: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20210107122909.16317-2-yong.wu@mediatek.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/iommu.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ffeebda8d6def..c304a6a30d42e 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2426,9 +2426,6 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, size -= pgsize; }
- if (ops->iotlb_sync_map) - ops->iotlb_sync_map(domain); - /* unroll mapping in case something went wrong */ if (ret) iommu_unmap(domain, orig_iova, orig_size - size); @@ -2438,18 +2435,31 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, return ret; }
+static int _iommu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot, gfp_t gfp) +{ + const struct iommu_ops *ops = domain->ops; + int ret; + + ret = __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); + if (ret == 0 && ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); + + return ret; +} + int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { might_sleep(); - return __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); + return _iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); } EXPORT_SYMBOL_GPL(iommu_map);
int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { - return __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); + return _iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(iommu_map_atomic);
@@ -2533,6 +2543,7 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot, gfp_t gfp) { + const struct iommu_ops *ops = domain->ops; size_t len = 0, mapped = 0; phys_addr_t start; unsigned int i = 0; @@ -2563,6 +2574,8 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, sg = sg_next(sg); }
+ if (ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); return mapped;
out_err:
From: Douglas Anderson dianders@chromium.org
[ Upstream commit b8437a3ef8c485903d05d1f261328aaf0c0a6cc2 ]
Sleeping while atomic = bad. Let's fix an obvious typo to try to avoid it.
The warning that was seen (on a downstream kernel with the problematic patch backported):
BUG: sleeping function called from invalid context at mm/page_alloc.c:4726 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 9, name: ksoftirqd/0 CPU: 0 PID: 9 Comm: ksoftirqd/0 Not tainted 5.4.93-12508-gc10c93e28e39 #1 Call trace: dump_backtrace+0x0/0x154 show_stack+0x20/0x2c dump_stack+0xa0/0xfc ___might_sleep+0x11c/0x12c __might_sleep+0x50/0x84 __alloc_pages_nodemask+0xf8/0x2bc __arm_lpae_alloc_pages+0x48/0x1b4 __arm_lpae_map+0x124/0x274 __arm_lpae_map+0x1cc/0x274 arm_lpae_map+0x140/0x170 arm_smmu_map+0x78/0xbc __iommu_map+0xd4/0x210 _iommu_map+0x4c/0x84 iommu_map_atomic+0x44/0x58 __iommu_dma_map+0x8c/0xc4 iommu_dma_map_page+0xac/0xf0
Fixes: d8c1df02ac7f ("iommu: Move iotlb_sync_map out from __iommu_map") Signed-off-by: Douglas Anderson dianders@chromium.org Reviewed-by: Yong Wu yong.wu@mediatek.com Acked-by: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20210201170611.1.I64a7b62579287d668d7c89e105dcedf4... Signed-off-by: Joerg Roedel jroedel@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index c304a6a30d42e..fd5f59373fc62 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2441,7 +2441,7 @@ static int _iommu_map(struct iommu_domain *domain, unsigned long iova, const struct iommu_ops *ops = domain->ops; int ret;
- ret = __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); + ret = __iommu_map(domain, iova, paddr, size, prot, gfp); if (ret == 0 && ops->iotlb_sync_map) ops->iotlb_sync_map(domain);
From: Parav Pandit parav@nvidia.com
[ Upstream commit d286ac1d05210695c312b9018b3aa7c2048e9aca ]
When mlx5_ib_stage_init_init() fails, return the error code related to failure instead of -ENOMEM.
Fixes: 16c1975f1032 ("IB/mlx5: Create profile infrastructure to add and remove stages") Link: https://lore.kernel.org/r/20210127150010.1876121-8-leon@kernel.org Signed-off-by: Parav Pandit parav@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/mlx5/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 9b772457286f2..3562e69eacb14 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -3995,8 +3995,7 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
err_mp: mlx5_ib_cleanup_multiport_master(dev); - - return -ENOMEM; + return err; }
static int mlx5_ib_enable_driver(struct ib_device *dev)
From: Parav Pandit parav@nvidia.com
[ Upstream commit 131be26750379592f0dd6244b2a90bbb504a10bb ]
When RDMA device has 255 ports, loop iterator i overflows. Due to which cm_add_one() port iterator loops infinitely. Use core provided port iterator to avoid the infinite loop.
Fixes: a977049dacde ("[PATCH] IB: Add the kernel CM implementation") Link: https://lore.kernel.org/r/20210127150010.1876121-9-leon@kernel.org Signed-off-by: Mark Bloch mbloch@nvidia.com Signed-off-by: Parav Pandit parav@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/cm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 98165589c8ab6..be996dba040cc 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -4333,7 +4333,7 @@ static int cm_add_one(struct ib_device *ib_device) unsigned long flags; int ret; int count = 0; - u8 i; + unsigned int i;
cm_dev = kzalloc(struct_size(cm_dev, port, ib_device->phys_port_cnt), GFP_KERNEL); @@ -4345,7 +4345,7 @@ static int cm_add_one(struct ib_device *ib_device) cm_dev->going_down = 0;
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); - for (i = 1; i <= ib_device->phys_port_cnt; i++) { + rdma_for_each_port (ib_device, i) { if (!rdma_cap_ib_cm(ib_device, i)) continue;
@@ -4431,7 +4431,7 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data) .clr_port_cap_mask = IB_PORT_CM_SUP }; unsigned long flags; - int i; + unsigned int i;
write_lock_irqsave(&cm.device_lock, flags); list_del(&cm_dev->list); @@ -4441,7 +4441,7 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data) cm_dev->going_down = 1; spin_unlock_irq(&cm.lock);
- for (i = 1; i <= ib_device->phys_port_cnt; i++) { + rdma_for_each_port (ib_device, i) { if (!rdma_cap_ib_cm(ib_device, i)) continue;
From: Steven Rostedt (VMware) rostedt@goodmis.org
[ Upstream commit befe6d946551d65cddbd32b9cb0170b0249fd5ed ]
The list of tracepoint callbacks is managed by an array that is protected by RCU. To update this array, a new array is allocated, the updates are copied over to the new array, and then the list of functions for the tracepoint is switched over to the new array. After a completion of an RCU grace period, the old array is freed.
This process happens for both adding a callback as well as removing one. But on removing a callback, if the new array fails to be allocated, the callback is not removed, and may be used after it is freed by the clients of the tracepoint.
There's really no reason to fail if the allocation for a new array fails when removing a function. Instead, the function can simply be replaced by a stub function that could be cleaned up on the next modification of the array. That is, instead of calling the function registered to the tracepoint, it would call a stub function in its place.
Link: https://lore.kernel.org/r/20201115055256.65625-1-mmullins@mmlx.us Link: https://lore.kernel.org/r/20201116175107.02db396d@gandalf.local.home Link: https://lore.kernel.org/r/20201117211836.54acaef2@oasis.local.home Link: https://lkml.kernel.org/r/20201118093405.7a6d2290@gandalf.local.home
[ Note, this version does use undefined compiler behavior (assuming that a stub function with no parameters or return, can be called by a location that thinks it has parameters but still no return value. Static calls do the same thing, so this trick is not without precedent.
There's another solution that uses RCU tricks and is more complex, but can be an alternative if this solution becomes an issue.
Link: https://lore.kernel.org/lkml/20210127170721.58bce7cc@gandalf.local.home/ ]
Cc: Peter Zijlstra peterz@infradead.org Cc: Josh Poimboeuf jpoimboe@redhat.com Cc: Mathieu Desnoyers mathieu.desnoyers@efficios.com Cc: Ingo Molnar mingo@redhat.com Cc: Alexei Starovoitov ast@kernel.org Cc: Daniel Borkmann daniel@iogearbox.net Cc: Dmitry Vyukov dvyukov@google.com Cc: Martin KaFai Lau kafai@fb.com Cc: Song Liu songliubraving@fb.com Cc: Yonghong Song yhs@fb.com Cc: Andrii Nakryiko andriin@fb.com Cc: John Fastabend john.fastabend@gmail.com Cc: KP Singh kpsingh@chromium.org Cc: netdev netdev@vger.kernel.org Cc: bpf bpf@vger.kernel.org Cc: Kees Cook keescook@chromium.org Cc: Florian Weimer fw@deneb.enyo.de Fixes: 97e1c18e8d17b ("tracing: Kernel Tracepoints") Reported-by: syzbot+83aa762ef23b6f0d1991@syzkaller.appspotmail.com Reported-by: syzbot+d29e58bb557324e55e5e@syzkaller.appspotmail.com Reported-by: Matt Mullins mmullins@mmlx.us Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Tested-by: Matt Mullins mmullins@mmlx.us Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/tracepoint.c | 80 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-)
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 7261fa0f5e3cc..e8f20ae29c18f 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -53,6 +53,12 @@ struct tp_probes { struct tracepoint_func probes[]; };
+/* Called in removal of a func but failed to allocate a new tp_funcs */ +static void tp_stub_func(void) +{ + return; +} + static inline void *allocate_probes(int count) { struct tp_probes *p = kmalloc(struct_size(p, probes, count), @@ -131,6 +137,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, { struct tracepoint_func *old, *new; int nr_probes = 0; + int stub_funcs = 0; int pos = -1;
if (WARN_ON(!tp_func->func)) @@ -147,14 +154,34 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, if (old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data) return ERR_PTR(-EEXIST); + if (old[nr_probes].func == tp_stub_func) + stub_funcs++; } } - /* + 2 : one for new probe, one for NULL func */ - new = allocate_probes(nr_probes + 2); + /* + 2 : one for new probe, one for NULL func - stub functions */ + new = allocate_probes(nr_probes + 2 - stub_funcs); if (new == NULL) return ERR_PTR(-ENOMEM); if (old) { - if (pos < 0) { + if (stub_funcs) { + /* Need to copy one at a time to remove stubs */ + int probes = 0; + + pos = -1; + for (nr_probes = 0; old[nr_probes].func; nr_probes++) { + if (old[nr_probes].func == tp_stub_func) + continue; + if (pos < 0 && old[nr_probes].prio < prio) + pos = probes++; + new[probes++] = old[nr_probes]; + } + nr_probes = probes; + if (pos < 0) + pos = probes; + else + nr_probes--; /* Account for insertion */ + + } else if (pos < 0) { pos = nr_probes; memcpy(new, old, nr_probes * sizeof(struct tracepoint_func)); } else { @@ -188,8 +215,9 @@ static void *func_remove(struct tracepoint_func **funcs, /* (N -> M), (N > 1, M >= 0) probes */ if (tp_func->func) { for (nr_probes = 0; old[nr_probes].func; nr_probes++) { - if (old[nr_probes].func == tp_func->func && - old[nr_probes].data == tp_func->data) + if ((old[nr_probes].func == tp_func->func && + old[nr_probes].data == tp_func->data) || + old[nr_probes].func == tp_stub_func) nr_del++; } } @@ -208,14 +236,32 @@ static void *func_remove(struct tracepoint_func **funcs, /* N -> M, (N > 1, M > 0) */ /* + 1 for NULL */ new = allocate_probes(nr_probes - nr_del + 1); - if (new == NULL) - return ERR_PTR(-ENOMEM); - for (i = 0; old[i].func; i++) - if (old[i].func != tp_func->func - || old[i].data != tp_func->data) - new[j++] = old[i]; - new[nr_probes - nr_del].func = NULL; - *funcs = new; + if (new) { + for (i = 0; old[i].func; i++) + if ((old[i].func != tp_func->func + || old[i].data != tp_func->data) + && old[i].func != tp_stub_func) + new[j++] = old[i]; + new[nr_probes - nr_del].func = NULL; + *funcs = new; + } else { + /* + * Failed to allocate, replace the old function + * with calls to tp_stub_func. + */ + for (i = 0; old[i].func; i++) + if (old[i].func == tp_func->func && + old[i].data == tp_func->data) { + old[i].func = tp_stub_func; + /* Set the prio to the next event. */ + if (old[i + 1].func) + old[i].prio = + old[i + 1].prio; + else + old[i].prio = -1; + } + *funcs = old; + } } debug_print_probes(*funcs); return old; @@ -295,10 +341,12 @@ static int tracepoint_remove_func(struct tracepoint *tp, tp_funcs = rcu_dereference_protected(tp->funcs, lockdep_is_held(&tracepoints_mutex)); old = func_remove(&tp_funcs, func); - if (IS_ERR(old)) { - WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); + if (WARN_ON_ONCE(IS_ERR(old))) return PTR_ERR(old); - } + + if (tp_funcs == old) + /* Failed allocating new tp_funcs, replaced func with stub */ + return 0;
if (!tp_funcs) { /* Removed last function */
From: David Gow davidgow@google.com
[ Upstream commit ddd0521549a975e6148732d6ca6b89ffa862c0e5 ]
The Xilinx zynqmp RTC driver makes use of IOMEM functions like devm_platform_ioremap_resource(), which are only available if CONFIG_HAS_IOMEM is defined.
This causes the driver not to be enable under make ARCH=um allyesconfig, even though it won't build.
By adding a dependency on HAS_IOMEM, the driver will not be enabled on architectures which don't support it.
Fixes: 09ef18bcd5ac ("rtc: use devm_platform_ioremap_resource() to simplify code") Signed-off-by: David Gow davidgow@google.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Link: https://lore.kernel.org/r/20210127035146.1523286-1-davidgow@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e4bef40831c75..4e2b3a175607b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1301,7 +1301,7 @@ config RTC_DRV_OPAL
config RTC_DRV_ZYNQMP tristate "Xilinx Zynq Ultrascale+ MPSoC RTC" - depends on OF + depends on OF && HAS_IOMEM help If you say yes here you get support for the RTC controller found on Xilinx Zynq Ultrascale+ MPSoC.
From: David E. Box david.e.box@linux.intel.com
[ Upstream commit 35d8a973fe4d38afee944db636c3d2b1df3741a7 ]
Fix error in Kconfig that exposed INTEL_PMT_CLASS as a user selectable option. It is already selected by INTEL_PMT_TELEMETRY and INTEL_PMT_CRASHLOG which are user selectable.
Fixes: e2729113ce66 ("platform/x86: Intel PMT class driver") Signed-off-by: David E. Box david.e.box@linux.intel.com Link: https://lore.kernel.org/r/20210126205508.30907-1-david.e.box@linux.intel.com Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 91e6176cdfbdf..af75c3342c061 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1369,7 +1369,7 @@ config INTEL_PMC_CORE - MPHY/PLL gating status (Sunrisepoint PCH only)
config INTEL_PMT_CLASS - tristate "Intel Platform Monitoring Technology (PMT) Class driver" + tristate help The Intel Platform Monitoring Technology (PMT) class driver provides the basic sysfs interface and file hierarchy uses by PMT devices.
From: David E. Box david.e.box@linux.intel.com
[ Upstream commit f3f6da5014dea3cc005b36948abe3664b5d1f7d3 ]
All devices that expose Intel Platform Monitoring Technology (PMT) telemetry are currently owned by the intel_pmt MFD driver. Therefore make the telemetry driver depend on the MFD driver for build.
Fixes: 68fe8e6e2c4b ("platform/x86: Intel PMT Telemetry capability driver") Signed-off-by: David E. Box david.e.box@linux.intel.com Link: https://lore.kernel.org/r/20210126205508.30907-2-david.e.box@linux.intel.com Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index af75c3342c061..9948c5f4928d4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1382,6 +1382,7 @@ config INTEL_PMT_CLASS
config INTEL_PMT_TELEMETRY tristate "Intel Platform Monitoring Technology (PMT) Telemetry driver" + depends on MFD_INTEL_PMT select INTEL_PMT_CLASS help The Intel Platform Monitory Technology (PMT) Telemetry driver provides
From: David E. Box david.e.box@linux.intel.com
[ Upstream commit fdd3feb37e36bec2ad75d76f8ac4d0273c5c0a91 ]
All devices that expose Intel Platform Monitoring Technology (PMT) crashlog are currently owned by the intel_pmt MFD driver. Therefore make the crashlog driver depend on the MFD driver for build.
Fixes: 5ef9998c96b0 ("platform/x86: Intel PMT Crashlog capability driver") Signed-off-by: David E. Box david.e.box@linux.intel.com Link: https://lore.kernel.org/r/20210126205508.30907-3-david.e.box@linux.intel.com Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 9948c5f4928d4..ac4125ec06603 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1394,6 +1394,7 @@ config INTEL_PMT_TELEMETRY
config INTEL_PMT_CRASHLOG tristate "Intel Platform Monitoring Technology (PMT) Crashlog driver" + depends on MFD_INTEL_PMT select INTEL_PMT_CLASS help The Intel Platform Monitoring Technology (PMT) crashlog driver provides
From: Arnaldo Carvalho de Melo acme@redhat.com
[ Upstream commit c69bf11ad3d30b6bf01cfa538ddff1a59467c734 ]
When we lookup an address and don't find a map we should filter that sample if the user specified a list of --dso entries to filter on, fix it.
Before:
$ perf script sleep 274800 2843.556162: 1 cycles:u: ffffffffbb26bff4 [unknown] ([unknown]) sleep 274800 2843.556168: 1 cycles:u: ffffffffbb2b047d [unknown] ([unknown]) sleep 274800 2843.556171: 1 cycles:u: ffffffffbb2706b2 [unknown] ([unknown]) sleep 274800 2843.556174: 6 cycles:u: ffffffffbb2b0267 [unknown] ([unknown]) sleep 274800 2843.556176: 59 cycles:u: ffffffffbb2b03b1 [unknown] ([unknown]) sleep 274800 2843.556180: 691 cycles:u: ffffffffbb26bff4 [unknown] ([unknown]) sleep 274800 2843.556189: 9160 cycles:u: 7fa9550eeaa3 __GI___tunables_init+0xf3 (/usr/lib64/ld-2.32.so) sleep 274800 2843.556312: 86937 cycles:u: 7fa9550e157b _dl_lookup_symbol_x+0x4b (/usr/lib64/ld-2.32.so) $
So we have some samples we somehow didn't find in a map for, if we now do:
$ perf report --stdio --dso /usr/lib64/ld-2.32.so # dso: /usr/lib64/ld-2.32.so # # Total Lost Samples: 0 # # Samples: 8 of event 'cycles:u' # Event count (approx.): 96856 # # Overhead Command Symbol # ........ ....... ........................ # 89.76% sleep [.] _dl_lookup_symbol_x 9.46% sleep [.] __GI___tunables_init 0.71% sleep [k] 0xffffffffbb26bff4 0.06% sleep [k] 0xffffffffbb2b03b1 0.01% sleep [k] 0xffffffffbb2b0267 0.00% sleep [k] 0xffffffffbb2706b2 0.00% sleep [k] 0xffffffffbb2b047d $
After this patch we get the right output with just entries for the DSOs specified in --dso:
$ perf report --stdio --dso /usr/lib64/ld-2.32.so # dso: /usr/lib64/ld-2.32.so # # Total Lost Samples: 0 # # Samples: 8 of event 'cycles:u' # Event count (approx.): 96856 # # Overhead Command Symbol # ........ ....... ........................ # 89.76% sleep [.] _dl_lookup_symbol_x 9.46% sleep [.] __GI___tunables_init $ #
Fixes: 96415e4d3f5fdf9c ("perf symbols: Avoid unnecessary symbol loading when dso list is specified") Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Andi Kleen ak@linux.intel.com Cc: Ingo Molnar mingo@redhat.com Cc: Jin Yao yao.jin@linux.intel.com Cc: Jiri Olsa jolsa@kernel.org Cc: Kan Liang kan.liang@intel.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20210128131209.GD775562@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/event.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 05616d4138a96..7e440fa90c938 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -673,6 +673,8 @@ int machine__resolve(struct machine *machine, struct addr_location *al, }
al->sym = map__find_symbol(al->map, al->addr); + } else if (symbol_conf.dso_list) { + al->filtered |= (1 << HIST_FILTER__DSO); }
if (symbol_conf.sym_list) {
From: John Garry john.garry@huawei.com
[ Upstream commit 2bf797be81fa808f05f1a7a65916619132256a27 ]
The "briefdescription" for event 0x35 has a typo - fix it.
Fixes: d35c595bf005 ("perf vendor events arm64: Revise core JSON events for eMAG") Signed-off-by: John Garry john.garry@huawei.com Acked-by: Will Deacon will@kernel.org Cc: James Clark james.clark@arm.com Cc: Jiri Olsa jolsa@redhat.com Cc: Leo Yan leo.yan@linaro.org Cc: Mark Rutland mark.rutland@arm.com Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Nakamura, Shunsuke/中村 俊介 nakamura.shun@fujitsu.com Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@openeuler.org Link: https://lore.kernel.org/r/1611835236-34696-2-git-send-email-john.garry@huawe... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json index 40010a8724b3a..ce6e7e7960579 100644 --- a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json +++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json @@ -114,7 +114,7 @@ "PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count", "EventCode": "0x35", "EventName": "L2I_TLB_ACCESS", - "BriefDescription": "L2D TLB access" + "BriefDescription": "L2I TLB access" }, { "PublicDescription": "Branch target buffer misprediction",
From: Bob Pearson rpearsonhpe@gmail.com
[ Upstream commit 7d9ae80e31df57dd3253e1ec514f0000aa588a81 ]
check_type_state() in rxe_recv.c is written as if the type bits in the packet opcode were a bit mask which is not correct. This patch corrects this code to compare all 3 type bits to the required type.
Fixes: 8700e3e7c485 ("Soft RoCE driver") Link: https://lore.kernel.org/r/20210127214500.3707-1-rpearson@hpe.com Signed-off-by: Bob Pearson rpearson@hpe.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/rxe/rxe_recv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index c9984a28eecc7..db0ee5c3962e4 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -9,21 +9,26 @@ #include "rxe.h" #include "rxe_loc.h"
+/* check that QP matches packet opcode type and is in a valid state */ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct rxe_qp *qp) { + unsigned int pkt_type; + if (unlikely(!qp->valid)) goto err1;
+ pkt_type = pkt->opcode & 0xe0; + switch (qp_type(qp)) { case IB_QPT_RC: - if (unlikely((pkt->opcode & IB_OPCODE_RC) != 0)) { + if (unlikely(pkt_type != IB_OPCODE_RC)) { pr_warn_ratelimited("bad qp type\n"); goto err1; } break; case IB_QPT_UC: - if (unlikely(!(pkt->opcode & IB_OPCODE_UC))) { + if (unlikely(pkt_type != IB_OPCODE_UC)) { pr_warn_ratelimited("bad qp type\n"); goto err1; } @@ -31,7 +36,7 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, case IB_QPT_UD: case IB_QPT_SMI: case IB_QPT_GSI: - if (unlikely(!(pkt->opcode & IB_OPCODE_UD))) { + if (unlikely(pkt_type != IB_OPCODE_UD)) { pr_warn_ratelimited("bad qp type\n"); goto err1; }
From: Bob Pearson rpearsonhpe@gmail.com
[ Upstream commit 8fc1b7027fc162738d5a85c82410e501a371a404 ]
rxe_rcv_mcast_pkt() in rxe_recv.c can leak SKBs in error path code. The loop over the QPs attached to a multicast group creates new cloned SKBs for all but the last QP in the list and passes the SKB and its clones to rxe_rcv_pkt() for further processing. Any QPs that do not pass some checks are skipped. If the last QP in the list fails the tests the SKB is leaked. This patch checks if the SKB for the last QP was used and if not frees it. Also removes a redundant loop invariant assignment.
Fixes: 8700e3e7c485 ("Soft RoCE driver") Fixes: 71abf20b28ff ("RDMA/rxe: Handle skb_clone() failure in rxe_recv.c") Link: https://lore.kernel.org/r/20210128174752.16128-1-rpearson@hpe.com Signed-off-by: Bob Pearson rpearson@hpe.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/rxe/rxe_recv.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index db0ee5c3962e4..cb69a125e2806 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -257,7 +257,6 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
list_for_each_entry(mce, &mcg->qp_list, qp_list) { qp = mce->qp; - pkt = SKB_TO_PKT(skb);
/* validate qp for incoming packet */ err = check_type_state(rxe, pkt, qp); @@ -269,12 +268,18 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb) continue;
/* for all but the last qp create a new clone of the - * skb and pass to the qp. + * skb and pass to the qp. If an error occurs in the + * checks for the last qp in the list we need to + * free the skb since it hasn't been passed on to + * rxe_rcv_pkt() which would free it later. */ - if (mce->qp_list.next != &mcg->qp_list) + if (mce->qp_list.next != &mcg->qp_list) { per_qp_skb = skb_clone(skb, GFP_ATOMIC); - else + } else { per_qp_skb = skb; + /* show we have consumed the skb */ + skb = NULL; + }
if (unlikely(!per_qp_skb)) continue; @@ -289,9 +294,8 @@ static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
rxe_drop_ref(mcg); /* drop ref from rxe_pool_get_key. */
- return; - err1: + /* free skb if not consumed */ kfree_skb(skb); }
From: Bob Pearson rpearsonhpe@gmail.com
[ Upstream commit 5120bf0a5fc15dec210a0fe0f39e4a256bb6e349 ]
rxe_net.c sends packets at the IP layer with skb->data pointing at the IP header but receives packets from a UDP tunnel with skb->data pointing at the UDP header. On the loopback path this was not correctly accounted for. This patch corrects for this by using sbk_pull() to strip the IP header from the skb on received packets.
Fixes: 8700e3e7c485 ("Soft RoCE driver") Link: https://lore.kernel.org/r/20210128182301.16859-1-rpearson@hpe.com Signed-off-by: Bob Pearson rpearson@hpe.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/rxe/rxe_net.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 943914c2a50c7..bce44502ab0ed 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -414,6 +414,11 @@ int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb)
void rxe_loopback(struct sk_buff *skb) { + if (skb->protocol == htons(ETH_P_IP)) + skb_pull(skb, sizeof(struct iphdr)); + else + skb_pull(skb, sizeof(struct ipv6hdr)); + rxe_rcv(skb); }
From: Alain Volmat alain.volmat@foss.st.com
[ Upstream commit 2269f5a8b1a7b38651d62676b98182828f29d11a ]
On 0 byte transfer request, return straight from the xfer function after finalizing the transfer.
Fixes: dcbe0d84dfa5 ("spi: add driver for STM32 SPI controller") Signed-off-by: Alain Volmat alain.volmat@foss.st.com Link: https://lore.kernel.org/r/1612551572-495-2-git-send-email-alain.volmat@foss.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-stm32.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 6017209c6d2f7..6eeb39669a866 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1677,6 +1677,10 @@ static int stm32_spi_transfer_one(struct spi_master *master, struct stm32_spi *spi = spi_master_get_devdata(master); int ret;
+ /* Don't do anything on 0 bytes transfers */ + if (transfer->len == 0) + return 0; + spi->tx_buf = transfer->tx_buf; spi->rx_buf = transfer->rx_buf; spi->tx_len = spi->tx_buf ? transfer->len : 0;
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit b0b5b16b78cea1b2b990a69ab8e07a42ccf7a2ed ]
A recent fix improved the way the resource gets passed to the low-level accessors, but left one warning that appears in configurations with a resource_size_t that is wider than a pointer:
In file included from drivers/mfd/altera-sysmgr.c:19: drivers/mfd/altera-sysmgr.c: In function 'sysmgr_probe': drivers/mfd/altera-sysmgr.c:148:40: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] 148 | regmap = devm_regmap_init(dev, NULL, (void *)res->start, | ^ include/linux/regmap.h:646:6: note: in definition of macro '__regmap_lockdep_wrapper' 646 | fn(__VA_ARGS__, &_key, \ | ^~~~~~~~~~~ drivers/mfd/altera-sysmgr.c:148:12: note: in expansion of macro 'devm_regmap_init' 148 | regmap = devm_regmap_init(dev, NULL, (void *)res->start, | ^~~~~~~~~~~~~~~~
I had tried a different approach that would store the address in the private data as a phys_addr_t, but the easiest solution now seems to be to add a double cast to shut up the warning.
As the address is passed to an inline assembly, it is guaranteed to not be wider than a register anyway.
Fixes: d9ca7801b6e5 ("mfd: altera-sysmgr: Fix physical address storing hacks") Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mfd/altera-sysmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index 193a96c8b1eab..20cb294c75122 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -145,7 +145,8 @@ static int sysmgr_probe(struct platform_device *pdev) sysmgr_config.reg_write = s10_protected_reg_write;
/* Need physical address for SMCC call */ - regmap = devm_regmap_init(dev, NULL, (void *)res->start, + regmap = devm_regmap_init(dev, NULL, + (void *)(uintptr_t)res->start, &sysmgr_config); } else { base = devm_ioremap(dev, res->start, resource_size(res));
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 26783d74cc6a440ee3ef9836a008a697981013d0 ]
The "req" struct is always added to the "wm831x->auxadc_pending" list, but it's only removed from the list on the success path. If a failure occurs then the "req" struct is freed but it's still on the list, leading to a use after free.
Fixes: 78bb3688ea18 ("mfd: Support multiple active WM831x AUXADC conversions") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Acked-by: Charles Keepax ckeepax@opensource.cirrus.com Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mfd/wm831x-auxadc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c index 8a7cc0f86958b..65b98f3fbd929 100644 --- a/drivers/mfd/wm831x-auxadc.c +++ b/drivers/mfd/wm831x-auxadc.c @@ -93,11 +93,10 @@ static int wm831x_auxadc_read_irq(struct wm831x *wm831x, wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
mutex_lock(&wm831x->auxadc_lock); - - list_del(&req->list); ret = req->val;
out: + list_del(&req->list); mutex_unlock(&wm831x->auxadc_lock);
kfree(req);
From: Nathan Lynch nathanl@linux.ibm.com
[ Upstream commit 768d70e19ba525debd571b36e6d0ab19956c63d7 ]
dlpar_configure_connector() has two problems in its handling of ibm,configure-connector's return status:
1. When the status is -2 (busy, call again), we call ibm,configure-connector again immediately without checking whether to schedule, which can result in monopolizing the CPU. 2. Extended delay status (9900..9905) goes completely unhandled, causing the configuration to unnecessarily terminate.
Fix both of these issues by using rtas_busy_delay().
Fixes: ab519a011caa ("powerpc/pseries: Kernel DLPAR Infrastructure") Signed-off-by: Nathan Lynch nathanl@linux.ibm.com Reviewed-by: Tyrel Datwyler tyreld@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210107025900.410369-1-nathanl@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/platforms/pseries/dlpar.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 16e86ba8aa209..f6b7749d6ada7 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -127,7 +127,6 @@ void dlpar_free_cc_nodes(struct device_node *dn) #define NEXT_PROPERTY 3 #define PREV_PARENT 4 #define MORE_MEMORY 5 -#define CALL_AGAIN -2 #define ERR_CFG_USE -9003
struct device_node *dlpar_configure_connector(__be32 drc_index, @@ -168,6 +167,9 @@ struct device_node *dlpar_configure_connector(__be32 drc_index,
spin_unlock(&rtas_data_buf_lock);
+ if (rtas_busy_delay(rc)) + continue; + switch (rc) { case COMPLETE: break; @@ -216,9 +218,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, last_dn = last_dn->parent; break;
- case CALL_AGAIN: - break; - case MORE_MEMORY: case ERR_CFG_USE: default:
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit 903178d0ce6bb30ef80a3604ab9ee2b57869fbc9 ]
For unimplemented instructions or unimplemented SPRs, the 8xx triggers a "Software Emulation Exception" (0x1000). That interrupt doesn't set reason bits in SRR1 as the "Program Check Exception" does.
Go through emulation_assist_interrupt() to set REASON_ILLEGAL.
Fixes: fbbcc3bb139e ("powerpc/8xx: Remove SoftwareEmulation()") Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/ad782af87a222efc79cfb06079b0fd23d4224eaf.161251518... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/head_8xx.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 52702f3db6df6..9eb63cf6ac38e 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -165,7 +165,7 @@ SystemCall: /* On the MPC8xx, this is a software emulation interrupt. It occurs * for all unimplemented and illegal instructions. */ - EXCEPTION(0x1000, SoftEmu, program_check_exception, EXC_XFER_STD) + EXCEPTION(0x1000, SoftEmu, emulation_assist_interrupt, EXC_XFER_STD)
. = 0x1100 /*
From: Sandipan Das sandipan@linux.ibm.com
[ Upstream commit bbda4b6c7d7c7f79da71f95c92a5d76be22c3efd ]
The Power ISA says that the fixed-point load and update instructions must neither use R0 for the base address (RA) nor have the destination (RT) and the base address (RA) as the same register. Similarly, for fixed-point stores and floating-point loads and stores, the instruction is invalid when R0 is used as the base address (RA).
This is applicable to the following instructions. * Load Byte and Zero with Update (lbzu) * Load Byte and Zero with Update Indexed (lbzux) * Load Halfword and Zero with Update (lhzu) * Load Halfword and Zero with Update Indexed (lhzux) * Load Halfword Algebraic with Update (lhau) * Load Halfword Algebraic with Update Indexed (lhaux) * Load Word and Zero with Update (lwzu) * Load Word and Zero with Update Indexed (lwzux) * Load Word Algebraic with Update Indexed (lwaux) * Load Doubleword with Update (ldu) * Load Doubleword with Update Indexed (ldux) * Load Floating Single with Update (lfsu) * Load Floating Single with Update Indexed (lfsux) * Load Floating Double with Update (lfdu) * Load Floating Double with Update Indexed (lfdux) * Store Byte with Update (stbu) * Store Byte with Update Indexed (stbux) * Store Halfword with Update (sthu) * Store Halfword with Update Indexed (sthux) * Store Word with Update (stwu) * Store Word with Update Indexed (stwux) * Store Doubleword with Update (stdu) * Store Doubleword with Update Indexed (stdux) * Store Floating Single with Update (stfsu) * Store Floating Single with Update Indexed (stfsux) * Store Floating Double with Update (stfdu) * Store Floating Double with Update Indexed (stfdux)
E.g. the following behaviour is observed for an invalid load and update instruction having RA = RT.
While a userspace program having an instruction word like 0xe9ce0001, i.e. ldu r14, 0(r14), runs without getting receiving a SIGILL on a Power system (observed on P8 and P9), the outcome of executing that instruction word varies and its behaviour can be considered to be undefined.
Attaching an uprobe at that instruction's address results in emulation which currently performs the load as well as writes the effective address back to the base register. This might not match the outcome from hardware.
To remove any inconsistencies, this adds additional checks for the aforementioned instructions to make sure that the emulation infrastructure treats them as unknown. The kernel can then fallback to executing such instructions on hardware.
Fixes: 0016a4cf5582 ("powerpc: Emulate most Book I instructions in emulate_step()") Signed-off-by: Sandipan Das sandipan@linux.ibm.com Reviewed-by: Naveen N. Rao naveen.n.rao@linux.vnet.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210204080744.135785-1-sandipan@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/lib/sstep.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 33935869e4976..25cfa9c622c58 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -3019,6 +3019,20 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
}
+ if (OP_IS_LOAD_STORE(op->type) && (op->type & UPDATE)) { + switch (GETTYPE(op->type)) { + case LOAD: + if (ra == rd) + goto unknown_opcode; + fallthrough; + case STORE: + case LOAD_FP: + case STORE_FP: + if (ra == 0) + goto unknown_opcode; + } + } + #ifdef CONFIG_VSX if ((GETTYPE(op->type) == LOAD_VSX || GETTYPE(op->type) == STORE_VSX) &&
From: Sandipan Das sandipan@linux.ibm.com
[ Upstream commit 22b89ba178dd0a66a26699ead014a3e73ff8e044 ]
Commit 8813ff49607e ("powerpc/sstep: Check instruction validity against ISA version before emulation") introduced a proper way to skip unknown instructions. This makes sure that the same is used for the darn instruction when the range selection bits have a reserved value.
Fixes: a23987ef267a ("powerpc: sstep: Add support for darn instruction") Signed-off-by: Sandipan Das sandipan@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210204080744.135785-2-sandipan@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/lib/sstep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 25cfa9c622c58..bb5c20d4ca91c 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1918,7 +1918,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, goto compute_done; }
- return -1; + goto unknown_opcode; #ifdef __powerpc64__ case 777: /* modsd */ if (!cpu_has_feature(CPU_FTR_ARCH_300))
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org
[ Upstream commit 78ddb79cab178534b2c1d9ab95823f2af882ee8e ]
For some reason global GFM_MASK ended up with bit 1 instead of bit 0. Remove the global GFM_MASK and reuse mux_mask field.
Fixes: a2d8f507803e ("clk: qcom: Add support to LPASS AUDIO_CC Glitch Free Mux clocks") Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210119113851.18946-1-srinivas.kandagatla@linaro.... Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/qcom/lpass-gfm-sm8250.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/qcom/lpass-gfm-sm8250.c b/drivers/clk/qcom/lpass-gfm-sm8250.c index d366c7c2abc77..f5e31e692b9b4 100644 --- a/drivers/clk/qcom/lpass-gfm-sm8250.c +++ b/drivers/clk/qcom/lpass-gfm-sm8250.c @@ -33,14 +33,13 @@ struct clk_gfm { void __iomem *gfm_mux; };
-#define GFM_MASK BIT(1) #define to_clk_gfm(_hw) container_of(_hw, struct clk_gfm, hw)
static u8 clk_gfm_get_parent(struct clk_hw *hw) { struct clk_gfm *clk = to_clk_gfm(hw);
- return readl(clk->gfm_mux) & GFM_MASK; + return readl(clk->gfm_mux) & clk->mux_mask; }
static int clk_gfm_set_parent(struct clk_hw *hw, u8 index) @@ -51,9 +50,10 @@ static int clk_gfm_set_parent(struct clk_hw *hw, u8 index) val = readl(clk->gfm_mux);
if (index) - val |= GFM_MASK; + val |= clk->mux_mask; else - val &= ~GFM_MASK; + val &= ~clk->mux_mask; +
writel(val, clk->gfm_mux);
From: Taniya Das tdas@codeaurora.org
[ Upstream commit d79dfa19ca4235c28be62952bda6091babdcf8f3 ]
There are intermittent GDSC power-up failures observed for titan top gdsc, which requires the XO clock. Thus mark all the MM XO clocks always enabled from probe.
Fixes: 8d4025943e13 ("clk: qcom: camcc-sc7180: Use runtime PM ops instead of clk ones") Signed-off-by: Taniya Das tdas@codeaurora.org Link: https://lore.kernel.org/r/1611128871-5898-1-git-send-email-tdas@codeaurora.o... Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/qcom/gcc-sc7180.c | 47 +++-------------------------------- 1 file changed, 4 insertions(+), 43 deletions(-)
diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c index b05901b249172..88e896abb6631 100644 --- a/drivers/clk/qcom/gcc-sc7180.c +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */
#include <linux/clk-provider.h> @@ -919,19 +919,6 @@ static struct clk_branch gcc_camera_throttle_hf_axi_clk = { }, };
-static struct clk_branch gcc_camera_xo_clk = { - .halt_reg = 0xb02c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0xb02c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_camera_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_ce1_ahb_clk = { .halt_reg = 0x4100c, .halt_check = BRANCH_HALT_VOTED, @@ -1096,19 +1083,6 @@ static struct clk_branch gcc_disp_throttle_hf_axi_clk = { }, };
-static struct clk_branch gcc_disp_xo_clk = { - .halt_reg = 0xb030, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0xb030, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_disp_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x64000, .halt_check = BRANCH_HALT, @@ -2159,19 +2133,6 @@ static struct clk_branch gcc_video_throttle_axi_clk = { }, };
-static struct clk_branch gcc_video_xo_clk = { - .halt_reg = 0xb028, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0xb028, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_video_xo_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_mss_cfg_ahb_clk = { .halt_reg = 0x8a000, .halt_check = BRANCH_HALT, @@ -2304,7 +2265,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = { [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, [GCC_CAMERA_THROTTLE_HF_AXI_CLK] = &gcc_camera_throttle_hf_axi_clk.clkr, - [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, @@ -2317,7 +2277,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = { [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, [GCC_DISP_THROTTLE_HF_AXI_CLK] = &gcc_disp_throttle_hf_axi_clk.clkr, - [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, @@ -2413,7 +2372,6 @@ static struct clk_regmap *gcc_sc7180_clocks[] = { [GCC_VIDEO_AXI_CLK] = &gcc_video_axi_clk.clkr, [GCC_VIDEO_GPLL0_DIV_CLK_SRC] = &gcc_video_gpll0_div_clk_src.clkr, [GCC_VIDEO_THROTTLE_AXI_CLK] = &gcc_video_throttle_axi_clk.clkr, - [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, [GPLL0] = &gpll0.clkr, [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr, [GPLL6] = &gpll6.clkr, @@ -2510,6 +2468,9 @@ static int gcc_sc7180_probe(struct platform_device *pdev) regmap_update_bits(regmap, 0x0b004, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x0b008, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x0b00c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b02c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b028, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b030, BIT(0), BIT(0)); regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0));
ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
From: AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org
[ Upstream commit 292f75ecff07e8a07fe2e3e19b4b567d0b698842 ]
All of the GPLLs in the MSM8998 Global Clock Controller are Fabia PLLs and not generic alphas: this was producing bad effects over the entire clock tree of MSM8998, where any GPLL child clock was declaring a false clock rate, due to their parent also showing the same.
The issue resides in the calculation of the clock rate for the specific Alpha PLL type, where Fabia has a different register layout; switching the MSM8998 GPLLs to the correct Alpha Fabia PLL type fixes the rate (calculation) reading. While at it, also make these PLLs fixed since their rate is supposed to *never* be changed while the system runs, as this would surely crash the entire SoC.
Now all the children of all the PLLs are also complying with their specified clock table and system stability is improved.
Fixes: b5f5f525c547 ("clk: qcom: Add MSM8998 Global Clock Control (GCC) driver") Signed-off-by: AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org Link: https://lore.kernel.org/r/20210114221059.483390-7-angelogioacchino.delregno@... Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/qcom/gcc-msm8998.c | 100 ++++++++++++++++----------------- 1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index 9d7016bcd6800..b8dcfe62312bb 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -135,7 +135,7 @@ static struct pll_vco fabia_vco[] = {
static struct clk_alpha_pll gpll0 = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -145,58 +145,58 @@ static struct clk_alpha_pll gpll0 = { .name = "gpll0", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, };
static struct clk_alpha_pll_postdiv gpll0_out_even = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_even", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll0_out_main = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_main", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll0_out_odd = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_odd", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll0_out_test = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_test", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll gpll1 = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -206,58 +206,58 @@ static struct clk_alpha_pll gpll1 = { .name = "gpll1", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, };
static struct clk_alpha_pll_postdiv gpll1_out_even = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_even", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll1_out_main = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_main", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll1_out_odd = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_odd", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll1_out_test = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_test", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll gpll2 = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -267,58 +267,58 @@ static struct clk_alpha_pll gpll2 = { .name = "gpll2", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, };
static struct clk_alpha_pll_postdiv gpll2_out_even = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_even", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll2_out_main = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_main", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll2_out_odd = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_odd", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll2_out_test = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_test", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll gpll3 = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -328,58 +328,58 @@ static struct clk_alpha_pll gpll3 = { .name = "gpll3", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, };
static struct clk_alpha_pll_postdiv gpll3_out_even = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_even", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll3_out_main = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_main", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll3_out_odd = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_odd", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll3_out_test = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_test", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll gpll4 = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -389,52 +389,52 @@ static struct clk_alpha_pll gpll4 = { .name = "gpll4", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, };
static struct clk_alpha_pll_postdiv gpll4_out_even = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_even", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll4_out_main = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_main", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll4_out_odd = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_odd", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
static struct clk_alpha_pll_postdiv gpll4_out_test = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_test", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, };
From: Daniel Latypov dlatypov@google.com
[ Upstream commit cfd607e43da4a20753744f134e201310262b827a ]
* Stop leaking file objects. * Use self.addCleanup() to ensure we call cleanup functions even if setUp() fails. * use mock.patch.stopall instead of more error-prone manual approach
Signed-off-by: Daniel Latypov dlatypov@google.com Reviewed-by: David Gow davidgow@google.com Tested-by: Brendan Higgins brendanhiggins@google.com Acked-by: Brendan Higgins brendanhiggins@google.com Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/kunit/kunit_tool_test.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py index b593f4448e839..9a036e9d44554 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -288,19 +288,17 @@ class StrContains(str): class KUnitMainTest(unittest.TestCase): def setUp(self): path = get_absolute_path('test_data/test_is_test_passed-all_passed.log') - file = open(path) - all_passed_log = file.readlines() - self.print_patch = mock.patch('builtins.print') - self.print_mock = self.print_patch.start() + with open(path) as file: + all_passed_log = file.readlines() + + self.print_mock = mock.patch('builtins.print').start() + self.addCleanup(mock.patch.stopall) + self.linux_source_mock = mock.Mock() self.linux_source_mock.build_reconfig = mock.Mock(return_value=True) self.linux_source_mock.build_um_kernel = mock.Mock(return_value=True) self.linux_source_mock.run_kernel = mock.Mock(return_value=all_passed_log)
- def tearDown(self): - self.print_patch.stop() - pass - def test_config_passes_args_pass(self): kunit.main(['config', '--build_dir=.kunit'], self.linux_source_mock) assert self.linux_source_mock.build_reconfig.call_count == 1
From: John Stultz john.stultz@linaro.org
[ Upstream commit 64ba3d591c9d2be2a9c09e99b00732afe002ad0d ]
Copied in from somewhere else, the makefile was including the kerne's usr/include dir, which caused the asm/ioctl.h file to be used.
Unfortunately, that file has different values for _IOC_SIZEBITS and _IOC_WRITE than include/uapi/asm-generic/ioctl.h which then causes the _IOCW macros to give the wrong ioctl numbers, specifically for DMA_BUF_IOCTL_SYNC.
This patch simply removes the extra include from the Makefile
Cc: Shuah Khan shuah@kernel.org Cc: Brian Starkey brian.starkey@arm.com Cc: Sumit Semwal sumit.semwal@linaro.org Cc: Laura Abbott labbott@kernel.org Cc: Hridya Valsaraju hridya@google.com Cc: Suren Baghdasaryan surenb@google.com Cc: Sandeep Patil sspatil@google.com Cc: Daniel Mentz danielmentz@google.com Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-kselftest@vger.kernel.org Fixes: a8779927fd86c ("kselftests: Add dma-heap test") Signed-off-by: John Stultz john.stultz@linaro.org Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/dmabuf-heaps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/dmabuf-heaps/Makefile b/tools/testing/selftests/dmabuf-heaps/Makefile index 607c2acd20829..604b43ece15f5 100644 --- a/tools/testing/selftests/dmabuf-heaps/Makefile +++ b/tools/testing/selftests/dmabuf-heaps/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -CFLAGS += -static -O3 -Wl,-no-as-needed -Wall -I../../../../usr/include +CFLAGS += -static -O3 -Wl,-no-as-needed -Wall
TEST_GEN_PROGS = dmabuf-heap
From: Lang Cheng chenglang@huawei.com
[ Upstream commit 9dd052474a2645b2a6171d19ad17b05b180d446d ]
The RQ/SRQ of HIP08 needs one special sge to stop receive reliably. So the driver needs to allocate at least one SGE when creating RQ/SRQ and ensure that at least one SGE is filled with the special value during post_recv.
Besides, the kernel driver should only do this for kernel ULP. For userspace ULP, the userspace driver will allocate the reserved SGE in buffer, and the kernel driver just needs to pin the corresponding size of memory based on the userspace driver's requirements.
Link: https://lore.kernel.org/r/1611997090-48820-2-git-send-email-liweihang@huawei... Signed-off-by: Lang Cheng chenglang@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_device.h | 4 +++ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 28 ++++++++++----- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3 +- drivers/infiniband/hw/hns/hns_roce_qp.c | 37 +++++++++++++++---- drivers/infiniband/hw/hns/hns_roce_srq.c | 40 +++++++++++++++++++-- 5 files changed, 93 insertions(+), 19 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index ad8253245a85f..dd3e3886ab96d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -65,6 +65,8 @@ #define HNS_ROCE_CQE_WCMD_EMPTY_BIT 0x2 #define HNS_ROCE_MIN_CQE_CNT 16
+#define HNS_ROCE_RESERVED_SGE 1 + #define HNS_ROCE_MAX_IRQ_NUM 128
#define HNS_ROCE_SGE_IN_WQE 2 @@ -393,6 +395,7 @@ struct hns_roce_wq { spinlock_t lock; u32 wqe_cnt; /* WQE num */ u32 max_gs; + u32 rsv_sge; int offset; int wqe_shift; /* WQE size */ u32 head; @@ -496,6 +499,7 @@ struct hns_roce_srq { unsigned long srqn; u32 wqe_cnt; int max_gs; + u32 rsv_sge; int wqe_shift; void __iomem *db_reg_l;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 833e1f259936f..4d1e4bddf8327 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -741,6 +741,7 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp, unsigned long flags; void *wqe = NULL; u32 wqe_idx; + u32 max_sge; int nreq; int ret; int i; @@ -754,6 +755,7 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp, goto out; }
+ max_sge = hr_qp->rq.max_gs - hr_qp->rq.rsv_sge; for (nreq = 0; wr; ++nreq, wr = wr->next) { if (unlikely(hns_roce_wq_overflow(&hr_qp->rq, nreq, hr_qp->ibqp.recv_cq))) { @@ -764,9 +766,9 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp,
wqe_idx = (hr_qp->rq.head + nreq) & (hr_qp->rq.wqe_cnt - 1);
- if (unlikely(wr->num_sge > hr_qp->rq.max_gs)) { + if (unlikely(wr->num_sge > max_sge)) { ibdev_err(ibdev, "num_sge = %d >= max_sge = %u.\n", - wr->num_sge, hr_qp->rq.max_gs); + wr->num_sge, max_sge); ret = -EINVAL; *bad_wr = wr; goto out; @@ -781,9 +783,10 @@ static int hns_roce_v2_post_recv(struct ib_qp *ibqp, dseg++; }
- if (wr->num_sge < hr_qp->rq.max_gs) { + if (hr_qp->rq.rsv_sge) { dseg->lkey = cpu_to_le32(HNS_ROCE_INVALID_LKEY); dseg->addr = 0; + dseg->len = cpu_to_le32(HNS_ROCE_INVALID_SGE_LENGTH); }
/* rq support inline data */ @@ -879,6 +882,7 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, __le32 *srq_idx; int ret = 0; int wqe_idx; + u32 max_sge; void *wqe; int nreq; int i; @@ -886,9 +890,13 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, spin_lock_irqsave(&srq->lock, flags);
ind = srq->head & (srq->wqe_cnt - 1); + max_sge = srq->max_gs - srq->rsv_sge;
for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (unlikely(wr->num_sge >= srq->max_gs)) { + if (unlikely(wr->num_sge > max_sge)) { + ibdev_err(&hr_dev->ib_dev, + "srq: num_sge = %d, max_sge = %u.\n", + wr->num_sge, max_sge); ret = -EINVAL; *bad_wr = wr; break; @@ -916,9 +924,9 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, dseg[i].addr = cpu_to_le64(wr->sg_list[i].addr); }
- if (wr->num_sge < srq->max_gs) { - dseg[i].len = 0; - dseg[i].lkey = cpu_to_le32(0x100); + if (srq->rsv_sge) { + dseg[i].len = cpu_to_le32(HNS_ROCE_INVALID_SGE_LENGTH); + dseg[i].lkey = cpu_to_le32(HNS_ROCE_INVALID_LKEY); dseg[i].addr = 0; }
@@ -1999,10 +2007,12 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev) caps->max_sq_sg = le16_to_cpu(resp_a->max_sq_sg); caps->max_sq_inline = le16_to_cpu(resp_a->max_sq_inline); caps->max_rq_sg = le16_to_cpu(resp_a->max_rq_sg); + caps->max_rq_sg = roundup_pow_of_two(caps->max_rq_sg); caps->max_extend_sg = le32_to_cpu(resp_a->max_extend_sg); caps->num_qpc_timer = le16_to_cpu(resp_a->num_qpc_timer); caps->num_cqc_timer = le16_to_cpu(resp_a->num_cqc_timer); caps->max_srq_sges = le16_to_cpu(resp_a->max_srq_sges); + caps->max_srq_sges = roundup_pow_of_two(caps->max_srq_sges); caps->num_aeq_vectors = resp_a->num_aeq_vectors; caps->num_other_vectors = resp_a->num_other_vectors; caps->max_sq_desc_sz = resp_a->max_sq_desc_sz; @@ -5083,7 +5093,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, done: qp_attr->cur_qp_state = qp_attr->qp_state; qp_attr->cap.max_recv_wr = hr_qp->rq.wqe_cnt; - qp_attr->cap.max_recv_sge = hr_qp->rq.max_gs; + qp_attr->cap.max_recv_sge = hr_qp->rq.max_gs - hr_qp->rq.rsv_sge;
if (!ibqp->uobject) { qp_attr->cap.max_send_wr = hr_qp->sq.wqe_cnt; @@ -5395,7 +5405,7 @@ static int hns_roce_v2_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr)
attr->srq_limit = limit_wl; attr->max_wr = srq->wqe_cnt - 1; - attr->max_sge = srq->max_gs; + attr->max_sge = srq->max_gs - srq->rsv_sge;
out: hns_roce_free_cmd_mailbox(hr_dev, mailbox); diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index bdaccf86460dd..09d88d97a7ff9 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -96,7 +96,8 @@ #define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ PAGE_SIZE #define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED 0xFFFFF000 #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM 2 -#define HNS_ROCE_INVALID_LKEY 0x100 +#define HNS_ROCE_INVALID_LKEY 0x0 +#define HNS_ROCE_INVALID_SGE_LENGTH 0x80000000 #define HNS_ROCE_CMQ_TX_TIMEOUT 30000 #define HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE 2 #define HNS_ROCE_V2_RSV_QPS 8 diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index 1116371adf74f..8695c96e66964 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -413,9 +413,32 @@ static void free_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) mutex_unlock(&hr_dev->qp_table.bank_mutex); }
+static u32 proc_rq_sge(struct hns_roce_dev *dev, struct hns_roce_qp *hr_qp, + bool user) +{ + u32 max_sge = dev->caps.max_rq_sg; + + if (dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) + return max_sge; + + /* Reserve SGEs only for HIP08 in kernel; The userspace driver will + * calculate number of max_sge with reserved SGEs when allocating wqe + * buf, so there is no need to do this again in kernel. But the number + * may exceed the capacity of SGEs recorded in the firmware, so the + * kernel driver should just adapt the value accordingly. + */ + if (user) + max_sge = roundup_pow_of_two(max_sge + 1); + else + hr_qp->rq.rsv_sge = 1; + + return max_sge; +} + static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap, - struct hns_roce_qp *hr_qp, int has_rq) + struct hns_roce_qp *hr_qp, int has_rq, bool user) { + u32 max_sge = proc_rq_sge(hr_dev, hr_qp, user); u32 cnt;
/* If srq exist, set zero for relative number of rq */ @@ -431,8 +454,9 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap,
/* Check the validity of QP support capacity */ if (!cap->max_recv_wr || cap->max_recv_wr > hr_dev->caps.max_wqes || - cap->max_recv_sge > hr_dev->caps.max_rq_sg) { - ibdev_err(&hr_dev->ib_dev, "RQ config error, depth=%u, sge=%d\n", + cap->max_recv_sge > max_sge) { + ibdev_err(&hr_dev->ib_dev, + "RQ config error, depth = %u, sge = %u\n", cap->max_recv_wr, cap->max_recv_sge); return -EINVAL; } @@ -444,7 +468,8 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap, return -EINVAL; }
- hr_qp->rq.max_gs = roundup_pow_of_two(max(1U, cap->max_recv_sge)); + hr_qp->rq.max_gs = roundup_pow_of_two(max(1U, cap->max_recv_sge) + + hr_qp->rq.rsv_sge);
if (hr_dev->caps.max_rq_sg <= HNS_ROCE_SGE_IN_WQE) hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz); @@ -459,7 +484,7 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap, hr_qp->rq_inl_buf.wqe_cnt = 0;
cap->max_recv_wr = cnt; - cap->max_recv_sge = hr_qp->rq.max_gs; + cap->max_recv_sge = hr_qp->rq.max_gs - hr_qp->rq.rsv_sge;
return 0; } @@ -919,7 +944,7 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, hr_qp->sq_signal_bits = IB_SIGNAL_REQ_WR;
ret = set_rq_size(hr_dev, &init_attr->cap, hr_qp, - hns_roce_qp_has_rq(init_attr)); + hns_roce_qp_has_rq(init_attr), !!udata); if (ret) { ibdev_err(ibdev, "failed to set user RQ size, ret = %d.\n", ret); diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index c4ae57e4173a1..8e20085b8920a 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 Hisilicon Limited. */
+#include <linux/pci.h> #include <rdma/ib_umem.h> #include "hns_roce_device.h" #include "hns_roce_cmd.h" @@ -279,6 +280,28 @@ static void free_srq_wrid(struct hns_roce_srq *srq) srq->wrid = NULL; }
+static u32 proc_srq_sge(struct hns_roce_dev *dev, struct hns_roce_srq *hr_srq, + bool user) +{ + u32 max_sge = dev->caps.max_srq_sges; + + if (dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) + return max_sge; + + /* Reserve SGEs only for HIP08 in kernel; The userspace driver will + * calculate number of max_sge with reserved SGEs when allocating wqe + * buf, so there is no need to do this again in kernel. But the number + * may exceed the capacity of SGEs recorded in the firmware, so the + * kernel driver should just adapt the value accordingly. + */ + if (user) + max_sge = roundup_pow_of_two(max_sge + 1); + else + hr_srq->rsv_sge = 1; + + return max_sge; +} + int hns_roce_create_srq(struct ib_srq *ib_srq, struct ib_srq_init_attr *init_attr, struct ib_udata *udata) @@ -288,6 +311,7 @@ int hns_roce_create_srq(struct ib_srq *ib_srq, struct hns_roce_srq *srq = to_hr_srq(ib_srq); struct ib_device *ibdev = &hr_dev->ib_dev; struct hns_roce_ib_create_srq ucmd = {}; + u32 max_sge; int ret; u32 cqn;
@@ -295,16 +319,24 @@ int hns_roce_create_srq(struct ib_srq *ib_srq, init_attr->srq_type != IB_SRQT_XRC) return -EOPNOTSUPP;
- /* Check the actual SRQ wqe and SRQ sge num */ + max_sge = proc_srq_sge(hr_dev, srq, !!udata); + if (init_attr->attr.max_wr >= hr_dev->caps.max_srq_wrs || - init_attr->attr.max_sge > hr_dev->caps.max_srq_sges) + init_attr->attr.max_sge > max_sge) { + ibdev_err(&hr_dev->ib_dev, + "SRQ config error, depth = %u, sge = %d\n", + init_attr->attr.max_wr, init_attr->attr.max_sge); return -EINVAL; + }
mutex_init(&srq->mutex); spin_lock_init(&srq->lock);
srq->wqe_cnt = roundup_pow_of_two(init_attr->attr.max_wr + 1); - srq->max_gs = init_attr->attr.max_sge; + srq->max_gs = + roundup_pow_of_two(init_attr->attr.max_sge + srq->rsv_sge); + init_attr->attr.max_wr = srq->wqe_cnt; + init_attr->attr.max_sge = srq->max_gs;
if (udata) { ret = ib_copy_from_udata(&ucmd, udata, @@ -351,6 +383,8 @@ int hns_roce_create_srq(struct ib_srq *ib_srq,
srq->event = hns_roce_ib_srq_event; resp.srqn = srq->srqn; + srq->max_gs = init_attr->attr.max_sge; + init_attr->attr.max_sge = srq->max_gs - srq->rsv_sge;
if (udata) { ret = ib_copy_to_udata(udata, &resp,
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit 1620f09b96ec14c1ff1ff64ee0aeabc027c653d5 ]
If a user posts WR by wr_list, the head pointer of idx_queue won't be updated until all wqes are filled, so the judgment of whether head equals to tail will get a wrong result. Fix above issue and move the head and tail pointer from the srq structure into the idx_queue structure. After idx_queue is filled with wqe idx, the head pointer of it will increase.
Fixes: c7bcb13442e1 ("RDMA/hns: Add SRQ support for hip08 kernel mode") Link: https://lore.kernel.org/r/1611997090-48820-3-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_device.h | 4 ++-- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 19 ++++++++++++++----- drivers/infiniband/hw/hns/hns_roce_srq.c | 5 +++-- 3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index dd3e3886ab96d..2e42e25957938 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -492,6 +492,8 @@ struct hns_roce_idx_que { struct hns_roce_mtr mtr; int entry_shift; unsigned long *bitmap; + u32 head; + u32 tail; };
struct hns_roce_srq { @@ -511,8 +513,6 @@ struct hns_roce_srq { u64 *wrid; struct hns_roce_idx_que idx_que; spinlock_t lock; - u16 head; - u16 tail; struct mutex mutex; void (*event)(struct hns_roce_srq *srq, enum hns_roce_event event); }; diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 4d1e4bddf8327..c05e418b6e538 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -849,11 +849,20 @@ static void hns_roce_free_srq_wqe(struct hns_roce_srq *srq, int wqe_index) spin_lock(&srq->lock);
bitmap_clear(srq->idx_que.bitmap, wqe_index, 1); - srq->tail++; + srq->idx_que.tail++;
spin_unlock(&srq->lock); }
+int hns_roce_srqwq_overflow(struct hns_roce_srq *srq, int nreq) +{ + struct hns_roce_idx_que *idx_que = &srq->idx_que; + unsigned int cur; + + cur = idx_que->head - idx_que->tail; + return cur + nreq >= srq->wqe_cnt - 1; +} + static int find_empty_entry(struct hns_roce_idx_que *idx_que, unsigned long size) { @@ -889,7 +898,7 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq,
spin_lock_irqsave(&srq->lock, flags);
- ind = srq->head & (srq->wqe_cnt - 1); + ind = srq->idx_que.head & (srq->wqe_cnt - 1); max_sge = srq->max_gs - srq->rsv_sge;
for (nreq = 0; wr; ++nreq, wr = wr->next) { @@ -902,7 +911,7 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, break; }
- if (unlikely(srq->head == srq->tail)) { + if (unlikely(hns_roce_srqwq_overflow(srq, nreq))) { ret = -ENOMEM; *bad_wr = wr; break; @@ -938,7 +947,7 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, }
if (likely(nreq)) { - srq->head += nreq; + srq->idx_que.head += nreq;
/* * Make sure that descriptors are written before @@ -950,7 +959,7 @@ static int hns_roce_v2_post_srq_recv(struct ib_srq *ibsrq, cpu_to_le32(HNS_ROCE_V2_SRQ_DB << V2_DB_BYTE_4_CMD_S | (srq->srqn & V2_DB_BYTE_4_TAG_M)); srq_db.parameter = - cpu_to_le32(srq->head & V2_DB_PARAMETER_IDX_M); + cpu_to_le32(srq->idx_que.head & V2_DB_PARAMETER_IDX_M);
hns_roce_write64(hr_dev, (__le32 *)&srq_db, srq->db_reg_l); } diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index 8e20085b8920a..9f60a0a745e11 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -247,6 +247,9 @@ static int alloc_srq_idx(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq, } }
+ idx_que->head = 0; + idx_que->tail = 0; + return 0; err_idx_mtr: hns_roce_mtr_destroy(hr_dev, &idx_que->mtr); @@ -265,8 +268,6 @@ static void free_srq_idx(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
static int alloc_srq_wrid(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) { - srq->head = 0; - srq->tail = srq->wqe_cnt - 1; srq->wrid = kvmalloc_array(srq->wqe_cnt, sizeof(u64), GFP_KERNEL); if (!srq->wrid) return -ENOMEM;
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit b5df9b7a2f965b7903850d8f89846ffe0080b84b ]
According to the IB Specification, srq_limit shouldn't be configured during SRQ creation. If a user set srq_limit at this time, the driver should forced it to zero, or the result of creating SRQ will conflict with the result of querying SRQ.
Fixes: c7bcb13442e1 ("RDMA/hns: Add SRQ support for hip08 kernel mode") Link: https://lore.kernel.org/r/1611997090-48820-4-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_srq.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index 9f60a0a745e11..ecc42c59e3cfc 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -338,6 +338,7 @@ int hns_roce_create_srq(struct ib_srq *ib_srq, roundup_pow_of_two(init_attr->attr.max_sge + srq->rsv_sge); init_attr->attr.max_wr = srq->wqe_cnt; init_attr->attr.max_sge = srq->max_gs; + init_attr->attr.srq_limit = 0;
if (udata) { ret = ib_copy_from_udata(&ucmd, udata,
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit bb74fe7e81c8b2b65c6a351a247fdb9a969cbaec ]
When an error occurs, the qp_table must be cleared, regardless of whether the SRQ feature is enabled.
Fixes: 5c1f167af112 ("RDMA/hns: Init SRQ table for hip08") Link: https://lore.kernel.org/r/1611997090-48820-5-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_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index d9179bae4989d..60822e666f351 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -772,8 +772,7 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev) return 0;
err_qp_table_free: - if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ) - hns_roce_cleanup_qp_table(hr_dev); + hns_roce_cleanup_qp_table(hr_dev);
err_cq_table_free: hns_roce_cleanup_cq_table(hr_dev);
From: Wenpeng Liang liangwenpeng@huawei.com
[ Upstream commit 6ee00fbf733d7e17ca935e5636adfce605b10659 ]
Each SRQs contain an reserved WQE, it is inappropriate and should be removed.
Fixes: c7bcb13442e1 ("RDMA/hns: Add SRQ support for hip08 kernel mode") Link: https://lore.kernel.org/r/1611997090-48820-6-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_device.h | 1 + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 +++--- drivers/infiniband/hw/hns/hns_roce_srq.c | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 2e42e25957938..9ac6d760aa5b3 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -54,6 +54,7 @@ /* Hardware specification only for v1 engine */ #define HNS_ROCE_MIN_CQE_NUM 0x40 #define HNS_ROCE_MIN_WQE_NUM 0x20 +#define HNS_ROCE_MIN_SRQ_WQE_NUM 1
/* Hardware specification only for v1 engine */ #define HNS_ROCE_MAX_INNER_MTPT_NUM 0x7 diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index c05e418b6e538..a909993552e7f 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -860,7 +860,7 @@ int hns_roce_srqwq_overflow(struct hns_roce_srq *srq, int nreq) unsigned int cur;
cur = idx_que->head - idx_que->tail; - return cur + nreq >= srq->wqe_cnt - 1; + return cur + nreq >= srq->wqe_cnt; }
static int find_empty_entry(struct hns_roce_idx_que *idx_que, @@ -5350,7 +5350,7 @@ static int hns_roce_v2_modify_srq(struct ib_srq *ibsrq, return -EINVAL;
if (srq_attr_mask & IB_SRQ_LIMIT) { - if (srq_attr->srq_limit >= srq->wqe_cnt) + if (srq_attr->srq_limit > srq->wqe_cnt) return -EINVAL;
mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); @@ -5413,7 +5413,7 @@ static int hns_roce_v2_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr) SRQC_BYTE_8_SRQ_LIMIT_WL_S);
attr->srq_limit = limit_wl; - attr->max_wr = srq->wqe_cnt - 1; + attr->max_wr = srq->wqe_cnt; attr->max_sge = srq->max_gs - srq->rsv_sge;
out: diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index ecc42c59e3cfc..51de9305bb4de 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -322,7 +322,7 @@ int hns_roce_create_srq(struct ib_srq *ib_srq,
max_sge = proc_srq_sge(hr_dev, srq, !!udata);
- if (init_attr->attr.max_wr >= hr_dev->caps.max_srq_wrs || + if (init_attr->attr.max_wr > hr_dev->caps.max_srq_wrs || init_attr->attr.max_sge > max_sge) { ibdev_err(&hr_dev->ib_dev, "SRQ config error, depth = %u, sge = %d\n", @@ -333,7 +333,9 @@ int hns_roce_create_srq(struct ib_srq *ib_srq, mutex_init(&srq->mutex); spin_lock_init(&srq->lock);
- srq->wqe_cnt = roundup_pow_of_two(init_attr->attr.max_wr + 1); + init_attr->attr.max_wr = max_t(u32, init_attr->attr.max_wr, + HNS_ROCE_MIN_SRQ_WQE_NUM); + srq->wqe_cnt = roundup_pow_of_two(init_attr->attr.max_wr); srq->max_gs = roundup_pow_of_two(init_attr->attr.max_sge + srq->rsv_sge); init_attr->attr.max_wr = srq->wqe_cnt;
From: Kamal Heib kamalheib1@gmail.com
[ Upstream commit 429fa9698957d1a910535ce5e33aedf5adfdabc1 ]
The size of tx_valid_cpus was calculated under the assumption that the numa nodes identifiers are continuous, which is not the case in all archs as this could lead to the following panic when trying to access an invalid tx_valid_cpus index, avoid the following panic by using nr_node_ids instead of num_online_nodes() to allocate the tx_valid_cpus size.
Kernel attempted to read user page (8) - exploit attempt? (uid: 0) BUG: Kernel NULL pointer dereference on read at 0x00000008 Faulting instruction address: 0xc0080000081b4a90 Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV Modules linked in: siw(+) rfkill rpcrdma ib_isert iscsi_target_mod ib_iser libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm sunrpc ib_umad rdma_cm ib_cm iw_cm i40iw ib_uverbs ib_core i40e ses enclosure scsi_transport_sas ipmi_powernv ibmpowernv at24 ofpart ipmi_devintf regmap_i2c ipmi_msghandler powernv_flash uio_pdrv_genirq uio mtd opal_prd zram ip_tables xfs libcrc32c sd_mod t10_pi ast i2c_algo_bit drm_vram_helper drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec drm_ttm_helper ttm drm vmx_crypto aacraid drm_panel_orientation_quirks dm_mod CPU: 40 PID: 3279 Comm: modprobe Tainted: G W X --------- --- 5.11.0-0.rc4.129.eln108.ppc64le #2 NIP: c0080000081b4a90 LR: c0080000081b4a2c CTR: c0000000007ce1c0 REGS: c000000027fa77b0 TRAP: 0300 Tainted: G W X --------- --- (5.11.0-0.rc4.129.eln108.ppc64le) MSR: 9000000002009033 <SF,HV,VEC,EE,ME,IR,DR,RI,LE> CR: 44224882 XER: 00000000 CFAR: c0000000007ce200 DAR: 0000000000000008 DSISR: 40000000 IRQMASK: 0 GPR00: c0080000081b4a2c c000000027fa7a50 c0080000081c3900 0000000000000040 GPR04: c000000002023080 c000000012e1c300 000020072ad70000 0000000000000001 GPR08: c000000001726068 0000000000000008 0000000000000008 c0080000081b5758 GPR12: c0000000007ce1c0 c0000007fffc3000 00000001590b1e40 0000000000000000 GPR16: 0000000000000000 0000000000000001 000000011ad68fc8 00007fffcc09c5c8 GPR20: 0000000000000008 0000000000000000 00000001590b2850 00000001590b1d30 GPR24: 0000000000043d68 000000011ad67a80 000000011ad67a80 0000000000100000 GPR28: c000000012e1c300 c0000000020271c8 0000000000000001 c0080000081bf608 NIP [c0080000081b4a90] siw_init_cpulist+0x194/0x214 [siw] LR [c0080000081b4a2c] siw_init_cpulist+0x130/0x214 [siw] Call Trace: [c000000027fa7a50] [c0080000081b4a2c] siw_init_cpulist+0x130/0x214 [siw] (unreliable) [c000000027fa7a90] [c0080000081b4e68] siw_init_module+0x40/0x2a0 [siw] [c000000027fa7b30] [c0000000000124f4] do_one_initcall+0x84/0x2e0 [c000000027fa7c00] [c000000000267ffc] do_init_module+0x7c/0x350 [c000000027fa7c90] [c00000000026a180] __do_sys_init_module+0x210/0x250 [c000000027fa7db0] [c0000000000387e4] system_call_exception+0x134/0x230 [c000000027fa7e10] [c00000000000d660] system_call_common+0xf0/0x27c Instruction dump: 40810044 3d420000 e8bf0000 e88a82d0 3d420000 e90a82c8 792a1f24 7cc4302a 7d2642aa 79291f24 7d25482a 7d295214 <7d4048a8> 7d4a3b78 7d4049ad 40c2fff4
Fixes: bdcf26bf9b3a ("rdma/siw: network and RDMA core interface") Link: https://lore.kernel.org/r/20210201112922.141085-1-kamalheib1@gmail.com Signed-off-by: Kamal Heib kamalheib1@gmail.com Reviewed-by: Bernard Metzler bmt@zurich.ibm.com Tested-by: Yi Zhang yi.zhang@redhat.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/siw/siw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c index ee95cf29179d2..41c46dfaebf66 100644 --- a/drivers/infiniband/sw/siw/siw_main.c +++ b/drivers/infiniband/sw/siw/siw_main.c @@ -135,7 +135,7 @@ static struct {
static int siw_init_cpulist(void) { - int i, num_nodes = num_possible_nodes(); + int i, num_nodes = nr_node_ids;
memset(siw_tx_thread, 0, sizeof(siw_tx_thread));
From: Weihang Li liweihang@huawei.com
[ Upstream commit 773f841ab1aeb0134e3872eb3545592732db8218 ]
ULP usually set IB(V)_QP_AV when trying to modify QP to RTR if they want to record sgid index into QPC. For UD QPs, it is useless because it will be included in WQE. For RC QPs, it will be filled in hns_roce_set_path(). So sgid index shouldn't be filled by default. Then hns_get_gid_index() is moved to hns_roce_hw_v1.c because it is only called in it.
Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC") Link: https://lore.kernel.org/r/1612517974-31867-2-git-send-email-liweihang@huawei... 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_v1.c | 16 ++++++++++++++++ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 11 ----------- drivers/infiniband/hw/hns/hns_roce_main.c | 16 ---------------- 3 files changed, 16 insertions(+), 27 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c index f68585ff8e8a5..c2539a8d91116 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c @@ -43,6 +43,22 @@ #include "hns_roce_hem.h" #include "hns_roce_hw_v1.h"
+/** + * hns_get_gid_index - Get gid index. + * @hr_dev: pointer to structure hns_roce_dev. + * @port: port, value range: 0 ~ MAX + * @gid_index: gid_index, value range: 0 ~ MAX + * Description: + * N ports shared gids, allocation method as follow: + * GID[0][0], GID[1][0],.....GID[N - 1][0], + * GID[0][0], GID[1][0],.....GID[N - 1][0], + * And so on + */ +u8 hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index) +{ + return gid_index * hr_dev->caps.num_ports + port; +} + static void set_data_seg(struct hns_roce_wqe_data_seg *dseg, struct ib_sge *sg) { dseg->lkey = cpu_to_le32(sg->lkey); diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index a909993552e7f..b8f6d5f706ddc 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -4254,7 +4254,6 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, struct hns_roce_v2_qp_context *context, struct hns_roce_v2_qp_context *qpc_mask) { - const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr); struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); struct ib_device *ibdev = &hr_dev->ib_dev; @@ -4262,7 +4261,6 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, dma_addr_t irrl_ba; enum ib_mtu mtu; u8 lp_pktn_ini; - u8 port_num; u64 *mtts; u8 *dmac; u8 *smac; @@ -4343,15 +4341,6 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, V2_QPC_BYTE_56_DQPN_M, V2_QPC_BYTE_56_DQPN_S, 0); }
- /* Configure GID index */ - port_num = rdma_ah_get_port_num(&attr->ah_attr); - roce_set_field(context->byte_20_smac_sgid_idx, - V2_QPC_BYTE_20_SGID_IDX_M, V2_QPC_BYTE_20_SGID_IDX_S, - hns_get_gid_index(hr_dev, port_num - 1, - grh->sgid_index)); - roce_set_field(qpc_mask->byte_20_smac_sgid_idx, - V2_QPC_BYTE_20_SGID_IDX_M, V2_QPC_BYTE_20_SGID_IDX_S, 0); - memcpy(&(context->dmac), dmac, sizeof(u32)); roce_set_field(context->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M, V2_QPC_BYTE_52_DMAC_S, *((u16 *)(&dmac[4]))); diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 60822e666f351..baadb12b13752 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -42,22 +42,6 @@ #include "hns_roce_device.h" #include "hns_roce_hem.h"
-/** - * hns_get_gid_index - Get gid index. - * @hr_dev: pointer to structure hns_roce_dev. - * @port: port, value range: 0 ~ MAX - * @gid_index: gid_index, value range: 0 ~ MAX - * Description: - * N ports shared gids, allocation method as follow: - * GID[0][0], GID[1][0],.....GID[N - 1][0], - * GID[0][0], GID[1][0],.....GID[N - 1][0], - * And so on - */ -u8 hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index) -{ - return gid_index * hr_dev->caps.num_ports + port; -} - static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u8 port, u8 *addr) { u8 phy_port;
From: Weihang Li liweihang@huawei.com
[ Upstream commit ea4092f3b56b236d08890ea589506ebd76248c53 ]
This bit should be in type of enum ib_sig_type, or there will be a sparse warning.
Fixes: bfe860351e31 ("RDMA/hns: Fix cast from or to restricted __le32 for driver") Link: https://lore.kernel.org/r/1612517974-31867-3-git-send-email-liweihang@huawei... Reported-by: kernel test robot lkp@intel.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_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 9ac6d760aa5b3..54abe615b502a 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -652,7 +652,7 @@ struct hns_roce_qp { struct hns_roce_db sdb; unsigned long en_flags; u32 doorbell_qpn; - u32 sq_signal_bits; + enum ib_sig_type sq_signal_bits; struct hns_roce_wq sq;
struct hns_roce_mtr mtr;
From: Xi Wang wangxi11@huawei.com
[ Upstream commit 9ea9a53ea93be1cc66729ceb920f0d07285d6bfd ]
Add the mapped page count checking flow to avoid invalid page size when creating MTR.
Fixes: 38389eaa4db1 ("RDMA/hns: Add mtr support for mixed multihop addressing") Link: https://lore.kernel.org/r/1612517974-31867-4-git-send-email-liweihang@huawei... Signed-off-by: Xi Wang wangxi11@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_hem.c | 9 ++-- drivers/infiniband/hw/hns/hns_roce_mr.c | 56 ++++++++++++++---------- 2 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index edc9d6b98d954..cfd2e1b60c7f0 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c @@ -1075,9 +1075,8 @@ static struct roce_hem_item *hem_list_alloc_item(struct hns_roce_dev *hr_dev, return NULL;
if (exist_bt) { - hem->addr = dma_alloc_coherent(hr_dev->dev, - count * BA_BYTE_LEN, - &hem->dma_addr, GFP_KERNEL); + hem->addr = dma_alloc_coherent(hr_dev->dev, count * BA_BYTE_LEN, + &hem->dma_addr, GFP_KERNEL); if (!hem->addr) { kfree(hem); return NULL; @@ -1336,6 +1335,10 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev, if (ba_num < 1) return -ENOMEM;
+ if (ba_num > unit) + return -ENOBUFS; + + ba_num = min_t(int, ba_num, unit); INIT_LIST_HEAD(&temp_root); offset = r->offset; /* indicate to last region */ diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 1bcffd93ff3e3..1e0465f05b7da 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -631,30 +631,26 @@ int hns_roce_dealloc_mw(struct ib_mw *ibmw) }
static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, - dma_addr_t *pages, struct hns_roce_buf_region *region) + struct hns_roce_buf_region *region, dma_addr_t *pages, + int max_count) { + int count, npage; + int offset, end; __le64 *mtts; - int offset; - int count; - int npage; u64 addr; - int end; int i;
- /* if hopnum is 0, buffer cannot store BAs, so skip write mtt */ - if (!region->hopnum) - return 0; - offset = region->offset; end = offset + region->count; npage = 0; - while (offset < end) { + while (offset < end && npage < max_count) { + count = 0; mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list, offset, &count, NULL); if (!mtts) return -ENOBUFS;
- for (i = 0; i < count; i++) { + for (i = 0; i < count && npage < max_count; i++) { if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) addr = to_hr_hw_page_addr(pages[npage]); else @@ -666,7 +662,7 @@ static int mtr_map_region(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, offset += count; }
- return 0; + return npage; }
static inline bool mtr_has_mtt(struct hns_roce_buf_attr *attr) @@ -833,8 +829,8 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, { struct ib_device *ibdev = &hr_dev->ib_dev; struct hns_roce_buf_region *r; - unsigned int i; - int err; + unsigned int i, mapped_cnt; + int ret;
/* * Only use the first page address as root ba when hopnum is 0, this @@ -845,26 +841,42 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, return 0; }
- for (i = 0; i < mtr->hem_cfg.region_count; i++) { + for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count && + mapped_cnt < page_cnt; i++) { r = &mtr->hem_cfg.region[i]; + /* if hopnum is 0, no need to map pages in this region */ + if (!r->hopnum) { + mapped_cnt += r->count; + continue; + } + if (r->offset + r->count > page_cnt) { - err = -EINVAL; + ret = -EINVAL; ibdev_err(ibdev, "failed to check mtr%u end %u + %u, max %u.\n", i, r->offset, r->count, page_cnt); - return err; + return ret; }
- err = mtr_map_region(hr_dev, mtr, &pages[r->offset], r); - if (err) { + ret = mtr_map_region(hr_dev, mtr, r, &pages[r->offset], + page_cnt - mapped_cnt); + if (ret < 0) { ibdev_err(ibdev, "failed to map mtr%u offset %u, ret = %d.\n", - i, r->offset, err); - return err; + i, r->offset, ret); + return ret; } + mapped_cnt += ret; + ret = 0; }
- return 0; + if (mapped_cnt < page_cnt) { + ret = -ENOBUFS; + ibdev_err(ibdev, "failed to map mtr pages count: %u < %u.\n", + mapped_cnt, page_cnt); + } + + return ret; }
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
From: Lijun Ou oulijun@huawei.com
[ Upstream commit 7373de9adb19aebed2781d3fdde576533d626d7a ]
This feature should only be enabled by querying capability from firmware.
Fixes: ba6bb7e97421 ("RDMA/hns: Add interfaces to get pf capabilities from firmware") Link: https://lore.kernel.org/r/1612517974-31867-5-git-send-email-liweihang@huawei... Signed-off-by: Lijun Ou oulijun@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 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index b8f6d5f706ddc..43ed927860569 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -1883,7 +1883,6 @@ static void set_default_caps(struct hns_roce_dev *hr_dev)
caps->flags = HNS_ROCE_CAP_FLAG_REREG_MR | HNS_ROCE_CAP_FLAG_ROCE_V1_V2 | - HNS_ROCE_CAP_FLAG_RQ_INLINE | HNS_ROCE_CAP_FLAG_RECORD_DB | HNS_ROCE_CAP_FLAG_SQ_RECORD_DB;
From: Michael Tretter m.tretter@pengutronix.de
[ Upstream commit 0225daea08141b1dff681502d5af70b71e8b11ec ]
If a driver registers a divider clock with a parent_hw instead of the parent_name, the parent_hw is ignored and the clock does not have a parent.
Fix this by initializing the parents the same way they are initialized for clock gates.
Fixes: ff258817137a ("clk: divider: Add support for specifying parents via DT/pointers") Signed-off-by: Michael Tretter m.tretter@pengutronix.de Reviewed-by: Stephen Boyd sboyd@kernel.org Acked-by: Michal Simek michal.simek@xilinx.com Link: https://lore.kernel.org/r/20210121071659.1226489-3-m.tretter@pengutronix.de Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/clk-divider.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c499799693ccc..344997203f0e7 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -494,8 +494,13 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, else init.ops = &clk_divider_ops; init.flags = flags; - init.parent_names = (parent_name ? &parent_name: NULL); - init.num_parents = (parent_name ? 1 : 0); + init.parent_names = parent_name ? &parent_name : NULL; + init.parent_hws = parent_hw ? &parent_hw : NULL; + init.parent_data = parent_data; + if (parent_name || parent_hw || parent_data) + init.num_parents = 1; + else + init.num_parents = 0;
/* struct clk_divider assignments */ div->reg = reg;
From: Andy Shevchenko andriy.shevchenko@linux.intel.com
[ Upstream commit 54c5d3bfb0cfb7b31259765524567871dee11615 ]
Wildcat Point has two SPI controllers and added one is actually second one. Fix the numbering by adding the description of the first one.
Fixes: caba248db286 ("spi: spi-pxa2xx-pci: Add ID and driver type for WildcatPoint PCH") Cc: Leif Liddy leif.liddy@gmail.com Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Link: https://lore.kernel.org/r/20210208163816.22147-1-andriy.shevchenko@linux.int... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-pxa2xx-pci.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index f236e3034cf85..aafac128bb5f1 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -21,7 +21,8 @@ enum { PORT_BSW1, PORT_BSW2, PORT_CE4100, - PORT_LPT, + PORT_LPT0, + PORT_LPT1, };
struct pxa_spi_info { @@ -57,8 +58,10 @@ static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 }; static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 }; static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 };
-static struct dw_dma_slave lpt_tx_param = { .dst_id = 0 }; -static struct dw_dma_slave lpt_rx_param = { .src_id = 1 }; +static struct dw_dma_slave lpt1_tx_param = { .dst_id = 0 }; +static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 }; +static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 }; +static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 };
static bool lpss_dma_filter(struct dma_chan *chan, void *param) { @@ -185,12 +188,19 @@ static struct pxa_spi_info spi_info_configs[] = { .num_chipselect = 1, .max_clk_rate = 50000000, }, - [PORT_LPT] = { + [PORT_LPT0] = { .type = LPSS_LPT_SSP, .port_id = 0, .setup = lpss_spi_setup, - .tx_param = &lpt_tx_param, - .rx_param = &lpt_rx_param, + .tx_param = &lpt0_tx_param, + .rx_param = &lpt0_rx_param, + }, + [PORT_LPT1] = { + .type = LPSS_LPT_SSP, + .port_id = 1, + .setup = lpss_spi_setup, + .tx_param = &lpt1_tx_param, + .rx_param = &lpt1_rx_param, }, };
@@ -285,8 +295,9 @@ static const struct pci_device_id pxa2xx_spi_pci_devices[] = { { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, - { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT }, - { }, + { PCI_VDEVICE(INTEL, 0x9ce5), PORT_LPT0 }, + { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT1 }, + { } }; MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
From: Alexey Kardashevskiy aik@ozlabs.ru
[ Upstream commit 7d506ca97b665b95e698a53697dad99fae813c1a ]
The amount of code executed with enabled user space access (unlocked KUAP) should be minimal. However with CONFIG_PROVE_LOCKING or CONFIG_DEBUG_ATOMIC_SLEEP enabled, might_fault() calls into various parts of the kernel, and may even end up replaying interrupts which in turn may access user space and forget to restore the KUAP state.
The problem places are: 1. strncpy_from_user (and similar) which unlock KUAP and call unsafe_get_user -> __get_user_allowed -> __get_user_nocheck() with do_allow=false to skip KUAP as the caller took care of it. 2. __unsafe_put_user_goto() which is called with unlocked KUAP.
eg: WARNING: CPU: 30 PID: 1 at arch/powerpc/include/asm/book3s/64/kup.h:324 arch_local_irq_restore+0x160/0x190 NIP arch_local_irq_restore+0x160/0x190 LR lock_is_held_type+0x140/0x200 Call Trace: 0xc00000007f392ff8 (unreliable) ___might_sleep+0x180/0x320 __might_fault+0x50/0xe0 filldir64+0x2d0/0x5d0 call_filldir+0xc8/0x180 ext4_readdir+0x948/0xb40 iterate_dir+0x1ec/0x240 sys_getdents64+0x80/0x290 system_call_exception+0x160/0x280 system_call_common+0xf0/0x27c
Change __get_user_nocheck() to look at `do_allow` to decide whether to skip might_fault(). Since strncpy_from_user/etc call might_fault() anyway before unlocking KUAP, there should be no visible change.
Drop might_fault() in __unsafe_put_user_goto() as it is only called from unsafe_put_user(), which already has KUAP unlocked.
Since keeping might_fault() is still desirable for debugging, add calls to it in user_[read|write]_access_begin(). That also allows us to drop the is_kernel_addr() test, because there should be no code using user_[read|write]_access_begin() in order to access a kernel address.
Fixes: de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace Access Protection") Signed-off-by: Alexey Kardashevskiy aik@ozlabs.ru [mpe: Combine with related patch from myself, merge change logs] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210204121612.32721-1-aik@ozlabs.ru Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/uaccess.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 501c9a79038c0..f53bfefb4a577 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -216,8 +216,6 @@ do { \ #define __put_user_nocheck_goto(x, ptr, size, label) \ do { \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - if (!is_kernel_addr((unsigned long)__pu_addr)) \ - might_fault(); \ __chk_user_ptr(ptr); \ __put_user_size_goto((x), __pu_addr, (size), label); \ } while (0) @@ -313,7 +311,7 @@ do { \ __typeof__(size) __gu_size = (size); \ \ __chk_user_ptr(__gu_addr); \ - if (!is_kernel_addr((unsigned long)__gu_addr)) \ + if (do_allow && !is_kernel_addr((unsigned long)__gu_addr)) \ might_fault(); \ barrier_nospec(); \ if (do_allow) \ @@ -508,6 +506,9 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t { if (unlikely(!access_ok(ptr, len))) return false; + + might_fault(); + allow_read_write_user((void __user *)ptr, ptr, len); return true; } @@ -521,6 +522,9 @@ user_read_access_begin(const void __user *ptr, size_t len) { if (unlikely(!access_ok(ptr, len))) return false; + + might_fault(); + allow_read_from_user(ptr, len); return true; } @@ -532,6 +536,9 @@ user_write_access_begin(const void __user *ptr, size_t len) { if (unlikely(!access_ok(ptr, len))) return false; + + might_fault(); + allow_write_to_user((void __user *)ptr, len); return true; }
From: Alexey Kardashevskiy aik@ozlabs.ru
[ Upstream commit 60a707d0c99aff4eadb7fd334c5fd21df386723e ]
Since de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace Access Protection"), user access helpers call user_{read|write}_access_{begin|end} when user space access is allowed.
Commit 890274c2dc4c ("powerpc/64s: Implement KUAP for Radix MMU") made the mentioned helpers program a AMR special register to allow such access for a short period of time, most of the time AMR is expected to block user memory access by the kernel.
Since the code accesses the user space memory, unsafe_get_user() calls might_fault() which calls arch_local_irq_restore() if either CONFIG_PROVE_LOCKING or CONFIG_DEBUG_ATOMIC_SLEEP is enabled. arch_local_irq_restore() then attempts to replay pending soft interrupts as KUAP regions have hardware interrupts enabled.
If a pending interrupt happens to do user access (performance interrupts do that), it enables access for a short period of time so after returning from the replay, the user access state remains blocked and if a user page fault happens - "Bug: Read fault blocked by AMR!" appears and SIGSEGV is sent.
An example trace: Bug: Read fault blocked by AMR! WARNING: CPU: 0 PID: 1603 at /home/aik/p/kernel/arch/powerpc/include/asm/book3s/64/kup-radix.h:145 CPU: 0 PID: 1603 Comm: amr Not tainted 5.10.0-rc6_v5.10-rc6_a+fstn1 #24 NIP: c00000000009ece8 LR: c00000000009ece4 CTR: 0000000000000000 REGS: c00000000dc63560 TRAP: 0700 Not tainted (5.10.0-rc6_v5.10-rc6_a+fstn1) MSR: 8000000000021033 <SF,ME,IR,DR,RI,LE> CR: 28002888 XER: 20040000 CFAR: c0000000001fa928 IRQMASK: 1 GPR00: c00000000009ece4 c00000000dc637f0 c000000002397600 000000000000001f GPR04: c0000000020eb318 0000000000000000 c00000000dc63494 0000000000000027 GPR08: c00000007fe4de68 c00000000dfe9180 0000000000000000 0000000000000001 GPR12: 0000000000002000 c0000000030a0000 0000000000000000 0000000000000000 GPR16: 0000000000000000 0000000000000000 0000000000000000 bfffffffffffffff GPR20: 0000000000000000 c0000000134a4020 c0000000019c2218 0000000000000fe0 GPR24: 0000000000000000 0000000000000000 c00000000d106200 0000000040000000 GPR28: 0000000000000000 0000000000000300 c00000000dc63910 c000000001946730 NIP __do_page_fault+0xb38/0xde0 LR __do_page_fault+0xb34/0xde0 Call Trace: __do_page_fault+0xb34/0xde0 (unreliable) handle_page_fault+0x10/0x2c --- interrupt: 300 at strncpy_from_user+0x290/0x440 LR = strncpy_from_user+0x284/0x440 strncpy_from_user+0x2f0/0x440 (unreliable) getname_flags+0x88/0x2c0 do_sys_openat2+0x2d4/0x5f0 do_sys_open+0xcc/0x140 system_call_exception+0x160/0x240 system_call_common+0xf0/0x27c
To fix it save/restore the AMR when replaying interrupts, and also add a check if AMR was not blocked prior to replaying interrupts.
Originally found by syzkaller.
Fixes: 890274c2dc4c ("powerpc/64s: Implement KUAP for Radix MMU") Signed-off-by: Alexey Kardashevskiy aik@ozlabs.ru Reviewed-by: Nicholas Piggin npiggin@gmail.com [mpe: Use normal commit citation format and add full oops log to change log, move kuap_check_amr() into the restore routine to avoid warnings about unreconciled IRQ state] Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210202091541.36499-1-aik@ozlabs.ru Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/kernel/irq.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index cc7a6271b6b4e..e8a548447dd68 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -269,6 +269,31 @@ again: } }
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP) +static inline void replay_soft_interrupts_irqrestore(void) +{ + unsigned long kuap_state = get_kuap(); + + /* + * Check if anything calls local_irq_enable/restore() when KUAP is + * disabled (user access enabled). We handle that case here by saving + * and re-locking AMR but we shouldn't get here in the first place, + * hence the warning. + */ + kuap_check_amr(); + + if (kuap_state != AMR_KUAP_BLOCKED) + set_kuap(AMR_KUAP_BLOCKED); + + replay_soft_interrupts(); + + if (kuap_state != AMR_KUAP_BLOCKED) + set_kuap(kuap_state); +} +#else +#define replay_soft_interrupts_irqrestore() replay_soft_interrupts() +#endif + notrace void arch_local_irq_restore(unsigned long mask) { unsigned char irq_happened; @@ -332,7 +357,7 @@ notrace void arch_local_irq_restore(unsigned long mask) irq_soft_mask_set(IRQS_ALL_DISABLED); trace_hardirqs_off();
- replay_soft_interrupts(); + replay_soft_interrupts_irqrestore(); local_paca->irq_happened = 0;
trace_hardirqs_on();
From: Jonathan Marek jonathan@marek.ca
[ Upstream commit 20ccc362c3d20da734af896e075b74222589f2c0 ]
Use the correct name to avoid ldo7 commands being sent to ldo6's address.
Fixes: 06369bcc15a1 ("regulator: qcom-rpmh: Add support for SM8150") Signed-off-by: Jonathan Marek jonathan@marek.ca Reviewed-by: Vinod Koul vkoul@kernel.org Link: https://lore.kernel.org/r/20210211034935.5622-1-jonathan@marek.ca Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/qcom-rpmh-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 98320e1d8bf66..37a2abbe85c72 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -937,7 +937,7 @@ static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), - RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l7"), {}, };
From: Ryan Chen ryan_chen@aspeedtech.com
[ Upstream commit 6286ce1e3ece54799f12775f8ce2a1cba9cbcfc5 ]
Starting from A2, the A-PLL calculation has changed. Use the existing formula for A0/A1 and the new formula for A2 onwards.
Fixes: d3d04f6c330a ("clk: Add support for AST2600 SoC") Signed-off-by: Ryan Chen ryan_chen@aspeedtech.com Link: https://lore.kernel.org/r/20210119061715.6043-1-ryan_chen@aspeedtech.com Reviewed-by: Joel Stanley joel@jms.id.au Signed-off-by: Stephen Boyd sboyd@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/clk-ast2600.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c index 177368cac6dd6..a55b37fc2c8bd 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -17,7 +17,8 @@
#define ASPEED_G6_NUM_CLKS 71
-#define ASPEED_G6_SILICON_REV 0x004 +#define ASPEED_G6_SILICON_REV 0x014 +#define CHIP_REVISION_ID GENMASK(23, 16)
#define ASPEED_G6_RESET_CTRL 0x040 #define ASPEED_G6_RESET_CTRL2 0x050 @@ -190,18 +191,34 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val) static struct clk_hw *ast2600_calc_apll(const char *name, u32 val) { unsigned int mult, div; + u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV);
- if (val & BIT(20)) { - /* Pass through mode */ - mult = div = 1; + if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) { + if (val & BIT(24)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */ + u32 m = val & 0x1fff; + u32 n = (val >> 13) & 0x3f; + u32 p = (val >> 19) & 0xf; + + mult = (m + 1); + div = (n + 1) * (p + 1); + } } else { - /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ - u32 m = (val >> 5) & 0x3f; - u32 od = (val >> 4) & 0x1; - u32 n = val & 0xf; + if (val & BIT(20)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ + u32 m = (val >> 5) & 0x3f; + u32 od = (val >> 4) & 0x1; + u32 n = val & 0xf;
- mult = (2 - od) * (m + 2); - div = n + 1; + mult = (2 - od) * (m + 2); + div = n + 1; + } } return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, mult, div);
From: Tom Zanussi zanussi@kernel.org
[ Upstream commit b5734e997e1117afb479ffda500e36fa91aea3e8 ]
Some of the synthetic event errors and positions have changed in the code - update those and add several more tests.
Also add a runtime check to ensure that the kernel supports dynamic strings in synthetic events, which these tests require.
Link: https://lkml.kernel.org/r/51402656433455baead34f068c6e9466b64df9c0.161220861...
Fixes: 81ff92a93d95 (selftests/ftrace: Add test case for synthetic event syntax errors) Reported-by: Masami Hiramatsu mhiramat@kernel.org Signed-off-by: Tom Zanussi zanussi@kernel.org Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../trigger-synthetic_event_syntax_errors.tc | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc index ada594fe16cb3..955e3ceea44b5 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc @@ -1,19 +1,38 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: event trigger - test synthetic_events syntax parser errors -# requires: synthetic_events error_log +# requires: synthetic_events error_log "char name[]' >> synthetic_events":README
check_error() { # command-with-error-pos-by-^ ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events' }
+check_dyn_error() { # command-with-error-pos-by-^ + ftrace_errlog_check 'synthetic_events' "$1" 'dynamic_events' +} + check_error 'myevent ^chr arg' # INVALID_TYPE -check_error 'myevent ^char str[];; int v' # INVALID_TYPE -check_error 'myevent char ^str]; int v' # INVALID_NAME -check_error 'myevent char ^str;[]' # INVALID_NAME -check_error 'myevent ^char str[; int v' # INVALID_TYPE -check_error '^mye;vent char str[]' # BAD_NAME -check_error 'myevent char str[]; ^int' # INVALID_FIELD -check_error '^myevent' # INCOMPLETE_CMD +check_error 'myevent ^unsigned arg' # INCOMPLETE_TYPE + +check_error 'myevent char ^str]; int v' # BAD_NAME +check_error '^mye-vent char str[]' # BAD_NAME +check_error 'myevent char ^st-r[]' # BAD_NAME + +check_error 'myevent char str;^[]' # INVALID_FIELD +check_error 'myevent char str; ^int' # INVALID_FIELD + +check_error 'myevent char ^str[; int v' # INVALID_ARRAY_SPEC +check_error 'myevent char ^str[kdjdk]' # INVALID_ARRAY_SPEC +check_error 'myevent char ^str[257]' # INVALID_ARRAY_SPEC + +check_error '^mye;vent char str[]' # INVALID_CMD +check_error '^myevent ; char str[]' # INVALID_CMD +check_error '^myevent; char str[]' # INVALID_CMD +check_error '^myevent ;char str[]' # INVALID_CMD +check_error '^; char str[]' # INVALID_CMD +check_error '^;myevent char str[]' # INVALID_CMD +check_error '^myevent' # INVALID_CMD + +check_dyn_error '^s:junk/myevent char str[' # INVALID_DYN_CMD
exit 0
From: Dmitry Safonov dima@arista.com
[ Upstream commit 96de68fff5ded8833bf5832658cb43c54f86ff6c ]
GCC (GCC) 8.4.0 20200304 fails to build perf with: : util/symbol.c: In function 'dso__load_bfd_symbols': : util/symbol.c:1626:16: error: comparison of integer expressions of different signednes : for (i = 0; i < symbols_count; ++i) { : ^ : util/symbol.c:1632:16: error: comparison of integer expressions of different signednes : while (i + 1 < symbols_count && : ^ : util/symbol.c:1637:13: error: comparison of integer expressions of different signednes : if (i + 1 < symbols_count && : ^ : cc1: all warnings being treated as errors
It's unlikely that the symtable will be that big, but the fix is an oneliner and as perf has CORE_CFLAGS += -Wextra, which makes build to fail together with CORE_CFLAGS += -Werror
Fixes: eac9a4342e54 ("perf symbols: Try reading the symbol table with libbfd") Signed-off-by: Dmitry Safonov dima@arista.com Acked-by: Namhyung Kim namhyung@kernel.org Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Dmitry Safonov 0x7f454c46@gmail.com Cc: Jacek Caban jacek@codeweavers.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Remi Bernon rbernon@codeweavers.com Link: http://lore.kernel.org/lkml/20210209145148.178702-1-dima@arista.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/symbol.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 64a039cbba1b5..1645fb4ec9ed4 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1561,12 +1561,11 @@ static int bfd2elf_binding(asymbol *symbol) int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) { int err = -1; - long symbols_size, symbols_count; + long symbols_size, symbols_count, i; asection *section; asymbol **symbols, *sym; struct symbol *symbol; bfd *abfd; - u_int i; u64 start, len;
abfd = bfd_openr(dso->long_name, NULL);
From: Matti Vaittinen matti.vaittinen@fi.rohmeurope.com
[ Upstream commit c294554111a835598b557db789d9ad2379b512a2 ]
The ROHM BD718x7 and BD71828 drivers support setting HW state specific voltages from device-tree. This is used also by various in-tree DTS files.
These drivers do incorrectly try to compose bit-map using enum values. By a chance this works for first two valid levels having values 1 and 2 - but setting values for the rest of the levels do indicate capability of setting values for first levels as well. Luckily the regulators which support setting values for SUSPEND/LPSR do usually also support setting values for RUN and IDLE too - thus this has not been such a fatal issue.
Fix this by defining the old enum values as bits and fixing the parsing code. This allows keeping existing IC specific drivers intact and only slightly changing the rohm-regulator.c
Fixes: 21b72156ede8b ("regulator: bd718x7: Split driver to common and bd718x7 specific parts") Signed-off-by: Matti Vaittinen matti.vaittinen@fi.rohmeurope.com Acked-by: Lee Jones lee.jones@linaro.org Link: https://lore.kernel.org/r/20210212080023.GA880728@localhost.localdomain Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/regulator/rohm-regulator.c | 9 ++++++--- include/linux/mfd/rohm-generic.h | 14 ++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c index 399002383b28b..5c558b153d55e 100644 --- a/drivers/regulator/rohm-regulator.c +++ b/drivers/regulator/rohm-regulator.c @@ -52,9 +52,12 @@ int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs, char *prop; unsigned int reg, mask, omask, oreg = desc->enable_reg;
- for (i = 0; i < ROHM_DVS_LEVEL_MAX && !ret; i++) { - if (dvs->level_map & (1 << i)) { - switch (i + 1) { + for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) { + int bit; + + bit = BIT(i); + if (dvs->level_map & bit) { + switch (bit) { case ROHM_DVS_LEVEL_RUN: prop = "rohm,dvs-run-voltage"; reg = dvs->run_reg; diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h index 4283b5b33e040..2b85b9deb03ae 100644 --- a/include/linux/mfd/rohm-generic.h +++ b/include/linux/mfd/rohm-generic.h @@ -20,14 +20,12 @@ struct rohm_regmap_dev { struct regmap *regmap; };
-enum { - ROHM_DVS_LEVEL_UNKNOWN, - ROHM_DVS_LEVEL_RUN, - ROHM_DVS_LEVEL_IDLE, - ROHM_DVS_LEVEL_SUSPEND, - ROHM_DVS_LEVEL_LPSR, - ROHM_DVS_LEVEL_MAX = ROHM_DVS_LEVEL_LPSR, -}; +#define ROHM_DVS_LEVEL_RUN BIT(0) +#define ROHM_DVS_LEVEL_IDLE BIT(1) +#define ROHM_DVS_LEVEL_SUSPEND BIT(2) +#define ROHM_DVS_LEVEL_LPSR BIT(3) +#define ROHM_DVS_LEVEL_VALID_AMOUNT 4 +#define ROHM_DVS_LEVEL_UNKNOWN 0
/** * struct rohm_dvs_config - dynamic voltage scaling register descriptions
From: Kees Cook keescook@chromium.org
[ Upstream commit 386f771aad15dd535f2368b4adc9958c0160edd4 ]
Since "data" is u32, &data is a "u32 *" type, which means pointer math will move in u32-sized steps. This was meant to be a byte offset, so cast &data to "char *" to aim the copy into the correct location.
Seen with -Warray-bounds (and found by Coverity):
In file included from ./include/linux/string.h:269, from ./arch/powerpc/include/asm/paca.h:15, from ./arch/powerpc/include/asm/current.h:13, from ./include/linux/mutex.h:14, from ./include/linux/notifier.h:14, from ./include/linux/clk.h:14, from drivers/spi/spi-dw-bt1.c:12: In function 'memcpy', inlined from 'dw_spi_bt1_dirmap_copy_from_map' at drivers/spi/spi-dw-bt1.c:87:3: ./include/linux/fortify-string.h:20:29: warning: '__builtin_memcpy' offset 4 is out of the bounds [0, 4] of object 'data' with type 'u32' {aka 'unsigned int'} [-Warray-bounds] 20 | #define __underlying_memcpy __builtin_memcpy | ^ ./include/linux/fortify-string.h:191:9: note: in expansion of macro '__underlying_memcpy' 191 | return __underlying_memcpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~ drivers/spi/spi-dw-bt1.c: In function 'dw_spi_bt1_dirmap_copy_from_map': drivers/spi/spi-dw-bt1.c:77:6: note: 'data' declared here 77 | u32 data; | ^~~~
Addresses-Coverity: CID 1497771 Out-of-bounds access Fixes: abf00907538e ("spi: dw: Add Baikal-T1 SPI Controller glue driver") Signed-off-by: Kees Cook keescook@chromium.org Reviewed-by: Gustavo A. R. Silva gustavoars@kernel.org Acked-by: Serge Semin fancer.lancer@gmail.com Link: https://lore.kernel.org/r/20210211203714.1929862-1-keescook@chromium.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi-dw-bt1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c index 4aa8596fb1f2b..5be6b7b80c21b 100644 --- a/drivers/spi/spi-dw-bt1.c +++ b/drivers/spi/spi-dw-bt1.c @@ -84,7 +84,7 @@ static void dw_spi_bt1_dirmap_copy_from_map(void *to, void __iomem *from, size_t if (shift) { chunk = min_t(size_t, 4 - shift, len); data = readl_relaxed(from - shift); - memcpy(to, &data + shift, chunk); + memcpy(to, (char *)&data + shift, chunk); from += chunk; to += chunk; len -= chunk;
From: Nicolas Saenz Julienne nsaenzjulienne@suse.de
[ Upstream commit b306320322c9cfaa465bc2c7367acf6072b1ac0e ]
With the introduction of 26751de25d25 ("spi: bcm2835: Micro-optimise FIFO loops") it has become apparent that some users might initiate zero-length SPI transfers. A fact the micro-optimization omitted, and which turned out to cause crashes[1].
Instead of changing the micro-optimization itself, use a bigger hammer and skip zero-length transfers altogether for drivers using the default transfer_one_message() implementation.
Reported-by: Phil Elwell phil@raspberrypi.com Fixes: 26751de25d25 ("spi: bcm2835: Micro-optimise FIFO loops") Signed-off-by: Nicolas Saenz Julienne nsaenzjulienne@suse.de
[1] https://github.com/raspberrypi/linux/issues/4100 Link: https://lore.kernel.org/r/20210211180820.25757-1-nsaenzjulienne@suse.de
Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 720ab34784c1d..ccca3a7409fac 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1267,7 +1267,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, ptp_read_system_prets(xfer->ptp_sts); }
- if (xfer->tx_buf || xfer->rx_buf) { + if ((xfer->tx_buf || xfer->rx_buf) && xfer->len) { reinit_completion(&ctlr->xfer_completion);
fallback_pio:
From: John Ogness john.ogness@linutronix.de
[ Upstream commit 13791c80b0cdf54d92fc54221cdf490683b109de ]
If message sizes average larger than expected (more than 32 characters), the data_ring will wrap before the desc_ring. Once the data_ring wraps, it will start invalidating descriptors. These invalid descriptors hang around until they are eventually recycled when the desc_ring wraps. Readers do not care about invalid descriptors, but they still need to iterate past them. If the average message size is much larger than 32 characters, then there will be many invalid descriptors preceding the valid descriptors.
The function prb_first_valid_seq() always begins at the oldest descriptor and searches for the first valid descriptor. This can be rather expensive for the above scenario. And, in fact, because of its heavy usage in /dev/kmsg, there have been reports of long delays and even RCU stalls.
For code that does not need to search from the oldest record, replace prb_first_valid_seq() usage with prb_read_valid_*() functions, which provide a start sequence number to search from.
Fixes: 896fbe20b4e2333fb55 ("printk: use the lockless ringbuffer") Reported-by: kernel test robot oliver.sang@intel.com Reported-by: J. Avila elavila@google.com Signed-off-by: John Ogness john.ogness@linutronix.de Reviewed-by: Petr Mladek pmladek@suse.com Signed-off-by: Petr Mladek pmladek@suse.com Link: https://lore.kernel.org/r/20210211173152.1629-1-john.ogness@linutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/printk/printk.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 5a95c688621fa..575a34b88936f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -735,9 +735,9 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, logbuf_lock_irq(); }
- if (user->seq < prb_first_valid_seq(prb)) { + if (r->info->seq != user->seq) { /* our last seen message is gone, return error and reset */ - user->seq = prb_first_valid_seq(prb); + user->seq = r->info->seq; ret = -EPIPE; logbuf_unlock_irq(); goto out; @@ -812,6 +812,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) static __poll_t devkmsg_poll(struct file *file, poll_table *wait) { struct devkmsg_user *user = file->private_data; + struct printk_info info; __poll_t ret = 0;
if (!user) @@ -820,9 +821,9 @@ static __poll_t devkmsg_poll(struct file *file, poll_table *wait) poll_wait(file, &log_wait, wait);
logbuf_lock_irq(); - if (prb_read_valid(prb, user->seq, NULL)) { + if (prb_read_valid_info(prb, user->seq, &info, NULL)) { /* return error when data has vanished underneath us */ - if (user->seq < prb_first_valid_seq(prb)) + if (info.seq != user->seq) ret = EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI; else ret = EPOLLIN|EPOLLRDNORM; @@ -1559,6 +1560,7 @@ static void syslog_clear(void)
int do_syslog(int type, char __user *buf, int len, int source) { + struct printk_info info; bool clear = false; static int saved_console_loglevel = LOGLEVEL_DEFAULT; int error; @@ -1629,9 +1631,14 @@ int do_syslog(int type, char __user *buf, int len, int source) /* Number of chars in the log buffer */ case SYSLOG_ACTION_SIZE_UNREAD: logbuf_lock_irq(); - if (syslog_seq < prb_first_valid_seq(prb)) { + if (!prb_read_valid_info(prb, syslog_seq, &info, NULL)) { + /* No unread messages. */ + logbuf_unlock_irq(); + return 0; + } + if (info.seq != syslog_seq) { /* messages are gone, move to first one */ - syslog_seq = prb_first_valid_seq(prb); + syslog_seq = info.seq; syslog_partial = 0; } if (source == SYSLOG_FROM_PROC) { @@ -1643,7 +1650,6 @@ int do_syslog(int type, char __user *buf, int len, int source) error = prb_next_seq(prb) - syslog_seq; } else { bool time = syslog_partial ? syslog_time : printk_time; - struct printk_info info; unsigned int line_count; u64 seq;
@@ -3429,9 +3435,11 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, goto out;
logbuf_lock_irqsave(flags); - if (dumper->cur_seq < prb_first_valid_seq(prb)) { - /* messages are gone, move to first available one */ - dumper->cur_seq = prb_first_valid_seq(prb); + if (prb_read_valid_info(prb, dumper->cur_seq, &info, NULL)) { + if (info.seq != dumper->cur_seq) { + /* messages are gone, move to first available one */ + dumper->cur_seq = info.seq; + } }
/* last entry */
From: Nicholas Fraser nfraser@codeweavers.com
[ Upstream commit 77771a97011fa9146ccfaf2983a3a2885dc57b6f ]
The first time dso__load() was called on a PE file it always returned -1 error. This caused the first call to map__find_symbol() to always fail on a PE file so the first sample from each PE file always had symbol <unknown>. Subsequent samples succeed however because the DSO is already loaded.
This fixes dso__load() to return 0 when successfully loading a DSO with libbfd.
Fixes: eac9a4342e5447ca ("perf symbols: Try reading the symbol table with libbfd") Signed-off-by: Nicholas Fraser nfraser@codeweavers.com Cc: Adrian Hunter adrian.hunter@intel.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Frank Ch. Eigler fche@redhat.com Cc: Huw Davies huw@codeweavers.com Cc: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@redhat.com Cc: Kim Phillips kim.phillips@amd.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Remi Bernon rbernon@codeweavers.com Cc: Song Liu songliubraving@fb.com Cc: Tommi Rantala tommi.t.rantala@nokia.com Cc: Ulrich Czekalla uczekalla@codeweavers.com Link: http://lore.kernel.org/lkml/1671b43b-09c3-1911-dbf8-7f030242fbf7@codeweavers... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/symbol.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1645fb4ec9ed4..7dcf3327c5f7d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1866,8 +1866,10 @@ int dso__load(struct dso *dso, struct map *map) if (nsexit) nsinfo__mountns_enter(dso->nsinfo, &nsc);
- if (bfdrc == 0) + if (bfdrc == 0) { + ret = 0; break; + }
if (!is_reg || sirc < 0) continue;
From: J. Bruce Fields bfields@redhat.com
[ Upstream commit bd5ae9288d6451bd346a1b4a59d4fe7e62ba29b7 ]
These pernet operations may depend on stuff set up or torn down in the module init/exit functions. And they may be called at any time in between. So it makes more sense for them to be the last to be registered in the init function, and the first to be unregistered in the exit function.
In particular, without this, the drc slab is being destroyed before all the per-net drcs are shut down, resulting in an "Objects remaining in nfsd_drc on __kmem_cache_shutdown()" warning in exit_nfsd.
Reported-by: Zhi Li yieli@redhat.com Fixes: 3ba75830ce17 "nfsd4: drc containerization" Signed-off-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfsd/nfsctl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index f6d5d783f4a45..0759e589ab52b 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1522,12 +1522,9 @@ static int __init init_nfsd(void) int retval; printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
- retval = register_pernet_subsys(&nfsd_net_ops); - if (retval < 0) - return retval; retval = register_cld_notifier(); if (retval) - goto out_unregister_pernet; + return retval; retval = nfsd4_init_slabs(); if (retval) goto out_unregister_notifier; @@ -1544,9 +1541,14 @@ static int __init init_nfsd(void) goto out_free_lockd; retval = register_filesystem(&nfsd_fs_type); if (retval) + goto out_free_exports; + retval = register_pernet_subsys(&nfsd_net_ops); + if (retval < 0) goto out_free_all; return 0; out_free_all: + unregister_pernet_subsys(&nfsd_net_ops); +out_free_exports: remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); out_free_lockd: @@ -1559,13 +1561,12 @@ out_free_slabs: nfsd4_free_slabs(); out_unregister_notifier: unregister_cld_notifier(); -out_unregister_pernet: - unregister_pernet_subsys(&nfsd_net_ops); return retval; }
static void __exit exit_nfsd(void) { + unregister_pernet_subsys(&nfsd_net_ops); nfsd_drc_slab_free(); remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); @@ -1575,7 +1576,6 @@ static void __exit exit_nfsd(void) nfsd4_exit_pnfs(); unregister_filesystem(&nfsd_fs_type); unregister_cld_notifier(); - unregister_pernet_subsys(&nfsd_net_ops); }
MODULE_AUTHOR("Olaf Kirch okir@monad.swb.de");
From: Chuck Lever chuck.lever@oracle.com
[ Upstream commit 0ac24c320c4d89a9de6ec802591398b8675c7b3c ]
RDMA core mutex locking was restructured by commit d114c6feedfe ("RDMA/cma: Add missing locking to rdma_accept()") [Aug 2020]. When lock debugging is enabled, the RPC/RDMA server trips over the new lockdep assertion in rdma_accept() because it doesn't call rdma_accept() from its CM event handler.
As a temporary fix, have svc_rdma_accept() take the handler_mutex explicitly. In the meantime, let's consider how to restructure the RPC/RDMA transport to invoke rdma_accept() from the proper context.
Calls to svc_rdma_accept() are serialized with calls to svc_rdma_free() by the generic RPC server layer.
Suggested-by: Jason Gunthorpe jgg@nvidia.com Link: https://lore.kernel.org/linux-rdma/20210209154014.GO4247@nvidia.com/ Fixes: d114c6feedfe ("RDMA/cma: Add missing locking to rdma_accept()") Signed-off-by: Chuck Lever chuck.lever@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index afba4e9d5425d..c895f80df659c 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -475,9 +475,6 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) if (!svc_rdma_post_recvs(newxprt)) goto errout;
- /* Swap out the handler */ - newxprt->sc_cm_id->event_handler = svc_rdma_cma_handler; - /* Construct RDMA-CM private message */ pmsg.cp_magic = rpcrdma_cmp_magic; pmsg.cp_version = RPCRDMA_CMP_VERSION; @@ -498,7 +495,10 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) } conn_param.private_data = &pmsg; conn_param.private_data_len = sizeof(pmsg); + rdma_lock_handler(newxprt->sc_cm_id); + newxprt->sc_cm_id->event_handler = svc_rdma_cma_handler; ret = rdma_accept(newxprt->sc_cm_id, &conn_param); + rdma_unlock_handler(newxprt->sc_cm_id); if (ret) { trace_svcrdma_accept_err(newxprt, ret); goto errout;
From: Jeff Layton jlayton@kernel.org
[ Upstream commit 64f36da5625f7f9853b86750eaa89d499d16a2e9 ]
A primary reason for skipping ceph_check_caps after putting the references was to avoid the locking in ceph_check_caps during a reconnect. __ceph_put_cap_refs can still call ceph_flush_snaps in that case though, and that takes many of the same inconvenient locks.
Fix the logic in __ceph_put_cap_refs to skip flushing snaps when the skip_checking_caps flag is set.
Fixes: e64f44a88465 ("ceph: skip checking caps when session reconnecting and releasing reqs") Signed-off-by: Jeff Layton jlayton@kernel.org Reviewed-by: Ilya Dryomov idryomov@gmail.com Signed-off-by: Ilya Dryomov idryomov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ceph/caps.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 255a512f1277e..638d18c198ea7 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3093,10 +3093,12 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had, dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), last ? " last" : "", put ? " put" : "");
- if (last && !skip_checking_caps) - ceph_check_caps(ci, 0, NULL); - else if (flushsnaps) - ceph_flush_snaps(ci, NULL); + if (!skip_checking_caps) { + if (last) + ceph_check_caps(ci, 0, NULL); + else if (flushsnaps) + ceph_flush_snaps(ci, NULL); + } if (wake) wake_up_all(&ci->i_cap_wq); while (put-- > 0)
From: Lang Cheng chenglang@huawei.com
[ Upstream commit 8f86e2eadac968200a6ab1d7074fc0f5cbc1e075 ]
When posting a multi-descriptors command, the error code of previous failed descriptors may be rewrote to 0 by a later successful descriptor.
Fixes: a04ff739f2a9 ("RDMA/hns: Add command queue support for hip08 RoCE driver") Link: https://lore.kernel.org/r/1612688143-28226-3-git-send-email-liweihang@huawei... Signed-off-by: Lang Cheng chenglang@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 | 7 +++---- 1 file changed, 3 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 43ed927860569..0f76e193317e6 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -1264,7 +1264,7 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, u32 timeout = 0; int handle = 0; u16 desc_ret; - int ret = 0; + int ret; int ntc;
spin_lock_bh(&csq->lock); @@ -1309,15 +1309,14 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, if (hns_roce_cmq_csq_done(hr_dev)) { complete = true; handle = 0; + ret = 0; while (handle < num) { /* get the result of hardware write back */ desc_to_use = &csq->desc[ntc]; desc[handle] = *desc_to_use; dev_dbg(hr_dev->dev, "Get cmq desc:\n"); desc_ret = le16_to_cpu(desc[handle].retval); - if (desc_ret == CMD_EXEC_SUCCESS) - ret = 0; - else + if (unlikely(desc_ret != CMD_EXEC_SUCCESS)) ret = -EIO; priv->cmq.last_status = desc_ret; ntc++;
From: Avihai Horon avihaih@nvidia.com
[ Upstream commit fe454dc31e84f8c14cb8942fcb61666c9f40745b ]
ucma_process_join() allocates struct ucma_multicast mc and frees it if an error occurs during its run. Specifically, if an error occurs in copy_to_user(), a use-after-free might happen in the following scenario:
1. mc struct is allocated. 2. rdma_join_multicast() is called and succeeds. During its run, cma_iboe_join_multicast() enqueues a work that will later use the aforementioned mc struct. 3. copy_to_user() is called and fails. 4. mc struct is deallocated. 5. The work that was enqueued by cma_iboe_join_multicast() is run and calls ucma_create_uevent() which tries to access mc struct (which is freed by now).
Fix this bug by cancelling the work enqueued by cma_iboe_join_multicast(). Since cma_work_handler() frees struct cma_work, we don't use it in cma_iboe_join_multicast() so we can safely cancel the work later.
The following syzkaller report revealed it:
BUG: KASAN: use-after-free in ucma_create_uevent+0x2dd/0x;3f0 drivers/infiniband/core/ucma.c:272 Read of size 8 at addr ffff88810b3ad110 by task kworker/u8:1/108
CPU: 1 PID: 108 Comm: kworker/u8:1 Not tainted 5.10.0-rc6+ #257 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Workqueue: rdma_cm cma_work_handler Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xbe/0xf9 lib/dump_stack.c:118 print_address_description.constprop.0+0x3e/0×60 mm/kasan/report.c:385 __kasan_report mm/kasan/report.c:545 [inline] kasan_report.cold+0x1f/0×37 mm/kasan/report.c:562 ucma_create_uevent+0x2dd/0×3f0 drivers/infiniband/core/ucma.c:272 ucma_event_handler+0xb7/0×3c0 drivers/infiniband/core/ucma.c:349 cma_cm_event_handler+0x5d/0×1c0 drivers/infiniband/core/cma.c:1977 cma_work_handler+0xfa/0×190 drivers/infiniband/core/cma.c:2718 process_one_work+0x54c/0×930 kernel/workqueue.c:2272 worker_thread+0x82/0×830 kernel/workqueue.c:2418 kthread+0x1ca/0×220 kernel/kthread.c:292 ret_from_fork+0x1f/0×30 arch/x86/entry/entry_64.S:296
Allocated by task 359: kasan_save_stack+0x1b/0×40 mm/kasan/common.c:48 kasan_set_track mm/kasan/common.c:56 [inline] __kasan_kmalloc mm/kasan/common.c:461 [inline] __kasan_kmalloc.constprop.0+0xc2/0xd0 mm/kasan/common.c:434 kmalloc include/linux/slab.h:552 [inline] kzalloc include/linux/slab.h:664 [inline] ucma_process_join+0x16e/0×3f0 drivers/infiniband/core/ucma.c:1453 ucma_join_multicast+0xda/0×140 drivers/infiniband/core/ucma.c:1538 ucma_write+0x1f7/0×280 drivers/infiniband/core/ucma.c:1724 vfs_write fs/read_write.c:603 [inline] vfs_write+0x191/0×4c0 fs/read_write.c:585 ksys_write+0x1a1/0×1e0 fs/read_write.c:658 do_syscall_64+0x2d/0×40 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 359: kasan_save_stack+0x1b/0×40 mm/kasan/common.c:48 kasan_set_track+0x1c/0×30 mm/kasan/common.c:56 kasan_set_free_info+0x1b/0×30 mm/kasan/generic.c:355 __kasan_slab_free+0x112/0×160 mm/kasan/common.c:422 slab_free_hook mm/slub.c:1544 [inline] slab_free_freelist_hook mm/slub.c:1577 [inline] slab_free mm/slub.c:3142 [inline] kfree+0xb3/0×3e0 mm/slub.c:4124 ucma_process_join+0x22d/0×3f0 drivers/infiniband/core/ucma.c:1497 ucma_join_multicast+0xda/0×140 drivers/infiniband/core/ucma.c:1538 ucma_write+0x1f7/0×280 drivers/infiniband/core/ucma.c:1724 vfs_write fs/read_write.c:603 [inline] vfs_write+0x191/0×4c0 fs/read_write.c:585 ksys_write+0x1a1/0×1e0 fs/read_write.c:658 do_syscall_64+0x2d/0×40 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 The buggy address belongs to the object at ffff88810b3ad100 which belongs to the cache kmalloc-192 of size 192 The buggy address is located 16 bytes inside of 192-byte region [ffff88810b3ad100, ffff88810b3ad1c0)
Fixes: b5de0c60cc30 ("RDMA/cma: Fix use after free race in roce multicast join") Link: https://lore.kernel.org/r/20210211090517.1278415-1-leon@kernel.org Reported-by: Amit Matityahu mitm@nvidia.com Signed-off-by: Avihai Horon avihaih@nvidia.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/cma.c | 70 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 29 deletions(-)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index c51b84b2d2f37..e3638f80e1d52 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -352,7 +352,13 @@ struct ib_device *cma_get_ib_dev(struct cma_device *cma_dev)
struct cma_multicast { struct rdma_id_private *id_priv; - struct ib_sa_multicast *sa_mc; + union { + struct ib_sa_multicast *sa_mc; + struct { + struct work_struct work; + struct rdma_cm_event event; + } iboe_join; + }; struct list_head list; void *context; struct sockaddr_storage addr; @@ -1823,6 +1829,8 @@ static void destroy_mc(struct rdma_id_private *id_priv, cma_igmp_send(ndev, &mgid, false); dev_put(ndev); } + + cancel_work_sync(&mc->iboe_join.work); } kfree(mc); } @@ -2683,6 +2691,28 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, return (id_priv->query_id < 0) ? id_priv->query_id : 0; }
+static void cma_iboe_join_work_handler(struct work_struct *work) +{ + struct cma_multicast *mc = + container_of(work, struct cma_multicast, iboe_join.work); + struct rdma_cm_event *event = &mc->iboe_join.event; + struct rdma_id_private *id_priv = mc->id_priv; + int ret; + + mutex_lock(&id_priv->handler_mutex); + if (READ_ONCE(id_priv->state) == RDMA_CM_DESTROYING || + READ_ONCE(id_priv->state) == RDMA_CM_DEVICE_REMOVAL) + goto out_unlock; + + ret = cma_cm_event_handler(id_priv, event); + WARN_ON(ret); + +out_unlock: + mutex_unlock(&id_priv->handler_mutex); + if (event->event == RDMA_CM_EVENT_MULTICAST_JOIN) + rdma_destroy_ah_attr(&event->param.ud.ah_attr); +} + static void cma_work_handler(struct work_struct *_work) { struct cma_work *work = container_of(_work, struct cma_work, work); @@ -4478,10 +4508,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) cma_make_mc_event(status, id_priv, multicast, &event, mc); ret = cma_cm_event_handler(id_priv, &event); rdma_destroy_ah_attr(&event.param.ud.ah_attr); - if (ret) { - destroy_id_handler_unlock(id_priv); - return 0; - } + WARN_ON(ret);
out: mutex_unlock(&id_priv->handler_mutex); @@ -4604,7 +4631,6 @@ static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, struct cma_multicast *mc) { - struct cma_work *work; struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; int err = 0; struct sockaddr *addr = (struct sockaddr *)&mc->addr; @@ -4618,10 +4644,6 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, if (cma_zero_addr(addr)) return -EINVAL;
- work = kzalloc(sizeof *work, GFP_KERNEL); - if (!work) - return -ENOMEM; - gid_type = id_priv->cma_dev->default_gid_type[id_priv->id.port_num - rdma_start_port(id_priv->cma_dev->device)]; cma_iboe_set_mgid(addr, &ib.rec.mgid, gid_type); @@ -4632,10 +4654,9 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
if (dev_addr->bound_dev_if) ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if); - if (!ndev) { - err = -ENODEV; - goto err_free; - } + if (!ndev) + return -ENODEV; + ib.rec.rate = iboe_get_rate(ndev); ib.rec.hop_limit = 1; ib.rec.mtu = iboe_get_mtu(ndev->mtu); @@ -4653,24 +4674,15 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, err = -ENOTSUPP; } dev_put(ndev); - if (err || !ib.rec.mtu) { - if (!err) - err = -EINVAL; - goto err_free; - } + if (err || !ib.rec.mtu) + return err ?: -EINVAL; + rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr, &ib.rec.port_gid); - work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler); - cma_make_mc_event(0, id_priv, &ib, &work->event, mc); - /* Balances with cma_id_put() in cma_work_handler */ - cma_id_get(id_priv); - queue_work(cma_wq, &work->work); + INIT_WORK(&mc->iboe_join.work, cma_iboe_join_work_handler); + cma_make_mc_event(0, id_priv, &ib, &mc->iboe_join.event, mc); + queue_work(cma_wq, &mc->iboe_join.work); return 0; - -err_free: - kfree(work); - return err; }
int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit e6daa8f61d8def10f0619fe51b4c794f69598e4f ]
BUG: KASAN: stack-out-of-bounds in _mlx4_ib_post_send+0x1bd2/0x2770 [mlx4_ib] Read of size 4 at addr ffff8880d5a7f980 by task kworker/0:1H/565
CPU: 0 PID: 565 Comm: kworker/0:1H Tainted: G O 5.4.84-storage #5.4.84-1+feature+linux+5.4.y+dbg+20201216.1319+b6b887b~deb10 Hardware name: Supermicro H8QG6/H8QG6, BIOS 3.00 09/04/2012 Workqueue: ib-comp-wq ib_cq_poll_work [ib_core] Call Trace: dump_stack+0x96/0xe0 print_address_description.constprop.4+0x1f/0x300 ? irq_work_claim+0x2e/0x50 __kasan_report.cold.8+0x78/0x92 ? _mlx4_ib_post_send+0x1bd2/0x2770 [mlx4_ib] kasan_report+0x10/0x20 _mlx4_ib_post_send+0x1bd2/0x2770 [mlx4_ib] ? check_chain_key+0x1d7/0x2e0 ? _mlx4_ib_post_recv+0x630/0x630 [mlx4_ib] ? lockdep_hardirqs_on+0x1a8/0x290 ? stack_depot_save+0x218/0x56e ? do_profile_hits.isra.6.cold.13+0x1d/0x1d ? check_chain_key+0x1d7/0x2e0 ? save_stack+0x4d/0x80 ? save_stack+0x19/0x80 ? __kasan_slab_free+0x125/0x170 ? kfree+0xe7/0x3b0 rdma_write_sg+0x5b0/0x950 [rtrs_server]
The problem is when we send imm_wr, the type should be ib_rdma_wr, so hw driver like mlx4 can do rdma_wr(wr), so fix it by use the ib_rdma_wr as type for imm_wr.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20210212134525.103456-2-jinpu.wang@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Gioh Kim gi-oh.kim@cloud.ionos.com Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 64 +++++++++++++------------- 1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index d017ede304b76..1150d50b5d1e4 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -222,7 +222,8 @@ static int rdma_write_sg(struct rtrs_srv_op *id) dma_addr_t dma_addr = sess->dma_addr[id->msg_id]; struct rtrs_srv_mr *srv_mr; struct rtrs_srv *srv = sess->srv; - struct ib_send_wr inv_wr, imm_wr; + struct ib_send_wr inv_wr; + struct ib_rdma_wr imm_wr; struct ib_rdma_wr *wr = NULL; enum ib_send_flags flags; size_t sg_cnt; @@ -274,15 +275,15 @@ static int rdma_write_sg(struct rtrs_srv_op *id) if (need_inval && always_invalidate) { wr->wr.next = &rwr.wr; rwr.wr.next = &inv_wr; - inv_wr.next = &imm_wr; + inv_wr.next = &imm_wr.wr; } else if (always_invalidate) { wr->wr.next = &rwr.wr; - rwr.wr.next = &imm_wr; + rwr.wr.next = &imm_wr.wr; } else if (need_inval) { wr->wr.next = &inv_wr; - inv_wr.next = &imm_wr; + inv_wr.next = &imm_wr.wr; } else { - wr->wr.next = &imm_wr; + wr->wr.next = &imm_wr.wr; } /* * From time to time we have to post signaled sends, @@ -300,7 +301,7 @@ static int rdma_write_sg(struct rtrs_srv_op *id) inv_wr.ex.invalidate_rkey = rkey; }
- imm_wr.next = NULL; + imm_wr.wr.next = NULL; if (always_invalidate) { struct rtrs_msg_rkey_rsp *msg;
@@ -321,22 +322,22 @@ static int rdma_write_sg(struct rtrs_srv_op *id) list.addr = srv_mr->iu->dma_addr; list.length = sizeof(*msg); list.lkey = sess->s.dev->ib_pd->local_dma_lkey; - imm_wr.sg_list = &list; - imm_wr.num_sge = 1; - imm_wr.opcode = IB_WR_SEND_WITH_IMM; + imm_wr.wr.sg_list = &list; + imm_wr.wr.num_sge = 1; + imm_wr.wr.opcode = IB_WR_SEND_WITH_IMM; ib_dma_sync_single_for_device(sess->s.dev->ib_dev, srv_mr->iu->dma_addr, srv_mr->iu->size, DMA_TO_DEVICE); } else { - imm_wr.sg_list = NULL; - imm_wr.num_sge = 0; - imm_wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM; + imm_wr.wr.sg_list = NULL; + imm_wr.wr.num_sge = 0; + imm_wr.wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM; } - imm_wr.send_flags = flags; - imm_wr.ex.imm_data = cpu_to_be32(rtrs_to_io_rsp_imm(id->msg_id, + imm_wr.wr.send_flags = flags; + imm_wr.wr.ex.imm_data = cpu_to_be32(rtrs_to_io_rsp_imm(id->msg_id, 0, need_inval));
- imm_wr.wr_cqe = &io_comp_cqe; + imm_wr.wr.wr_cqe = &io_comp_cqe; ib_dma_sync_single_for_device(sess->s.dev->ib_dev, dma_addr, offset, DMA_BIDIRECTIONAL);
@@ -363,7 +364,8 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, { struct rtrs_sess *s = con->c.sess; struct rtrs_srv_sess *sess = to_srv_sess(s); - struct ib_send_wr inv_wr, imm_wr, *wr = NULL; + struct ib_send_wr inv_wr, *wr = NULL; + struct ib_rdma_wr imm_wr; struct ib_reg_wr rwr; struct rtrs_srv *srv = sess->srv; struct rtrs_srv_mr *srv_mr; @@ -400,15 +402,15 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, if (need_inval && always_invalidate) { wr = &inv_wr; inv_wr.next = &rwr.wr; - rwr.wr.next = &imm_wr; + rwr.wr.next = &imm_wr.wr; } else if (always_invalidate) { wr = &rwr.wr; - rwr.wr.next = &imm_wr; + rwr.wr.next = &imm_wr.wr; } else if (need_inval) { wr = &inv_wr; - inv_wr.next = &imm_wr; + inv_wr.next = &imm_wr.wr; } else { - wr = &imm_wr; + wr = &imm_wr.wr; } /* * From time to time we have to post signalled sends, @@ -417,13 +419,13 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, flags = (atomic_inc_return(&con->wr_cnt) % srv->queue_depth) ? 0 : IB_SEND_SIGNALED; imm = rtrs_to_io_rsp_imm(id->msg_id, errno, need_inval); - imm_wr.next = NULL; + imm_wr.wr.next = NULL; if (always_invalidate) { struct ib_sge list; struct rtrs_msg_rkey_rsp *msg;
srv_mr = &sess->mrs[id->msg_id]; - rwr.wr.next = &imm_wr; + rwr.wr.next = &imm_wr.wr; rwr.wr.opcode = IB_WR_REG_MR; rwr.wr.wr_cqe = &local_reg_cqe; rwr.wr.num_sge = 0; @@ -440,21 +442,21 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, list.addr = srv_mr->iu->dma_addr; list.length = sizeof(*msg); list.lkey = sess->s.dev->ib_pd->local_dma_lkey; - imm_wr.sg_list = &list; - imm_wr.num_sge = 1; - imm_wr.opcode = IB_WR_SEND_WITH_IMM; + imm_wr.wr.sg_list = &list; + imm_wr.wr.num_sge = 1; + imm_wr.wr.opcode = IB_WR_SEND_WITH_IMM; ib_dma_sync_single_for_device(sess->s.dev->ib_dev, srv_mr->iu->dma_addr, srv_mr->iu->size, DMA_TO_DEVICE); } else { - imm_wr.sg_list = NULL; - imm_wr.num_sge = 0; - imm_wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM; + imm_wr.wr.sg_list = NULL; + imm_wr.wr.num_sge = 0; + imm_wr.wr.opcode = IB_WR_RDMA_WRITE_WITH_IMM; } - imm_wr.send_flags = flags; - imm_wr.wr_cqe = &io_comp_cqe; + imm_wr.wr.send_flags = flags; + imm_wr.wr.wr_cqe = &io_comp_cqe;
- imm_wr.ex.imm_data = cpu_to_be32(imm); + imm_wr.wr.ex.imm_data = cpu_to_be32(imm);
err = ib_post_send(id->con->c.qp, wr, NULL); if (unlikely(err))
From: Md Haris Iqbal haris.iqbal@cloud.ionos.com
[ Upstream commit 03e9b33a0fd677f554b03352646c13459bf60458 ]
While adding a path from the client side to an already established session, it was possible to provide the destination IP to a different server. This is dangerous.
This commit adds an extra member to the rtrs_msg_conn_req structure, named first_conn; which is supposed to notify if the connection request is the first for that session or not.
On the server side, if a session does not exist but the first_conn received inside the rtrs_msg_conn_req structure is 1, the connection request is failed. This signifies that the connection request is for an already existing session, and since the server did not find one, it is an wrong connection request.
Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality") Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20210212134525.103456-3-jinpu.wang@cloud.ionos.com Signed-off-by: Md Haris Iqbal haris.iqbal@cloud.ionos.com Reviewed-by: Lutz Pogrell lutz.pogrell@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 7 +++++++ drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 + drivers/infiniband/ulp/rtrs/rtrs-pri.h | 4 +++- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 21 +++++++++++++++------ 4 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 172bf7f221ff0..785cd1cf2a402 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -31,6 +31,8 @@ */ #define RTRS_RECONNECT_SEED 8
+#define FIRST_CONN 0x01 + MODULE_DESCRIPTION("RDMA Transport Client"); MODULE_LICENSE("GPL");
@@ -1662,6 +1664,7 @@ static int rtrs_rdma_route_resolved(struct rtrs_clt_con *con) .cid_num = cpu_to_le16(sess->s.con_num), .recon_cnt = cpu_to_le16(sess->s.recon_cnt), }; + msg.first_conn = sess->for_new_clt ? FIRST_CONN : 0; uuid_copy(&msg.sess_uuid, &sess->s.uuid); uuid_copy(&msg.paths_uuid, &clt->paths_uuid);
@@ -1747,6 +1750,8 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, scnprintf(sess->hca_name, sizeof(sess->hca_name), sess->s.dev->ib_dev->name); sess->s.src_addr = con->c.cm_id->route.addr.src_addr; + /* set for_new_clt, to allow future reconnect on any path */ + sess->for_new_clt = 1; }
return 0; @@ -2676,6 +2681,8 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, err = PTR_ERR(sess); goto close_all_sess; } + if (!i) + sess->for_new_clt = 1; list_add_tail_rcu(&sess->s.entry, &clt->paths_list);
err = init_sess(sess); diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.h b/drivers/infiniband/ulp/rtrs/rtrs-clt.h index b8dbd701b3cb2..7c9e155027969 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.h +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.h @@ -143,6 +143,7 @@ struct rtrs_clt_sess { int max_send_sge; u32 flags; struct kobject kobj; + u8 for_new_clt; struct rtrs_clt_stats *stats; /* cache hca_port and hca_name to display in sysfs */ u8 hca_port; diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h index d5621e6fad1b1..8caad0a2322bf 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h +++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h @@ -188,7 +188,9 @@ struct rtrs_msg_conn_req { __le16 recon_cnt; uuid_t sess_uuid; uuid_t paths_uuid; - u8 reserved[12]; + u8 first_conn : 1; + u8 reserved_bits : 7; + u8 reserved[11]; };
/** diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 1150d50b5d1e4..b6cb09972de55 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1334,7 +1334,8 @@ static void free_srv(struct rtrs_srv *srv) }
static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx, - const uuid_t *paths_uuid) + const uuid_t *paths_uuid, + bool first_conn) { struct rtrs_srv *srv; int i; @@ -1347,12 +1348,20 @@ static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx, return srv; } } + /* + * If this request is not the first connection request from the + * client for this session then fail and return error. + */ + if (!first_conn) { + mutex_unlock(&ctx->srv_mutex); + return ERR_PTR(-ENXIO); + }
/* need to allocate a new srv */ srv = kzalloc(sizeof(*srv), GFP_KERNEL); if (!srv) { mutex_unlock(&ctx->srv_mutex); - return NULL; + return ERR_PTR(-ENOMEM); }
INIT_LIST_HEAD(&srv->paths_list); @@ -1387,7 +1396,7 @@ err_free_chunks:
err_free_srv: kfree(srv); - return NULL; + return ERR_PTR(-ENOMEM); }
static void put_srv(struct rtrs_srv *srv) @@ -1788,13 +1797,13 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, goto reject_w_econnreset; } recon_cnt = le16_to_cpu(msg->recon_cnt); - srv = get_or_create_srv(ctx, &msg->paths_uuid); + srv = get_or_create_srv(ctx, &msg->paths_uuid, msg->first_conn); /* * "refcount == 0" happens if a previous thread calls get_or_create_srv * allocate srv, but chunks of srv are not allocated yet. */ - if (!srv || refcount_read(&srv->refcount) == 0) { - err = -ENOMEM; + if (IS_ERR(srv) || refcount_read(&srv->refcount) == 0) { + err = PTR_ERR(srv); goto reject_w_err; } mutex_lock(&srv->paths_mutex);
From: Gioh Kim gi-oh.kim@cloud.ionos.com
[ Upstream commit f7452a7e96c120d73100387d5f87de9fce7133cb ]
kmemleak reported an error as below:
unreferenced object 0xffff8880674b7640 (size 64): comm "kworker/4:1H", pid 113, jiffies 4296403507 (age 507.840s) hex dump (first 32 bytes): 69 70 3a 31 39 32 2e 31 36 38 2e 31 32 32 2e 31 ip:192.168.122.1 31 30 40 69 70 3a 31 39 32 2e 31 36 38 2e 31 32 10@ip:192.168.12 backtrace: [<0000000054413611>] kstrdup+0x2e/0x60 [<0000000078e3120a>] kobject_set_name_vargs+0x2f/0xb0 [<00000000ca2be3ee>] kobject_init_and_add+0xb0/0x120 [<0000000062ba5e78>] rtrs_srv_create_sess_files+0x14c/0x314 [rtrs_server] [<00000000b45b7217>] rtrs_srv_info_req_done+0x5b1/0x800 [rtrs_server] [<000000008fc5aa8f>] __ib_process_cq+0x94/0x100 [ib_core] [<00000000a9599cb4>] ib_cq_poll_work+0x32/0xc0 [ib_core] [<00000000cfc376be>] process_one_work+0x4bc/0x980 [<0000000016e5c96a>] worker_thread+0x78/0x5c0 [<00000000c20b8be0>] kthread+0x191/0x1e0 [<000000006c9c0003>] ret_from_fork+0x3a/0x50
It is caused by the not-freed kobject of rtrs_srv_sess. The kobject embedded in rtrs_srv_sess has ref-counter 2 after calling process_info_req(). Therefore it must call kobject_put twice. Currently it calls kobject_put only once at rtrs_srv_destroy_sess_files because kobject_del removes the state_in_sysfs flag and then kobject_put in free_sess() is not called.
This patch moves kobject_del() into free_sess() so that the kobject of rtrs_srv_sess can be freed. And also this patch adds the missing call of sysfs_remove_group() to clean-up the sysfs directory.
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality") Link: https://lore.kernel.org/r/20210212134525.103456-4-jinpu.wang@cloud.ionos.com Signed-off-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 2 +- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c index 0a3886629cae8..94e3f3290500a 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c @@ -305,7 +305,7 @@ void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess *sess) if (sess->kobj.state_in_sysfs) { kobject_del(&sess->stats->kobj_stats); kobject_put(&sess->stats->kobj_stats); - kobject_del(&sess->kobj); + sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group); kobject_put(&sess->kobj);
rtrs_srv_destroy_once_sysfs_root_folders(sess); diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index b6cb09972de55..77ec87f1a660b 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1476,10 +1476,12 @@ static bool __is_path_w_addr_exists(struct rtrs_srv *srv,
static void free_sess(struct rtrs_srv_sess *sess) { - if (sess->kobj.state_in_sysfs) + if (sess->kobj.state_in_sysfs) { + kobject_del(&sess->kobj); kobject_put(&sess->kobj); - else + } else { kfree(sess); + } }
static void rtrs_srv_close_work(struct work_struct *work)
From: Gioh Kim gi-oh.kim@cloud.ionos.com
[ Upstream commit e2853c49477d104c01d3c7944e1fb5074eb11d9f ]
put_device() decreases the ref-count and then the device will be cleaned-up, while at is also add missing put_device in rtrs_srv_create_once_sysfs_root_folders
This patch solves a kmemleak error as below:
unreferenced object 0xffff88809a7a0710 (size 8): comm "kworker/4:1H", pid 113, jiffies 4295833049 (age 6212.380s) hex dump (first 8 bytes): 62 6c 61 00 6b 6b 6b a5 bla.kkk. backtrace: [<0000000054413611>] kstrdup+0x2e/0x60 [<0000000078e3120a>] kobject_set_name_vargs+0x2f/0xb0 [<00000000f1a17a6b>] dev_set_name+0xab/0xe0 [<00000000d5502e32>] rtrs_srv_create_sess_files+0x2fb/0x314 [rtrs_server] [<00000000ed11a1ef>] rtrs_srv_info_req_done+0x631/0x800 [rtrs_server] [<000000008fc5aa8f>] __ib_process_cq+0x94/0x100 [ib_core] [<00000000a9599cb4>] ib_cq_poll_work+0x32/0xc0 [ib_core] [<00000000cfc376be>] process_one_work+0x4bc/0x980 [<0000000016e5c96a>] worker_thread+0x78/0x5c0 [<00000000c20b8be0>] kthread+0x191/0x1e0 [<000000006c9c0003>] ret_from_fork+0x3a/0x50
Fixes: baa5b28b7a47 ("RDMA/rtrs-srv: Replace device_register with device_initialize and device_add") Link: https://lore.kernel.org/r/20210212134525.103456-5-jinpu.wang@cloud.ionos.com Signed-off-by: Gioh Kim gi-oh.kim@cloud.ionos.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c index 94e3f3290500a..126a96e75c621 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c @@ -183,6 +183,7 @@ static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess) err = -ENOMEM; pr_err("kobject_create_and_add(): %d\n", err); device_del(&srv->dev); + put_device(&srv->dev); goto unlock; } dev_set_uevent_suppress(&srv->dev, false); @@ -208,6 +209,7 @@ rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess) kobject_put(srv->kobj_paths); mutex_unlock(&srv->paths_mutex); device_del(&srv->dev); + put_device(&srv->dev); } else { mutex_unlock(&srv->paths_mutex); }
From: Jack Wang jinpu.wang@cloud.ionos.com
[ Upstream commit ed408529679737a9a7ad816c8de5d59ba104bb11 ]
smatch gives the warning:
drivers/infiniband/ulp/rtrs/rtrs-srv.c:1805 rtrs_rdma_connect() warn: passing zero to 'PTR_ERR'
Which is trying to say smatch has shown that srv is not an error pointer and thus cannot be passed to PTR_ERR.
The solution is to move the list_add() down after full initilization of rtrs_srv. To avoid holding the srv_mutex too long, only hold it during the list operation as suggested by Leon.
Fixes: 03e9b33a0fd6 ("RDMA/rtrs: Only allow addition of path to an already established session") Link: https://lore.kernel.org/r/20210216143807.65923-1-jinpu.wang@cloud.ionos.com Reported-by: kernel test robot lkp@intel.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Jack Wang jinpu.wang@cloud.ionos.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-srv.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 77ec87f1a660b..3850d2a938f8e 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1348,21 +1348,18 @@ static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx, return srv; } } + mutex_unlock(&ctx->srv_mutex); /* * If this request is not the first connection request from the * client for this session then fail and return error. */ - if (!first_conn) { - mutex_unlock(&ctx->srv_mutex); + if (!first_conn) return ERR_PTR(-ENXIO); - }
/* need to allocate a new srv */ srv = kzalloc(sizeof(*srv), GFP_KERNEL); - if (!srv) { - mutex_unlock(&ctx->srv_mutex); + if (!srv) return ERR_PTR(-ENOMEM); - }
INIT_LIST_HEAD(&srv->paths_list); mutex_init(&srv->paths_mutex); @@ -1372,8 +1369,6 @@ static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx, srv->ctx = ctx; device_initialize(&srv->dev); srv->dev.release = rtrs_srv_dev_release; - list_add(&srv->ctx_list, &ctx->srv_list); - mutex_unlock(&ctx->srv_mutex);
srv->chunks = kcalloc(srv->queue_depth, sizeof(*srv->chunks), GFP_KERNEL); @@ -1386,6 +1381,9 @@ static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx, goto err_free_chunks; } refcount_set(&srv->refcount, 1); + mutex_lock(&ctx->srv_mutex); + list_add(&srv->ctx_list, &ctx->srv_list); + mutex_unlock(&ctx->srv_mutex);
return srv;
@@ -1800,11 +1798,7 @@ static int rtrs_rdma_connect(struct rdma_cm_id *cm_id, } recon_cnt = le16_to_cpu(msg->recon_cnt); srv = get_or_create_srv(ctx, &msg->paths_uuid, msg->first_conn); - /* - * "refcount == 0" happens if a previous thread calls get_or_create_srv - * allocate srv, but chunks of srv are not allocated yet. - */ - if (IS_ERR(srv) || refcount_read(&srv->refcount) == 0) { + if (IS_ERR(srv)) { err = PTR_ERR(srv); goto reject_w_err; }
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit b0b7d2815839024e5181bd2572f5d8d4f65363b3 ]
If v4l2_ctrl_handler_setup() fails then probe() should return an error code instead of returning success.
Fixes: cee1e3e2ef39 ("media: add video control handlers using V4L2 control framework") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/YBKFkbATXa5fA3xj@mwanda Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/touchscreen/sur40.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 620cdd7d214a6..12f2562b0141b 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -787,6 +787,7 @@ static int sur40_probe(struct usb_interface *interface, dev_err(&interface->dev, "Unable to register video controls."); v4l2_ctrl_handler_free(&sur40->hdl); + error = sur40->hdl.error; goto err_unreg_v4l2; }
From: Yang Jihong yangjihong1@huawei.com
[ Upstream commit e16c2ce7c5ed5de881066c1fd10ba5c09af69559 ]
Commit da231338ec9c0987 ("perf record: Use an eventfd to wakeup when done") uses eventfd() to solve a rare race where the setting and checking of 'done' which add done_fd to pollfd. When draining buffer, revents of done_fd is 0 and evlist__filter_pollfd function returns a non-zero value. As a result, perf record does not stop profiling.
The following simple scenarios can trigger this condition:
# sleep 10 & # perf record -p $!
After the sleep process exits, perf record should stop profiling and exit. However, perf record keeps running.
If pollfd revents contains only POLLERR or POLLHUP, perf record indicates that buffer is draining and need to stop profiling. Use fdarray_flag__nonfilterable() to set done eventfd to nonfilterable objects, so that evlist__filter_pollfd() does not filter and check done eventfd.
Fixes: da231338ec9c0987 ("perf record: Use an eventfd to wakeup when done") Signed-off-by: Yang Jihong yangjihong1@huawei.com Tested-by: Arnaldo Carvalho de Melo acme@redhat.com Tested-by: Jiri Olsa jolsa@redhat.com Cc: Adrian Hunter adrian.hunter@intel.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Alexey Budankov alexey.budankov@linux.intel.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: zhangjinhao2@huawei.com Link: http://lore.kernel.org/lkml/20210205065001.23252-1-yangjihong1@huawei.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/builtin-record.c | 2 +- tools/perf/util/evlist.c | 8 ++++++++ tools/perf/util/evlist.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fd39116506123..51e593e896ea5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1663,7 +1663,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) status = -1; goto out_delete_session; } - err = evlist__add_pollfd(rec->evlist, done_fd); + err = evlist__add_wakeup_eventfd(rec->evlist, done_fd); if (err < 0) { pr_err("Failed to add wakeup eventfd to poll list\n"); status = err; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 05363a7247c41..fea4c1e8010d9 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -572,6 +572,14 @@ int evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask) return perf_evlist__filter_pollfd(&evlist->core, revents_and_mask); }
+#ifdef HAVE_EVENTFD_SUPPORT +int evlist__add_wakeup_eventfd(struct evlist *evlist, int fd) +{ + return perf_evlist__add_pollfd(&evlist->core, fd, NULL, POLLIN, + fdarray_flag__nonfilterable); +} +#endif + int evlist__poll(struct evlist *evlist, int timeout) { return perf_evlist__poll(&evlist->core, timeout); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 1aae75895dea0..6d4d62151bc89 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -142,6 +142,10 @@ struct evsel *evlist__find_tracepoint_by_name(struct evlist *evlist, const char int evlist__add_pollfd(struct evlist *evlist, int fd); int evlist__filter_pollfd(struct evlist *evlist, short revents_and_mask);
+#ifdef HAVE_EVENTFD_SUPPORT +int evlist__add_wakeup_eventfd(struct evlist *evlist, int fd); +#endif + int evlist__poll(struct evlist *evlist, int timeout);
struct evsel *evlist__id2evsel(struct evlist *evlist, u64 id);
From: Dave Rigby d.rigby@me.com
[ Upstream commit 4e1481445407b86a483616c4542ffdc810efb680 ]
When locating the DWARF module for a given address, __find_debuginfo() requires a 'struct dso' passed via the userdata argument.
However, this field is only set in __report_module() if the module is found in via dwfl_addrmodule(), not if it is found later via dwfl_report_elf().
Set userdata irrespective of how the DWARF module was found, as long as we found a module.
Fixes: bf53fc6b5f41 ("perf unwind: Fix separate debug info files when using elfutils' libdw's unwinder") Signed-off-by: Dave Rigby d.rigby@me.com Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=211801 Acked-by: Jan Kratochvil jan.kratochvil@redhat.com Acked-by: Jiri Olsa jolsa@redhat.com Link: https://lore.kernel.org/linux-perf-users/20210218165654.36604-1-d.rigby@me.c... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/unwind-libdw.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 0ada907c60d49..a74b517f74974 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -60,10 +60,8 @@ static int __report_module(struct addr_location *al, u64 ip, mod = dwfl_addrmodule(ui->dwfl, ip); if (mod) { Dwarf_Addr s; - void **userdatap;
- dwfl_module_info(mod, &userdatap, &s, NULL, NULL, NULL, NULL, NULL); - *userdatap = dso; + dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); if (s != al->map->start - al->map->pgoff) mod = 0; } @@ -79,6 +77,13 @@ static int __report_module(struct addr_location *al, u64 ip, al->map->start - al->map->pgoff, false); }
+ if (mod) { + void **userdatap; + + dwfl_module_info(mod, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); + *userdatap = dso; + } + return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; }
From: Adrian Hunter adrian.hunter@intel.com
[ Upstream commit 03fb0f859b45d1eb05c984ab4bd3bef67e45ede2 ]
Add missing CYC packet processing when walking through PSB+. This improves the accuracy of timestamps that follow PSB+, until the next MTC.
Fixes: 3d49807870f08 ("perf tools: Add new Intel PT packet definitions") Signed-off-by: Adrian Hunter adrian.hunter@intel.com Reviewed-by: Andi Kleen ak@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Link: https://lore.kernel.org/r/20210205175350.23817-2-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 697513f351549..91cba05827369 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1761,6 +1761,9 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) break;
case INTEL_PT_CYC: + intel_pt_calc_cyc_timestamp(decoder); + break; + case INTEL_PT_VMCS: case INTEL_PT_MNT: case INTEL_PT_PAD:
From: Adrian Hunter adrian.hunter@intel.com
[ Upstream commit 20aa39708a5999b7921b27482a756766272286ac ]
The code assumed a change in cycle count means accurate IPC. That is not correct, for example when sampling both branches and instructions, or at a FUP packet (which is not CYC-eligible) address. Fix by using an explicit flag to indicate when IPC can be sampled.
Fixes: 5b1dc0fd1da06 ("perf intel-pt: Add support for samples to contain IPC ratio") Signed-off-by: Adrian Hunter adrian.hunter@intel.com Reviewed-by: Andi Kleen ak@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/20210205175350.23817-3-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../util/intel-pt-decoder/intel-pt-decoder.c | 11 ++++++++++- .../util/intel-pt-decoder/intel-pt-decoder.h | 1 + tools/perf/util/intel-pt.c | 16 ++++++---------- 3 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 91cba05827369..ef29f6b25e60a 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2814,9 +2814,18 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) } if (intel_pt_sample_time(decoder->pkt_state)) { intel_pt_update_sample_time(decoder); - if (decoder->sample_cyc) + if (decoder->sample_cyc) { decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; + decoder->state.flags |= INTEL_PT_SAMPLE_IPC; + decoder->sample_cyc = false; + } } + /* + * When using only TSC/MTC to compute cycles, IPC can be + * sampled as soon as the cycle count changes. + */ + if (!decoder->have_cyc) + decoder->state.flags |= INTEL_PT_SAMPLE_IPC; }
decoder->state.timestamp = decoder->sample_timestamp; diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 8645fc2654811..b52937b03c8c8 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -17,6 +17,7 @@ #define INTEL_PT_ABORT_TX (1 << 1) #define INTEL_PT_ASYNC (1 << 2) #define INTEL_PT_FUP_IP (1 << 3) +#define INTEL_PT_SAMPLE_IPC (1 << 4)
enum intel_pt_sample_type { INTEL_PT_BRANCH = 1 << 0, diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 60214de42f31b..d6d93ee030190 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1381,7 +1381,8 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) sample.branch_stack = (struct branch_stack *)&dummy_bs; }
- sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_br_cyc_cnt; + if (ptq->state->flags & INTEL_PT_SAMPLE_IPC) + sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_br_cyc_cnt; if (sample.cyc_cnt) { sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_br_insn_cnt; ptq->last_br_insn_cnt = ptq->ipc_insn_cnt; @@ -1431,7 +1432,8 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) else sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt;
- sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_in_cyc_cnt; + if (ptq->state->flags & INTEL_PT_SAMPLE_IPC) + sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_in_cyc_cnt; if (sample.cyc_cnt) { sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_in_insn_cnt; ptq->last_in_insn_cnt = ptq->ipc_insn_cnt; @@ -1966,14 +1968,8 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
ptq->have_sample = false;
- if (ptq->state->tot_cyc_cnt > ptq->ipc_cyc_cnt) { - /* - * Cycle count and instruction count only go together to create - * a valid IPC ratio when the cycle count changes. - */ - ptq->ipc_insn_cnt = ptq->state->tot_insn_cnt; - ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt; - } + ptq->ipc_insn_cnt = ptq->state->tot_insn_cnt; + ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
/* * Do PEBS first to allow for the possibility that the PEBS timestamp
From: Adrian Hunter adrian.hunter@intel.com
[ Upstream commit 6af4b60033e0ce0332fcdf256c965ad41942821a ]
The code assumed every CYC-eligible packet has a CYC packet, which is not the case when CYC thresholds are used. Fix by checking if a CYC packet is actually present in that case.
Fixes: 5b1dc0fd1da06 ("perf intel-pt: Add support for samples to contain IPC ratio") Signed-off-by: Adrian Hunter adrian.hunter@intel.com Reviewed-by: Andi Kleen ak@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Link: https://lore.kernel.org/r/20210205175350.23817-4-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../util/intel-pt-decoder/intel-pt-decoder.c | 27 +++++++++++++++++++ .../util/intel-pt-decoder/intel-pt-decoder.h | 1 + tools/perf/util/intel-pt.c | 13 +++++++++ 3 files changed, 41 insertions(+)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index ef29f6b25e60a..197eb58a39cb7 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -24,6 +24,13 @@ #include "intel-pt-decoder.h" #include "intel-pt-log.h"
+#define BITULL(x) (1ULL << (x)) + +/* IA32_RTIT_CTL MSR bits */ +#define INTEL_PT_CYC_ENABLE BITULL(1) +#define INTEL_PT_CYC_THRESHOLD (BITULL(22) | BITULL(21) | BITULL(20) | BITULL(19)) +#define INTEL_PT_CYC_THRESHOLD_SHIFT 19 + #define INTEL_PT_BLK_SIZE 1024
#define BIT63 (((uint64_t)1 << 63)) @@ -167,6 +174,8 @@ struct intel_pt_decoder { uint64_t sample_tot_cyc_cnt; uint64_t base_cyc_cnt; uint64_t cyc_cnt_timestamp; + uint64_t ctl; + uint64_t cyc_threshold; double tsc_to_cyc; bool continuous_period; bool overflow; @@ -204,6 +213,14 @@ static uint64_t intel_pt_lower_power_of_2(uint64_t x) return x << i; }
+static uint64_t intel_pt_cyc_threshold(uint64_t ctl) +{ + if (!(ctl & INTEL_PT_CYC_ENABLE)) + return 0; + + return (ctl & INTEL_PT_CYC_THRESHOLD) >> INTEL_PT_CYC_THRESHOLD_SHIFT; +} + static void intel_pt_setup_period(struct intel_pt_decoder *decoder) { if (decoder->period_type == INTEL_PT_PERIOD_TICKS) { @@ -245,12 +262,15 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
decoder->flags = params->flags;
+ decoder->ctl = params->ctl; decoder->period = params->period; decoder->period_type = params->period_type;
decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio;
+ decoder->cyc_threshold = intel_pt_cyc_threshold(decoder->ctl); + intel_pt_setup_period(decoder);
decoder->mtc_shift = params->mtc_period; @@ -2017,6 +2037,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) { + int last_packet_type = INTEL_PT_PAD; bool no_tip = false; int err;
@@ -2025,6 +2046,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) if (err) return err; next: + if (decoder->cyc_threshold) { + if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) + decoder->sample_cyc = false; + last_packet_type = decoder->packet.type; + } + if (decoder->hop) { switch (intel_pt_hop_trace(decoder, &no_tip, &err)) { case HOP_IGNORE: diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index b52937b03c8c8..48adaa78acfc2 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -244,6 +244,7 @@ struct intel_pt_params { void *data; bool return_compression; bool branch_enable; + uint64_t ctl; uint64_t period; enum intel_pt_period_type period_type; unsigned max_non_turbo_ratio; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index d6d93ee030190..2fff6f760457f 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -893,6 +893,18 @@ static bool intel_pt_sampling_mode(struct intel_pt *pt) return false; }
+static u64 intel_pt_ctl(struct intel_pt *pt) +{ + struct evsel *evsel; + u64 config; + + evlist__for_each_entry(pt->session->evlist, evsel) { + if (intel_pt_get_config(pt, &evsel->core.attr, &config)) + return config; + } + return 0; +} + static u64 intel_pt_ns_to_ticks(const struct intel_pt *pt, u64 ns) { u64 quot, rem; @@ -1026,6 +1038,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, params.data = ptq; params.return_compression = intel_pt_return_compression(pt); params.branch_enable = intel_pt_branch_enable(pt); + params.ctl = intel_pt_ctl(pt); params.max_non_turbo_ratio = pt->max_non_turbo_ratio; params.mtc_period = intel_pt_mtc_period(pt); params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
From: Namhyung Kim namhyung@kernel.org
[ Upstream commit c5c97cadd7ed13381cb6b4bef5c841a66938d350 ]
The ubsan reported the following error. It was because sample's raw data missed u32 padding at the end. So it broke the alignment of the array after it.
The raw data contains an u32 size prefix so the data size should have an u32 padding after 8-byte aligned data.
27: Sample parsing :util/synthetic-events.c:1539:4: runtime error: store to misaligned address 0x62100006b9bc for type '__u64' (aka 'unsigned long long'), which requires 8 byte alignment 0x62100006b9bc: note: pointer points here 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ^ #0 0x561532a9fc96 in perf_event__synthesize_sample util/synthetic-events.c:1539:13 #1 0x5615327f4a4f in do_test tests/sample-parsing.c:284:8 #2 0x5615327f3f50 in test__sample_parsing tests/sample-parsing.c:381:9 #3 0x56153279d3a1 in run_test tests/builtin-test.c:424:9 #4 0x56153279c836 in test_and_print tests/builtin-test.c:454:9 #5 0x56153279b7eb in __cmd_test tests/builtin-test.c:675:4 #6 0x56153279abf0 in cmd_test tests/builtin-test.c:821:9 #7 0x56153264e796 in run_builtin perf.c:312:11 #8 0x56153264cf03 in handle_internal_command perf.c:364:8 #9 0x56153264e47d in run_argv perf.c:408:2 #10 0x56153264c9a9 in main perf.c:538:3 #11 0x7f137ab6fbbc in __libc_start_main (/lib64/libc.so.6+0x38bbc) #12 0x561532596828 in _start ...
SUMMARY: UndefinedBehaviorSanitizer: misaligned-pointer-use util/synthetic-events.c:1539:4 in
Fixes: 045f8cd8542d ("perf tests: Add a sample parsing test") Signed-off-by: Namhyung Kim namhyung@kernel.org Acked-by: Adrian Hunter adrian.hunter@intel.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Andi Kleen ak@linux.intel.com Cc: Ian Rogers irogers@google.com Cc: Ingo Molnar mingo@kernel.org Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Link: https://lore.kernel.org/r/20210214091638.519643-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/perf/tests/sample-parsing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index 2393916f6128a..92869eea5dbd4 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -196,7 +196,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) .data = {1, -1ULL, 211, 212, 213}, }; u64 regs[64]; - const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; + const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 0 }; const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; const u64 aux_data[] = {0xa55a, 0, 0xeeddee, 0x0282028202820282}; struct perf_sample sample = {
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 0958351e93fa0ac142f6dd8bd844441594f30a57 ]
If elo_setup_10() fails then this should return an error code instead of success.
Fixes: fae3006e4b42 ("Input: elo - add support for non-pressure-sensitive touchscreens") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/YBKFd5CvDu+jVmfW@mwanda Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/touchscreen/elo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index e0bacd34866ad..96173232e53fe 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -341,8 +341,10 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) switch (elo->id) {
case 0: /* 10-byte protocol */ - if (elo_setup_10(elo)) + if (elo_setup_10(elo)) { + err = -EIO; goto fail3; + }
break;
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit 80bddf5c93a99e11fc9faf7e4b575d01cecd45d3 ]
Currently COMPAT on SPARC64 selects COMPAT_BINFMT_ELF unconditionally, even when BINFMT_ELF is not enabled. This causes a kconfig warning.
Instead, just select COMPAT_BINFMT_ELF if BINFMT_ELF is enabled. This builds cleanly with no kconfig warnings.
WARNING: unmet direct dependencies detected for COMPAT_BINFMT_ELF Depends on [n]: COMPAT [=y] && BINFMT_ELF [=n] Selected by [y]: - COMPAT [=y] && SPARC64 [=y]
Fixes: 26b4c912185a ("sparc,sparc64: unify Kconfig files") Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: "David S. Miller" davem@davemloft.net Cc: sparclinux@vger.kernel.org Cc: Sam Ravnborg sam@ravnborg.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- arch/sparc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c9c34dc52b7d8..639dde28124a2 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -494,7 +494,7 @@ config COMPAT bool depends on SPARC64 default y - select COMPAT_BINFMT_ELF + select COMPAT_BINFMT_ELF if BINFMT_ELF select HAVE_UID16 select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit b3554aa2470b5db1222c31e08ec9c29ab33eabc7 ]
Fix Sparc build when CONFIG_PROC_FS is not enabled.
Fixes this build error: arch/sparc/kernel/led.c:107:30: error: 'led_proc_ops' defined but not used [-Werror=unused-const-variable=] 107 | static const struct proc_ops led_proc_ops = { | ^~~~~~~~~~~~ cc1: all warnings being treated as errors
Fixes: 97a32539b956 ("proc: convert everything to "struct proc_ops"") Reported-by: kernel test robot lkp@intel.com Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: Alexey Dobriyan adobriyan@gmail.com Cc: Andrew Morton akpm@linux-foundation.org Cc: Lars Kotthoff metalhead@metalhead.ws Cc: "David S. Miller" davem@davemloft.net Cc: sparclinux@vger.kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- arch/sparc/kernel/led.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c index bd48575172c32..3a66e62eb2a0e 100644 --- a/arch/sparc/kernel/led.c +++ b/arch/sparc/kernel/led.c @@ -50,6 +50,7 @@ static void led_blink(struct timer_list *unused) add_timer(&led_blink_timer); }
+#ifdef CONFIG_PROC_FS static int led_proc_show(struct seq_file *m, void *v) { if (get_auxio() & AUXIO_LED) @@ -111,6 +112,7 @@ static const struct proc_ops led_proc_ops = { .proc_release = single_release, .proc_write = led_proc_write, }; +#endif
static struct proc_dir_entry *led;
From: Dmitry Torokhov dmitry.torokhov@gmail.com
[ Upstream commit 836f308cb5c72d48e2dff8d3e64c3adb94f4710d ]
zinitix_init_touch() returns error code or 0 for success and therefore return type must be int, not bool.
Fixes: 26822652c85e ("Input: add zinitix touchscreen driver") Reported-by: kernel test robot lkp@intel.com Reported-by: Jiapeng Chong jiapeng.chong@linux.alibaba.com Link: https://lore.kernel.org/r/YC8z2bXc3Oy8pABa@google.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/touchscreen/zinitix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c index a3e3adbabc673..b1548971d683e 100644 --- a/drivers/input/touchscreen/zinitix.c +++ b/drivers/input/touchscreen/zinitix.c @@ -190,7 +190,7 @@ static int zinitix_write_cmd(struct i2c_client *client, u16 reg) return 0; }
-static bool zinitix_init_touch(struct bt541_ts_data *bt541) +static int zinitix_init_touch(struct bt541_ts_data *bt541) { struct i2c_client *client = bt541->client; int i;
From: Michael Tretter m.tretter@pengutronix.de
[ Upstream commit 6524d8eac258452e547f8a49c8a965ac6dd8a161 ]
The st1232 can switch from NORMAL to IDLE state after the configured idle time (by default 8 s). If the st1232 is not reset during probe, it might already be ready but in IDLE state. Since it does not enter NORMAL state in this case, probe fails.
Fix the wait function to report the IDLE state as ready, too.
Fixes: f605be6a57b4 ("Input: st1232 - wait until device is ready before reading resolution") Signed-off-by: Michael Tretter m.tretter@pengutronix.de Link: https://lore.kernel.org/r/20210219110556.1858969-1-m.tretter@pengutronix.de Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/touchscreen/st1232.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index b4e7bcbe9b91d..885f0572488dd 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -94,7 +94,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
for (retries = 10; retries; retries--) { error = st1232_ts_read_data(ts, REG_STATUS, 1); - if (!error && ts->read_buf[0] == (STATUS_NORMAL | ERROR_NONE)) + if (!error && ts->read_buf[0] == (STATUS_NORMAL | STATUS_IDLE | ERROR_NONE)) return 0;
usleep_range(1000, 2000);
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit fd749fe4bcb00ad80d9eece709f804bb4ac6bf1e ]
When CONFIG_EPOLL is not set/enabled, sys_oabi-compat.c has build errors. Fix these by surrounding them with ifdef CONFIG_EPOLL/endif and providing stubs for the "EPOLL is not set" case.
../arch/arm/kernel/sys_oabi-compat.c: In function 'sys_oabi_epoll_ctl': ../arch/arm/kernel/sys_oabi-compat.c:257:6: error: implicit declaration of function 'ep_op_has_event' [-Werror=implicit-function-declaration] 257 | if (ep_op_has_event(op) && | ^~~~~~~~~~~~~~~ ../arch/arm/kernel/sys_oabi-compat.c:264:9: error: implicit declaration of function 'do_epoll_ctl'; did you mean 'sys_epoll_ctl'? [-Werror=implicit-function-declaration] 264 | return do_epoll_ctl(epfd, op, fd, &kernel, false); | ^~~~~~~~~~~~
Fixes: c281634c8652 ("ARM: compat: remove KERNEL_DS usage in sys_oabi_epoll_ctl()") Signed-off-by: Randy Dunlap rdunlap@infradead.org Reported-by: kernel test robot lkp@intel.com # from an lkp .config file Cc: linux-arm-kernel@lists.infradead.org Cc: Nicolas Pitre nico@fluxnic.net Cc: Alexander Viro viro@zeniv.linux.org.uk Cc: patches@armlinux.org.uk Acked-by: Nicolas Pitre nico@fluxnic.net Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/kernel/sys_oabi-compat.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 0203e545bbc8d..075a2e0ed2c15 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -248,6 +248,7 @@ struct oabi_epoll_event { __u64 data; } __attribute__ ((packed,aligned(4)));
+#ifdef CONFIG_EPOLL asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, struct oabi_epoll_event __user *event) { @@ -298,6 +299,20 @@ asmlinkage long sys_oabi_epoll_wait(int epfd, kfree(kbuf); return err ? -EFAULT : ret; } +#else +asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, + struct oabi_epoll_event __user *event) +{ + return -EINVAL; +} + +asmlinkage long sys_oabi_epoll_wait(int epfd, + struct oabi_epoll_event __user *events, + int maxevents, int timeout) +{ + return -EINVAL; +} +#endif
struct oabi_sembuf { unsigned short sem_num;
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 1bff77f41a805b16b5355497c217656711601282 ]
NORMAL (0x0) and IDLE (0x4) are really two different states. Hence you cannot check for both using a bitmask, as that checks for IDLE only, breaking operation for devices that are in NORMAL state.
Fix the wait function to report either state as ready.
Fixes: 6524d8eac258452e ("Input: st1232 - add IDLE state as ready condition") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Michael Tretter m.tretter@pengutronix.de Link: https://lore.kernel.org/r/20210223090201.1430542-1-geert+renesas@glider.be Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/input/touchscreen/st1232.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 885f0572488dd..6abae665ca71d 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -94,8 +94,13 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
for (retries = 10; retries; retries--) { error = st1232_ts_read_data(ts, REG_STATUS, 1); - if (!error && ts->read_buf[0] == (STATUS_NORMAL | STATUS_IDLE | ERROR_NONE)) - return 0; + if (!error) { + switch (ts->read_buf[0]) { + case STATUS_NORMAL | ERROR_NONE: + case STATUS_IDLE | ERROR_NONE: + return 0; + } + }
usleep_range(1000, 2000); }
From: Aswath Govindraju a-govindraju@ti.com
[ Upstream commit 13613a2246bf531f5fc04e8e62e8f21a3d39bf1c ]
Fix module autoprobe by correcting module alias to match the string from /sys/class/.../spi1.0/modalias content.
Fixes: 06b4501e88ad ("misc/eeprom: add driver for microwire 93xx46 EEPROMs") Signed-off-by: Aswath Govindraju a-govindraju@ti.com Link: https://lore.kernel.org/r/20210107163957.28664-2-a-govindraju@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/eeprom/eeprom_93xx46.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 7c45f82b43027..206d920dc92fc 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -511,4 +511,4 @@ module_spi_driver(eeprom_93xx46_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs"); MODULE_AUTHOR("Anatolij Gustschin agust@denx.de"); -MODULE_ALIAS("spi:93xx46"); +MODULE_ALIAS("spi:eeprom-93xx46");
From: Chris Ruehl chris.ruehl@gtsys.com.hk
[ Upstream commit 39961bd6b70e5a5d7c4b5483ad8e1db6b5765c60 ]
rockchip_emmc_phy_init() return variable is not set with the error value if clk_get() failed. 'emmcclk' is optional, thus use clk_get_optional() and if the return value != NULL make error processing and set the return code accordingly.
Fixes: 52c0624a10cce phy: rockchip-emmc: Set phyctrl_frqsel based on card clock Signed-off-by: Chris Ruehl chris.ruehl@gtsys.com.hk Reviewed-by: Douglas Anderson dianders@chromium.org Link: https://lore.kernel.org/r/20201210080454.17379-1-chris.ruehl@gtsys.com.hk Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c index 1e424f263e7ab..496d199852aff 100644 --- a/drivers/phy/rockchip/phy-rockchip-emmc.c +++ b/drivers/phy/rockchip/phy-rockchip-emmc.c @@ -248,15 +248,17 @@ static int rockchip_emmc_phy_init(struct phy *phy) * - SDHCI driver to get the PHY * - SDHCI driver to init the PHY * - * The clock is optional, so upon any error we just set to NULL. + * The clock is optional, using clk_get_optional() to get the clock + * and do error processing if the return value != NULL * * NOTE: we don't do anything special for EPROBE_DEFER here. Given the * above expected use case, EPROBE_DEFER isn't sensible to expect, so * it's just like any other error. */ - rk_phy->emmcclk = clk_get(&phy->dev, "emmcclk"); + rk_phy->emmcclk = clk_get_optional(&phy->dev, "emmcclk"); if (IS_ERR(rk_phy->emmcclk)) { - dev_dbg(&phy->dev, "Error getting emmcclk: %d\n", ret); + ret = PTR_ERR(rk_phy->emmcclk); + dev_err(&phy->dev, "Error getting emmcclk: %d\n", ret); rk_phy->emmcclk = NULL; }
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 266df28f9ac16b0dff553d78bc3fb1c084b96b9d ]
This error path should return -EINVAL, but currently it returns success.
Fixes: d09945eacad0 ("phy: cadence-torrent: Check total lane count for all subnodes is within limit") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/X9s7Wxq+b6ls0q7o@mwanda Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/cadence/phy-cadence-torrent.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index f310e15d94cbc..591a15834b48f 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -2298,6 +2298,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
if (total_num_lanes > MAX_NUM_LANES) { dev_err(dev, "Invalid lane configuration\n"); + ret = -EINVAL; goto put_lnk_rst; }
From: Aswath Govindraju a-govindraju@ti.com
[ Upstream commit 4540b9fbd8ebb21bb3735796d300a1589ee5fbf2 ]
Module alias "spi:93xx46" is used by non device tree users like drivers/misc/eeprom/digsy_mtc_eeprom.c and removing it will break support for them.
Fix this by adding back the module alias "spi:93xx46".
Fixes: 13613a2246bf ("misc: eeprom_93xx46: Fix module alias to enable module autoprobe") Signed-off-by: Aswath Govindraju a-govindraju@ti.com Link: https://lore.kernel.org/r/20210113051253.15061-1-a-govindraju@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/eeprom/eeprom_93xx46.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 206d920dc92fc..d92c4d2c521a3 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -511,4 +511,5 @@ module_spi_driver(eeprom_93xx46_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs"); MODULE_AUTHOR("Anatolij Gustschin agust@denx.de"); +MODULE_ALIAS("spi:93xx46"); MODULE_ALIAS("spi:eeprom-93xx46");
From: Marek Vasut marek.vasut+renesas@gmail.com
[ Upstream commit c4e0fec2f7ee013dbf86445394ff47f719408f99 ]
This fixes MSI operation on legacy PCI cards, which cannot issue 64bit MSIs. The R-Car controller only has one MSI trigger address instead of two, one for 64bit and one for 32bit MSI, set the address to 32bit PCIe space so that legacy PCI cards can also trigger MSIs.
Link: https://lore.kernel.org/r/20201016120431.7062-1-marek.vasut@gmail.com Fixes: 290c1fb35860 ("PCI: rcar: Add MSI support for PCIe") Tested-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Tested-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Marek Vasut marek.vasut+renesas@gmail.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Reviewed-by: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Cc: Bjorn Helgaas bhelgaas@google.com Cc: Geert Uytterhoeven geert+renesas@glider.be Cc: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Cc: Wolfram Sang wsa@the-dreams.de Cc: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com Cc: linux-renesas-soc@vger.kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-rcar-host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index 4d1c4b24e5370..a728e8f9ad3c8 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -735,7 +735,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie_host *host) }
/* setup MSI data target */ - msi->pages = __get_free_pages(GFP_KERNEL, 0); + msi->pages = __get_free_pages(GFP_KERNEL | GFP_DMA32, 0); rcar_pcie_hw_enable_msi(host);
return 0;
From: Srinivas Kandagatla srinivas.kandagatla@linaro.org
[ Upstream commit 6d5e7af1f6f5924de5dd1ebe97675c2363100878 ]
link_id can be zero and if we have multiple controller instances in a system like Qualcomm debugfs will end-up with duplicate namespace resulting in incorrect debugfs entries.
Using id should give a unique debugfs directory entry and should fix below warning too. "debugfs: Directory 'master-0' with parent 'soundwire' already present!"
Fixes: bf03473d5bcc ("soundwire: add debugfs support") Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210115162559.20869-1-srinivas.kandagatla@linaro.... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c index b6cad0d59b7b9..5f9efa42bb25b 100644 --- a/drivers/soundwire/debugfs.c +++ b/drivers/soundwire/debugfs.c @@ -19,7 +19,7 @@ void sdw_bus_debugfs_init(struct sdw_bus *bus) return;
/* create the debugfs master-N */ - snprintf(name, sizeof(name), "master-%d", bus->link_id); + snprintf(name, sizeof(name), "master-%d", bus->id); bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root); }
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit db9d9f944f95e7f3aa60ac00cbd502415152c421 ]
The existing code reports a NAK only when ACK=0 This is not aligned with the SoundWire 1.x specifications.
Table 32 in the SoundWire 1.2 specification shows that a Device shall not set NAK=1 if ACK=1. But Table 33 shows the Combined Response may very well be NAK=1/ACK=1, e.g. if another Device than the one addressed reports a parity error.
NAK=1 signals a 'Command_Aborted', regardless of the ACK bit value.
Move the tests for NAK so that the NAK=1/ACK=1 combination is properly detected according to the specification.
Fixes: 956baa1992f9a ('soundwire: cdns: Add sdw_master_ops and IO transfer support') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210115053738.22630-5-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/cadence_master.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 9fa55164354a2..580660599f461 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -484,10 +484,10 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns, if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { no_ack = 1; dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n"); - if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { - nack = 1; - dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); - } + } + if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { + nack = 1; + dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); } }
From: Simon South simon@simonsouth.net
[ Upstream commit d9b657a5cdbd960de35dee7e06473caf44a9016f ]
Commit 457f74abbed0 ("pwm: rockchip: Keep enabled PWMs running while probing") modified rockchip_pwm_probe() to access a PWM device's registers directly to check whether or not the device is enabled, but did not also change the function so it first enables the device's APB clock to be certain the device can respond. This risks hanging the kernel on systems with PWM devices that use more than a single clock.
Avoid this by enabling the device's APB clock before accessing its registers (and disabling the clock when register access is complete).
Fixes: 457f74abbed0 ("pwm: rockchip: Keep enabled PWMs running while probing") Reported-by: Thierry Reding thierry.reding@gmail.com Suggested-by: Trent Piepho tpiepho@gmail.com Signed-off-by: Simon South simon@simonsouth.net Signed-off-by: Thierry Reding thierry.reding@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pwm/pwm-rockchip.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 389a5e1404128..e6929bc739684 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -330,9 +330,9 @@ static int rockchip_pwm_probe(struct platform_device *pdev) return ret; }
- ret = clk_prepare(pc->pclk); + ret = clk_prepare_enable(pc->pclk); if (ret) { - dev_err(&pdev->dev, "Can't prepare APB clk: %d\n", ret); + dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); goto err_clk; }
@@ -362,10 +362,12 @@ static int rockchip_pwm_probe(struct platform_device *pdev) if ((ctrl & enable_conf) != enable_conf) clk_disable(pc->clk);
+ clk_disable(pc->pclk); + return 0;
err_pclk: - clk_unprepare(pc->pclk); + clk_disable_unprepare(pc->pclk); err_clk: clk_disable_unprepare(pc->clk);
From: Simon South simon@simonsouth.net
[ Upstream commit d5d8d675865ccddfe4da26c85f22c55cec663bf2 ]
If rockchip_pwm_probe() fails to register a PWM device it calls clk_unprepare() for the device's PWM clock, without having first disabled the clock and before jumping to an error handler that also unprepares it. This is likely to produce warnings from the kernel about the clock being unprepared when it is still enabled, and then being unprepared when it has already been unprepared.
Prevent these warnings by removing this unnecessary call to clk_unprepare().
Fixes: 48cf973cae33 ("pwm: rockchip: Avoid glitches on already running PWMs") Signed-off-by: Simon South simon@simonsouth.net Signed-off-by: Thierry Reding thierry.reding@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pwm/pwm-rockchip.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index e6929bc739684..90f969f9f5e2b 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -351,7 +351,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
ret = pwmchip_add(&pc->chip); if (ret < 0) { - clk_unprepare(pc->clk); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); goto err_pclk; }
From: Simon South simon@simonsouth.net
[ Upstream commit d21ba5d6217bd5a6a696678385906ed1994b380b ]
Commit 48cf973cae33 ("pwm: rockchip: Avoid glitches on already running PWMs") introduced a potential race condition in rockchip_pwm_probe(): A consumer could enable an inactive PWM, or disable a running one, between rockchip_pwm_probe() registering the device via pwmchip_add() and checking whether it is enabled (to determine whether it was started by a bootloader). This could result in a device's PWM clock being either enabled once more than necessary, potentially causing it to continue running when no longer needed, or disabled once more than necessary, producing a warning from the kernel.
Eliminate these possibilities by modifying rockchip_pwm_probe() so it checks whether a device is enabled before registering it rather than after.
Fixes: 48cf973cae33 ("pwm: rockchip: Avoid glitches on already running PWMs") Reported-by: Trent Piepho tpiepho@gmail.com Signed-off-by: Simon South simon@simonsouth.net Signed-off-by: Thierry Reding thierry.reding@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pwm/pwm-rockchip.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 90f969f9f5e2b..f3a5641f6bca5 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -288,6 +288,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) const struct of_device_id *id; struct rockchip_pwm_chip *pc; u32 enable_conf, ctrl; + bool enabled; int ret, count;
id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); @@ -349,6 +350,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev) pc->chip.of_pwm_n_cells = 3; }
+ enable_conf = pc->data->enable_conf; + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); + enabled = (ctrl & enable_conf) == enable_conf; + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); @@ -356,9 +361,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) }
/* Keep the PWM clk enabled if the PWM appears to be up and running. */ - enable_conf = pc->data->enable_conf; - ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); - if ((ctrl & enable_conf) != enable_conf) + if (!enabled) clk_disable(pc->clk);
clk_disable(pc->pclk);
From: Pan Bian bianpan2016@163.com
[ Upstream commit ae191d2e513ae5274224777ae67018a584074a28 ]
Also drop the reference count of the node on error path.
Link: https://lore.kernel.org/r/20210120143745.699-1-bianpan2016@163.com Fixes: 508f610648b9 ("PCI: xilinx-cpm: Add Versal CPM Root Port driver") Signed-off-by: Pan Bian bianpan2016@163.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-xilinx-cpm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/pcie-xilinx-cpm.c b/drivers/pci/controller/pcie-xilinx-cpm.c index f92e0152e65e3..67937facd90cd 100644 --- a/drivers/pci/controller/pcie-xilinx-cpm.c +++ b/drivers/pci/controller/pcie-xilinx-cpm.c @@ -404,6 +404,7 @@ static int xilinx_cpm_pcie_init_irq_domain(struct xilinx_cpm_pcie_port *port) return 0; out: xilinx_cpm_free_irq_domains(port); + of_node_put(pcie_intc_node); dev_err(dev, "Failed to allocate IRQ domains\n");
return -ENOMEM;
From: Jorgen Hansen jhansen@vmware.com
[ Upstream commit 5a16c535409f8dcb7568e20737309e3027ae3e49 ]
When the VMCI host support releases guest memory in the case where the VM was killed, the pinned guest pages aren't locked. Use set_page_dirty_lock() instead of set_page_dirty().
Testing done: Killed VM while having an active VMCI based vSocket connection and observed warning from ext4. With this fix, no warning was observed. Ran various vSocket tests without issues.
Fixes: 06164d2b72aa ("VMCI: queue pairs implementation.") Reviewed-by: Vishnu Dasa vdasa@vmware.com Signed-off-by: Jorgen Hansen jhansen@vmware.com Link: https://lore.kernel.org/r/1611160360-30299-1-git-send-email-jhansen@vmware.c... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/vmw_vmci/vmci_queue_pair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index c49065887e8f5..df6b19c4c49b5 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -630,7 +630,7 @@ static void qp_release_pages(struct page **pages,
for (i = 0; i < num_pages; i++) { if (dirty) - set_page_dirty(pages[i]); + set_page_dirty_lock(pages[i]);
put_page(pages[i]); pages[i] = NULL;
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit ef9e4005cbaf022c6251263aa27836acccaef65d ]
After 34e3207205ef ("PCI: handle positive error codes"), pci_user_read_config_*() and pci_user_write_config_*() return 0 or negative errno values, not PCIBIOS_* values like PCIBIOS_SUCCESSFUL or PCIBIOS_BAD_REGISTER_NUMBER.
Remove comparisons with PCIBIOS_SUCCESSFUL and check only for non-zero. It happens that PCIBIOS_SUCCESSFUL is zero, so this is not a functional change, but it aligns this code with the user accessors.
[bhelgaas: commit log] Fixes: 34e3207205ef ("PCI: handle positive error codes") Link: https://lore.kernel.org/r/f1220314-e518-1e18-bf94-8e6f8c703758@gmail.com Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/syscall.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index 31e39558d49d8..8b003c890b87b 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -20,7 +20,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, u16 word; u32 dword; long err; - long cfg_ret; + int cfg_ret;
if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -46,7 +46,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, }
err = -EIO; - if (cfg_ret != PCIBIOS_SUCCESSFUL) + if (cfg_ret) goto error;
switch (len) { @@ -105,7 +105,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_byte(dev, off, byte); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break;
@@ -114,7 +114,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_word(dev, off, word); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break;
@@ -123,7 +123,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_dword(dev, off, dword); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break;
From: Alexander Usyskin alexander.usyskin@intel.com
[ Upstream commit 3a77df62deb2e62de0dc26c1cb763cc152329287 ]
Use mei_set_devstate() wrapper upon hbm stop command response, to trigger sysfs event.
Fixes: 43b8a7ed4739 ("mei: expose device state in sysfs") Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210129120752.850325-3-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/mei/hbm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 686e8b6a4c55e..0cba3c6dfb148 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1373,7 +1373,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) return -EPROTO; }
- dev->dev_state = MEI_DEV_POWER_DOWN; + mei_set_devstate(dev, MEI_DEV_POWER_DOWN); dev_info(dev->dev, "hbm: stop response: resetting.\n"); /* force the reset */ return -EPROTO;
From: Iskren Chernev iskren.chernev@gmail.com
[ Upstream commit 6cefa31e810404dafdfcdb94874146cea11626c2 ]
The msm_gem_get_iova should be guarded with gpu != NULL and not aspace != NULL, because aspace is NULL when using vram carveout.
Fixes: 933415e24bd0d ("drm/msm: Add support for private address space instances")
Signed-off-by: Iskren Chernev iskren.chernev@gmail.com Tested-by: Alexey Minnekhanov alexeymin@postmarketos.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/msm_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 108c405e03dd9..94525ac76d4e6 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -788,9 +788,10 @@ static int msm_ioctl_gem_info_iova(struct drm_device *dev, struct drm_file *file, struct drm_gem_object *obj, uint64_t *iova) { + struct msm_drm_private *priv = dev->dev_private; struct msm_file_private *ctx = file->driver_priv;
- if (!ctx->aspace) + if (!priv->gpu) return -EINVAL;
/*
From: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org
[ Upstream commit 276619c0923f8fa6a82e60edb88a82468645362d ]
Domain attribute setting for LLCC is guarded by !IS_ERR check which works fine only when CONFIG_QCOM_LLCC=y but when it is disabled, the LLCC apis return NULL and that is not handled by IS_ERR check. Due to this, domain attribute for LLCC will be set even on GPUs which do not support it and cause issues, so correct this by using IS_ERR_OR_NULL checks appropriately. Meanwhile also cleanup comment block and remove unwanted blank line.
Fixes: 00fd44a1a470 ("drm/msm: Only enable A6xx LLCC code on A6xx") Fixes: 474dadb8b0d5 ("drm/msm/a6xx: Add support for using system cache(LLC)") Signed-off-by: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 130661898546a..3b798e883f822 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1117,7 +1117,7 @@ static void a6xx_llc_slices_init(struct platform_device *pdev, a6xx_gpu->llc_slice = llcc_slice_getd(LLCC_GPU); a6xx_gpu->htw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
- if (IS_ERR(a6xx_gpu->llc_slice) && IS_ERR(a6xx_gpu->htw_llc_slice)) + if (IS_ERR_OR_NULL(a6xx_gpu->llc_slice) && IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice)) a6xx_gpu->llc_mmio = ERR_PTR(-EINVAL); }
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index f09175698827a..b35914de1b275 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -200,15 +200,15 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, if (!iommu) return NULL;
- if (adreno_is_a6xx(adreno_gpu)) { struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct io_pgtable_domain_attr pgtbl_cfg; + /* - * This allows GPU to set the bus attributes required to use system - * cache on behalf of the iommu page table walker. - */ - if (!IS_ERR(a6xx_gpu->htw_llc_slice)) { + * This allows GPU to set the bus attributes required to use system + * cache on behalf of the iommu page table walker. + */ + if (!IS_ERR_OR_NULL(a6xx_gpu->htw_llc_slice)) { pgtbl_cfg.quirks = IO_PGTABLE_QUIRK_ARM_OUTER_WBWA; iommu_domain_set_attr(iommu, DOMAIN_ATTR_IO_PGTABLE_CFG, &pgtbl_cfg); }
From: Konrad Dybcio konrad.dybcio@somainline.org
[ Upstream commit 33a7808ce1aea6e2edc1af25db25928137940c02 ]
The previous registers were *almost* correct, but instead of PHYs, they were pointing at DSI PLLs, resulting in the PHY id autodetection failing miserably.
Fixes: dcefc117cc19 ("drm/msm/dsi: Add support for msm8x94") Signed-off-by: Konrad Dybcio konrad.dybcio@somainline.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c index 1afb7c579dbbb..eca86bf448f74 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c @@ -139,7 +139,7 @@ const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { .disable = dsi_20nm_phy_disable, .init = msm_dsi_phy_init_common, }, - .io_start = { 0xfd998300, 0xfd9a0300 }, + .io_start = { 0xfd998500, 0xfd9a0500 }, .num_dsi_phy = 2, };
From: Iskren Chernev iskren.chernev@gmail.com
[ Upstream commit 68e4f01fddb4ead80e8c7084db489307f22c9cbb ]
Before the offending commit in msm_atomic_commit_tail wait_flush was called once per frame, after the commit was submitted. After it wait_flush is also called at the beginning to ensure previous potentially async commits are done.
For cmd panels the source of wait_flush is a ping-pong irq notifying a completion. The completion needs to be notified with complete_all so multiple waiting parties (new async committers) can proceed.
Signed-off-by: Iskren Chernev iskren.chernev@gmail.com Suggested-by: Rob Clark robdclark@gmail.com Fixes: 2d99ced787e3d ("drm/msm: async commit support") Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 0c8f9f88301fa..f5d71b2740793 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -1180,7 +1180,7 @@ static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus) struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, pp_done);
- complete(&mdp5_crtc->pp_completion); + complete_all(&mdp5_crtc->pp_completion); }
static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
From: Eric Anholt eric@anholt.net
[ Upstream commit 7a7cbf2a819740674455ad36155c662367261296 ]
We were using the same force-poweron bit in the two codepaths, so they could race to have one of them lose GPU power early.
freedreno CI was seeing intermittent errors like: [drm:_a6xx_gmu_set_oob] *ERROR* Timeout waiting for GMU OOB set GPU_SET: 0x0 and this issue could have contributed to it.
Signed-off-by: Eric Anholt eric@anholt.net Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support") Reviewed-by: Jordan Crouse jcrouse@codeaurora.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 ++++++++++++++++++++++--- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 ++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++-- 3 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index e6703ae987608..b3318f86aabc0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -264,6 +264,16 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) } name = "GPU_SET"; break; + case GMU_OOB_PERFCOUNTER_SET: + if (gmu->legacy) { + request = GMU_OOB_PERFCOUNTER_REQUEST; + ack = GMU_OOB_PERFCOUNTER_ACK; + } else { + request = GMU_OOB_PERFCOUNTER_REQUEST_NEW; + ack = GMU_OOB_PERFCOUNTER_ACK_NEW; + } + name = "PERFCOUNTER"; + break; case GMU_OOB_BOOT_SLUMBER: request = GMU_OOB_BOOT_SLUMBER_REQUEST; ack = GMU_OOB_BOOT_SLUMBER_ACK; @@ -301,9 +311,14 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { if (!gmu->legacy) { - WARN_ON(state != GMU_OOB_GPU_SET); - gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, - 1 << GMU_OOB_GPU_SET_CLEAR_NEW); + if (state == GMU_OOB_GPU_SET) { + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, + 1 << GMU_OOB_GPU_SET_CLEAR_NEW); + } else { + WARN_ON(state != GMU_OOB_PERFCOUNTER_SET); + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, + 1 << GMU_OOB_PERFCOUNTER_CLEAR_NEW); + } return; }
@@ -312,6 +327,10 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << GMU_OOB_GPU_SET_CLEAR); break; + case GMU_OOB_PERFCOUNTER_SET: + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, + 1 << GMU_OOB_PERFCOUNTER_CLEAR); + break; case GMU_OOB_BOOT_SLUMBER: gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << GMU_OOB_BOOT_SLUMBER_CLEAR); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index c6d2bced8e5de..9fa278de2106a 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -156,6 +156,7 @@ enum a6xx_gmu_oob_state { GMU_OOB_BOOT_SLUMBER = 0, GMU_OOB_GPU_SET, GMU_OOB_DCVS_SET, + GMU_OOB_PERFCOUNTER_SET, };
/* These are the interrupt / ack bits for each OOB request that are set @@ -190,6 +191,13 @@ enum a6xx_gmu_oob_state { #define GMU_OOB_GPU_SET_ACK_NEW 31 #define GMU_OOB_GPU_SET_CLEAR_NEW 31
+#define GMU_OOB_PERFCOUNTER_REQUEST 17 +#define GMU_OOB_PERFCOUNTER_ACK 25 +#define GMU_OOB_PERFCOUNTER_CLEAR 25 + +#define GMU_OOB_PERFCOUNTER_REQUEST_NEW 28 +#define GMU_OOB_PERFCOUNTER_ACK_NEW 30 +#define GMU_OOB_PERFCOUNTER_CLEAR_NEW 30
void a6xx_hfi_init(struct a6xx_gmu *gmu); int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 3b798e883f822..2dc6b342cf9b5 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1171,12 +1171,12 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
/* Force the GPU power on so we can read this register */ - a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
*value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO, REG_A6XX_RBBM_PERFCTR_CP_0_HI);
- a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); return 0; }
From: Eric Anholt eric@anholt.net
[ Upstream commit 5f98b33b04c02c0d9088c7486c59d058696782f9 ]
Now that we're not racing with GPU setup, also fix races of timestamps against other timestamps. In freedreno CI, we were seeing this path trigger timeouts on setting the GMU bit, producing:
[drm:_a6xx_gmu_set_oob] *ERROR* Timeout waiting for GMU OOB set GPU_SET: 0x0
and this triggered especially on the first set of tests right after boot (it's probably easier to lose the race than one might think, given that we start many tests in parallel, and waiting for NFS to page in code probably means that lots of tests hit the same point of screen init at the same time). As of this patch, the message seems to have completely gone away.
Signed-off-by: Eric Anholt eric@anholt.net Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support") Reviewed-by: Jordan Crouse jcrouse@codeaurora.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 2dc6b342cf9b5..0366419d8bfed 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1169,6 +1169,9 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + static DEFINE_MUTEX(perfcounter_oob); + + mutex_lock(&perfcounter_oob);
/* Force the GPU power on so we can read this register */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); @@ -1177,6 +1180,7 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) REG_A6XX_RBBM_PERFCTR_CP_0_HI);
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); + mutex_unlock(&perfcounter_oob); return 0; }
From: Stephen Boyd swboyd@chromium.org
[ Upstream commit 6ec9351809612fa1c0256fb3e39b49b6100e2983 ]
Lockdep complains about an AA deadlock when rebooting the device.
base-commit: 19c329f6808995b142b3966301f217c831e7cf31
============================================ WARNING: possible recursive locking detected 5.4.91 #1 Not tainted -------------------------------------------- reboot/5213 is trying to acquire lock: ffffff80d13391b0 (&kms->commit_lock[i]){+.+.}, at: lock_crtcs+0x60/0xa4
but task is already holding lock: ffffff80d1339110 (&kms->commit_lock[i]){+.+.}, at: lock_crtcs+0x60/0xa4
other info that might help us debug this: Possible unsafe locking scenario:
CPU0 ---- lock(&kms->commit_lock[i]); lock(&kms->commit_lock[i]);
*** DEADLOCK ***
May be due to missing lock nesting notation
6 locks held by reboot/5213: __arm64_sys_reboot+0x148/0x2a0 device_shutdown+0x10c/0x2c4 drm_atomic_helper_shutdown+0x48/0xfc modeset_lock+0x120/0x24c lock_crtcs+0x60/0xa4
stack backtrace: CPU: 4 PID: 5213 Comm: reboot Not tainted 5.4.91 #1 Hardware name: Google Pompom (rev1) with LTE (DT) Call trace: dump_backtrace+0x0/0x1dc show_stack+0x24/0x30 dump_stack+0xfc/0x1a8 __lock_acquire+0xcd0/0x22b8 lock_acquire+0x1ec/0x240 __mutex_lock_common+0xe0/0xc84 mutex_lock_nested+0x48/0x58 lock_crtcs+0x60/0xa4 msm_atomic_commit_tail+0x348/0x570 commit_tail+0xdc/0x178 drm_atomic_helper_commit+0x160/0x168 drm_atomic_commit+0x68/0x80
This is because lockdep thinks all the locks taken in lock_crtcs() are the same lock, when they actually aren't. That's because we call mutex_init() in msm_kms_init() and that assigns one static key for every lock initialized in this loop. Let's allocate a dynamic number of lock_class_keys and assign them to each lock so that lockdep can figure out an AA deadlock isn't possible here.
Fixes: b3d91800d9ac ("drm/msm: Fix race condition in msm driver with async layer updates") Cc: Krishna Manikandan mkrishn@codeaurora.org Signed-off-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/msm_kms.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index d8151a89e1631..4735251a394d8 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -157,6 +157,7 @@ struct msm_kms { * from the crtc's pending_timer close to end of the frame: */ struct mutex commit_lock[MAX_CRTCS]; + struct lock_class_key commit_lock_keys[MAX_CRTCS]; unsigned pending_crtc_mask; struct msm_pending_timer pending_timers[MAX_CRTCS]; }; @@ -166,8 +167,11 @@ static inline int msm_kms_init(struct msm_kms *kms, { unsigned i, ret;
- for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++) - mutex_init(&kms->commit_lock[i]); + for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++) { + lockdep_register_key(&kms->commit_lock_keys[i]); + __mutex_init(&kms->commit_lock[i], "&kms->commit_lock[i]", + &kms->commit_lock_keys[i]); + }
kms->funcs = funcs;
From: Judy Hsiao judyhsiao@google.com
[ Upstream commit c703d5789590935c573bbd080a2166b72d51a017 ]
1. Trigger the unplug event in msm_dp_display_disable() to shutdown audio properly. 2. Reset the completion before signal the disconnect event.
Fixes: 158b9aa74479 ("drm/msm/dp: wait for audio notification before disabling clocks") Reviewed-by: Stephen Boyd swboyd@chromium.org Tested-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Judy Hsiao judyhsiao@chromium.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 3bc7ed21de286..81f6794a25100 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -651,8 +651,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
/* signal the disconnect event early to ensure proper teardown */ - dp_display_handle_plugged_change(g_dp_display, false); reinit_completion(&dp->audio_comp); + dp_display_handle_plugged_change(g_dp_display, false);
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, true); @@ -890,6 +890,9 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
/* wait only if audio was enabled */ if (dp_display->audio_enabled) { + /* signal the disconnect event */ + reinit_completion(&dp->audio_comp); + dp_display_handle_plugged_change(dp_display, false); if (!wait_for_completion_timeout(&dp->audio_comp, HZ * 5)) DRM_ERROR("audio comp timeout\n");
From: Keqian Zhu zhukeqian1@huawei.com
[ Upstream commit d0a78f91761fcd837da1e7a4b0f8368873adc646 ]
If a group with non-pinned-page dirty scope is detached with dirty logging enabled, we should fully populate the dirty bitmaps at the time it's removed since we don't know the extent of its previous DMA, nor will the group be present to trigger the full bitmap when the user retrieves the dirty bitmap.
Fixes: d6a4c185660c ("vfio iommu: Implementation of ioctl for dirty pages tracking") Suggested-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Keqian Zhu zhukeqian1@huawei.com Signed-off-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vfio/vfio_iommu_type1.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 0b4dedaa91289..161725395f2fb 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -236,6 +236,18 @@ static void vfio_dma_populate_bitmap(struct vfio_dma *dma, size_t pgsize) } }
+static void vfio_iommu_populate_bitmap_full(struct vfio_iommu *iommu) +{ + struct rb_node *n; + unsigned long pgshift = __ffs(iommu->pgsize_bitmap); + + for (n = rb_first(&iommu->dma_list); n; n = rb_next(n)) { + struct vfio_dma *dma = rb_entry(n, struct vfio_dma, node); + + bitmap_set(dma->bitmap, 0, dma->size >> pgshift); + } +} + static int vfio_dma_bitmap_alloc_all(struct vfio_iommu *iommu, size_t pgsize) { struct rb_node *n; @@ -2415,8 +2427,11 @@ detach_group_done: * Removal of a group without dirty tracking may allow the iommu scope * to be promoted. */ - if (update_dirty_scope) + if (update_dirty_scope) { update_pinned_page_dirty_scope(iommu); + if (iommu->dirty_page_tracking) + vfio_iommu_populate_bitmap_full(iommu); + } mutex_unlock(&iommu->lock); }
From: Keqian Zhu zhukeqian1@huawei.com
[ Upstream commit 4a19f37a3dd3f29997735e61b25ddad24b8abe73 ]
vfio_sanity_check_pfn_list() is used to check whether pfn_list and notifier are empty when remove the external domain, so it makes a wrong assumption that only external domain will use the pinning interface.
Now we apply the pfn_list check when a vfio_dma is removed and apply the notifier check when all domains are removed.
Fixes: a54eb55045ae ("vfio iommu type1: Add support for mediated devices") Signed-off-by: Keqian Zhu zhukeqian1@huawei.com Signed-off-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vfio/vfio_iommu_type1.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 161725395f2fb..78bd28873945a 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -957,6 +957,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma) { + WARN_ON(!RB_EMPTY_ROOT(&dma->pfn_list)); vfio_unmap_unpin(iommu, dma, true); vfio_unlink_dma(iommu, dma); put_task_struct(dma->task); @@ -2250,23 +2251,6 @@ static void vfio_iommu_unmap_unpin_reaccount(struct vfio_iommu *iommu) } }
-static void vfio_sanity_check_pfn_list(struct vfio_iommu *iommu) -{ - struct rb_node *n; - - n = rb_first(&iommu->dma_list); - for (; n; n = rb_next(n)) { - struct vfio_dma *dma; - - dma = rb_entry(n, struct vfio_dma, node); - - if (WARN_ON(!RB_EMPTY_ROOT(&dma->pfn_list))) - break; - } - /* mdev vendor driver must unregister notifier */ - WARN_ON(iommu->notifier.head); -} - /* * Called when a domain is removed in detach. It is possible that * the removed domain decided the iova aperture window. Modify the @@ -2366,10 +2350,10 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, kfree(group);
if (list_empty(&iommu->external_domain->group_list)) { - vfio_sanity_check_pfn_list(iommu); - - if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) + if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) { + WARN_ON(iommu->notifier.head); vfio_iommu_unmap_unpin_all(iommu); + }
kfree(iommu->external_domain); iommu->external_domain = NULL; @@ -2403,10 +2387,12 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, */ if (list_empty(&domain->group_list)) { if (list_is_singular(&iommu->domain_list)) { - if (!iommu->external_domain) + if (!iommu->external_domain) { + WARN_ON(iommu->notifier.head); vfio_iommu_unmap_unpin_all(iommu); - else + } else { vfio_iommu_unmap_unpin_reaccount(iommu); + } } iommu_domain_free(domain->domain); list_del(&domain->next); @@ -2490,7 +2476,6 @@ static void vfio_iommu_type1_release(void *iommu_data)
if (iommu->external_domain) { vfio_release_domain(iommu->external_domain, true); - vfio_sanity_check_pfn_list(iommu); kfree(iommu->external_domain); }
From: Max Gurtovoy mgurtovoy@nvidia.com
[ Upstream commit 7e31d6dc2c78b2a0ba0039ca97ca98a581e8db82 ]
In case allocation fails, we must behave correctly and exit with error.
Fixes: e6b817d4b821 ("vfio-pci/zdev: Add zPCI capabilities to VFIO_DEVICE_GET_INFO") Signed-off-by: Max Gurtovoy mgurtovoy@nvidia.com Reviewed-by: Cornelia Huck cohuck@redhat.com Reviewed-by: Matthew Rosato mjrosato@linux.ibm.com Signed-off-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vfio/pci/vfio_pci_zdev.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c index 2296856340311..1bb7edac56899 100644 --- a/drivers/vfio/pci/vfio_pci_zdev.c +++ b/drivers/vfio/pci/vfio_pci_zdev.c @@ -74,6 +74,8 @@ static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_pci_device *vdev, int ret;
cap = kmalloc(cap_size, GFP_KERNEL); + if (!cap) + return -ENOMEM;
cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL; cap->header.version = 1; @@ -98,6 +100,8 @@ static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_pci_device *vdev, int ret;
cap = kmalloc(cap_size, GFP_KERNEL); + if (!cap) + return -ENOMEM;
cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP; cap->header.version = 1;
From: Theodore Ts'o tytso@mit.edu
[ Upstream commit b5776e7524afbd4569978ff790864755c438bba7 ]
In the case where we need to do an interior node split, and immediately afterwards, we are unable to allocate a new directory leaf block due to ENOSPC, the directory index checksum's will not be filled in correctly (and indeed, will not be correctly journalled).
This looks like a bug that was introduced when we added largedir support. The original code doesn't make any sense (and should have been caught in code review), but it was hidden because most of the time, the index node checksum will be set by do_split(). But if do_split bails out due to ENOSPC, then ext4_handle_dirty_dx_node() won't get called, and so the directory index checksum field will not get set, leading to:
EXT4-fs error (device sdb): dx_probe:858: inode #6635543: block 4022: comm nfsd: Directory index failed checksum
Google-Bug-Id: 176345532 Fixes: e08ac99fa2a2 ("ext4: add largedir feature") Cc: Artem Blagodarenko artem.blagodarenko@gmail.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ext4/namei.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index cf652ba3e74d2..df0368d578b16 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2401,11 +2401,10 @@ again: (frame - 1)->bh); if (err) goto journal_error; - if (restart) { - err = ext4_handle_dirty_dx_node(handle, dir, - frame->bh); + err = ext4_handle_dirty_dx_node(handle, dir, + frame->bh); + if (err) goto journal_error; - } } else { struct dx_root *dxroot; memcpy((char *) entries2, (char *) entries,
From: Geert Uytterhoeven geert+renesas@glider.be
[ Upstream commit 6b46e60a6943d629d69924be3169d8f214624ab2 ]
The Intel Lightning Mountain (LGM) USB3 USB is only present on Intel Lightning Mountain SoCs. Hence add a dependency on X86, to prevent asking the user about this driver when configuring a kernel without Intel Lightning Mountain platform support.
Fixes: 1cce8f73a561c944 ("phy: Add USB3 PHY support for Intel LGM SoC") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Link: https://lore.kernel.org/r/20210129131753.2656306-1-geert+renesas@glider.be Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 00dabe5fab8a0..68d9c2f6a5caf 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -52,6 +52,7 @@ config PHY_XGENE config USB_LGM_PHY tristate "INTEL Lightning Mountain USB PHY Driver" depends on USB_SUPPORT + depends on X86 || COMPILE_TEST select USB_PHY select REGULATOR select REGULATOR_FIXED_VOLTAGE
From: Suzuki K Poulose suzuki.poulose@arm.com
[ Upstream commit df81b43802f43c0954a55e5d513e8750a1ab4d31 ]
When the ETM is affected by Qualcomm errata, modifying the TRCPDCR could cause the system hang. Even though this is taken care of during enable/disable ETM, the ETM state save/restore could still access the TRCPDCR. Make sure we skip the access during the save/restore.
Found by code inspection.
Link: https://lore.kernel.org/r/20210110224850.1880240-3-suzuki.poulose@arm.com Fixes: 02510a5aa78d ("coresight: etm4x: Add support to skip trace unit power up") Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Cc: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org Cc: Tingwei Zhang tingwei@codeaurora.org Tested-by: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org Reviewed-by: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Signed-off-by: Mathieu Poirier mathieu.poirier@linaro.org Link: https://lore.kernel.org/r/20210201181351.1475223-5-mathieu.poirier@linaro.or... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hwtracing/coresight/coresight-etm4x-core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index b20b6ff17cf65..200fa1c8aa0be 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -1355,7 +1355,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);
- state->trcpdcr = readl(drvdata->base + TRCPDCR); + if (!drvdata->skip_power_up) + state->trcpdcr = readl(drvdata->base + TRCPDCR);
/* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { @@ -1373,9 +1374,9 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) * potentially save power on systems that respect the TRCPDCR_PU * despite requesting software to save/restore state. */ - writel_relaxed((state->trcpdcr & ~TRCPDCR_PU), - drvdata->base + TRCPDCR); - + if (!drvdata->skip_power_up) + writel_relaxed((state->trcpdcr & ~TRCPDCR_PU), + drvdata->base + TRCPDCR); out: CS_LOCK(drvdata->base); return ret; @@ -1469,7 +1470,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
- writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR); + if (!drvdata->skip_power_up) + writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR);
drvdata->state_needs_restore = false;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 72e008ce307fa2f35f6783997378b32e83122839 ]
This doesn't call of_node_put() on the error path so it leads to a memory leak.
Fixes: 0749aa25af82 ("nvmem: core: fix regression in of_nvmem_cell_get()") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210129171430.11328-2-srinivas.kandagatla@linaro.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvmem/core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 177f5bf27c6d5..68ae6f24b57fd 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -713,6 +713,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) cell->name, nvmem->stride); /* Cells already added will be freed later. */ kfree_const(cell->name); + of_node_put(cell->np); kfree(cell); return -EINVAL; }
From: Ahmad Fatoum a.fatoum@pengutronix.de
[ Upstream commit 0445efacec75b85c2a3c176957ee050ba9be53f0 ]
The nvmem cell binding applies to all eeprom child nodes matching "^.*@[0-9a-f]+$" without taking a compatible into account.
Linux drivers, like at24, are even more extensive and assume _all_ at24 eeprom child nodes to be nvmem cells since e888d445ac33 ("nvmem: resolve cells from DT at registration time").
Since df5f3b6f5357 ("dt-bindings: nvmem: stm32: new property for data access"), the additionalProperties: True means it's Ok to have other properties as long as they don't match "^.*@[0-9a-f]+$".
The barebox bootloader extends the MTD partitions binding to EEPROM and can fix up following device tree node:
&eeprom { partitions { compatible = "fixed-partitions"; }; };
This is allowed binding-wise, but drivers using nvmem_register() like at24 will fail to parse because the function expects all child nodes to have a reg property present. This results in the whole EEPROM driver probe failing despite the device tree being correct.
Fix this by skipping nodes lacking a reg property instead of returning an error. This effectively makes the drivers adhere to the binding because all nodes with a unit address must have a reg property and vice versa.
Fixes: e888d445ac33 ("nvmem: resolve cells from DT at registration time"). Signed-off-by: Ahmad Fatoum a.fatoum@pengutronix.de Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210129171430.11328-6-srinivas.kandagatla@linaro.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvmem/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 68ae6f24b57fd..a5ab1e0c74cf6 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -682,7 +682,9 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
for_each_child_of_node(parent, child) { addr = of_get_property(child, "reg", &len); - if (!addr || (len < 2 * sizeof(u32))) { + if (!addr) + continue; + if (len < 2 * sizeof(u32)) { dev_err(dev, "nvmem: invalid reg on %pOF\n", child); return -EINVAL; }
From: Rob Clark robdclark@chromium.org
[ Upstream commit c8d99bb938d3303989c4988caf090084073e85a2 ]
In moving code around, we ended up using the same pointer to copy_from_user() the relocs tables as we used for the cmd table entry, which is clearly not right. This went unnoticed because modern mesa on non-ancent kernels does not actually use relocs. But this broke ancient mesa on modern kernels.
Reported-by: Emil Velikov emil.velikov@collabora.com Fixes: 20224d715a88 ("drm/msm/submit: Move copy_from_user ahead of locking bos") Signed-off-by: Rob Clark robdclark@chromium.org Reviewed-by: Akhil P Oommen akhilpo@codeaurora.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/msm_gem_submit.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index d04c349d8112a..5480852bdedaf 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -198,6 +198,8 @@ static int submit_lookup_cmds(struct msm_gem_submit *submit, submit->cmd[i].idx = submit_cmd.submit_idx; submit->cmd[i].nr_relocs = submit_cmd.nr_relocs;
+ userptr = u64_to_user_ptr(submit_cmd.relocs); + sz = array_size(submit_cmd.nr_relocs, sizeof(struct drm_msm_gem_submit_reloc)); /* check for overflow: */
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit b04c975e654cfdea6d691cd403b5a81cce7e593d ]
When a Slave device is resumed, it may resume the bus and restart the enumeration. During that process, we absolutely don't want to call regular read/write routines which will wait for the resume to complete, otherwise a deadlock occurs.
Fixes: 60ee9be25571 ('soundwire: bus: add PM/no-PM versions of read/write functions') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rander Wang rander.wang@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210122070634.12825-2-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index d1e8c3a54976b..60c42508c6c6b 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -489,6 +489,18 @@ sdw_read_no_pm(struct sdw_slave *slave, u32 addr) return buf; }
+static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) +{ + int tmp; + + tmp = sdw_read_no_pm(slave, addr); + if (tmp < 0) + return tmp; + + tmp = (tmp & ~mask) | val; + return sdw_write_no_pm(slave, addr, tmp); +} + /** * sdw_nread() - Read "n" contiguous SDW Slave registers * @slave: SDW Slave @@ -1256,7 +1268,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave) val = slave->prop.scp_int1_mask;
/* Enable SCP interrupts */ - ret = sdw_update(slave, SDW_SCP_INTMASK1, val, val); + ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1, val, val); if (ret < 0) { dev_err(slave->bus->dev, "SDW_SCP_INTMASK1 write failed:%d\n", ret); @@ -1271,7 +1283,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave) val = prop->dp0_prop->imp_def_interrupts; val |= SDW_DP0_INT_PORT_READY | SDW_DP0_INT_BRA_FAILURE;
- ret = sdw_update(slave, SDW_DP0_INTMASK, val, val); + ret = sdw_update_no_pm(slave, SDW_DP0_INTMASK, val, val); if (ret < 0) dev_err(slave->bus->dev, "SDW_DP0_INTMASK read failed:%d\n", ret);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 299e9780b9196bcb15b26dfdccd3244eb072d560 ]
When a Slave device is resumed, it may resume the bus and restart the enumeration. During that process, we absolutely don't want to call regular read/write routines which will wait for the resume to complete, otherwise a deadlock occurs.
This patch fixes the same problem as the previous one, but is split to make the life of linux-stable maintainers less painful.
Fixes: 29d158f90690 ('soundwire: bus: initialize bus clock base and scale registers') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rander Wang rander.wang@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210122070634.12825-3-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 60c42508c6c6b..b1830032b0522 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1222,7 +1222,7 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave) } scale_index++;
- ret = sdw_write(slave, SDW_SCP_BUS_CLOCK_BASE, base); + ret = sdw_write_no_pm(slave, SDW_SCP_BUS_CLOCK_BASE, base); if (ret < 0) { dev_err(&slave->dev, "SDW_SCP_BUS_CLOCK_BASE write failed:%d\n", ret); @@ -1230,13 +1230,13 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave) }
/* initialize scale for both banks */ - ret = sdw_write(slave, SDW_SCP_BUSCLOCK_SCALE_B0, scale_index); + ret = sdw_write_no_pm(slave, SDW_SCP_BUSCLOCK_SCALE_B0, scale_index); if (ret < 0) { dev_err(&slave->dev, "SDW_SCP_BUSCLOCK_SCALE_B0 write failed:%d\n", ret); return ret; } - ret = sdw_write(slave, SDW_SCP_BUSCLOCK_SCALE_B1, scale_index); + ret = sdw_write_no_pm(slave, SDW_SCP_BUSCLOCK_SCALE_B1, scale_index); if (ret < 0) dev_err(&slave->dev, "SDW_SCP_BUSCLOCK_SCALE_B1 write failed:%d\n", ret);
From: Bard Liao yung-chuan.liao@linux.intel.com
[ Upstream commit 167790abb90fa073d8341ee0e408ccad3d2109cd ]
sdw_write_no_pm and sdw_read_no_pm are useful when we want to do IO without touching PM.
Fixes: 0231453bc08f ('soundwire: bus: add clock stop helpers') Fixes: 60ee9be25571 ('soundwire: bus: add PM/no-PM versions of read/write functions') Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210122070634.12825-5-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 7 ++++--- include/linux/soundwire/sdw.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index b1830032b0522..483d5a389c92a 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -405,10 +405,11 @@ sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) return sdw_transfer(slave->bus, &msg); }
-static int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value) +int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value) { return sdw_nwrite_no_pm(slave, addr, 1, &value); } +EXPORT_SYMBOL(sdw_write_no_pm);
static int sdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr) @@ -476,8 +477,7 @@ int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 val } EXPORT_SYMBOL(sdw_bwrite_no_pm_unlocked);
-static int -sdw_read_no_pm(struct sdw_slave *slave, u32 addr) +int sdw_read_no_pm(struct sdw_slave *slave, u32 addr) { u8 buf; int ret; @@ -488,6 +488,7 @@ sdw_read_no_pm(struct sdw_slave *slave, u32 addr) else return buf; } +EXPORT_SYMBOL(sdw_read_no_pm);
static int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) { diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index f0b01b728640d..d08039d65825e 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -1005,6 +1005,8 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus);
int sdw_read(struct sdw_slave *slave, u32 addr); int sdw_write(struct sdw_slave *slave, u32 addr, u8 value); +int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value); +int sdw_read_no_pm(struct sdw_slave *slave, u32 addr); int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val); int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 973794e85610d9a716a897baa9007ff56e192826 ]
Intel stress-tests routinely report IO timeouts and invalid power management transitions. Upon further analysis, we seem to be using the wrong devices in pm_runtime calls.
Before reading and writing registers, we first need to make sure the Slave is fully resumed. The existing code attempts to do such that, however because of a confusion dating from 2017 and copy/paste, we end-up resuming the parent only instead of resuming the codec device.
This can lead to accesses to the Slave registers while the bus is still being configured and the Slave not enumerated, and as a result IO errors occur.
This is a classic problem, similar confusions happened for HDaudio between bus and codec device, leading to power management issues.
Fix by using the relevant device for all uses of pm_runtime functions.
Fixes: 60ee9be255712 ('soundwire: bus: add PM/no-PM versions of read/write functions') Fixes: aa79293517b39 ('soundwire: bus: fix io error when processing alert event') Fixes: 9d715fa005ebc ('soundwire: Add IO transfer') Reported-by: Bard Liao yung-chuan.liao@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rander Wang rander.wang@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210122070634.12825-9-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 483d5a389c92a..662b3b0302467 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -513,16 +513,16 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) { int ret;
- ret = pm_runtime_get_sync(slave->bus->dev); + ret = pm_runtime_get_sync(&slave->dev); if (ret < 0 && ret != -EACCES) { - pm_runtime_put_noidle(slave->bus->dev); + pm_runtime_put_noidle(&slave->dev); return ret; }
ret = sdw_nread_no_pm(slave, addr, count, val);
- pm_runtime_mark_last_busy(slave->bus->dev); - pm_runtime_put(slave->bus->dev); + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put(&slave->dev);
return ret; } @@ -539,16 +539,16 @@ int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) { int ret;
- ret = pm_runtime_get_sync(slave->bus->dev); + ret = pm_runtime_get_sync(&slave->dev); if (ret < 0 && ret != -EACCES) { - pm_runtime_put_noidle(slave->bus->dev); + pm_runtime_put_noidle(&slave->dev); return ret; }
ret = sdw_nwrite_no_pm(slave, addr, count, val);
- pm_runtime_mark_last_busy(slave->bus->dev); - pm_runtime_put(slave->bus->dev); + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put(&slave->dev);
return ret; } @@ -1453,7 +1453,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) ret = pm_runtime_get_sync(&slave->dev); if (ret < 0 && ret != -EACCES) { dev_err(&slave->dev, "Failed to resume device: %d\n", ret); - pm_runtime_put_noidle(slave->bus->dev); + pm_runtime_put_noidle(&slave->dev); return ret; }
From: Stephen Boyd swboyd@chromium.org
[ Upstream commit 182b4a2d251305201b6f9cae29067f7112f05835 ]
A missing semicolon here causes my external display to stop working. Indeed, missing the semicolon on the return statement leads to dp_panel_update_tu_timings() not existing because the compiler thinks it's part of the return statement of a void function, so it must not be important.
$ ./scripts/bloat-o-meter before.o after.o add/remove: 1/1 grow/shrink: 0/1 up/down: 7400/-7540 (-140) Function old new delta dp_panel_update_tu_timings - 7400 +7400 _dp_ctrl_calc_tu.constprop 18024 17900 -124 dp_panel_update_tu_timings.constprop 7416 - -7416 Total: Before=54440, After=54300, chg -0.26%
Add a semicolon so this function works like it used to.
Cc: Sean Paul sean@poorly.run Cc: Kuogee Hsieh khsieh@codeaurora.org Cc: linux-arm-msm@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: freedreno@lists.freedesktop.org Cc: Lee Jones lee.jones@linaro.org Fixes: cc9014bf63a4 ("drm/msm/dp/dp_ctrl: Move 'tu' from the stack to the heap") Signed-off-by: Stephen Boyd swboyd@chromium.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index e3462f5d96d75..6cbe10af0a7af 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -631,7 +631,7 @@ static void _dp_ctrl_calc_tu(struct dp_tu_calc_input *in,
tu = kzalloc(sizeof(*tu), GFP_KERNEL); if (!tu) - return + return;
dp_panel_update_tu_timings(in, tu);
From: Jonathan Marek jonathan@marek.ca
[ Upstream commit b212658aebda82f92967bcbd4c7380d607c3d803 ]
dma_map_sgtable() returns 0 on success, which is the opposite of what this code was doing.
Fixes: 7cd7edb89437 ("misc: fastrpc: fix common struct sg_table related issues") Acked-by: Marek Szyprowski m.szyprowski@samsung.com Signed-off-by: Jonathan Marek jonathan@marek.ca Link: https://lore.kernel.org/r/20210208200401.31100-1-jonathan@marek.ca Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/fastrpc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 70eb5ed942d03..f12e909034ac0 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -520,12 +520,13 @@ fastrpc_map_dma_buf(struct dma_buf_attachment *attachment, { struct fastrpc_dma_buf_attachment *a = attachment->priv; struct sg_table *table; + int ret;
table = &a->sgt;
- if (!dma_map_sgtable(attachment->dev, table, dir, 0)) - return ERR_PTR(-ENOMEM); - + ret = dma_map_sgtable(attachment->dev, table, dir, 0); + if (ret) + table = ERR_PTR(ret); return table; }
From: Tzung-Bi Shih tzungbi@google.com
[ Upstream commit 8c545f52dce44368fff524e13116e696e005c074 ]
Acknowledges watchdog IRQ after handled or kernel keeps receiving the interrupt.
Fixes: fd0b6c1ff85a ("remoteproc/mediatek: Add support for mt8192 SCP") Signed-off-by: Tzung-Bi Shih tzungbi@google.com Link: https://lore.kernel.org/r/20210127082046.3735157-1-tzungbi@google.com Signed-off-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/remoteproc/mtk_common.h | 1 + drivers/remoteproc/mtk_scp.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h index 988edb4977c31..bcab38511bf31 100644 --- a/drivers/remoteproc/mtk_common.h +++ b/drivers/remoteproc/mtk_common.h @@ -47,6 +47,7 @@
#define MT8192_CORE0_SW_RSTN_CLR 0x10000 #define MT8192_CORE0_SW_RSTN_SET 0x10004 +#define MT8192_CORE0_WDT_IRQ 0x10030 #define MT8192_CORE0_WDT_CFG 0x10034
#define SCP_FW_VER_LEN 32 diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index e0c2356903616..eba825b46696e 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -197,17 +197,19 @@ static void mt8192_scp_irq_handler(struct mtk_scp *scp)
scp_to_host = readl(scp->reg_base + MT8192_SCP2APMCU_IPC_SET);
- if (scp_to_host & MT8192_SCP_IPC_INT_BIT) + if (scp_to_host & MT8192_SCP_IPC_INT_BIT) { scp_ipi_handler(scp); - else - scp_wdt_handler(scp, scp_to_host);
- /* - * SCP won't send another interrupt until we clear - * MT8192_SCP2APMCU_IPC. - */ - writel(MT8192_SCP_IPC_INT_BIT, - scp->reg_base + MT8192_SCP2APMCU_IPC_CLR); + /* + * SCP won't send another interrupt until we clear + * MT8192_SCP2APMCU_IPC. + */ + writel(MT8192_SCP_IPC_INT_BIT, + scp->reg_base + MT8192_SCP2APMCU_IPC_CLR); + } else { + scp_wdt_handler(scp, scp_to_host); + writel(1, scp->reg_base + MT8192_CORE0_WDT_IRQ); + } }
static irqreturn_t scp_irq_handler(int irq, void *priv)
From: Loic Poulain loic.poulain@linaro.org
[ Upstream commit db4e8de1935b0202960e9ebb88ab93e8bd1e66b1 ]
mhi_deinit_chan_ctxt functionthat takes care of unitializing channel resources, including unmapping coherent MHI areas, can be called from different path in case of controller unregistering/removal: - From a client driver remove callback, via mhi_unprepare_channel - From mhi_driver_remove that unitialize all channels
mhi_driver_remove() |-> driver->remove() | |-> mhi_unprepare_channel() | |-> mhi_deinit_chan_ctxt() |... |-> mhi_deinit_chan_ctxt()
This leads to double dma freeing...
Fix that by preventing deinit for already uninitialized channel.
Link: https://lore.kernel.org/r/1612894264-15956-1-git-send-email-loic.poulain@lin... Fixes: a7f422f2f89e ("bus: mhi: Fix channel close issue on driver remove") Reported-by: Kalle Valo kvalo@codeaurora.org Tested-by: Kalle Valo kvalo@codeaurora.org Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Loic Poulain loic.poulain@linaro.org Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Link: https://lore.kernel.org/r/20210210082538.2494-2-manivannan.sadhasivam@linaro... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bus/mhi/core/init.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index f0697f433c2f1..08c45457c90fe 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -552,6 +552,9 @@ void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, tre_ring = &mhi_chan->tre_ring; chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan];
+ if (!chan_ctxt->rbase) /* Already uninitialized */ + return; + mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size, tre_ring->pre_aligned, tre_ring->dma_handle); vfree(buf_ring->base);
From: Bard Liao yung-chuan.liao@linux.intel.com
[ Upstream commit d288a5712ef961e16d588bbdb2d846e00b5ef154 ]
sdw_update_slave_status will be invoked when a codec is attached, and the codec driver will initialize the codec with regmap functions while the codec device is pm_runtime suspended.
regmap routines currently rely on regular SoundWire IO functions, which will call pm_runtime_get_sync()/put_autosuspend.
This causes a deadlock where the resume routine waits for an initialization complete signal that while the initialization complete can only be reached when the resume completes.
The only solution if we allow regmap functions to be used in resume operations as well as during codec initialization is to use _no_pm routines. The duty of making sure the bus is operational needs to be handled above the regmap level.
Fixes: 7c22ce6e21840 ('regmap: Add SoundWire bus support') Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Acked-by: Mark Brown broonie@kernel.org Link: https://lore.kernel.org/r/20210122070634.12825-6-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/base/regmap/regmap-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/regmap/regmap-sdw.c b/drivers/base/regmap/regmap-sdw.c index c83be26434e76..966de8a136d90 100644 --- a/drivers/base/regmap/regmap-sdw.c +++ b/drivers/base/regmap/regmap-sdw.c @@ -13,7 +13,7 @@ static int regmap_sdw_write(void *context, unsigned int reg, unsigned int val) struct device *dev = context; struct sdw_slave *slave = dev_to_sdw_dev(dev);
- return sdw_write(slave, reg, val); + return sdw_write_no_pm(slave, reg, val); }
static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val) @@ -22,7 +22,7 @@ static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val) struct sdw_slave *slave = dev_to_sdw_dev(dev); int read;
- read = sdw_read(slave, reg); + read = sdw_read_no_pm(slave, reg); if (read < 0) return read;
From: Geert Uytterhoeven geert@linux-m68k.org
[ Upstream commit 302fdadeafe4be539f247abf25f61822e4a5a577 ]
EXT4_KUNIT_TESTS selects EXT4_FS, thus enabling an optional feature the user may not want to enable. Fix this by making the test depend on EXT4_FS instead.
Fixes: 1cbeab1b242d16fd ("ext4: add kunit test for decoding extended timestamps") Reviewed-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Geert Uytterhoeven geert@linux-m68k.org Link: https://lore.kernel.org/r/20210122110234.2825685-1-geert@linux-m68k.org Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ext4/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 619dd35ddd48a..86699c8cab281 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -103,8 +103,7 @@ config EXT4_DEBUG
config EXT4_KUNIT_TESTS tristate "KUnit tests for ext4" if !KUNIT_ALL_TESTS - select EXT4_FS - depends on KUNIT + depends on EXT4_FS && KUNIT default KUNIT_ALL_TESTS help This builds the ext4 KUnit tests.
From: Magnum Shan magnum.shan@unisoc.com
[ Upstream commit 4450f128c51160bfded6b483eba37d0628d7adb2 ]
According to the specification, bit[2] represents SPRD_OUTBOX_FIFO_FULL, not bit[0], so correct it.
Fixes: ca27fc26cd22 ("mailbox: sprd: Add Spreadtrum mailbox driver") Signed-off-by: Magnum Shan magnum.shan@unisoc.com Signed-off-by: Chunyan Zhang chunyan.zhang@unisoc.com Reviewed-by: Baolin Wang baolin.wang7@gmail.com Signed-off-by: Jassi Brar jaswinder.singh@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mailbox/sprd-mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mailbox/sprd-mailbox.c b/drivers/mailbox/sprd-mailbox.c index f6fab24ae8a9a..4c325301a2fe8 100644 --- a/drivers/mailbox/sprd-mailbox.c +++ b/drivers/mailbox/sprd-mailbox.c @@ -35,7 +35,7 @@ #define SPRD_MBOX_IRQ_CLR BIT(0)
/* Bit and mask definiation for outbox's SPRD_MBOX_FIFO_STS register */ -#define SPRD_OUTBOX_FIFO_FULL BIT(0) +#define SPRD_OUTBOX_FIFO_FULL BIT(2) #define SPRD_OUTBOX_FIFO_WR_SHIFT 16 #define SPRD_OUTBOX_FIFO_RD_SHIFT 24 #define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0)
From: Shiyang Ruan ruansy.fnst@cn.fujitsu.com
[ Upstream commit 7323fb22f05ff1d20498d267828870a5fbbaebd6 ]
The return value of range_parse() indicates the size when it is positive. The error code should be negative.
Signed-off-by: Shiyang Ruan ruansy.fnst@cn.fujitsu.com Reviewed-by: Joao Martins joao.m.martins@oracle.com Link: https://lore.kernel.org/r/20210126021331.1059933-1-ruansy.fnst@cn.fujitsu.co... Reported-by: Zhang Qilong zhangqilong3@huawei.com Fixes: 8490e2e25b5a ("device-dax: add a range mapping allocation attribute") Signed-off-by: Dan Williams dan.j.williams@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dax/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index 737b207c9e30d..3003558c1a8bb 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -1038,7 +1038,7 @@ static ssize_t range_parse(const char *opt, size_t len, struct range *range) { unsigned long long addr = 0; char *start, *end, *str; - ssize_t rc = EINVAL; + ssize_t rc = -EINVAL;
str = kstrdup(opt, GFP_KERNEL); if (!str)
From: Russell King rmk+kernel@armlinux.org.uk
[ Upstream commit f8ee579d53aca887d93f5f411462f25c085a5106 ]
We allow up to PCI_EXP_SLTSTA2 registers to be accessed, but the pcie_cap_regs_behavior[] array only covers up to PCI_EXP_RTSTA. Expand this array to avoid walking off the end of it.
Do the same for pci_regs_behavior for consistency[], and add a BUILD_BUG_ON() to also check the bridge->conf structure size.
Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic") Link: https://lore.kernel.org/r/E1l6z9W-0006Re-MQ@rmk-PC.armlinux.org.uk Signed-off-by: Russell King rmk+kernel@armlinux.org.uk Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Pali Rohár pali@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/pci-bridge-emul.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 139869d50eb26..fdaf86a888b73 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -21,8 +21,9 @@ #include "pci-bridge-emul.h"
#define PCI_BRIDGE_CONF_END PCI_STD_HEADER_SIZEOF +#define PCI_CAP_PCIE_SIZEOF (PCI_EXP_SLTSTA2 + 2) #define PCI_CAP_PCIE_START PCI_BRIDGE_CONF_END -#define PCI_CAP_PCIE_END (PCI_CAP_PCIE_START + PCI_EXP_SLTSTA2 + 2) +#define PCI_CAP_PCIE_END (PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
/** * struct pci_bridge_reg_behavior - register bits behaviors @@ -46,7 +47,8 @@ struct pci_bridge_reg_behavior { u32 w1c; };
-static const struct pci_bridge_reg_behavior pci_regs_behavior[] = { +static const +struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = { [PCI_VENDOR_ID / 4] = { .ro = ~0 }, [PCI_COMMAND / 4] = { .rw = (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | @@ -164,7 +166,8 @@ static const struct pci_bridge_reg_behavior pci_regs_behavior[] = { }, };
-static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = { +static const +struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = { [PCI_CAP_LIST_ID / 4] = { /* * Capability ID, Next Capability Pointer and @@ -260,6 +263,8 @@ static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = { int pci_bridge_emul_init(struct pci_bridge_emul *bridge, unsigned int flags) { + BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END); + bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; bridge->conf.cache_line_size = 0x10;
From: Krzysztof Wilczyński kw@linux.com
[ Upstream commit 1002573ee33efef0988a9a546c075a9fa37d2498 ]
Function cdns_pcie_host_map_dma_ranges() iterates over a PCIe host bridge DMA ranges using the resource_list_for_each_entry() iterator, returning an error if cdns_pcie_host_bar_config() fails.
49e427e6bdd1 ("Merge branch 'pci/host-probe-refactor'") botched a merge so it *always* returned after the first DMA range, even if no error occurred.
Fix the error checking so we return early only when an error occurs.
[bhelgaas: commit log] Fixes: 49e427e6bdd1 ("Merge branch 'pci/host-probe-refactor'") Link: https://lore.kernel.org/r/20210216205935.3112661-1-kw@linux.com Signed-off-by: Krzysztof Wilczyński kw@linux.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 811c1cb2e8deb..1cb7cfc75d6e4 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -321,9 +321,10 @@ static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
resource_list_for_each_entry(entry, &bridge->dma_ranges) { err = cdns_pcie_host_bar_config(rc, entry); - if (err) + if (err) { dev_err(dev, "Fail to configure IB using dma-ranges\n"); - return err; + return err; + } }
return 0;
From: Slawomir Laba slawomirx.laba@intel.com
[ Upstream commit 92c6058024e87087cf1b99b0389d67c0a886360e ]
When a packet contains an IPv6 header with next header which is an extension header and not a protocol one, the kernel function skb_transport_header called with such sk_buff will return a pointer to the extension header and not to the TCP one.
The above explained call caused a problem with packet processing for skb with encapsulation for tunnel with I40E_TX_CTX_EXT_IP_IPV6. The extension header was not skipped at all.
The ipv6_skip_exthdr function does check if next header of the IPV6 header is an extension header and doesn't modify the l4_proto pointer if it points to a protocol header value so its safe to omit the comparison of exthdr and l4.hdr pointers. The ipv6_skip_exthdr can return value -1. This means that the skipping process failed and there is something wrong with the packet so it will be dropped.
Fixes: a3fd9d8876a5 ("i40e/i40evf: Handle IPv6 extension headers in checksum offload") Signed-off-by: Slawomir Laba slawomirx.laba@intel.com Signed-off-by: Przemyslaw Patynowski przemyslawx.patynowski@intel.com Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 4aca637d4a23c..32d97315f3f52 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3113,13 +3113,16 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
l4_proto = ip.v4->protocol; } else if (*tx_flags & I40E_TX_FLAGS_IPV6) { + int ret; + tunnel |= I40E_TX_CTX_EXT_IP_IPV6;
exthdr = ip.hdr + sizeof(*ip.v6); l4_proto = ip.v6->nexthdr; - if (l4.hdr != exthdr) - ipv6_skip_exthdr(skb, exthdr - skb->data, - &l4_proto, &frag_off); + ret = ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_proto, &frag_off); + if (ret < 0) + return -1; }
/* define outer transport */
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit d2c788f739b6f68090e968a2ee31b543701e795f ]
Zero-initialize AQ command data structures to comply with API specifications.
Fixes: 2f4b411a3d67 ("i40e: Enable cloud filters via tc-flower") Fixes: f4492db16df8 ("i40e: Add NPAR BW get and set functions") Signed-off-by: Andrzej Sawuła andrzej.sawula@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Reviewed-by: Arkadiusz Kubalewski arkadiusz.kubalewski@intel.com Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1db482d310c2d..9b1251a710c09 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7667,6 +7667,8 @@ int i40e_add_del_cloud_filter(struct i40e_vsi *vsi, if (filter->flags >= ARRAY_SIZE(flag_table)) return I40E_ERR_CONFIG;
+ memset(&cld_filter, 0, sizeof(cld_filter)); + /* copy element needed to add cloud filter from filter */ i40e_set_cld_element(filter, &cld_filter);
@@ -7734,6 +7736,8 @@ int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi, !ipv6_addr_any(&filter->ip.v6.src_ip6)) return -EOPNOTSUPP;
+ memset(&cld_filter, 0, sizeof(cld_filter)); + /* copy element needed to add cloud filter from filter */ i40e_set_cld_element(filter, &cld_filter.element);
@@ -11709,6 +11713,8 @@ i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf) struct i40e_aqc_configure_partition_bw_data bw_data; i40e_status status;
+ memset(&bw_data, 0, sizeof(bw_data)); + /* Set the valid bit for this PF */ bw_data.pf_valid_bits = cpu_to_le16(BIT(pf->hw.pf_id)); bw_data.max_bw[pf->hw.pf_id] = pf->max_bw & I40E_ALT_BW_VALUE_MASK;
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit 4cdb9f80dcd46aab3c0020b4a6920c22735c5d6e ]
During driver loading flow control settings were written to FW using a variable which was always zero, since it was being set only by ethtool. This behavior has been corrected and driver no longer overwrites the default FW/NVM settings.
Fixes: 373149fc99a0 ("i40e: Decrease the scope of rtnl lock") Signed-off-by: Dawid Lukwinski dawid.lukwinski@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_main.c | 27 --------------------- 1 file changed, 27 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9b1251a710c09..bcfa6dcac29f7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10005,7 +10005,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state); struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; struct i40e_hw *hw = &pf->hw; - u8 set_fc_aq_fail = 0; i40e_status ret; u32 val; int v; @@ -10131,13 +10130,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) i40e_stat_str(&pf->hw, ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
- /* make sure our flow control settings are restored */ - ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); - if (ret) - dev_dbg(&pf->pdev->dev, "setting flow control: ret = %s last_status = %s\n", - i40e_stat_str(&pf->hw, ret), - i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); - /* Rebuild the VSIs and VEBs that existed before reset. * They are still in our local switch element arrays, so only * need to rebuild the switch model in the HW. @@ -14720,7 +14712,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int err; u32 val; u32 i; - u8 set_fc_aq_fail;
err = pci_enable_device_mem(pdev); if (err) @@ -15054,24 +15045,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } INIT_LIST_HEAD(&pf->vsi[pf->lan_vsi]->ch_list);
- /* Make sure flow control is set according to current settings */ - err = i40e_set_fc(hw, &set_fc_aq_fail, true); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_GET) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on get_phy_cap\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_SET) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on set_phy_config\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_UPDATE) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on get_link_info\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - /* if FDIR VSI was set up, start it now */ for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit 28b1208e7a7fa3ddc9345b022bb93e53d9dcc28a ]
Fix addition of VLAN filter for PF after enabling FW LLDP agent. Changing LLDP Agent causes FW to re-initialize per NVM settings. Remove default PF filter and move "Enable/Disable" to currently used reset flag. Without this patch PF would try to add MAC VLAN filter with default switch filter present. This causes AQ error and sets promiscuous mode on.
Fixes: c65e78f87f81 ("i40e: Further implementation of LLDP") Signed-off-by: Przemyslaw Patynowski przemyslawx.patynowski@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Reviewed-by: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com Reviewed-by: Aleksandr Loktionov aleksandr.loktionov@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +++++++++------- drivers/net/ethernet/intel/i40e/i40e_main.c | 9 ++++----- 2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 26ba1f3eb2d85..9e81f85ee2d8d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -4878,7 +4878,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) enum i40e_admin_queue_err adq_err; struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; - bool is_reset_needed; + u32 reset_needed = 0; i40e_status status; u32 i, j;
@@ -4923,9 +4923,11 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) flags_complete: changed_flags = orig_flags ^ new_flags;
- is_reset_needed = !!(changed_flags & (I40E_FLAG_VEB_STATS_ENABLED | - I40E_FLAG_LEGACY_RX | I40E_FLAG_SOURCE_PRUNING_DISABLED | - I40E_FLAG_DISABLE_FW_LLDP)); + if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP) + reset_needed = I40E_PF_RESET_AND_REBUILD_FLAG; + if (changed_flags & (I40E_FLAG_VEB_STATS_ENABLED | + I40E_FLAG_LEGACY_RX | I40E_FLAG_SOURCE_PRUNING_DISABLED)) + reset_needed = BIT(__I40E_PF_RESET_REQUESTED);
/* Before we finalize any flag changes, we need to perform some * checks to ensure that the changes are supported and safe. @@ -5057,7 +5059,7 @@ flags_complete: case I40E_AQ_RC_EEXIST: dev_warn(&pf->pdev->dev, "FW LLDP agent is already running\n"); - is_reset_needed = false; + reset_needed = 0; break; case I40E_AQ_RC_EPERM: dev_warn(&pf->pdev->dev, @@ -5086,8 +5088,8 @@ flags_complete: /* Issue reset to cause things to take effect, as additional bits * are added we will need to create a mask of bits requiring reset */ - if (is_reset_needed) - i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true); + if (reset_needed) + i40e_do_reset(pf, reset_needed, true);
return 0; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index bcfa6dcac29f7..b268adb3e1d44 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8537,11 +8537,6 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired) dev_dbg(&pf->pdev->dev, "PFR requested\n"); i40e_handle_reset_warning(pf, lock_acquired);
- dev_info(&pf->pdev->dev, - pf->flags & I40E_FLAG_DISABLE_FW_LLDP ? - "FW LLDP is disabled\n" : - "FW LLDP is enabled\n"); - } else if (reset_flags & I40E_PF_RESET_AND_REBUILD_FLAG) { /* Request a PF Reset * @@ -8549,6 +8544,10 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired) */ i40e_prep_for_reset(pf, lock_acquired); i40e_reset_and_rebuild(pf, true, lock_acquired); + dev_info(&pf->pdev->dev, + pf->flags & I40E_FLAG_DISABLE_FW_LLDP ? + "FW LLDP is disabled\n" : + "FW LLDP is enabled\n");
} else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) { int v;
From: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com
[ Upstream commit dc8812626440fa6a27f1f3f654f6dc435e042e42 ]
When creating VFs they were sometimes not getting resources. It was caused by not executing i40e_reset_all_vfs due to flag __I40E_VF_DISABLE being set on PF. Because of this IAVF was never able to finish setup sequence never getting reset indication from PF. Changed test_and_set_bit __I40E_VF_DISABLE in i40e_sync_filters_subtask to test_bit and removed clear_bit. This function should not set this bit it should only check if it hasn't been already set.
Fixes: a7542b876075 ("i40e: check __I40E_VF_DISABLE bit in i40e_sync_filters_subtask") 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 Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b268adb3e1d44..3ca5644785556 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2616,7 +2616,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) return; if (!test_and_clear_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state)) return; - if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) { + if (test_bit(__I40E_VF_DISABLE, pf->state)) { set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state); return; } @@ -2634,7 +2634,6 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) } } } - clear_bit(__I40E_VF_DISABLE, pf->state); }
/**
From: Jann Horn jannh@google.com
[ Upstream commit c26958cb5a0d9053d1358258827638773f3d36ed ]
We need to take the mmap lock around find_vma() and subsequent use of the VMA. Otherwise, we can race with concurrent operations like munmap(), which can lead to use-after-free accesses to freed VMAs.
Fixes: 1000197d8013 ("nios2: System calls handling") Signed-off-by: Jann Horn jannh@google.com Signed-off-by: Ley Foon Tan ley.foon.tan@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/nios2/kernel/sys_nios2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/nios2/kernel/sys_nios2.c b/arch/nios2/kernel/sys_nios2.c index cd390ec4f88bf..b1ca856999521 100644 --- a/arch/nios2/kernel/sys_nios2.c +++ b/arch/nios2/kernel/sys_nios2.c @@ -22,6 +22,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op) { struct vm_area_struct *vma; + struct mm_struct *mm = current->mm;
if (len == 0) return 0; @@ -34,16 +35,22 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, if (addr + len < addr) return -EFAULT;
+ if (mmap_read_lock_killable(mm)) + return -EINTR; + /* * Verify that the specified address region actually belongs * to this process. */ - vma = find_vma(current->mm, addr); - if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) + vma = find_vma(mm, addr); + if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) { + mmap_read_unlock(mm); return -EFAULT; + }
flush_cache_range(vma, addr, addr + len);
+ mmap_read_unlock(mm); return 0; }
From: Andreas Oetken andreas.oetken@siemens.com
[ Upstream commit 9abcfcb20320e8f693e89d86573b58e6289931cb ]
The tls pointer must be pushed on the stack prior to calling nios2_clone as it is the 5th function argument. Prior handling of the tls pointer was done inside former called function copy_thread_tls using the r8 register from the current_pt_regs directly. This was a bad design and resulted in the current bug introduced in 04bd52fb.
Fixes: 04bd52fb ("nios2: enable HAVE_COPY_THREAD_TLS, switch to kernel_clone_args") Signed-off-by: Andreas Oetken andreas.oetken@siemens.com Signed-off-by: Ley Foon Tan ley.foon.tan@intel.com Acked-by: Christian Brauner christian.brauner@ubuntu.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/nios2/kernel/entry.S | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index da8442450e460..0794cd7803dfe 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S @@ -389,7 +389,10 @@ ENTRY(ret_from_interrupt) */ ENTRY(sys_clone) SAVE_SWITCH_STACK + subi sp, sp, 4 /* make space for tls pointer */ + stw r8, 0(sp) /* pass tls pointer (r8) via stack (5th argument) */ call nios2_clone + addi sp, sp, 4 RESTORE_SWITCH_STACK ret
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit 61c1e0eb8375def7c891bfe857bb795a57090526 ]
Fix insufficient distinction between IPv4 and IPv6 addresses when creating a filter. IPv4 and IPv6 are kept in the same memory area. If IPv6 is added, then it's caught by IPv4 check, which leads to err -95.
Fixes: 2f4b411a3d67 ("i40e: Enable cloud filters via tc-flower") Signed-off-by: Grzegorz Szczurek grzegorzx.szczurek@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Reviewed-by: Jaroslaw Gawin jaroslawx.gawin@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3ca5644785556..59971f62e6268 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7731,7 +7731,8 @@ int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi, return -EOPNOTSUPP;
/* adding filter using src_port/src_ip is not supported at this stage */ - if (filter->src_port || filter->src_ipv4 || + if (filter->src_port || + (filter->src_ipv4 && filter->n_proto != ETH_P_IPV6) || !ipv6_addr_any(&filter->ip.v6.src_ip6)) return -EOPNOTSUPP;
@@ -7760,7 +7761,7 @@ int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi, cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT); }
- } else if (filter->dst_ipv4 || + } else if ((filter->dst_ipv4 && filter->n_proto != ETH_P_IPV6) || !ipv6_addr_any(&filter->ip.v6.dst_ip6)) { cld_filter.element.flags = cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_IP_PORT);
From: Norbert Ciosek norbertx.ciosek@intel.com
[ Upstream commit b32cddd2247cf730731f93f1967d0147a40682c7 ]
Fixes the following sparse warnings: i40e_main.c:5953:32: warning: cast from restricted __le16 i40e_main.c:8008:29: warning: incorrect type in assignment (different base types) i40e_main.c:8008:29: expected unsigned int [assigned] [usertype] ipa i40e_main.c:8008:29: got restricted __le32 [usertype] i40e_main.c:8008:29: warning: incorrect type in assignment (different base types) i40e_main.c:8008:29: expected unsigned int [assigned] [usertype] ipa i40e_main.c:8008:29: got restricted __le32 [usertype] i40e_txrx.c:1950:59: warning: incorrect type in initializer (different base types) i40e_txrx.c:1950:59: expected unsigned short [usertype] vlan_tag i40e_txrx.c:1950:59: got restricted __le16 [usertype] l2tag1 i40e_txrx.c:1953:40: warning: cast to restricted __le16 i40e_xsk.c:448:38: warning: invalid assignment: |= i40e_xsk.c:448:38: left side has type restricted __le64 i40e_xsk.c:448:38: right side has type int
Fixes: 2f4b411a3d67 ("i40e: Enable cloud filters via tc-flower") Fixes: 2a508c64ad27 ("i40e: fix VLAN.TCI == 0 RX HW offload") Fixes: 3106c580fb7c ("i40e: Use batched xsk Tx interfaces to increase performance") Fixes: 8f88b3034db3 ("i40e: Add infrastructure for queue channel support") Signed-off-by: Norbert Ciosek norbertx.ciosek@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/i40e/i40e_main.c | 12 ++++++------ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 59971f62e6268..fcd6f623f2fd8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5920,7 +5920,7 @@ static int i40e_add_channel(struct i40e_pf *pf, u16 uplink_seid, ch->enabled_tc = !i40e_is_channel_macvlan(ch) && enabled_tc; ch->seid = ctxt.seid; ch->vsi_number = ctxt.vsi_number; - ch->stat_counter_idx = cpu_to_le16(ctxt.info.stat_counter_idx); + ch->stat_counter_idx = le16_to_cpu(ctxt.info.stat_counter_idx);
/* copy just the sections touched not the entire info * since not all sections are valid as returned by @@ -7599,8 +7599,8 @@ static inline void i40e_set_cld_element(struct i40e_cloud_filter *filter, struct i40e_aqc_cloud_filters_element_data *cld) { - int i, j; u32 ipa; + int i;
memset(cld, 0, sizeof(*cld)); ether_addr_copy(cld->outer_mac, filter->dst_mac); @@ -7611,14 +7611,14 @@ i40e_set_cld_element(struct i40e_cloud_filter *filter,
if (filter->n_proto == ETH_P_IPV6) { #define IPV6_MAX_INDEX (ARRAY_SIZE(filter->dst_ipv6) - 1) - for (i = 0, j = 0; i < ARRAY_SIZE(filter->dst_ipv6); - i++, j += 2) { + for (i = 0; i < ARRAY_SIZE(filter->dst_ipv6); i++) { ipa = be32_to_cpu(filter->dst_ipv6[IPV6_MAX_INDEX - i]); - ipa = cpu_to_le32(ipa); - memcpy(&cld->ipaddr.raw_v6.data[j], &ipa, sizeof(ipa)); + + *(__le32 *)&cld->ipaddr.raw_v6.data[i * 2] = cpu_to_le32(ipa); } } else { ipa = be32_to_cpu(filter->dst_ipv4); + memcpy(&cld->ipaddr.v4.data, &ipa, sizeof(ipa)); }
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 32d97315f3f52..903d4e8cb0a11 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1793,7 +1793,7 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring, skb_record_rx_queue(skb, rx_ring->queue_index);
if (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) { - u16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1; + __le16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1;
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), le16_to_cpu(vlan_tag)); diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 492ce213208d2..37a21fb999221 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -444,7 +444,7 @@ static void i40e_set_rs_bit(struct i40e_ring *xdp_ring) struct i40e_tx_desc *tx_desc;
tx_desc = I40E_TX_DESC(xdp_ring, ntu); - tx_desc->cmd_type_offset_bsz |= (I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT); + tx_desc->cmd_type_offset_bsz |= cpu_to_le64(I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT); }
/**
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 3a2eb515d1367c0f667b76089a6e727279c688b8 ]
This code does not allocate enough memory for the NUL terminator so it ends up putting it one character beyond the end of the buffer.
Fixes: 8756828a8148 ("octeontx2-af: Add NPA aura and pool contexts to debugfs") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index d27543c1a166a..bb3fdaf337519 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -385,7 +385,7 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp, u16 pcifunc; int ret, lf;
- cmd_buf = memdup_user(buffer, count); + cmd_buf = memdup_user(buffer, count + 1); if (IS_ERR(cmd_buf)) return -ENOMEM;
From: Uwe Kleine-König u.kleine-koenig@pengutronix.de
[ Upstream commit 72d6b2459dbd539c1369149e501fdc3dc8ddef16 ]
If state->duty_cycle is 0x100000000000000, the previous calculation of duty_scale overflows and yields a duty cycle ratio of 0% instead of 100%. Fix this by clamping the requested duty cycle to the maximal possible duty cycle first. This way it is possible to use a native integer division instead of a (depending on the architecture) more expensive 64bit division.
With this change in place duty_scale cannot be bigger than 256 which allows to simplify the calculation of duty_val.
Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator") Tested-by: Jeff LaBundy jeff@labundy.com Signed-off-by: Uwe Kleine-König u.kleine-koenig@pengutronix.de Signed-off-by: Thierry Reding thierry.reding@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pwm/pwm-iqs620a.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index 5ede8255926ef..14b18fb4f5274 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -46,7 +46,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, { struct iqs620_pwm_private *iqs620_pwm; struct iqs62x_core *iqs62x; - u64 duty_scale; + unsigned int duty_cycle; + unsigned int duty_scale; int ret;
if (state->polarity != PWM_POLARITY_NORMAL) @@ -70,7 +71,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, * For lower duty cycles (e.g. 0), the PWM output is simply disabled to * allow an external pull-down resistor to hold the GPIO3/LTX pin low. */ - duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS); + duty_cycle = min_t(u64, state->duty_cycle, IQS620_PWM_PERIOD_NS); + duty_scale = duty_cycle * 256 / IQS620_PWM_PERIOD_NS;
mutex_lock(&iqs620_pwm->lock);
@@ -82,7 +84,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, }
if (duty_scale) { - u8 duty_val = min_t(u64, duty_scale - 1, 0xff); + u8 duty_val = duty_scale - 1;
ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE, duty_val);
From: Dave Ertman david.m.ertman@intel.com
[ Upstream commit 7dcf7aa01c7b9f18727cbe0f9cb4136f1c6cdcc2 ]
In the driver currently, we are reporting max number of TCs to the DCBNL callback as a kernel define set to 8. This is preventing userspace applications performing DCBx to correctly down map the TCs from requested to actual values.
Report the actual max TC value to userspace from the capability struct.
Fixes: b94b013eb626 ("ice: Implement DCBNL support") Signed-off-by: Dave Ertman david.m.ertman@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c index 87f91b750d59a..842d44b63480f 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c @@ -136,7 +136,7 @@ ice_dcbnl_getnumtcs(struct net_device *dev, int __always_unused tcid, u8 *num) if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)) return -EINVAL;
- *num = IEEE_8021QAZ_MAX_TCS; + *num = pf->hw.func_caps.common_cap.maxtc; return 0; }
From: Brett Creeley brett.creeley@intel.com
[ Upstream commit a6aa7c8f998f4afddd73410aa043dad38162ce9e ]
Currently if an AVF driver doesn't account for the possibility of a port VLAN when determining its max packet size then packets at MTU will be dropped. It is not the VF driver's responsibility to account for a port VLAN so fix this. To fix this, do the following:
1. Add a function that determines the max packet size a VF is allowed by using the port's max packet size and whether the VF is in a port VLAN. If a port VLAN is configured then a VF's max packet size will always be the port's max packet size minus VLAN_HLEN. Otherwise it will be the port's max packet size.
2. Use this function to verify the max packet size from the VF.
3. If there is a port VLAN configured then add 4 bytes (VLAN_HLEN) to the VF's max packet size configuration.
Also, the VIRTCHNL_OP_GET_VF_RESOURCES message provides the capability to communicate a VF's max packet size. Use the new function for this purpose.
Fixes: 1071a8358a28 ("ice: Implement virtchnl commands for AVF support") Signed-off-by: Brett Creeley brett.creeley@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index ec7f6c64132ee..b3161c5def465 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -1878,6 +1878,29 @@ static int ice_vc_get_ver_msg(struct ice_vf *vf, u8 *msg) sizeof(struct virtchnl_version_info)); }
+/** + * ice_vc_get_max_frame_size - get max frame size allowed for VF + * @vf: VF used to determine max frame size + * + * Max frame size is determined based on the current port's max frame size and + * whether a port VLAN is configured on this VF. The VF is not aware whether + * it's in a port VLAN so the PF needs to account for this in max frame size + * checks and sending the max frame size to the VF. + */ +static u16 ice_vc_get_max_frame_size(struct ice_vf *vf) +{ + struct ice_vsi *vsi = vf->pf->vsi[vf->lan_vsi_idx]; + struct ice_port_info *pi = vsi->port_info; + u16 max_frame_size; + + max_frame_size = pi->phy.link_info.max_frame_size; + + if (vf->port_vlan_info) + max_frame_size -= VLAN_HLEN; + + return max_frame_size; +} + /** * ice_vc_get_vf_res_msg * @vf: pointer to the VF info @@ -1960,6 +1983,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg) vfres->max_vectors = pf->num_msix_per_vf; vfres->rss_key_size = ICE_VSIQF_HKEY_ARRAY_SIZE; vfres->rss_lut_size = ICE_VSIQF_HLUT_ARRAY_SIZE; + vfres->max_mtu = ice_vc_get_max_frame_size(vf);
vfres->vsi_res[0].vsi_id = vf->lan_vsi_num; vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV; @@ -2952,6 +2976,8 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
/* copy Rx queue info from VF into VSI */ if (qpi->rxq.ring_len > 0) { + u16 max_frame_size = ice_vc_get_max_frame_size(vf); + num_rxq++; vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr; vsi->rx_rings[i]->count = qpi->rxq.ring_len; @@ -2964,7 +2990,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) } vsi->rx_buf_len = qpi->rxq.databuffer_size; vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len; - if (qpi->rxq.max_pkt_size >= (16 * 1024) || + if (qpi->rxq.max_pkt_size > max_frame_size || qpi->rxq.max_pkt_size < 64) { v_ret = VIRTCHNL_STATUS_ERR_PARAM; goto error_param; @@ -2972,6 +2998,11 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) }
vsi->max_frame = qpi->rxq.max_pkt_size; + /* add space for the port VLAN since the VF driver is not + * expected to account for it in the MTU calculation + */ + if (vf->port_vlan_info) + vsi->max_frame += VLAN_HLEN; }
/* VF can request to configure less than allocated queues or default
From: Dave Ertman david.m.ertman@intel.com
[ Upstream commit 0d4907f65dc8fc5e897ad19956fca1acb3b33bc8 ]
DCBX_CAP bits were not being adjusted when switching between SW and FW controlled LLDP.
Adjust bits to correctly indicate which mode the LLDP logic is in.
Fixes: b94b013eb626 ("ice: Implement DCBNL support") Signed-off-by: Dave Ertman david.m.ertman@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice.h | 2 -- drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 4 ++++ drivers/net/ethernet/intel/ice/ice_ethtool.c | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index fa1e128c24eca..619d93f8b54c4 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -443,9 +443,7 @@ struct ice_pf { struct ice_hw_port_stats stats_prev; struct ice_hw hw; u8 stat_prev_loaded:1; /* has previous stats been loaded */ -#ifdef CONFIG_DCB u16 dcbx_cap; -#endif /* CONFIG_DCB */ u32 tx_timeout_count; unsigned long tx_timeout_last_recovery; u32 tx_timeout_recovery_level; diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c index 842d44b63480f..8c133a8be6add 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c @@ -160,6 +160,10 @@ static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode) { struct ice_pf *pf = ice_netdev_to_pf(netdev);
+ /* if FW LLDP agent is running, DCBNL not allowed to change mode */ + if (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) + return ICE_DCB_NO_HW_CHG; + /* No support for LLD_MANAGED modes or CEE+IEEE */ if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 69c113a4de7e6..d27b9cb3e8082 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -8,6 +8,7 @@ #include "ice_fltr.h" #include "ice_lib.h" #include "ice_dcb_lib.h" +#include <net/dcbnl.h>
struct ice_stats { char stat_string[ETH_GSTRING_LEN]; @@ -1238,6 +1239,9 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags) status = ice_init_pf_dcb(pf, true); if (status) dev_warn(dev, "Fail to init DCB\n"); + + pf->dcbx_cap &= ~DCB_CAP_DCBX_LLD_MANAGED; + pf->dcbx_cap |= DCB_CAP_DCBX_HOST; } else { enum ice_status status; bool dcbx_agent_status; @@ -1280,6 +1284,9 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags) if (status) dev_dbg(dev, "Fail to enable MIB change events\n");
+ pf->dcbx_cap &= ~DCB_CAP_DCBX_HOST; + pf->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED; + ice_nway_reset(netdev); } }
From: Henry Tieman henry.w.tieman@intel.com
[ Upstream commit 0393e46ac48a6832b1011c233ebcef84f8dbe4f5 ]
It was possible to have Rx queues that were not available for use by RSS. This would happen when increasing the number of Rx queues while there was a user defined RSS LUT.
Always update the number of available RSS queues when changing the number of Rx queues.
Fixes: 87324e747fde ("ice: Implement ethtool ops for channels") Signed-off-by: Henry Tieman henry.w.tieman@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 27 ++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index d27b9cb3e8082..aebebd2102da0 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3328,6 +3328,18 @@ ice_get_channels(struct net_device *dev, struct ethtool_channels *ch) ch->max_other = ch->other_count; }
+/** + * ice_get_valid_rss_size - return valid number of RSS queues + * @hw: pointer to the HW structure + * @new_size: requested RSS queues + */ +static int ice_get_valid_rss_size(struct ice_hw *hw, int new_size) +{ + struct ice_hw_common_caps *caps = &hw->func_caps.common_cap; + + return min_t(int, new_size, BIT(caps->rss_table_entry_width)); +} + /** * ice_vsi_set_dflt_rss_lut - set default RSS LUT with requested RSS size * @vsi: VSI to reconfigure RSS LUT on @@ -3355,14 +3367,10 @@ static int ice_vsi_set_dflt_rss_lut(struct ice_vsi *vsi, int req_rss_size) return -ENOMEM;
/* set RSS LUT parameters */ - if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { + if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) vsi->rss_size = 1; - } else { - struct ice_hw_common_caps *caps = &hw->func_caps.common_cap; - - vsi->rss_size = min_t(int, req_rss_size, - BIT(caps->rss_table_entry_width)); - } + else + vsi->rss_size = ice_get_valid_rss_size(hw, req_rss_size);
/* create/set RSS LUT */ ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); @@ -3441,9 +3449,12 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
ice_vsi_recfg_qs(vsi, new_rx, new_tx);
- if (new_rx && !netif_is_rxfh_configured(dev)) + if (!netif_is_rxfh_configured(dev)) return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
+ /* Update rss_size due to change in Rx queues */ + vsi->rss_size = ice_get_valid_rss_size(&pf->hw, new_rx); + return 0; }
From: Camelia Groza camelia.groza@nxp.com
[ Upstream commit 433dfc99aa3e0acbf655b961d98eb690162f758f ]
The current use of container_of is flawed and unnecessary. Obtain the dpaa_napi_portal reference from the private percpu data instead.
Fixes: a1e031ffb422 ("dpaa_eth: add XDP_REDIRECT support") Reported-by: Sascha Hauer s.hauer@pengutronix.de Signed-off-by: Camelia Groza camelia.groza@nxp.com Acked-by: Madalin Bucur madalin.bucur@oss.nxp.com Acked-by: Jesper Dangaard Brouer brouer@redhat.com Link: https://lore.kernel.org/r/20210218182106.22613-1-camelia.groza@nxp.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 6faa20bed4885..9905caeaeee3e 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2672,7 +2672,6 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal, u32 hash; u64 ns;
- np = container_of(&portal, struct dpaa_napi_portal, p); dpaa_fq = container_of(fq, struct dpaa_fq, fq_base); fd_status = be32_to_cpu(fd->status); fd_format = qm_fd_get_format(fd); @@ -2687,6 +2686,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
percpu_priv = this_cpu_ptr(priv->percpu_priv); percpu_stats = &percpu_priv->stats; + np = &percpu_priv->np;
if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal, sched_napi))) return qman_cb_dqrr_stop;
From: Song, Yoong Siang yoong.siang.song@intel.com
[ Upstream commit 24877687b375f2c476ffb726ea915fc85df09e3d ]
When link speed is not 100 Mbps, port transmit rate and speed divider are set to 8 and 1000000 respectively. These values are incorrect for CBS idleslope and sendslope HW values calculation if the link speed is not 1 Gbps.
This patch adds switch statement to set the values of port transmit rate and speed divider for 10 Gbps, 5 Gbps, 2.5 Gbps, 1 Gbps, and 100 Mbps. Note that CBS is not supported at 10 Mbps.
Fixes: bc41a6689b30 ("net: stmmac: tc: Remove the speed dependency") Fixes: 1f705bc61aee ("net: stmmac: Add support for CBS QDISC") Signed-off-by: Song, Yoong Siang yoong.siang.song@intel.com Link: https://lore.kernel.org/r/1613655653-11755-1-git-send-email-yoong.siang.song... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 56985542e2029..44bb133c30007 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -316,6 +316,32 @@ static int tc_setup_cbs(struct stmmac_priv *priv, if (!priv->dma_cap.av) return -EOPNOTSUPP;
+ /* Port Transmit Rate and Speed Divider */ + switch (priv->speed) { + case SPEED_10000: + ptr = 32; + speed_div = 10000000; + break; + case SPEED_5000: + ptr = 32; + speed_div = 5000000; + break; + case SPEED_2500: + ptr = 8; + speed_div = 2500000; + break; + case SPEED_1000: + ptr = 8; + speed_div = 1000000; + break; + case SPEED_100: + ptr = 4; + speed_div = 100000; + break; + default: + return -EOPNOTSUPP; + } + mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; if (mode_to_use == MTL_QUEUE_DCB && qopt->enable) { ret = stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_AVB); @@ -332,10 +358,6 @@ static int tc_setup_cbs(struct stmmac_priv *priv, priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; }
- /* Port Transmit Rate and Speed Divider */ - ptr = (priv->speed == SPEED_100) ? 4 : 8; - speed_div = (priv->speed == SPEED_100) ? 100000 : 1000000; - /* Final adjustments for HW */ value = div_s64(qopt->idleslope * 1024ll * ptr, speed_div); priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0);
From: Chuhong Yuan hslester96@gmail.com
[ Upstream commit 8eb65fda4a6dbd59cd5de24b106a10b6ee0d2176 ]
mlx4_do_mirror_rule() forgets to call mlx4_free_cmd_mailbox() to free the memory region allocated by mlx4_alloc_cmd_mailbox() before an exit. Add the missed call to fix it.
Fixes: 78efed275117 ("net/mlx4_core: Support mirroring VF DMFS rules on both ports") Signed-off-by: Chuhong Yuan hslester96@gmail.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Link: https://lore.kernel.org/r/20210221143559.390277-1-hslester96@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 394f43add85cf..a99e71bc7b3c9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -4986,6 +4986,7 @@ static int mlx4_do_mirror_rule(struct mlx4_dev *dev, struct res_fs_rule *fs_rule
if (!fs_rule->mirr_mbox) { mlx4_err(dev, "rule mirroring mailbox is null\n"); + mlx4_free_cmd_mailbox(dev, mailbox); return -EINVAL; } memcpy(mailbox->buf, fs_rule->mirr_mbox, fs_rule->mirr_mbox_size);
From: Chen-Yu Tsai wens@csie.org
[ Upstream commit 58adbfb3ebec460e8b58875c682bafd866808e80 ]
The Rockchip PCIe controller DT binding clearly states that 'ep-gpios' is an optional property. And indeed there are boards that don't require it.
Make the driver follow the binding by using devm_gpiod_get_optional() instead of devm_gpiod_get().
[bhelgaas: tidy whitespace] Link: https://lore.kernel.org/r/20210121162321.4538-2-wens@kernel.org Fixes: e77f847df54c ("PCI: rockchip: Add Rockchip PCIe controller support") Fixes: 956cd99b35a8 ("PCI: rockchip: Separate common code from RC driver") Fixes: 964bac9455be ("PCI: rockchip: Split out rockchip_pcie_parse_dt() to parse DT") Signed-off-by: Chen-Yu Tsai wens@csie.org Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-rockchip.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index 904dec0d3a88f..990a00e08bc5b 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -82,7 +82,7 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) }
rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev, - "mgmt-sticky"); + "mgmt-sticky"); if (IS_ERR(rockchip->mgmt_sticky_rst)) { if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER) dev_err(dev, "missing mgmt-sticky reset property in node\n"); @@ -118,11 +118,11 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) }
if (rockchip->is_rc) { - rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH); - if (IS_ERR(rockchip->ep_gpio)) { - dev_err(dev, "missing ep-gpios property in node\n"); - return PTR_ERR(rockchip->ep_gpio); - } + rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", + GPIOD_OUT_HIGH); + if (IS_ERR(rockchip->ep_gpio)) + return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), + "failed to get ep GPIO\n"); }
rockchip->aclk_pcie = devm_clk_get(dev, "aclk");
From: Taehee Yoo ap420073@gmail.com
[ Upstream commit 92584ddf550ae72d492858c19d1f9025e07a9350 ]
The debug check must be done after unregister_netdevice_many() call -- the hlist_del_rcu() for this is done inside .ndo_stop.
This is the same with commit 0fda7600c2e1 ("geneve: move debug check after netdev unregister")
Test commands: ip netns del A ip netns add A ip netns add B
ip netns exec B ip link add vxlan0 type vxlan vni 100 local 10.0.0.1 \ remote 10.0.0.2 dstport 4789 srcport 4789 4789 ip netns exec B ip link set vxlan0 netns A ip netns exec A ip link set vxlan0 up ip netns del B
Splat looks like: [ 73.176249][ T7] ------------[ cut here ]------------ [ 73.178662][ T7] WARNING: CPU: 4 PID: 7 at drivers/net/vxlan.c:4743 vxlan_exit_batch_net+0x52e/0x720 [vxlan] [ 73.182597][ T7] Modules linked in: vxlan openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 mlx5_core nfp mlxfw ixgbevf tls sch_fq_codel nf_tables nfnetlink ip_tables x_tables unix [ 73.190113][ T7] CPU: 4 PID: 7 Comm: kworker/u16:0 Not tainted 5.11.0-rc7+ #838 [ 73.193037][ T7] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 [ 73.196986][ T7] Workqueue: netns cleanup_net [ 73.198946][ T7] RIP: 0010:vxlan_exit_batch_net+0x52e/0x720 [vxlan] [ 73.201509][ T7] Code: 00 01 00 00 0f 84 39 fd ff ff 48 89 ca 48 c1 ea 03 80 3c 1a 00 0f 85 a6 00 00 00 89 c2 48 83 c2 02 49 8b 14 d4 48 85 d2 74 ce <0f> 0b eb ca e8 b9 51 db dd 84 c0 0f 85 4a fe ff ff 48 c7 c2 80 bc [ 73.208813][ T7] RSP: 0018:ffff888100907c10 EFLAGS: 00010286 [ 73.211027][ T7] RAX: 000000000000003c RBX: dffffc0000000000 RCX: ffff88800ec411f0 [ 73.213702][ T7] RDX: ffff88800a278000 RSI: ffff88800fc78c70 RDI: ffff88800fc78070 [ 73.216169][ T7] RBP: ffff88800b5cbdc0 R08: fffffbfff424de61 R09: fffffbfff424de61 [ 73.218463][ T7] R10: ffffffffa126f307 R11: fffffbfff424de60 R12: ffff88800ec41000 [ 73.220794][ T7] R13: ffff888100907d08 R14: ffff888100907c50 R15: ffff88800fc78c40 [ 73.223337][ T7] FS: 0000000000000000(0000) GS:ffff888114800000(0000) knlGS:0000000000000000 [ 73.225814][ T7] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 73.227616][ T7] CR2: 0000562b5cb4f4d0 CR3: 0000000105fbe001 CR4: 00000000003706e0 [ 73.229700][ T7] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 73.231820][ T7] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 73.233844][ T7] Call Trace: [ 73.234698][ T7] ? vxlan_err_lookup+0x3c0/0x3c0 [vxlan] [ 73.235962][ T7] ? ops_exit_list.isra.11+0x93/0x140 [ 73.237134][ T7] cleanup_net+0x45e/0x8a0 [ ... ]
Fixes: 57b61127ab7d ("vxlan: speedup vxlan tunnels dismantle") Signed-off-by: Taehee Yoo ap420073@gmail.com Link: https://lore.kernel.org/r/20210221154552.11749-1-ap420073@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/vxlan.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a8ad710629e69..0842371eca3d6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -4725,7 +4725,6 @@ static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan, *next; struct net_device *dev, *aux; - unsigned int h;
for_each_netdev_safe(net, dev, aux) if (dev->rtnl_link_ops == &vxlan_link_ops) @@ -4739,14 +4738,13 @@ static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) unregister_netdevice_queue(vxlan->dev, head); }
- for (h = 0; h < PORT_HASH_SIZE; ++h) - WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h])); }
static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) { struct net *net; LIST_HEAD(list); + unsigned int h;
rtnl_lock(); list_for_each_entry(net, net_list, exit_list) { @@ -4759,6 +4757,13 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
unregister_netdevice_many(&list); rtnl_unlock(); + + list_for_each_entry(net, net_list, exit_list) { + struct vxlan_net *vn = net_generic(net, vxlan_net_id); + + for (h = 0; h < PORT_HASH_SIZE; ++h) + WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h])); + } }
static struct pernet_operations vxlan_net_ops = {
From: Jason A. Donenfeld Jason@zx2c4.com
[ Upstream commit 99fff5264e7ab06f45b0ad60243475be0a8d0559 ]
If skb->protocol doesn't match the actual skb->data header, it's probably not a good idea to pass it off to icmp{,v6}_ndo_send, which is expecting to reply to a valid IP packet. So this commit has that early mismatch case jump to a later error label.
Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireguard/device.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index a3ed49cd95c31..82ce757c852ee 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -138,7 +138,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev) else if (skb->protocol == htons(ETH_P_IPV6)) net_dbg_ratelimited("%s: No peer has allowed IPs matching %pI6\n", dev->name, &ipv6_hdr(skb)->daddr); - goto err; + goto err_icmp; }
family = READ_ONCE(peer->endpoint.addr.sa_family); @@ -201,12 +201,13 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
err_peer: wg_peer_put(peer); -err: - ++dev->stats.tx_errors; +err_icmp: if (skb->protocol == htons(ETH_P_IP)) icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); else if (skb->protocol == htons(ETH_P_IPV6)) icmpv6_ndo_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); +err: + ++dev->stats.tx_errors; kfree_skb(skb); return ret; }
From: Jason A. Donenfeld Jason@zx2c4.com
[ Upstream commit bce2473927af8de12ad131a743f55d69d358c0b9 ]
The condition here was incorrect: a non-neon fallback implementation is available on arm32 when NEON is not supported.
Reported-by: Ilya Lipnitskiy ilya.lipnitskiy@gmail.com Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 260f9f46668b8..63339d29be905 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -87,7 +87,7 @@ config WIREGUARD select CRYPTO_CURVE25519_X86 if X86 && 64BIT select ARM_CRYPTO if ARM select ARM64_CRYPTO if ARM64 - select CRYPTO_CHACHA20_NEON if (ARM || ARM64) && KERNEL_MODE_NEON + select CRYPTO_CHACHA20_NEON if ARM || (ARM64 && KERNEL_MODE_NEON) select CRYPTO_POLY1305_NEON if ARM64 && KERNEL_MODE_NEON select CRYPTO_POLY1305_ARM if ARM select CRYPTO_CURVE25519_NEON if ARM && KERNEL_MODE_NEON
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit c57d117f2b2f2a19b570c36f2819ef8d8210af20 ]
The error handling in this function frees "reg" but it is still on the "o2hb_all_regions" list so it will lead to a use after freew. Joseph Qi points out that we need to clear the bit in the "o2hb_region_bitmap" as well
Link: https://lkml.kernel.org/r/YBk4M6HUG8jB/jc7@mwanda Fixes: 1cf257f51191 ("ocfs2: fix memory leak") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Joseph Qi joseph.qi@linux.alibaba.com Cc: Mark Fasheh mark@fasheh.com Cc: Joel Becker jlbec@evilplan.org Cc: Junxiao Bi junxiao.bi@oracle.com Cc: Changwei Ge gechangwei@live.cn Cc: Gang He ghe@suse.com Cc: Jun Piao piaojun@huawei.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ocfs2/cluster/heartbeat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 0179a73a3fa2c..12a7590601ddb 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -2042,7 +2042,7 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g o2hb_nego_timeout_handler, reg, NULL, ®->hr_handler_list); if (ret) - goto free; + goto remove_item;
ret = o2net_register_handler(O2HB_NEGO_APPROVE_MSG, reg->hr_key, sizeof(struct o2hb_nego_msg), @@ -2057,6 +2057,12 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g
unregister_handler: o2net_unregister_handler_list(®->hr_handler_list); +remove_item: + spin_lock(&o2hb_live_lock); + list_del(®->hr_all_item); + if (o2hb_global_heartbeat_active()) + clear_bit(reg->hr_region_num, o2hb_region_bitmap); + spin_unlock(&o2hb_live_lock); free: kfree(reg); return ERR_PTR(ret);
From: Muchun Song songmuchun@bytedance.com
[ Upstream commit b0ba3bff3e7bb6b58bb248bdd2f3d8ad52fd10c3 ]
Patch series "Convert all THP vmstat counters to pages", v6.
This patch series is aimed to convert all THP vmstat counters to pages.
The unit of some vmstat counters are pages, some are bytes, some are HPAGE_PMD_NR, and some are KiB. When we want to expose these vmstat counters to the userspace, we have to know the unit of the vmstat counters is which one. When the unit is bytes or kB, both clearly distinguishable by the B/KB suffix. But for the THP vmstat counters, we may make mistakes.
For example, the below is some bug fix for the THP vmstat counters:
- 7de2e9f195b9 ("mm: memcontrol: correct the NR_ANON_THPS counter of hierarchical memcg") - The first commit in this series ("fix NR_ANON_THPS accounting in charge moving")
This patch series can make the code clear. And make all the unit of the THP vmstat counters in pages. Finally, the unit of the vmstat counters are pages, kB and bytes. The B/KB suffix can tell us that the unit is bytes or kB. The rest which is without suffix are pages.
In this series, I changed the following vmstat counters unit from HPAGE_PMD_NR to pages. However, there is no change to the print format of output to user space.
- NR_ANON_THPS - NR_FILE_THPS - NR_SHMEM_THPS - NR_SHMEM_PMDMAPPED - NR_FILE_PMDMAPPED
Doing this also can make the statistics more accuracy for the THP vmstat counters. This series is consistent with 8f182270dfec ("mm/swap.c: flush lru pvecs on compound page arrival").
Because we use struct per_cpu_nodestat to cache the vmstat counters, which leads to inaccurate statistics especially THP vmstat counters. In the systems with hundreds of processors it can be GBs of memory. For example, for a 96 CPUs system, the threshold is the maximum number of 125. And the per cpu counters can cache 23.4375 GB in total.
The THP page is already a form of batched addition (it will add 512 worth of memory in one go) so skipping the batching seems like sensible. Although every THP stats update overflows the per-cpu counter, resorting to atomic global updates. But it can make the statistics more accuracy for the THP vmstat counters. From this point of view, I think that do this converting is reasonable.
Thanks Hugh for mentioning this. This was inspired by Johannes and Roman. Thanks to them.
This patch (of 7):
The unit of NR_ANON_THPS is HPAGE_PMD_NR already. So it should inc/dec by one rather than nr_pages.
Link: https://lkml.kernel.org/r/20201228164110.2838-1-songmuchun@bytedance.com Link: https://lkml.kernel.org/r/20201228164110.2838-2-songmuchun@bytedance.com Fixes: 468c398233da ("mm: memcontrol: switch to native NR_ANON_THPS counter") Signed-off-by: Muchun Song songmuchun@bytedance.com Acked-by: Michal Hocko mhocko@suse.com Acked-by: Johannes Weiner hannes@cmpxchg.org Acked-by: Pankaj Gupta pankaj.gupta@cloud.ionos.com Reviewed-by: Roman Gushchin guro@fb.com Reviewed-by: Shakeel Butt shakeelb@google.com Cc: Alexey Dobriyan adobriyan@gmail.com Cc: Feng Tang feng.tang@intel.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Hugh Dickins hughd@google.com Cc: Joonsoo Kim iamjoonsoo.kim@lge.com Cc: NeilBrown neilb@suse.de Cc: Rafael. J. Wysocki rafael@kernel.org Cc: Randy Dunlap rdunlap@infradead.org Cc: Sami Tolvanen samitolvanen@google.com Cc: Vladimir Davydov vdavydov.dev@gmail.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/memcontrol.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 913c2b9e5c72d..9f4db41d8e161 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5637,10 +5637,8 @@ static int mem_cgroup_move_account(struct page *page, __mod_lruvec_state(from_vec, NR_ANON_MAPPED, -nr_pages); __mod_lruvec_state(to_vec, NR_ANON_MAPPED, nr_pages); if (PageTransHuge(page)) { - __mod_lruvec_state(from_vec, NR_ANON_THPS, - -nr_pages); - __mod_lruvec_state(to_vec, NR_ANON_THPS, - nr_pages); + __dec_lruvec_state(from_vec, NR_ANON_THPS); + __inc_lruvec_state(to_vec, NR_ANON_THPS); }
}
From: Muchun Song songmuchun@bytedance.com
[ Upstream commit 96403bfe50c344b587ea53894954a9d152af1c9d ]
SLUB currently account kmalloc() and kmalloc_node() allocations larger than order-1 page per-node. But it forget to update the per-memcg vmstats. So it can lead to inaccurate statistics of "slab_unreclaimable" which is from memory.stat. Fix it by using mod_lruvec_page_state instead of mod_node_page_state.
Link: https://lkml.kernel.org/r/20210223092423.42420-1-songmuchun@bytedance.com Fixes: 6a486c0ad4dc ("mm, sl[ou]b: improve memory accounting") Signed-off-by: Muchun Song songmuchun@bytedance.com Reviewed-by: Shakeel Butt shakeelb@google.com Reviewed-by: Roman Gushchin guro@fb.com Reviewed-by: Michal Koutný mkoutny@suse.com Cc: Johannes Weiner hannes@cmpxchg.org Cc: Michal Hocko mhocko@kernel.org Cc: Vladimir Davydov vdavydov.dev@gmail.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/slab_common.c | 4 ++-- mm/slub.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/mm/slab_common.c b/mm/slab_common.c index e981c80d216c2..0b775cb5c1089 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -837,8 +837,8 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) page = alloc_pages(flags, order); if (likely(page)) { ret = page_address(page); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE_B, - PAGE_SIZE << order); + mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B, + PAGE_SIZE << order); } ret = kasan_kmalloc_large(ret, size, flags); /* As ret might get tagged, call kmemleak hook after KASAN. */ diff --git a/mm/slub.c b/mm/slub.c index b22a4b101c846..69dacc61b8435 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3999,8 +3999,8 @@ static void *kmalloc_large_node(size_t size, gfp_t flags, int node) page = alloc_pages_node(node, flags, order); if (page) { ptr = page_address(page); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE_B, - PAGE_SIZE << order); + mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B, + PAGE_SIZE << order); }
return kmalloc_large_node_hook(ptr, size, flags); @@ -4131,8 +4131,8 @@ void kfree(const void *x)
BUG_ON(!PageCompound(page)); kfree_hook(object); - mod_node_page_state(page_pgdat(page), NR_SLAB_UNRECLAIMABLE_B, - -(PAGE_SIZE << order)); + mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B, + -(PAGE_SIZE << order)); __free_pages(page, order); return; }
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit 90a3e375d324b2255b83e3dd29e99e2b05d82aaf ]
Since commit 42e4089c7890 ("x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings"), when the first pfn modify is not allowed, we would break the loop with pte unchanged. Then the wrong pte - 1 would be passed to pte_unmap_unlock.
Andi said:
"While the fix is correct, I'm not sure if it actually is a real bug. Is there any architecture that would do something else than unlocking the underlying page? If it's just the underlying page then it should be always the same page, so no bug"
Link: https://lkml.kernel.org/r/20210109080118.20885-1-linmiaohe@huawei.com Fixes: 42e4089c789 ("x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings") Signed-off-by: Hongxiang Lou louhongxiang@huawei.com Signed-off-by: Miaohe Lin linmiaohe@huawei.com Cc: Thomas Gleixner tglx@linutronix.de Cc: Dave Hansen dave.hansen@intel.com Cc: Andi Kleen ak@linux.intel.com Cc: Josh Poimboeuf jpoimboe@redhat.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c index 985dac0958dcf..db2a50637569f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2165,11 +2165,11 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, pgprot_t prot) { - pte_t *pte; + pte_t *pte, *mapped_pte; spinlock_t *ptl; int err = 0;
- pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + mapped_pte = pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); if (!pte) return -ENOMEM; arch_enter_lazy_mmu_mode(); @@ -2183,7 +2183,7 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd, pfn++; } while (pte++, addr += PAGE_SIZE, addr != end); arch_leave_lazy_mmu_mode(); - pte_unmap_unlock(pte - 1, ptl); + pte_unmap_unlock(mapped_pte, ptl); return err; }
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit cc2205a67dec5a700227a693fc113441e73e4641 ]
In hugetlb_sysfs_add_hstate(), we would do kobject_put() on hstate_kobjs when failed to create sysfs group but forget to set hstate_kobjs to NULL. Then in hugetlb_register_node() error path, we may free it again via hugetlb_unregister_node().
Link: https://lkml.kernel.org/r/20210107123249.36964-1-linmiaohe@huawei.com Fixes: a3437870160c ("hugetlb: new sysfs interface") Signed-off-by: Miaohe Lin linmiaohe@huawei.com Reviewed-by: Mike Kravetz mike.kravetz@oracle.com Reviewed-by: Muchun Song smuchun@gmail.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/hugetlb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 4bdb58ab14cbb..bc61eea60e07e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2988,8 +2988,10 @@ static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent, return -ENOMEM;
retval = sysfs_create_group(hstate_kobjs[hi], hstate_attr_group); - if (retval) + if (retval) { kobject_put(hstate_kobjs[hi]); + hstate_kobjs[hi] = NULL; + }
return retval; }
From: Chen Wandun chenwandun@huawei.com
[ Upstream commit 7ecc956551f8a66618f71838c790a9b0b4f9ca10 ]
If hugetlb_cma is enabled, it will skip boot time allocation when allocating gigantic page, that doesn't means allocation failure, so suppress this warning info.
Link: https://lkml.kernel.org/r/20210219123909.13130-1-chenwandun@huawei.com Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") Signed-off-by: Chen Wandun chenwandun@huawei.com Reviewed-by: Mike Kravetz mike.kravetz@oracle.com Cc: Roman Gushchin guro@fb.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/hugetlb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index bc61eea60e07e..63d15f0a6629f 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2520,7 +2520,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h) if (hstate_is_gigantic(h)) { if (hugetlb_cma_size) { pr_warn_once("HugeTLB: hugetlb_cma is enabled, skip boot time allocation\n"); - break; + goto free; } if (!alloc_bootmem_huge_page(h)) break; @@ -2538,7 +2538,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h) h->max_huge_pages, buf, i); h->max_huge_pages = i; } - +free: kfree(node_alloc_noretry); }
From: Wonhyuk Yang vvghjk1234@gmail.com
[ Upstream commit 15d28d0d11609c7a4f217b3d85e26456d9beb134 ]
In the fast_find_migrateblock(), it iterates ocer the freelist to find the proper pageblock. But there are some misbehaviors.
First, if the page we found is equal to cc->migrate_pfn, it is considered that we didn't find a suitable pageblock. Secondly, if the loop was terminated because order is less than PAGE_ALLOC_COSTLY_ORDER, it could be considered that we found a suitable one. Thirdly, if the skip bit is set on the page block and we goto continue, it doesn't check nr_scanned. Fourthly, if the page block's skip bit is set, it checks that page block is the last of list, which is unnecessary.
Link: https://lkml.kernel.org/r/20210128130411.6125-1-vvghjk1234@gmail.com Fixes: 70b44595eafe9 ("mm, compaction: use free lists to quickly locate a migration source") Signed-off-by: Wonhyuk Yang vvghjk1234@gmail.com Acked-by: Vlastimil Babka vbabka@suse.cz Cc: Mel Gorman mgorman@techsingularity.net Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- mm/compaction.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c index 190ccdaa6c192..2135c32efe8be 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -1702,6 +1702,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) unsigned long pfn = cc->migrate_pfn; unsigned long high_pfn; int order; + bool found_block = false;
/* Skip hints are relied on to avoid repeats on the fast search */ if (cc->ignore_skip_hint) @@ -1744,7 +1745,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) high_pfn = pageblock_start_pfn(cc->migrate_pfn + distance);
for (order = cc->order - 1; - order >= PAGE_ALLOC_COSTLY_ORDER && pfn == cc->migrate_pfn && nr_scanned < limit; + order >= PAGE_ALLOC_COSTLY_ORDER && !found_block && nr_scanned < limit; order--) { struct free_area *area = &cc->zone->free_area[order]; struct list_head *freelist; @@ -1759,7 +1760,11 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) list_for_each_entry(freepage, freelist, lru) { unsigned long free_pfn;
- nr_scanned++; + if (nr_scanned++ >= limit) { + move_freelist_tail(freelist, freepage); + break; + } + free_pfn = page_to_pfn(freepage); if (free_pfn < high_pfn) { /* @@ -1768,12 +1773,8 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) * the list assumes an entry is deleted, not * reordered. */ - if (get_pageblock_skip(freepage)) { - if (list_is_last(freelist, &freepage->lru)) - break; - + if (get_pageblock_skip(freepage)) continue; - }
/* Reorder to so a future search skips recent pages */ move_freelist_tail(freelist, freepage); @@ -1781,15 +1782,10 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) update_fast_start_pfn(cc, free_pfn); pfn = pageblock_start_pfn(free_pfn); cc->fast_search_fail = 0; + found_block = true; set_pageblock_skip(freepage); break; } - - if (nr_scanned >= limit) { - cc->fast_search_fail++; - move_freelist_tail(freelist, freepage); - break; - } } spin_unlock_irqrestore(&cc->zone->lock, flags); } @@ -1800,9 +1796,10 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc) * If fast scanning failed then use a cached entry for a page block * that had free pages as the basis for starting a linear scan. */ - if (pfn == cc->migrate_pfn) + if (!found_block) { + cc->fast_search_fail++; pfn = reinit_migrate_pfn(cc); - + } return pfn; }
From: Christian Melki christian.melki@t2data.com
[ Upstream commit 764d31cacfe48440745c4bbb55a62ac9471c9f19 ]
Following a similar reinstate for the KSZ9031.
Older kernels would use the genphy_soft_reset if the PHY did not implement a .soft_reset.
Bluntly removing that default may expose a lot of situations where various PHYs/board implementations won't recover on various changes. Like with this implementation during a 4.9.x to 5.4.x LTS transition. I think it's a good thing to remove unwanted soft resets but wonder if it did open a can of worms?
Atleast this fixes one iMX6 FEC/RMII/8081 combo.
Fixes: 6e2d85ec0559 ("net: phy: Stop with excessive soft reset") Signed-off-by: Christian Melki christian.melki@t2data.com Reviewed-by: Andrew Lunn andrew@lunn.ch Link: https://lore.kernel.org/r/20210224205536.9349-1-christian.melki@t2data.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/micrel.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 54e0d75203dac..57f8021b70af5 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1295,6 +1295,7 @@ static struct phy_driver ksphy_driver[] = { .driver_data = &ksz8081_type, .probe = kszphy_probe, .config_init = ksz8081_config_init, + .soft_reset = genphy_soft_reset, .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt, .get_sset_count = kszphy_get_sset_count,
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 6cf739131a15e4177e58a1b4f2bede9d5da78552 ]
Josef reported [0] that using jumbo packets fails on RTL8168e. Aligning the values for register MaxTxPacketSize with the vendor driver fixes the problem.
[0] https://bugzilla.kernel.org/show_bug.cgi?id=211827
Fixes: d58d46b5d851 ("r8169: jumbo fixes.") Reported-by: Josef Oškera joskera@redhat.com Tested-by: Josef Oškera joskera@redhat.com Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Link: https://lore.kernel.org/r/b15ddef7-0d50-4320-18f4-6a3f86fbfd3e@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/realtek/r8169_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 0d78408b4e269..470ff6b3ebef1 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -2315,14 +2315,14 @@ static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) { - RTL_W8(tp, MaxTxPacketSize, 0x3f); + RTL_W8(tp, MaxTxPacketSize, 0x24); RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01); }
static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) { - RTL_W8(tp, MaxTxPacketSize, 0x0c); + RTL_W8(tp, MaxTxPacketSize, 0x3f); RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01); }
From: Trond Myklebust trond.myklebust@hammerspace.com
[ Upstream commit 45901a231723a5a513ff08477983f3a274a6a910 ]
We don't want to ask for the ACL in a WRITE reply, since we don't have a preallocated buffer.
Instead of checking NFS_INO_INVALID_ACCESS, which is really about managing the access cache, we should look at the value of NFS_INO_INVALID_OTHER. Also ensure we assign the mode, owner and owner_group flags to the correct bit mask.
Finally, fix up the check for NFS_INO_INVALID_CTIME to retrieve the ctime, and add a check for NFS_INO_INVALID_CHANGE.
Fixes: 76bd5c016ef4 ("NFSv4: make cache consistency bitmask dynamic") Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/nfs/nfs4proc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 2f4679a62712a..fc8bbfd9beb36 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5438,15 +5438,16 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
if (cache_validity & NFS_INO_INVALID_ATIME) bitmask[1] |= FATTR4_WORD1_TIME_ACCESS; - if (cache_validity & NFS_INO_INVALID_ACCESS) - bitmask[0] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | - FATTR4_WORD1_OWNER_GROUP; - if (cache_validity & NFS_INO_INVALID_ACL) - bitmask[0] |= FATTR4_WORD0_ACL; - if (cache_validity & NFS_INO_INVALID_LABEL) + if (cache_validity & NFS_INO_INVALID_OTHER) + bitmask[1] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | + FATTR4_WORD1_OWNER_GROUP | + FATTR4_WORD1_NUMLINKS; + if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL) bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL; - if (cache_validity & NFS_INO_INVALID_CTIME) + if (cache_validity & NFS_INO_INVALID_CHANGE) bitmask[0] |= FATTR4_WORD0_CHANGE; + if (cache_validity & NFS_INO_INVALID_CTIME) + bitmask[1] |= FATTR4_WORD1_TIME_METADATA; if (cache_validity & NFS_INO_INVALID_MTIME) bitmask[1] |= FATTR4_WORD1_TIME_MODIFY; if (cache_validity & NFS_INO_INVALID_SIZE)
From: Sean Christopherson seanjc@google.com
[ Upstream commit 0a8ed2eaac102c746d8d114f2787f06cb3e55dfb ]
Intercept INVPCID if it's disabled in the guest, even when using NPT, as KVM needs to inject #UD in this case.
Fixes: 4407a797e941 ("KVM: SVM: Enable INVPCID feature on AMD") Cc: Babu Moger babu.moger@amd.com Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210212003411.1102677-2-seanjc@google.com Reviewed-by: Jim Mattson jmattson@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/svm/svm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 3442d44ca53b8..825ef6d281c98 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1105,12 +1105,12 @@ static u64 svm_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) static void svm_check_invpcid(struct vcpu_svm *svm) { /* - * Intercept INVPCID instruction only if shadow page table is - * enabled. Interception is not required with nested page table - * enabled. + * Intercept INVPCID if shadow paging is enabled to sync/free shadow + * roots, or if INVPCID is disabled in the guest to inject #UD. */ if (kvm_cpu_cap_has(X86_FEATURE_INVPCID)) { - if (!npt_enabled) + if (!npt_enabled || + !guest_cpuid_has(&svm->vcpu, X86_FEATURE_INVPCID)) svm_set_intercept(svm, INTERCEPT_INVPCID); else svm_clr_intercept(svm, INTERCEPT_INVPCID);
From: Sean Christopherson seanjc@google.com
[ Upstream commit c060c72ffeb448fbb5864faa1f672ebfe14dd25f ]
Zap SPTEs that are backed by ZONE_DEVICE pages when zappings SPTEs to rebuild them as huge pages in the TDP MMU. ZONE_DEVICE huge pages are managed differently than "regular" pages and are not compound pages. Likewise, PageTransCompoundMap() will not detect HugeTLB, so switch to PageCompound().
This matches the similar check in kvm_mmu_zap_collapsible_spte.
Cc: Ben Gardon bgardon@google.com Fixes: 14881998566d ("kvm: x86/mmu: Support disabling dirty logging for the tdp MMU") Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20210213005015.1651772-2-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/mmu/tdp_mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index b56d604809b8a..17976998bffbc 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1067,7 +1067,8 @@ static void zap_collapsible_spte_range(struct kvm *kvm,
pfn = spte_to_pfn(iter.old_spte); if (kvm_is_reserved_pfn(pfn) || - !PageTransCompoundMap(pfn_to_page(pfn))) + (!PageCompound(pfn_to_page(pfn)) && + !kvm_is_zone_device_pfn(pfn))) continue;
tdp_mmu_set_spte(kvm, &iter, 0);
From: YueHaibing yuehaibing@huawei.com
[ Upstream commit af982da9a612295a91f367469f8945c916a20dfd ]
Fix inconsistent IS_ERR and PTR_ERR in cifs_find_swn_reg(). The proper pointer to be passed as argument to PTR_ERR() is share_name.
This bug was detected with the help of Coccinelle.
Fixes: bf80e5d4259a ("cifs: Send witness register and unregister commands to userspace daemon") Signed-off-by: YueHaibing yuehaibing@huawei.com Reviewed-by: Samuel Cabrero scabrero@suse.de Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/cifs/cifs_swn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/cifs/cifs_swn.c b/fs/cifs/cifs_swn.c index d35f599aa00e6..f2d730fffccb3 100644 --- a/fs/cifs/cifs_swn.c +++ b/fs/cifs/cifs_swn.c @@ -272,7 +272,7 @@ static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon) if (IS_ERR(share_name)) { int ret;
- ret = PTR_ERR(net_name); + ret = PTR_ERR(share_name); cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n", __func__, tcon->treeName, ret); kfree(net_name);
From: Marc Zyngier maz@kernel.org
[ Upstream commit 9d41053e8dc115c92b8002c3db5f545d7602498b ]
Although there has been a bit of back and forth on the subject, it appears that invalidating TLBs requires an ISB instruction when FEAT_ETS is not implemented by the CPU.
From the bible:
| In an implementation that does not implement FEAT_ETS, a TLB | maintenance instruction executed by a PE, PEx, can complete at any | time after it is issued, but is only guaranteed to be finished for a | PE, PEx, after the execution of DSB by the PEx followed by a Context | synchronization event
Add the missing ISB in __primary_switch, just in case.
Fixes: 3c5e9f238bc4 ("arm64: head.S: move KASLR processing out of __enable_mmu()") Suggested-by: Will Deacon will@kernel.org Signed-off-by: Marc Zyngier maz@kernel.org Acked-by: Mark Rutland mark.rutland@arm.com Link: https://lore.kernel.org/r/20210224093738.3629662-3-maz@kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/kernel/head.S | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index a0dc987724eda..7ec430e18f95e 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -882,6 +882,7 @@ SYM_FUNC_START_LOCAL(__primary_switch)
tlbi vmalle1 // Remove any stale TLB entries dsb nsh + isb
msr sctlr_el1, x19 // re-enable the MMU isb
From: Maxime Ripard maxime@cerno.tech
[ Upstream commit a1858ce0cfe31368b23ba55794e409fb57ced4a4 ]
The brcmstb_send_i2c_cmd currently has a condition that is (CMD_RD || CMD_WR) which always evaluates to true, while the obvious fix is to test whether the cmd variable passed as parameter holds one of these two values.
Fixes: dd1aa2524bc5 ("i2c: brcmstb: Add Broadcom settop SoC i2c controller driver") Reported-by: Dave Stevenson dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard maxime@cerno.tech Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-brcmstb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index d4e0a0f6732ae..ba766d24219ef 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -316,7 +316,7 @@ static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev, goto cmd_out; }
- if ((CMD_RD || CMD_WR) && + if ((cmd == CMD_RD || cmd == CMD_WR) && bsc_readl(dev, iic_enable) & BSC_IIC_EN_NOACK_MASK) { rc = -EREMOTEIO; dev_dbg(dev->device, "controller received NOACK intr for %s\n",
From: Mårten Lindahl martenli@axis.com
[ Upstream commit f4ff0104d4c807a7f96aa3358c03d694895ee8ea ]
When the driver starts to send a message with the MASTER_ID field set (high speed), the whole I2C_ADDR register is overwritten including MASTER_ID as the SLV_ADDR_MAS field is set.
This patch preserves already written fields in I2C_ADDR when writing SLV_ADDR_MAS.
Fixes: 8a73cd4cfa15 ("i2c: exynos5: add High Speed I2C controller driver") Signed-off-by: Mårten Lindahl martenli@axis.com Reviewed-by: Krzysztof Kozlowski krzk@kernel.org Tested-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/i2c/busses/i2c-exynos5.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 20a9881a0d6cd..5ac30d95650cc 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -606,6 +606,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) u32 i2c_ctl; u32 int_en = 0; u32 i2c_auto_conf = 0; + u32 i2c_addr = 0; u32 fifo_ctl; unsigned long flags; unsigned short trig_lvl; @@ -640,7 +641,12 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN; }
- writel(HSI2C_SLV_ADDR_MAS(i2c->msg->addr), i2c->regs + HSI2C_ADDR); + i2c_addr = HSI2C_SLV_ADDR_MAS(i2c->msg->addr); + + if (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) + i2c_addr |= HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)); + + writel(i2c_addr, i2c->regs + HSI2C_ADDR);
writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); writel(i2c_ctl, i2c->regs + HSI2C_CTL);
From: Rik van Riel riel@surriel.com
[ Upstream commit cd89fb06509903f942a0ffe97ffa63034671ed0c ]
Currently if thp enabled=[madvise], mounting a tmpfs filesystem with huge=always and mmapping files from that tmpfs does not result in khugepaged collapsing those mappings, despite the mount flag indicating that it should.
Fix that by breaking up the blocks of tests in hugepage_vma_check a little bit, and testing things in the correct order.
Link: https://lkml.kernel.org/r/20201124194925.623931-4-riel@surriel.com Fixes: c2231020ea7b ("mm: thp: register mm for khugepaged when merging vma for shmem") Signed-off-by: Rik van Riel riel@surriel.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Hugh Dickins hughd@google.com Cc: Matthew Wilcox (Oracle) willy@infradead.org Cc: Mel Gorman mgorman@suse.de Cc: Michal Hocko mhocko@suse.com Cc: Vlastimil Babka vbabka@suse.cz Cc: Xu Yu xuyu@linux.alibaba.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/khugepaged.h | 2 ++ mm/khugepaged.c | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h index c941b73773216..2fcc01891b474 100644 --- a/include/linux/khugepaged.h +++ b/include/linux/khugepaged.h @@ -3,6 +3,7 @@ #define _LINUX_KHUGEPAGED_H
#include <linux/sched/coredump.h> /* MMF_VM_HUGEPAGE */ +#include <linux/shmem_fs.h>
#ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -57,6 +58,7 @@ static inline int khugepaged_enter(struct vm_area_struct *vma, { if (!test_bit(MMF_VM_HUGEPAGE, &vma->vm_mm->flags)) if ((khugepaged_always() || + (shmem_file(vma->vm_file) && shmem_huge_enabled(vma)) || (khugepaged_req_madv() && (vm_flags & VM_HUGEPAGE))) && !(vm_flags & VM_NOHUGEPAGE) && !test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 67ab391a53739..494d3cb0b58a3 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -442,18 +442,28 @@ static inline int khugepaged_test_exit(struct mm_struct *mm) static bool hugepage_vma_check(struct vm_area_struct *vma, unsigned long vm_flags) { - if ((!(vm_flags & VM_HUGEPAGE) && !khugepaged_always()) || - (vm_flags & VM_NOHUGEPAGE) || + /* Explicitly disabled through madvise. */ + if ((vm_flags & VM_NOHUGEPAGE) || test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) return false;
- if (shmem_file(vma->vm_file) || - (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && - vma->vm_file && - (vm_flags & VM_DENYWRITE))) { + /* Enabled via shmem mount options or sysfs settings. */ + if (shmem_file(vma->vm_file) && shmem_huge_enabled(vma)) { return IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff, HPAGE_PMD_NR); } + + /* THP settings require madvise. */ + if (!(vm_flags & VM_HUGEPAGE) && !khugepaged_always()) + return false; + + /* Read-only file mappings need to be aligned for THP to work. */ + if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && vma->vm_file && + (vm_flags & VM_DENYWRITE)) { + return IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff, + HPAGE_PMD_NR); + } + if (!vma->anon_vma || vma->vm_ops) return false; if (vma_is_temporary_stack(vma))
From: Dan Williams dan.j.williams@intel.com
[ Upstream commit 34dc45be4563f344d59ba0428416d0d265aa4f4d ]
Given 'struct dev_pagemap' spans both data pages and metadata pages be careful to consult the altmap if present to delineate metadata. In fact the pfn_first() helper already identifies the first valid data pfn, so export that helper for other code paths via pgmap_pfn_valid().
Other usage of get_dev_pagemap() are not a concern because those are operating on known data pfns having been looked up by get_user_pages(). I.e. metadata pfns are never user mapped.
Link: https://lkml.kernel.org/r/161058501758.1840162.4239831989762604527.stgit@dwi... Fixes: 6100e34b2526 ("mm, memory_failure: Teach memory_failure() about dev_pagemap pages") Signed-off-by: Dan Williams dan.j.williams@intel.com Reported-by: David Hildenbrand david@redhat.com Reviewed-by: David Hildenbrand david@redhat.com Reviewed-by: Naoya Horiguchi naoya.horiguchi@nec.com Cc: Michal Hocko mhocko@suse.com Cc: Oscar Salvador osalvador@suse.de Cc: Qian Cai cai@lca.pw Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/memremap.h | 6 ++++++ mm/memory-failure.c | 6 ++++++ mm/memremap.c | 15 +++++++++++++++ 3 files changed, 27 insertions(+)
diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 79c49e7f5c304..f5b464daeeca5 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h @@ -137,6 +137,7 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap); struct dev_pagemap *get_dev_pagemap(unsigned long pfn, struct dev_pagemap *pgmap); +bool pgmap_pfn_valid(struct dev_pagemap *pgmap, unsigned long pfn);
unsigned long vmem_altmap_offset(struct vmem_altmap *altmap); void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns); @@ -165,6 +166,11 @@ static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, return NULL; }
+static inline bool pgmap_pfn_valid(struct dev_pagemap *pgmap, unsigned long pfn) +{ + return false; +} + static inline unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) { return 0; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index e9481632fcd1b..4e3684d694c12 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1308,6 +1308,12 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags, */ put_page(page);
+ /* device metadata space is not recoverable */ + if (!pgmap_pfn_valid(pgmap, pfn)) { + rc = -ENXIO; + goto out; + } + /* * Prevent the inode from being freed while we are interrogating * the address_space, typically this would be handled by diff --git a/mm/memremap.c b/mm/memremap.c index 16b2fb482da11..2455bac895066 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -80,6 +80,21 @@ static unsigned long pfn_first(struct dev_pagemap *pgmap, int range_id) return pfn + vmem_altmap_offset(pgmap_altmap(pgmap)); }
+bool pgmap_pfn_valid(struct dev_pagemap *pgmap, unsigned long pfn) +{ + int i; + + for (i = 0; i < pgmap->nr_range; i++) { + struct range *range = &pgmap->ranges[i]; + + if (pfn >= PHYS_PFN(range->start) && + pfn <= PHYS_PFN(range->end)) + return pfn >= pfn_first(pgmap, i); + } + + return false; +} + static unsigned long pfn_end(struct dev_pagemap *pgmap, int range_id) { const struct range *range = &pgmap->ranges[range_id];
From: Miaohe Lin linmiaohe@huawei.com
[ Upstream commit 5d5d19eda6b0ee790af89c45e3f678345be6f50f ]
For PMD-mapped page (usually THP), pvmw->pte is NULL. For PTE-mapped THP, pvmw->pte is mapped. But for HugeTLB pages, pvmw->pte is not mapped and set to the relevant page table entry. So in page_vma_mapped_walk_done(), we may do pte_unmap() for HugeTLB pte which is not mapped. Fix this by checking pvmw->page against PageHuge before trying to do pte_unmap().
Link: https://lkml.kernel.org/r/20210127093349.39081-1-linmiaohe@huawei.com Fixes: ace71a19cec5 ("mm: introduce page_vma_mapped_walk()") Signed-off-by: Hongxiang Lou louhongxiang@huawei.com Signed-off-by: Miaohe Lin linmiaohe@huawei.com Tested-by: Sedat Dilek sedat.dilek@gmail.com Cc: Kees Cook keescook@chromium.org Cc: Nathan Chancellor natechancellor@gmail.com Cc: Mike Kravetz mike.kravetz@oracle.com Cc: Shakeel Butt shakeelb@google.com Cc: Johannes Weiner hannes@cmpxchg.org Cc: Vlastimil Babka vbabka@suse.cz Cc: Michel Lespinasse walken@google.com Cc: Nick Desaulniers ndesaulniers@google.com Cc: "Kirill A. Shutemov" kirill.shutemov@linux.intel.com Cc: Wei Yang richard.weiyang@linux.alibaba.com Cc: Dmitry Safonov 0x7f454c46@gmail.com Cc: Brian Geffon bgeffon@google.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/rmap.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 70085ca1a3fc9..def5c62c93b3b 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -213,7 +213,8 @@ struct page_vma_mapped_walk {
static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) { - if (pvmw->pte) + /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ + if (pvmw->pte && !PageHuge(pvmw->page)) pte_unmap(pvmw->pte); if (pvmw->ptl) spin_unlock(pvmw->ptl);
From: Josef Bacik josef@toxicpanda.com
[ Upstream commit 4508943794efdd94171549c0bd52810e2f4ad9fe ]
Since
sysctl: pass kernel pointers to ->proc_handler
we have been pre-allocating a buffer to copy the data from the proc handlers into, and then copying that to userspace. The problem is this just blindly kzalloc()'s the buffer size passed in from the read, which in the case of our 'cat' binary was 64kib. Order-4 allocations are not awesome, and since we can potentially allocate up to our maximum order, so use kvzalloc for these buffers.
[willy@infradead.org: changelog tweaks]
Link: https://lkml.kernel.org/r/6345270a2c1160b89dd5e6715461f388176899d1.161297241... Fixes: 32927393dc1c ("sysctl: pass kernel pointers to ->proc_handler") Signed-off-by: Josef Bacik josef@toxicpanda.com Reviewed-by: Christoph Hellwig hch@lst.de Acked-by: Vlastimil Babka vbabka@suse.cz Cc: Al Viro viro@zeniv.linux.org.uk Cc: Alexey Dobriyan adobriyan@gmail.com CC: Matthew Wilcox willy@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/proc/proc_sysctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index d2018f70d1fae..070d2df8ab9cf 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -571,7 +571,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter, error = -ENOMEM; if (count >= KMALLOC_MAX_SIZE) goto out; - kbuf = kzalloc(count + 1, GFP_KERNEL); + kbuf = kvzalloc(count + 1, GFP_KERNEL); if (!kbuf) goto out;
@@ -600,7 +600,7 @@ static ssize_t proc_sys_call_handler(struct kiocb *iocb, struct iov_iter *iter,
error = count; out_free_buf: - kfree(kbuf); + kvfree(kbuf); out: sysctl_head_finish(head);
From: Zhenzhong Duan zhenzhong.duan@gmail.com
[ Upstream commit 8bfb676492da208bd6dde0f22dff79840dbb5051 ]
"*" is missed in size determination as we are passing register set rather than a pointer.
Fixes: dcad7854fcce ("sky: switch to ->regset_get()") Signed-off-by: Zhenzhong Duan zhenzhong.duan@gmail.com Signed-off-by: Guo Ren guoren@linux.alibaba.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/csky/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c index d822144906ac1..a4cf2e2ac15ac 100644 --- a/arch/csky/kernel/ptrace.c +++ b/arch/csky/kernel/ptrace.c @@ -83,7 +83,7 @@ static int gpr_get(struct task_struct *target, /* Abiv1 regs->tls is fake and we need sync here. */ regs->tls = task_thread_info(target)->tp_value;
- return membuf_write(&to, regs, sizeof(regs)); + return membuf_write(&to, regs, sizeof(*regs)); }
static int gpr_set(struct task_struct *target,
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit eefb816acb0162e94a85a857f3a55148f671d5a5 ]
CNIC depends on MMU, but since 'select' does not follow any dependency chains, SCSI_BNX2X_FCOE also needs to depend on MMU, so that erroneous configs are not generated, which cause build errors in cnic.
WARNING: unmet direct dependencies detected for CNIC Depends on [n]: NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_BROADCOM [=y] && PCI [=y] && (IPV6 [=n] || IPV6 [=n]=n) && MMU [=n] Selected by [y]: - SCSI_BNX2X_FCOE [=y] && SCSI_LOWLEVEL [=y] && SCSI [=y] && PCI [=y] && (IPV6 [=n] || IPV6 [=n]=n) && LIBFC [=y] && LIBFCOE [=y]
riscv64-linux-ld: drivers/net/ethernet/broadcom/cnic.o: in function `.L154': cnic.c:(.text+0x1094): undefined reference to `uio_event_notify' riscv64-linux-ld: cnic.c:(.text+0x10bc): undefined reference to `uio_event_notify' riscv64-linux-ld: drivers/net/ethernet/broadcom/cnic.o: in function `.L1442': cnic.c:(.text+0x96a8): undefined reference to `__uio_register_device' riscv64-linux-ld: drivers/net/ethernet/broadcom/cnic.o: in function `.L0 ': cnic.c:(.text.unlikely+0x68): undefined reference to `uio_unregister_device'
Link: https://lore.kernel.org/r/20210213192428.22537-1-rdunlap@infradead.org Fixes: 853e2bd2103a ("[SCSI] bnx2fc: Broadcom FCoE offload driver") Cc: Saurav Kashyap skashyap@marvell.com Cc: Javed Hasan jhasan@marvell.com Cc: GR-QLogic-Storage-Upstream@marvell.com Cc: "James E.J. Bottomley" jejb@linux.ibm.com Cc: "Martin K. Petersen" martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org Reported-by: kernel test robot lkp@intel.com Signed-off-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/bnx2fc/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig index 3cf7e08df8093..ecdc0f0f4f4e6 100644 --- a/drivers/scsi/bnx2fc/Kconfig +++ b/drivers/scsi/bnx2fc/Kconfig @@ -5,6 +5,7 @@ config SCSI_BNX2X_FCOE depends on (IPV6 || IPV6=n) depends on LIBFC depends on LIBFCOE + depends on MMU select NETDEVICES select ETHERNET select NET_VENDOR_BROADCOM
From: Johannes Thumshirn johannes.thumshirn@wdc.com
[ Upstream commit 9acced3f58ad24407c1f9ebf53a8892c1e24cdb5 ]
Dan reported we're passing in GFP_NOIO to kvmalloc() which will then fallback to doing kmalloc() instead of an optional vmalloc() if the size exceeds kmalloc()s limits. This will break with drives that have zone numbers exceeding PAGE_SIZE/sizeof(u32).
Instead of passing in GFP_NOIO, enter an implicit GFP_NOIO allocation scope.
Link: https://lore.kernel.org/r/YCuvSfKw4qEQBr/t@mwanda Link: https://lore.kernel.org/r/5a6345e2989fd06c049ac4e4627f6acb492c15b8.161356982... Fixes: 5795eb443060: ("scsi: sd_zbc: emulate ZONE_APPEND commands") Cc: Damien Le Moal Damien.LeMoal@wdc.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Johannes Thumshirn johannes.thumshirn@wdc.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/sd_zbc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index cf07b7f935790..87a7274e4632b 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -688,6 +688,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) unsigned int nr_zones = sdkp->rev_nr_zones; u32 max_append; int ret = 0; + unsigned int flags;
/* * For all zoned disks, initialize zone append emulation data if not @@ -720,16 +721,19 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) disk->queue->nr_zones == nr_zones) goto unlock;
+ flags = memalloc_noio_save(); sdkp->zone_blocks = zone_blocks; sdkp->nr_zones = nr_zones; - sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_NOIO); + sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL); if (!sdkp->rev_wp_offset) { ret = -ENOMEM; + memalloc_noio_restore(flags); goto unlock; }
ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
+ memalloc_noio_restore(flags); kvfree(sdkp->rev_wp_offset); sdkp->rev_wp_offset = NULL;
From: Christoph Hellwig hch@lst.de
[ Upstream commit 4601b4b130de2329fe06df80ed5d77265f2058e5 ]
Historically the BLKRRPART ioctls called into the now defunct ->revalidate method, which caused the sd driver to check if any media is present. When the ->revalidate method was removed this revalidation was lost, leading to lots of I/O errors when using the eject command. Fix this by reopening the device to rescan the partitions, and thus calling the revalidation logic in the sd driver.
Fixes: 471bd0af544b ("sd: use bdev_check_media_change") Reported--by: Tom Seewald tseewald@gmail.com Signed-off-by: Christoph Hellwig hch@lst.de Tested-by: Tom Seewald tseewald@gmail.com Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Minwoo Im minwoo.im.dev@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/ioctl.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/block/ioctl.c b/block/ioctl.c index d61d652078f41..ff241e663c018 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -81,20 +81,27 @@ static int compat_blkpg_ioctl(struct block_device *bdev, } #endif
-static int blkdev_reread_part(struct block_device *bdev) +static int blkdev_reread_part(struct block_device *bdev, fmode_t mode) { - int ret; + struct block_device *tmp;
if (!disk_part_scan_enabled(bdev->bd_disk) || bdev_is_partition(bdev)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- mutex_lock(&bdev->bd_mutex); - ret = bdev_disk_changed(bdev, false); - mutex_unlock(&bdev->bd_mutex); + /* + * Reopen the device to revalidate the driver state and force a + * partition rescan. + */ + mode &= ~FMODE_EXCL; + set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
- return ret; + tmp = blkdev_get_by_dev(bdev->bd_dev, mode, NULL); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); + blkdev_put(tmp, mode); + return 0; }
static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, @@ -498,7 +505,7 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE; return 0; case BLKRRPART: - return blkdev_reread_part(bdev); + return blkdev_reread_part(bdev, mode); case BLKTRACESTART: case BLKTRACESTOP: case BLKTRACETEARDOWN:
From: Ming Lei ming.lei@redhat.com
[ Upstream commit 452c0bf8754fbeffdf579465b82a3c2bbe373c95 ]
Local variable of 'capacity' stores the previous disk capacity, and 'size' variable records the latest disk capacity, so swap them for fixing logging on capacity change.
Cc: Christoph Hellwig hch@lst.de Fixes: a782483cc1f8 ("block: remove the nr_sects field in struct hd_struct") Signed-off-by: Ming Lei ming.lei@redhat.com Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- block/genhd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/genhd.c b/block/genhd.c index 9e741a4f351be..07a0ef741de19 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -74,7 +74,7 @@ bool set_capacity_and_notify(struct gendisk *disk, sector_t size) return false;
pr_info("%s: detected capacity change from %lld to %lld\n", - disk->disk_name, size, capacity); + disk->disk_name, capacity, size);
/* * Historically we did not send a uevent for changes to/from an empty
From: Finn Thain fthain@telegraphics.com.au
[ Upstream commit 07f1dc8cc85bbfb2f9270f25060c4755f4509f45 ]
Unloading the falconide module results in a crash:
Unable to handle kernel NULL pointer dereference at virtual address 00000000 Oops: 00000000 Modules linked in: falconide(-) PC: [<002930b2>] ide_host_remove+0x2e/0x1d2 SR: 2000 SP: 00b49e28 a2: 009b0f90 d0: 00000000 d1: 009b0f90 d2: 00000000 d3: 00b48000 d4: 003cef32 d5: 00299188 a0: 0086d000 a1: 0086d000 Process rmmod (pid: 322, task=009b0f90) Frame format=7 eff addr=00000000 ssw=0505 faddr=00000000 wb 1 stat/addr/data: 0000 00000000 00000000 wb 2 stat/addr/data: 0000 00000000 00000000 wb 3 stat/addr/data: 0000 00000000 00018da9 push data: 00000000 00000000 00000000 00000000 Stack from 00b49e90: 004c456a 0027f176 0027cb0a 0027cb9e 00000000 0086d00a 2187d3f0 0027f0e0 00b49ebc 2187d1f6 00000000 00b49ec8 002811e8 0086d000 00b49ef0 0028024c 0086d00a 002800d6 00279a1a 00000001 00000001 0086d00a 2187d3f0 00279a58 00b49f1c 002802e0 0086d00a 2187d3f0 004c456a 0086d00a ef96af74 00000000 2187d3f0 002805d2 800de064 00b49f44 0027f088 2187d3f0 00ac1cf4 2187d3f0 004c43be 2187d3f0 00000000 2187d3f0 800b66a8 00b49f5c 00280776 2187d3f0 Call Trace: [<0027f176>] __device_driver_unlock+0x0/0x48 [<0027cb0a>] device_links_busy+0x0/0x94 [<0027cb9e>] device_links_unbind_consumers+0x0/0x130 [<0027f0e0>] __device_driver_lock+0x0/0x5a [<2187d1f6>] falconide_remove+0x12/0x18 [falconide] [<002811e8>] platform_drv_remove+0x1c/0x28 [<0028024c>] device_release_driver_internal+0x176/0x17c [<002800d6>] device_release_driver_internal+0x0/0x17c [<00279a1a>] get_device+0x0/0x22 [<00279a58>] put_device+0x0/0x18 [<002802e0>] driver_detach+0x56/0x82 [<002805d2>] driver_remove_file+0x0/0x24 [<0027f088>] bus_remove_driver+0x4c/0xa4 [<00280776>] driver_unregister+0x28/0x5a [<00281a00>] platform_driver_unregister+0x12/0x18 [<2187d2a0>] ide_falcon_driver_exit+0x10/0x16 [falconide] [<000764f0>] sys_delete_module+0x110/0x1f2 [<000e83ea>] sys_rename+0x1a/0x1e [<00002e0c>] syscall+0x8/0xc [<00188004>] ext4_multi_mount_protect+0x35a/0x3ce Code: 0029 9188 4bf9 0027 aa1c 283c 003c ef32 <265c> 4a8b 6700 00b8 2043 2028 000c 0280 00ff ff00 6600 0176 40c0 7202 b2b9 004c Disabling lock debugging due to kernel taint
This happens because the driver_data pointer is uninitialized. Add the missing platform_set_drvdata() call. For clarity, use the matching platform_get_drvdata() as well.
Cc: Michael Schmitz schmitzmic@gmail.com Cc: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com Fixes: 5ed0794cde593 ("m68k/atari: Convert Falcon IDE drivers to platform drivers") Reviewed-by: Geert Uytterhoeven geert@linux-m68k.org Reviewed-by: Michael Schmitz schmitzmic@gmail.com Signed-off-by: Finn Thain fthain@telegraphics.com.au Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/ide/falconide.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c index 77af4c1a3f38c..bb86d84558d9a 100644 --- a/drivers/ide/falconide.c +++ b/drivers/ide/falconide.c @@ -164,6 +164,7 @@ static int __init falconide_init(struct platform_device *pdev) if (rc) goto err_free;
+ platform_set_drvdata(pdev, host); return 0; err_free: ide_host_free(host); @@ -174,7 +175,7 @@ err:
static int falconide_remove(struct platform_device *pdev) { - struct ide_host *host = dev_get_drvdata(&pdev->dev); + struct ide_host *host = platform_get_drvdata(pdev);
ide_host_remove(host);
From: Bart Van Assche bvanassche@acm.org
commit aaf15f8c6de932861f1fce6aeec6a89ac0e354b6 upstream.
The SCSI core has been modified recently such that it only processes PM requests if rpm_status != RPM_ACTIVE. Since some Opal requests are submitted while rpm_status != RPM_ACTIVE, set flag RQF_PM for Opal requests.
See also https://bugzilla.kernel.org/show_bug.cgi?id=211227.
[mkp: updated sha for PM patch]
Link: https://lore.kernel.org/r/20210222021042.3534-1-bvanassche@acm.org Fixes: d80210f25ff0 ("sd: add support for TCG OPAL self encrypting disks") Fixes: e6044f714b25 ("scsi: core: Only process PM requests if rpm_status != RPM_ACTIVE") Cc: chriscjsus@yahoo.com Cc: Jens Axboe axboe@kernel.dk Cc: Alan Stern stern@rowland.harvard.edu Cc: stable@vger.kernel.org Reported-by: chriscjsus@yahoo.com Tested-by: chriscjsus@yahoo.com Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/sd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -707,9 +707,9 @@ static int sd_sec_submit(void *data, u16 put_unaligned_be16(spsp, &cdb[2]); put_unaligned_be32(len, &cdb[6]);
- ret = scsi_execute_req(sdev, cdb, - send ? DMA_TO_DEVICE : DMA_FROM_DEVICE, - buffer, len, NULL, SD_TIMEOUT, sdkp->max_retries, NULL); + ret = scsi_execute(sdev, cdb, send ? DMA_TO_DEVICE : DMA_FROM_DEVICE, + buffer, len, NULL, NULL, SD_TIMEOUT, sdkp->max_retries, 0, + RQF_PM, NULL); return ret <= 0 ? ret : -EIO; } #endif /* CONFIG_BLK_SED_OPAL */
From: Mikulas Patocka mpatocka@redhat.com
commit 97f433c3601a24d3513d06f575a389a2ca4e11e4 upstream.
We get I/O errors when we run md-raid1 on the top of dm-integrity on the top of ramdisk. device-mapper: integrity: Bio not aligned on 8 sectors: 0xff00, 0xff device-mapper: integrity: Bio not aligned on 8 sectors: 0xff00, 0xff device-mapper: integrity: Bio not aligned on 8 sectors: 0xffff, 0x1 device-mapper: integrity: Bio not aligned on 8 sectors: 0xffff, 0x1 device-mapper: integrity: Bio not aligned on 8 sectors: 0x8048, 0xff device-mapper: integrity: Bio not aligned on 8 sectors: 0x8147, 0xff device-mapper: integrity: Bio not aligned on 8 sectors: 0x8246, 0xff device-mapper: integrity: Bio not aligned on 8 sectors: 0x8345, 0xbb
The ramdisk device has logical_block_size 512 and max_sectors 255. The dm-integrity device uses logical_block_size 4096 and it doesn't affect the "max_sectors" value - thus, it inherits 255 from the ramdisk. So, we have a device with max_sectors not aligned on logical_block_size.
The md-raid device sees that the underlying leg has max_sectors 255 and it will split the bios on 255-sector boundary, making the bios unaligned on logical_block_size.
In order to fix the bug, we round down max_sectors to logical_block_size.
Cc: stable@vger.kernel.org Reviewed-by: Ming Lei ming.lei@redhat.com Signed-off-by: Mikulas Patocka mpatocka@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- block/blk-settings.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
--- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -481,6 +481,14 @@ void blk_queue_io_opt(struct request_que } EXPORT_SYMBOL(blk_queue_io_opt);
+static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lbs) +{ + sectors = round_down(sectors, lbs >> SECTOR_SHIFT); + if (sectors < PAGE_SIZE >> SECTOR_SHIFT) + sectors = PAGE_SIZE >> SECTOR_SHIFT; + return sectors; +} + /** * blk_stack_limits - adjust queue_limits for stacked devices * @t: the stacking driver limits (top device) @@ -607,6 +615,10 @@ int blk_stack_limits(struct queue_limits ret = -1; }
+ t->max_sectors = blk_round_down_sectors(t->max_sectors, t->logical_block_size); + t->max_hw_sectors = blk_round_down_sectors(t->max_hw_sectors, t->logical_block_size); + t->max_dev_sectors = blk_round_down_sectors(t->max_dev_sectors, t->logical_block_size); + /* Discard alignment and granularity */ if (b->discard_granularity) { alignment = queue_limit_discard_alignment(b, start);
From: Marcin Ślusarz marcin.slusarz@intel.com
commit 957e3f797917b36355766807b1d8a54a1ba0cfc9 upstream.
acpi_walk_namespace can return success without executing our callback which initializes info->handle. If the random value in this structure is a valid address (which is on the stack, so it's quite possible), then nothing bad will happen, because: sdw_intel_scan_controller -> acpi_bus_get_device -> acpi_get_device_data -> acpi_get_data_full -> acpi_ns_validate_handle will reject this handle.
However, if the value from the stack doesn't point to a valid address, we get this:
BUG: kernel NULL pointer dereference, address: 0000000000000050 PGD 0 P4D 0 Oops: 0000 [#1] SMP NOPTI CPU: 6 PID: 472 Comm: systemd-udevd Tainted: G W 5.10.0-1-amd64 #1 Debian 5.10.4-1 Hardware name: HP HP Pavilion Laptop 15-cs3xxx/86E2, BIOS F.05 01/01/2020 RIP: 0010:acpi_ns_validate_handle+0x1a/0x23 Code: 00 48 83 c4 10 5b 5d 41 5c 41 5d 41 5e 41 5f c3 0f 1f 44 00 00 48 8d 57 ff 48 89 f8 48 83 fa fd 76 08 48 8b 05 0c b8 67 01 c3 <80> 7f 08 0f 74 02 31 c0 c3 0f 1f 44 00 00 48 8b 3d f6 b7 67 01 e8 RSP: 0000:ffffc388807c7b20 EFLAGS: 00010213 RAX: 0000000000000048 RBX: ffffc388807c7b70 RCX: 0000000000000000 RDX: 0000000000000047 RSI: 0000000000000246 RDI: 0000000000000048 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: ffffffffc0f5f4d1 R11: ffffffff8f0cb268 R12: 0000000000001001 R13: ffffffff8e33b160 R14: 0000000000000048 R15: 0000000000000000 FS: 00007f24548288c0(0000) GS:ffff9f781fb80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000050 CR3: 0000000106158004 CR4: 0000000000770ee0 PKRU: 55555554 Call Trace: acpi_get_data_full+0x4d/0x92 acpi_bus_get_device+0x1f/0x40 sdw_intel_acpi_scan+0x59/0x230 [soundwire_intel] ? strstr+0x22/0x60 ? dmi_matches+0x76/0xe0 snd_intel_dsp_driver_probe.cold+0xaf/0x163 [snd_intel_dspcfg] azx_probe+0x7a/0x970 [snd_hda_intel] local_pci_probe+0x42/0x80 ? _cond_resched+0x16/0x40 pci_device_probe+0xfd/0x1b0 really_probe+0x205/0x460 driver_probe_device+0xe1/0x150 device_driver_attach+0xa1/0xb0 __driver_attach+0x8a/0x150 ? device_driver_attach+0xb0/0xb0 ? device_driver_attach+0xb0/0xb0 bus_for_each_dev+0x78/0xc0 bus_add_driver+0x12b/0x1e0 driver_register+0x8b/0xe0 ? 0xffffffffc0f65000 do_one_initcall+0x44/0x1d0 ? do_init_module+0x23/0x250 ? kmem_cache_alloc_trace+0xf5/0x200 do_init_module+0x5c/0x250 __do_sys_finit_module+0xb1/0x110 do_syscall_64+0x33/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Signed-off-by: Marcin Ślusarz marcin.slusarz@intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rafael J. Wysocki rafael.j.wysocki@intel.com CC: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210208120104.204761-1-marcin.slusarz@gmail.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soundwire/intel_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -405,11 +405,12 @@ int sdw_intel_acpi_scan(acpi_handle *par { acpi_status status;
+ info->handle = NULL; status = acpi_walk_namespace(ACPI_TYPE_DEVICE, parent_handle, 1, sdw_intel_acpi_cb, NULL, info, NULL); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) || info->handle == NULL) return -ENODEV;
return sdw_intel_scan_controller(info);
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit e1e6bd2995ac0e1ad0c2a2d906a06f59ce2ed293 upstream.
Property matching does not work for ACPI fwnodes if the value of the given property is not represented as a package in the _DSD package containing it. For example, the "compatible" property in the _DSD below
Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () {"compatible", "ethernet-phy-ieee802.3-c45"} } })
will not be found by fwnode_property_match_string(), because the ACPI code handling device properties does not regard the single value as a "list" in that case.
Namely, fwnode_property_match_string() invoked to match a given string property value first calls fwnode_property_read_string_array() with the last two arguments equal to NULL and 0, respectively, in order to count the items in the value of the given property, with the assumption that this value may be an array. For ACPI fwnodes, that operation is carried out by acpi_node_prop_read() which calls acpi_data_prop_read() for this purpose. However, when the return (val) pointer is NULL, that function only looks for a property whose value is a package without checking the single-value case at all.
To fix that, make acpi_data_prop_read() check the single-value case if its return pointer argument is NULL and modify acpi_data_prop_read_single() handling that case to attempt to read the value of the property if the return pointer is NULL and return 1 if that succeeds.
Fixes: 3708184afc77 ("device property: Move FW type specific functionality to FW specific files") Reported-by: Calvin Johnson calvin.johnson@oss.nxp.com Cc: 4.13+ stable@vger.kernel.org # 4.13+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Reviewed-by: Sakari Ailus sakari.ailus@linux.intel.com Reviewed-by: Mika Westerberg mika.westerberg@linux.intel.com Reviewed-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/property.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-)
--- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -787,9 +787,6 @@ static int acpi_data_prop_read_single(co const union acpi_object *obj; int ret;
- if (!val) - return -EINVAL; - if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj); if (ret) @@ -799,28 +796,43 @@ static int acpi_data_prop_read_single(co case DEV_PROP_U8: if (obj->integer.value > U8_MAX) return -EOVERFLOW; - *(u8 *)val = obj->integer.value; + + if (val) + *(u8 *)val = obj->integer.value; + break; case DEV_PROP_U16: if (obj->integer.value > U16_MAX) return -EOVERFLOW; - *(u16 *)val = obj->integer.value; + + if (val) + *(u16 *)val = obj->integer.value; + break; case DEV_PROP_U32: if (obj->integer.value > U32_MAX) return -EOVERFLOW; - *(u32 *)val = obj->integer.value; + + if (val) + *(u32 *)val = obj->integer.value; + break; default: - *(u64 *)val = obj->integer.value; + if (val) + *(u64 *)val = obj->integer.value; + break; } + + if (!val) + return 1; } else if (proptype == DEV_PROP_STRING) { ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj); if (ret) return ret;
- *(char **)val = obj->string.pointer; + if (val) + *(char **)val = obj->string.pointer;
return 1; } else { @@ -834,7 +846,7 @@ int acpi_dev_prop_read_single(struct acp { int ret;
- if (!adev) + if (!adev || !val) return -EINVAL;
ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val); @@ -928,10 +940,20 @@ static int acpi_data_prop_read(const str const union acpi_object *items; int ret;
- if (val && nval == 1) { + if (nval == 1 || !val) { ret = acpi_data_prop_read_single(data, propname, proptype, val); - if (ret >= 0) + /* + * The overflow error means that the property is there and it is + * single-value, but its type does not match, so return. + */ + if (ret >= 0 || ret == -EOVERFLOW) return ret; + + /* + * Reading this property as a single-value one failed, but its + * value may still be represented as one-element array, so + * continue. + */ }
ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
From: Qinglang Miao miaoqinglang@huawei.com
commit 67e40054de86aae520ddc2a072d7f6951812a14f upstream.
A list_add corruption is reported by Hulk Robot like this: ============== list_add corruption. Call Trace: link_obj+0xc0/0x1c0 link_group+0x21/0x140 configfs_register_subsystem+0xdb/0x380 acpi_configfs_init+0x25/0x1000 [acpi_configfs] do_one_initcall+0x149/0x820 do_init_module+0x1ef/0x720 load_module+0x35c8/0x4380 __do_sys_finit_module+0x10d/0x1a0 do_syscall_64+0x34/0x80
It's because of the missing check after configfs_register_default_group, where configfs_unregister_subsystem should be called once failure.
Fixes: 612bd01fc6e0 ("ACPI: add support for loading SSDTs via configfs") Reported-by: Hulk Robot hulkci@huawei.com Suggested-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Qinglang Miao miaoqinglang@huawei.com Cc: 4.10+ stable@vger.kernel.org # 4.10+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/acpi_configfs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/acpi/acpi_configfs.c +++ b/drivers/acpi/acpi_configfs.c @@ -268,7 +268,12 @@ static int __init acpi_configfs_init(voi
acpi_table_group = configfs_register_default_group(root, "table", &acpi_tables_type); - return PTR_ERR_OR_ZERO(acpi_table_group); + if (IS_ERR(acpi_table_group)) { + configfs_unregister_subsystem(&acpi_configfs); + return PTR_ERR(acpi_table_group); + } + + return 0; } module_init(acpi_configfs_init);
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit 538b0188da4653b9f4511a114f014354fb6fb7a5 upstream.
Commit 3c55e94c0ade ("cpufreq: ACPI: Extend frequency tables to cover boost frequencies") attempted to address a performance issue involving acpi-cpufreq, the schedutil governor and scale-invariance on x86 by extending the frequency tables created by acpi-cpufreq to cover the entire range of "turbo" (or "boost") frequencies, but that caused frequencies reported via /proc/cpuinfo and the scaling_cur_freq attribute in sysfs to change which may confuse users and monitoring tools.
For this reason, revert the part of commit 3c55e94c0ade adding the extra entry to the frequency table and use the observation that in principle cpuinfo.max_freq need not be equal to the maximum frequency listed in the frequency table for the given policy.
Namely, modify cpufreq_frequency_table_cpuinfo() to allow cpufreq drivers to set their own cpuinfo.max_freq above that frequency and change acpi-cpufreq to set cpuinfo.max_freq to the maximum boost frequency found via CPPC.
This should be sufficient to let all of the cpufreq subsystem know the real maximum frequency of the CPU without changing frequency reporting.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=211305 Fixes: 3c55e94c0ade ("cpufreq: ACPI: Extend frequency tables to cover boost frequencies") Reported-by: Matt McDonald gardotd426@gmail.com Tested-by: Matt McDonald gardotd426@gmail.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Tested-by: Giovanni Gherdovich ggherdovich@suse.cz Tested-by: Michael Larabel Michael@phoronix.com Cc: 5.11+ stable@vger.kernel.org # 5.11+ Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/acpi-cpufreq.c | 62 ++++++++++------------------------------- drivers/cpufreq/freq_table.c | 8 ++++- 2 files changed, 23 insertions(+), 47 deletions(-)
--- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -54,7 +54,6 @@ struct acpi_cpufreq_data { unsigned int resume; unsigned int cpu_feature; unsigned int acpi_perf_cpu; - unsigned int first_perf_state; cpumask_var_t freqdomain_cpus; void (*cpu_freq_write)(struct acpi_pct_register *reg, u32 val); u32 (*cpu_freq_read)(struct acpi_pct_register *reg); @@ -223,10 +222,10 @@ static unsigned extract_msr(struct cpufr
perf = to_perf_data(data);
- cpufreq_for_each_entry(pos, policy->freq_table + data->first_perf_state) + cpufreq_for_each_entry(pos, policy->freq_table) if (msr == perf->states[pos->driver_data].status) return pos->frequency; - return policy->freq_table[data->first_perf_state].frequency; + return policy->freq_table[0].frequency; }
static unsigned extract_freq(struct cpufreq_policy *policy, u32 val) @@ -365,7 +364,6 @@ static unsigned int get_cur_freq_on_cpu( struct cpufreq_policy *policy; unsigned int freq; unsigned int cached_freq; - unsigned int state;
pr_debug("%s (%d)\n", __func__, cpu);
@@ -377,11 +375,7 @@ static unsigned int get_cur_freq_on_cpu( if (unlikely(!data || !policy->freq_table)) return 0;
- state = to_perf_data(data)->state; - if (state < data->first_perf_state) - state = data->first_perf_state; - - cached_freq = policy->freq_table[state].frequency; + cached_freq = policy->freq_table[to_perf_data(data)->state].frequency; freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data)); if (freq != cached_freq) { /* @@ -680,7 +674,6 @@ static int acpi_cpufreq_cpu_init(struct struct cpuinfo_x86 *c = &cpu_data(cpu); unsigned int valid_states = 0; unsigned int result = 0; - unsigned int state_count; u64 max_boost_ratio; unsigned int i; #ifdef CONFIG_SMP @@ -795,28 +788,8 @@ static int acpi_cpufreq_cpu_init(struct goto err_unreg; }
- state_count = perf->state_count + 1; - - max_boost_ratio = get_max_boost_ratio(cpu); - if (max_boost_ratio) { - /* - * Make a room for one more entry to represent the highest - * available "boost" frequency. - */ - state_count++; - valid_states++; - data->first_perf_state = valid_states; - } else { - /* - * If the maximum "boost" frequency is unknown, ask the arch - * scale-invariance code to use the "nominal" performance for - * CPU utilization scaling so as to prevent the schedutil - * governor from selecting inadequate CPU frequencies. - */ - arch_set_max_freq_ratio(true); - } - - freq_table = kcalloc(state_count, sizeof(*freq_table), GFP_KERNEL); + freq_table = kcalloc(perf->state_count + 1, sizeof(*freq_table), + GFP_KERNEL); if (!freq_table) { result = -ENOMEM; goto err_unreg; @@ -851,27 +824,25 @@ static int acpi_cpufreq_cpu_init(struct } freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
+ max_boost_ratio = get_max_boost_ratio(cpu); if (max_boost_ratio) { - unsigned int state = data->first_perf_state; - unsigned int freq = freq_table[state].frequency; + unsigned int freq = freq_table[0].frequency;
/* * Because the loop above sorts the freq_table entries in the * descending order, freq is the maximum frequency in the table. * Assume that it corresponds to the CPPC nominal frequency and - * use it to populate the frequency field of the extra "boost" - * frequency entry. + * use it to set cpuinfo.max_freq. */ - freq_table[0].frequency = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT; + policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT; + } else { /* - * The purpose of the extra "boost" frequency entry is to make - * the rest of cpufreq aware of the real maximum frequency, but - * the way to request it is the same as for the first_perf_state - * entry that is expected to cover the entire range of "boost" - * frequencies of the CPU, so copy the driver_data value from - * that entry. + * If the maximum "boost" frequency is unknown, ask the arch + * scale-invariance code to use the "nominal" performance for + * CPU utilization scaling so as to prevent the schedutil + * governor from selecting inadequate CPU frequencies. */ - freq_table[0].driver_data = freq_table[state].driver_data; + arch_set_max_freq_ratio(true); }
policy->freq_table = freq_table; @@ -947,8 +918,7 @@ static void acpi_cpufreq_cpu_ready(struc { struct acpi_processor_performance *perf = per_cpu_ptr(acpi_perf_data, policy->cpu); - struct acpi_cpufreq_data *data = policy->driver_data; - unsigned int freq = policy->freq_table[data->first_perf_state].frequency; + unsigned int freq = policy->freq_table[0].frequency;
if (perf->states[0].core_frequency * 1000 != freq) pr_warn(FW_WARN "P-state 0 is not max freq\n"); --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -52,7 +52,13 @@ int cpufreq_frequency_table_cpuinfo(stru }
policy->min = policy->cpuinfo.min_freq = min_freq; - policy->max = policy->cpuinfo.max_freq = max_freq; + policy->max = max_freq; + /* + * If the driver has set its own cpuinfo.max_freq above max_freq, leave + * it as is. + */ + if (policy->cpuinfo.max_freq < max_freq) + policy->max = policy->cpuinfo.max_freq = max_freq;
if (policy->min == ~0) return -EINVAL;
From: Filipe Laíns lains@riseup.net
commit ef07c116d98772952807492bd32a61f5af172a94 upstream.
In e400071a805d6229223a98899e9da8c6233704a1 I added support for the receiver that comes with the G602 device, but unfortunately I screwed up during testing and it seems the keyboard events were actually not being sent to userspace. This resulted in keyboard events being broken in userspace, please backport the fix.
The receiver uses the normal 0x01 Logitech keyboard report descriptor, as expected, so it is just a matter of flagging it as supported.
Reported in https://github.com/libratbag/libratbag/issues/1124
Fixes: e400071a805d6 ("HID: logitech-dj: add the G602 receiver") Cc: stable@vger.kernel.org Signed-off-by: Filipe Laíns lains@riseup.net Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/hid/hid-logitech-dj.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -980,6 +980,7 @@ static void logi_hidpp_recv_queue_notif( case 0x07: device_type = "eQUAD step 4 Gaming"; logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem); + workitem.reports_supported |= STD_KEYBOARD; break; case 0x08: device_type = "eQUAD step 4 for gamepads";
From: Jason Gerecke killertofu@gmail.com
commit 88f38846bfb1a452a3d47e38aeab20a4ceb74294 upstream.
The `wacom_feature_mapping` function is careful to only set the the touch_max value a single time, but this care does not extend to the `wacom_wac_finger_event` function. In particular, if a device sends multiple HID_DG_CONTACTMAX items in a single feature report, the driver will end up retaining the value of last item.
The HID descriptor for the Cintiq Companion 2 does exactly this. It incorrectly sets a "Report Count" of 2, which will cause the driver to process two HID_DG_CONTACTCOUNT items. The first item has the actual count, while the second item should have been declared as a constant zero. The constant zero is the value the driver ends up using, however, since it is the last HID_DG_CONTACTCOUNT in the report.
Report ID (16), Usage (Contact Count Maximum), ; Contact count maximum (55h, static value) Report Count (2), Logical Maximum (10), Feature (Variable),
To address this, we add a check that the touch_max is not already set within the `wacom_wac_finger_event` function that processes the HID_DG_TOUCHMAX item. We emit a warning if the value is set and ignore the updated value.
This could potentially cause problems if there is a tablet which has a similar issue but requires the last item to be used. This is unlikely, however, since it would have to have a different non-zero value for HID_DG_CONTACTMAX earlier in the same report, which makes no sense except in the case of a firmware bug. Note that cases where the HID_DG_CONTACTMAX items are in different reports is already handled (and similarly ignored) by `wacom_feature_mapping` as mentioned above.
Link: https://github.com/linuxwacom/input-wacom/issues/223 Fixes: 184eccd40389 ("HID: wacom: generic: read HID_DG_CONTACTMAX from any feature report") Signed-off-by: Jason Gerecke jason.gerecke@wacom.com CC: stable@vger.kernel.org Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/hid/wacom_wac.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2600,7 +2600,12 @@ static void wacom_wac_finger_event(struc wacom_wac->is_invalid_bt_frame = !value; return; case HID_DG_CONTACTMAX: - features->touch_max = value; + if (!features->touch_max) { + features->touch_max = value; + } else { + hid_warn(hdev, "%s: ignoring attempt to overwrite non-zero touch_max " + "%d -> %d\n", __func__, features->touch_max, value); + } return; }
From: jeffrey.lin jeffrey.lin@rad-ic.com
commit fafd320ae51b9c72d371585b2501f86640ea7b7d upstream.
Add default write command package to prevent i2c quirk error of zero data length as Raydium touch firmware update is executed.
Signed-off-by: jeffrey.lin jeffrey.lin@rad-ic.com Link: https://lore.kernel.org/r/1608031217-7247-1-git-send-email-jeffrey.lin@raydi... Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/input/touchscreen/raydium_i2c_ts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -445,6 +445,7 @@ static int raydium_i2c_write_object(stru enum raydium_bl_ack state) { int error; + static const u8 cmd[] = { 0xFF, 0x39 };
error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len); if (error) { @@ -453,7 +454,7 @@ static int raydium_i2c_write_object(stru return error; }
- error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0); + error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, cmd, sizeof(cmd)); if (error) { dev_err(&client->dev, "Ack obj command failed: %d\n", error); return error;
From: Olivier Crête olivier.crete@ocrete.ca
commit 42ffcd1dba1796bcda386eb6f260df9fc23c90af upstream.
Signed-off-by: Olivier Crête olivier.crete@ocrete.ca Link: https://lore.kernel.org/r/20210204005318.615647-1-olivier.crete@collabora.co... Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/input/joystick/xpad.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -305,6 +305,7 @@ static const struct xpad_device { { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE }, + { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE }, { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 }, { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
From: Dan Carpenter dan.carpenter@oracle.com
commit 182d679b2298d62bf42bb14b12a8067b8e17b617 upstream.
The problem here is that "len" might be less than "joydev->nabs" so the loops which verfy abspam[i] and keypam[] might read beyond the buffer.
Fixes: 999b874f4aa3 ("Input: joydev - validate axis/button maps before clobbering current ones") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Link: https://lore.kernel.org/r/YCyzR8WvFRw4HWw6@mwanda [dtor: additional check for len being even in joydev_handle_JSIOCSBTNMAP] Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/input/joydev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -456,7 +456,7 @@ static int joydev_handle_JSIOCSAXMAP(str if (IS_ERR(abspam)) return PTR_ERR(abspam);
- for (i = 0; i < joydev->nabs; i++) { + for (i = 0; i < len && i < joydev->nabs; i++) { if (abspam[i] > ABS_MAX) { retval = -EINVAL; goto out; @@ -480,6 +480,9 @@ static int joydev_handle_JSIOCSBTNMAP(st int i; int retval = 0;
+ if (len % sizeof(*keypam)) + return -EINVAL; + len = min(len, sizeof(joydev->keypam));
/* Validate the map. */ @@ -487,7 +490,7 @@ static int joydev_handle_JSIOCSBTNMAP(st if (IS_ERR(keypam)) return PTR_ERR(keypam);
- for (i = 0; i < joydev->nkey; i++) { + for (i = 0; i < (len / 2) && i < joydev->nkey; i++) { if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { retval = -EINVAL; goto out;
From: Marcos Paulo de Souza mpdesouza@suse.com
commit b5d6e7ab7fe7d186878142e9fc1a05e4c3b65eb9 upstream.
After commit 77b425399f6d ("Input: i8042 - use chassis info to skip selftest on Asus laptops"), all modern Asus laptops have the i8042 selftest disabled. It has done by using chassys type "10" (laptop).
The Asus Zenbook Flip suffers from similar suspend/resume issues, but it _sometimes_ work and sometimes it doesn't. Setting noselftest makes it work reliably. In this case, we need to add chassis type "31" (convertible) in order to avoid selftest in this device.
Reported-by: Ludvig Norgren Guldhag ludvigng@gmail.com Signed-off-by: Marcos Paulo de Souza mpdesouza@suse.com Link: https://lore.kernel.org/r/20210219164638.761-1-mpdesouza@suse.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/input/serio/i8042-x86ia64io.h | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -588,6 +588,10 @@ static const struct dmi_system_id i8042_ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ }, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */ + }, }, { } };
From: James Reynolds jr@memlen.com
commit 1b43bad31fb0e00f45baf5b05bd21eb8d8ce7f58 upstream.
When processing a MCE_RSP_GETPORTSTATUS command, the bit index to set in ir->txports_cabled comes from response data, and isn't validated.
As ir->txports_cabled is a u8, nothing should be done if the bit index is greater than 7.
Cc: stable@vger.kernel.org Reported-by: syzbot+ec3b3128c576e109171d@syzkaller.appspotmail.com Signed-off-by: James Reynolds jr@memlen.com Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/rc/mceusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1169,7 +1169,7 @@ static void mceusb_handle_command(struct switch (subcmd) { /* the one and only 5-byte return value command */ case MCE_RSP_GETPORTSTATUS: - if (buf_in[5] == 0) + if (buf_in[5] == 0 && *hi < 8) ir->txports_cabled |= 1 << *hi; break;
From: Lech Perczak lech.perczak@gmail.com
commit 6420a569504e212d618d4a4736e2c59ed80a8478 upstream.
This patch prepares for qmi_wwan driver support for the device. Previously "option" driver mapped itself to interfaces 0 and 3 (matching ff/ff/ff), while interface 3 is in fact a QMI port. Interfaces 1 and 2 (matching ff/00/00) expose AT commands, and weren't supported previously at all. Without this patch, a possible conflict would exist if device ID was added to qmi_wwan driver for interface 3.
Update and simplify device ID to match interfaces 0-2 directly, to expose QCDM (0), PCUI (1), and modem (2) ports and avoid conflict with QMI (3), and ADB (4).
The modem is used inside ZTE MF283+ router and carriers identify it as such. Interface mapping is: 0: QCDM, 1: AT (PCUI), 2: AT (Modem), 3: QMI, 4: ADB
T: Bus=02 Lev=02 Prnt=02 Port=05 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=19d2 ProdID=1275 Rev=f0.00 S: Manufacturer=ZTE,Incorporated S: Product=ZTE Technologies MSM S: SerialNumber=P685M510ZTED0000CP&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&0 C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=87(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Cc: Johan Hovold johan@kernel.org Cc: Bjørn Mork bjorn@mork.no Signed-off-by: Lech Perczak lech.perczak@gmail.com Link: https://lore.kernel.org/r/20210207005443.12936-1-lech.perczak@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1569,7 +1569,8 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1274, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1275, 0xff, 0xff, 0xff) }, + { USB_DEVICE(ZTE_VENDOR_ID, 0x1275), /* ZTE P685M */ + .driver_info = RSVD(3) | RSVD(4) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1276, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1277, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1278, 0xff, 0xff, 0xff) },
From: Paul Cercueil paul@crapouillou.net
commit 0eaa1a3714db34a59ce121de5733c3909c529463 upstream.
musb_queue_resume_work() would call the provided callback if the runtime PM status was 'active'. Otherwise, it would enqueue the request if the hardware was still suspended (musb->is_runtime_suspended is true).
This causes a race with the runtime PM handlers, as it is possible to be in the case where the runtime PM status is not yet 'active', but the hardware has been awaken (PM resume function has been called).
When hitting the race, the resume work was not enqueued, which probably triggered other bugs further down the stack. For instance, a telnet connection on Ingenic SoCs would result in a 50/50 chance of a segmentation fault somewhere in the musb code.
Rework the code so that either we call the callback directly if (musb->is_runtime_suspended == 0), or enqueue the query otherwise.
Fixes: ea2f35c01d5e ("usb: musb: Fix sleeping function called from invalid context for hdrc glue") Cc: stable@vger.kernel.org # v4.9+ Tested-by: Tony Lindgren tony@atomide.com Reviewed-by: Tony Lindgren tony@atomide.com Signed-off-by: Paul Cercueil paul@crapouillou.net Link: https://lore.kernel.org/r/20210123142502.16980-1-paul@crapouillou.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/musb/musb_core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-)
--- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2240,32 +2240,35 @@ int musb_queue_resume_work(struct musb * { struct musb_pending_work *w; unsigned long flags; + bool is_suspended; int error;
if (WARN_ON(!callback)) return -EINVAL;
- if (pm_runtime_active(musb->controller)) - return callback(musb, data); + spin_lock_irqsave(&musb->list_lock, flags); + is_suspended = musb->is_runtime_suspended;
- w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); - if (!w) - return -ENOMEM; + if (is_suspended) { + w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); + if (!w) { + error = -ENOMEM; + goto out_unlock; + } + + w->callback = callback; + w->data = data;
- w->callback = callback; - w->data = data; - spin_lock_irqsave(&musb->list_lock, flags); - if (musb->is_runtime_suspended) { list_add_tail(&w->node, &musb->pending_list); error = 0; - } else { - dev_err(musb->controller, "could not add resume work %p\n", - callback); - devm_kfree(musb->controller, w); - error = -EINPROGRESS; } + +out_unlock: spin_unlock_irqrestore(&musb->list_lock, flags);
+ if (!is_suspended) + error = callback(musb, data); + return error; } EXPORT_SYMBOL_GPL(musb_queue_resume_work);
From: Thinh Nguyen Thinh.Nguyen@synopsys.com
commit a1679af85b2ae35a2b78ad04c18bb069c37330cc upstream.
Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it must be set to 0 when the controller operates in full-speed. See the programming guide for DEPCFG command section 3.2.2.1 (v3.30a).
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Link: https://lore.kernel.org/r/3f57026f993c0ce71498dbb06e49b3a47c4d0265.161282099... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -605,7 +605,17 @@ static int dwc3_gadget_set_ep_config(str params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1);
if (desc->bInterval) { - params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1); + u8 bInterval_m1; + + /* + * Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it + * must be set to 0 when the controller operates in full-speed. + */ + bInterval_m1 = min_t(u8, desc->bInterval - 1, 13); + if (dwc->gadget->speed == USB_SPEED_FULL) + bInterval_m1 = 0; + + params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1); dep->interval = 1 << (desc->bInterval - 1); }
From: Thinh Nguyen Thinh.Nguyen@synopsys.com
commit 4b049f55ed95cd889bcdb3034fd75e1f01852b38 upstream.
The dep->interval captures the number of frames/microframes per interval from bInterval. Fullspeed interrupt endpoint bInterval is the number of frames per interval and not 2^(bInterval - 1). So fix it here. This change is only for debugging purpose and should not affect the interrupt endpoint operation.
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Link: https://lore.kernel.org/r/1263b563dedc4ab8b0fb854fba06ce4bc56bd495.161282099... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -615,8 +615,13 @@ static int dwc3_gadget_set_ep_config(str if (dwc->gadget->speed == USB_SPEED_FULL) bInterval_m1 = 0;
+ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT && + dwc->gadget->speed == USB_SPEED_FULL) + dep->interval = desc->bInterval; + else + dep->interval = 1 << (desc->bInterval - 1); + params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1); - dep->interval = 1 << (desc->bInterval - 1); }
return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms);
From: Johan Hovold johan@kernel.org
commit 528222d0c8ce93e435a95cd1e476b60409dd5381 upstream.
The most-significant bit of the sub-integer-prescaler index is set in the high byte of the baudrate request wIndex also for FTX devices.
This fixes rates like 1152000 which got mapped to 1.2 MBd.
Reported-by: Vladimir svv75@mail.ru Link: https://bugzilla.kernel.org/show_bug.cgi?id=210351 Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/serial/ftdi_sio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1386,8 +1386,9 @@ static int change_speed(struct tty_struc index_value = get_ftdi_divisor(tty, port); value = (u16)index_value; index = (u16)(index_value >> 16); - if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) || - (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) { + if (priv->chip_type == FT2232C || priv->chip_type == FT2232H || + priv->chip_type == FT4232H || priv->chip_type == FT232H || + priv->chip_type == FTX) { /* Probably the BM type needs the MSB of the encoded fractional * divider also moved like for the chips above. Any infos? */ index = (u16)((index << 8) | priv->interface);
From: Johan Hovold johan@kernel.org
commit 979d9cbe75b922ab1695b8ad5576115774f72e62 upstream.
The latest chip family (HXN) apparently does not support setting the line speed using divisors and instead needs to use the direct encoding scheme for all rates.
This specifically enables 50, 110, 134, 200 bps and other rates not supported by the original chip type.
Fixes: ebd09f1cd417 ("USB: serial: pl2303: add support for PL2303HXN") Cc: stable@vger.kernel.org # 5.5 Cc: Charles Yeh charlesyeh522@gmail.com Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/serial/pl2303.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -183,6 +183,7 @@ struct pl2303_type_data { speed_t max_baud_rate; unsigned long quirks; unsigned int no_autoxonxoff:1; + unsigned int no_divisors:1; };
struct pl2303_serial_private { @@ -209,6 +210,7 @@ static const struct pl2303_type_data pl2 }, [TYPE_HXN] = { .max_baud_rate = 12000000, + .no_divisors = true, }, };
@@ -571,8 +573,12 @@ static void pl2303_encode_baud_rate(stru baud = min_t(speed_t, baud, spriv->type->max_baud_rate); /* * Use direct method for supported baud rates, otherwise use divisors. + * Newer chip types do not support divisor encoding. */ - baud_sup = pl2303_get_supported_baud_rate(baud); + if (spriv->type->no_divisors) + baud_sup = baud; + else + baud_sup = pl2303_get_supported_baud_rate(baud);
if (baud == baud_sup) baud = pl2303_encode_baud_rate_direct(buf, baud);
From: Dan Carpenter dan.carpenter@oracle.com
commit a70aa7dc60099bbdcbd6faca42a915d80f31161e upstream.
This should return -ENOMEM instead of 0 if the kmalloc() fails.
Fixes: 3f5429746d91 ("USB: Moschip 7840 USB-Serial Driver") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/serial/mos7840.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -883,8 +883,10 @@ static int mos7840_write(struct tty_stru if (urb->transfer_buffer == NULL) { urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); - if (!urb->transfer_buffer) + if (!urb->transfer_buffer) { + bytes_sent = -ENOMEM; goto exit; + } } transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
From: Dan Carpenter dan.carpenter@oracle.com
commit fea7372cbc40869876df0f045e367f6f97a1666c upstream.
This code should return -ENOMEM if the kmalloc() fails but instead it returns success.
Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Fixes: 0f64478cbc7a ("USB: add USB serial mos7720 driver") Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/serial/mos7720.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1092,8 +1092,10 @@ static int mos7720_write(struct tty_stru if (urb->transfer_buffer == NULL) { urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); - if (!urb->transfer_buffer) + if (!urb->transfer_buffer) { + bytes_sent = -ENOMEM; goto exit; + } } transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
From: Mathias Kresin dev@kresin.me
commit 36acd5e24e3000691fb8d1ee31cf959cb1582d35 upstream.
Commit 65dc2e725286 ("usb: dwc2: Update Core Reset programming flow.") revealed that the phy isn't ready immediately after enabling it's clocks. The dwc2_check_core_version() fails and the dwc2 usb driver errors out.
Add a short delay to let the phy get up and running. There isn't any documentation how much time is required, the value was chosen based on tests.
Signed-off-by: Mathias Kresin dev@kresin.me Acked-by: Hauke Mehrtens hauke@hauke-m.de Acked-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Cc: stable@vger.kernel.org # v5.7+ Link: https://lore.kernel.org/r/20210107224901.2102479-1-dev@kresin.me Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c +++ b/drivers/phy/lantiq/phy-lantiq-rcu-usb2.c @@ -124,8 +124,16 @@ static int ltq_rcu_usb2_phy_power_on(str reset_control_deassert(priv->phy_reset);
ret = clk_prepare_enable(priv->phy_gate_clk); - if (ret) + if (ret) { dev_err(dev, "failed to enable PHY gate\n"); + return ret; + } + + /* + * at least the xrx200 usb2 phy requires some extra time to be + * operational after enabling the clock + */ + usleep_range(100, 200);
return ret; }
From: Takashi Iwai tiwai@suse.de
commit 036f90dd92bb0aac66fdeec8386401dd396c6079 upstream.
The kerndoc comment for the new function snd_usb_endpoint_free_all() had a typo wrt the argument name. Fix it.
Fixes: 00272c61827e ("ALSA: usb-audio: Avoid unnecessary interface re-setup") Reported-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210205082837.6327-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/endpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1451,7 +1451,7 @@ void snd_usb_endpoint_release(struct snd
/** * snd_usb_endpoint_free_all: Free the resources of an snd_usb_endpoint - * @card: The chip + * @chip: The chip * * This free all endpoints and those resources */
From: Takashi Iwai tiwai@suse.de
commit d6cda4655e2a7612a1e48c49795a5330abc01c5a upstream.
When we stop an endpoint in release_urbs(), it ignores the inconsistent endpoint state and tries to release the resources. This shouldn't happen in theory, but it's still safer to abort the release and let the caller proper error handling.
Also, stop_and_unlink_urbs() called from release_urbs() does two step works, and it's more straightforward to split this to two functions again, so that the call from the PCM trigger won't take the path with sleeping.
This patch modifies the EP management code to adapt two points above.
Fixes: d0f09d1e4a88 ("ALSA: usb-audio: Refactoring endpoint URB deactivation") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203052.15606-2-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/endpoint.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-)
--- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -868,24 +868,22 @@ void snd_usb_endpoint_sync_pending_stop( }
/* - * Stop and unlink active urbs. + * Stop active urbs * - * This function checks and clears EP_FLAG_RUNNING state. - * When @wait_sync is set, it waits until all pending URBs are killed. + * This function moves the EP to STOPPING state if it's being RUNNING. */ -static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force, - bool wait_sync) +static int stop_urbs(struct snd_usb_endpoint *ep, bool force) { unsigned int i;
if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ return -EBADFD;
- if (atomic_read(&ep->running)) + if (!force && atomic_read(&ep->running)) return -EBUSY;
if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags)) - goto out; + return 0;
set_bit(EP_FLAG_STOPPING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); @@ -901,24 +899,25 @@ static int stop_and_unlink_urbs(struct s } }
- out: - if (wait_sync) - return wait_clear_urbs(ep); return 0; }
/* * release an endpoint's urbs */ -static void release_urbs(struct snd_usb_endpoint *ep, int force) +static int release_urbs(struct snd_usb_endpoint *ep, bool force) { - int i; + int i, err;
/* route incoming urbs to nirvana */ snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
- /* stop urbs */ - stop_and_unlink_urbs(ep, force, true); + /* stop and unlink urbs */ + err = stop_urbs(ep, force); + if (err) + return err; + + wait_clear_urbs(ep);
for (i = 0; i < ep->nurbs; i++) release_urb_ctx(&ep->urb[i]); @@ -928,6 +927,7 @@ static void release_urbs(struct snd_usb_
ep->syncbuf = NULL; ep->nurbs = 0; + return 0; }
/* @@ -1118,7 +1118,7 @@ static int data_ep_set_params(struct snd return 0;
out_of_memory: - release_urbs(ep, 0); + release_urbs(ep, false); return -ENOMEM; }
@@ -1162,7 +1162,7 @@ static int sync_ep_set_params(struct snd return 0;
out_of_memory: - release_urbs(ep, 0); + release_urbs(ep, false); return -ENOMEM; }
@@ -1180,7 +1180,9 @@ static int snd_usb_endpoint_set_params(s int err;
/* release old buffers, if any */ - release_urbs(ep, 0); + err = release_urbs(ep, false); + if (err < 0) + return err;
ep->datainterval = fmt->datainterval; ep->maxpacksize = fmt->maxpacksize; @@ -1433,7 +1435,7 @@ void snd_usb_endpoint_stop(struct snd_us WRITE_ONCE(ep->sync_source->sync_sink, NULL);
if (!atomic_dec_return(&ep->running)) - stop_and_unlink_urbs(ep, false, false); + stop_urbs(ep, false); }
/** @@ -1446,7 +1448,7 @@ void snd_usb_endpoint_stop(struct snd_us */ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) { - release_urbs(ep, 1); + release_urbs(ep, true); }
/**
From: Takashi Iwai tiwai@suse.de
commit 5c2b301476ec493be15546f05e23414e2aa9d472 upstream.
The endpoint management has bit flags to indicate the current state, and we're dealing two things: the running bit and the stopping bit. There is a thin window in transition from the running to the stopping in stop_urbs(), and as long as the bit flags are used, it's difficult to plug.
This patch modifies the state management code to use the atomic int and follow the explicit three states, STOPPED, RUNNING and STOPPING. The state change is done via atomic_cmpxhg() for avoiding possible races, and check the state change more strictly. The unexpected state change is now handled as an error.
Fixes: d0f09d1e4a88 ("ALSA: usb-audio: Refactoring endpoint URB deactivation") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203052.15606-3-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/card.h | 2 +- sound/usb/endpoint.c | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-)
--- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -71,7 +71,7 @@ struct snd_usb_endpoint { unsigned char altsetting; /* corresponding alternate setting */ unsigned char ep_idx; /* endpoint array index */
- unsigned long flags; /* running bit flags */ + atomic_t state; /* running state */
void (*prepare_data_urb) (struct snd_usb_substream *subs, struct urb *urb); --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -21,8 +21,11 @@ #include "clock.h" #include "quirks.h"
-#define EP_FLAG_RUNNING 1 -#define EP_FLAG_STOPPING 2 +enum { + EP_STATE_STOPPED, + EP_STATE_RUNNING, + EP_STATE_STOPPING, +};
/* interface refcounting */ struct snd_usb_iface_ref { @@ -115,6 +118,16 @@ static const char *usb_error_string(int } }
+static inline bool ep_state_running(struct snd_usb_endpoint *ep) +{ + return atomic_read(&ep->state) == EP_STATE_RUNNING; +} + +static inline bool ep_state_update(struct snd_usb_endpoint *ep, int old, int new) +{ + return atomic_cmpxchg(&ep->state, old, new) == old; +} + /** * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type * @@ -393,7 +406,7 @@ next_packet_fifo_dequeue(struct snd_usb_ */ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) { - while (test_bit(EP_FLAG_RUNNING, &ep->flags)) { + while (ep_state_running(ep)) {
unsigned long flags; struct snd_usb_packet_info *packet; @@ -454,13 +467,13 @@ static void snd_complete_urb(struct urb if (unlikely(atomic_read(&ep->chip->shutdown))) goto exit_clear;
- if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear;
if (usb_pipeout(ep->pipe)) { retire_outbound_urb(ep, ctx); /* can be stopped during retire callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear;
if (snd_usb_endpoint_implicit_feedback_sink(ep)) { @@ -474,12 +487,12 @@ static void snd_complete_urb(struct urb
prepare_outbound_urb(ep, ctx); /* can be stopped during prepare callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear; } else { retire_inbound_urb(ep, ctx); /* can be stopped during retire callback */ - if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + if (unlikely(!ep_state_running(ep))) goto exit_clear;
prepare_inbound_urb(ep, ctx); @@ -835,7 +848,7 @@ static int wait_clear_urbs(struct snd_us unsigned long end_time = jiffies + msecs_to_jiffies(1000); int alive;
- if (!test_bit(EP_FLAG_STOPPING, &ep->flags)) + if (atomic_read(&ep->state) != EP_STATE_STOPPING) return 0;
do { @@ -850,10 +863,11 @@ static int wait_clear_urbs(struct snd_us usb_audio_err(ep->chip, "timeout: still %d active urbs on EP #%x\n", alive, ep->ep_num); - clear_bit(EP_FLAG_STOPPING, &ep->flags);
- ep->sync_sink = NULL; - snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); + if (ep_state_update(ep, EP_STATE_STOPPING, EP_STATE_STOPPED)) { + ep->sync_sink = NULL; + snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); + }
return 0; } @@ -882,10 +896,9 @@ static int stop_urbs(struct snd_usb_endp if (!force && atomic_read(&ep->running)) return -EBUSY;
- if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags)) + if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING)) return 0;
- set_bit(EP_FLAG_STOPPING, &ep->flags); INIT_LIST_HEAD(&ep->ready_playback_urbs); ep->next_packet_head = 0; ep->next_packet_queued = 0; @@ -1362,7 +1375,8 @@ int snd_usb_endpoint_start(struct snd_us * from that context. */
- set_bit(EP_FLAG_RUNNING, &ep->flags); + if (!ep_state_update(ep, EP_STATE_STOPPED, EP_STATE_RUNNING)) + goto __error;
if (snd_usb_endpoint_implicit_feedback_sink(ep)) { for (i = 0; i < ep->nurbs; i++) {
From: Takashi Iwai tiwai@suse.de
commit 257d2d7e9e798305d65825cb82b0a7d1c0511e89 upstream.
In the later patch, we're going to issue the PCM sync_stop calls at disconnection. But currently the USB-audio driver can't handle it because it has a check of shutdown flag for stopping the URBs. This is basically superfluous (the stopping URBs are safe at disconnection state), so let's drop the check.
Fixes: dc5eafe7787c ("ALSA: usb-audio: Support PCM sync_stop") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210206203052.15606-4-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/endpoint.c | 3 --- sound/usb/pcm.c | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-)
--- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -890,9 +890,6 @@ static int stop_urbs(struct snd_usb_endp { unsigned int i;
- if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */ - return -EBADFD; - if (!force && atomic_read(&ep->running)) return -EBUSY;
--- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -270,10 +270,7 @@ static int snd_usb_pcm_sync_stop(struct { struct snd_usb_substream *subs = substream->runtime->private_data;
- if (!snd_usb_lock_shutdown(subs->stream->chip)) { - sync_pending_stops(subs); - snd_usb_unlock_shutdown(subs->stream->chip); - } + sync_pending_stops(subs); return 0; }
From: Takashi Iwai tiwai@suse.de
commit 15447b64789d9ade71eb374d5ae1f37d0bbce0bd upstream.
BOSS GP-10 with 0582:0185 requires the similar quirk to make the implicit feedback working like other BOSS devices.
Reported-by: Keith Milner kamilner@superlative.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210214154251.10750-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/implicit.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -73,6 +73,7 @@ static const struct snd_usb_implicit_fb_ /* No quirk for playback but with capture quirk (see below) */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130), /* BOSS BR-80 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0171), /* BOSS RC-505 */ + IMPLICIT_FB_SKIP_DEV(0x0582, 0x0185), /* BOSS GP-10 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189), /* BOSS GT-100v2 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d6), /* BOSS GT-1 */ IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8), /* BOSS Katana */ @@ -86,6 +87,7 @@ static const struct snd_usb_implicit_fb_ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x0171, 0x0d, 0x01), /* BOSS RC-505 */ + IMPLICIT_FB_FIXED_DEV(0x0582, 0x0185, 0x0d, 0x01), /* BOSS GP-10 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d6, 0x0d, 0x01), /* BOSS GT-1 */ IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */
From: Takashi Sakamoto o-takashi@sakamocchi.jp
commit c50bfc8a6866775be39d7e747e83e8a5a9051e2e upstream.
Fireface UCX, UFX, and FF802 are categorized for latter protocol of the series. Current support for FF802 (and UFX) includes failure to parse sync status register and results in EIO.
Further investigation figures out that the content of register differs depending on models. This commit adds tables specific to FF802 and UFX to fix it.
Fixes: 062bb452b078b ("ALSA: fireface: add support for RME FireFace 802") Cc: stable@vger.kernel.org Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp Link: https://lore.kernel.org/r/20210207154736.229551-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/firewire/fireface/ff-protocol-latter.c | 118 ++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 18 deletions(-)
--- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -15,6 +15,61 @@ #define LATTER_FETCH_MODE 0xffff00000010ULL #define LATTER_SYNC_STATUS 0x0000801c0000ULL
+// The content of sync status register differs between models. +// +// Fireface UCX: +// 0xf0000000: (unidentified) +// 0x0f000000: effective rate of sampling clock +// 0x00f00000: detected rate of word clock on BNC interface +// 0x000f0000: detected rate of ADAT or S/PDIF on optical interface +// 0x0000f000: detected rate of S/PDIF on coaxial interface +// 0x00000e00: effective source of sampling clock +// 0x00000e00: Internal +// 0x00000800: (unidentified) +// 0x00000600: Word clock on BNC interface +// 0x00000400: ADAT on optical interface +// 0x00000200: S/PDIF on coaxial or optical interface +// 0x00000100: Optical interface is used for ADAT signal +// 0x00000080: (unidentified) +// 0x00000040: Synchronized to word clock on BNC interface +// 0x00000020: Synchronized to ADAT or S/PDIF on optical interface +// 0x00000010: Synchronized to S/PDIF on coaxial interface +// 0x00000008: (unidentified) +// 0x00000004: Lock word clock on BNC interface +// 0x00000002: Lock ADAT or S/PDIF on optical interface +// 0x00000001: Lock S/PDIF on coaxial interface +// +// Fireface 802 (and perhaps UFX): +// 0xf0000000: effective rate of sampling clock +// 0x0f000000: detected rate of ADAT-B on 2nd optical interface +// 0x00f00000: detected rate of ADAT-A on 1st optical interface +// 0x000f0000: detected rate of AES/EBU on XLR or coaxial interface +// 0x0000f000: detected rate of word clock on BNC interface +// 0x00000e00: effective source of sampling clock +// 0x00000e00: internal +// 0x00000800: ADAT-B +// 0x00000600: ADAT-A +// 0x00000400: AES/EBU +// 0x00000200: Word clock +// 0x00000080: Synchronized to ADAT-B on 2nd optical interface +// 0x00000040: Synchronized to ADAT-A on 1st optical interface +// 0x00000020: Synchronized to AES/EBU on XLR or 2nd optical interface +// 0x00000010: Synchronized to word clock on BNC interface +// 0x00000008: Lock ADAT-B on 2nd optical interface +// 0x00000004: Lock ADAT-A on 1st optical interface +// 0x00000002: Lock AES/EBU on XLR or 2nd optical interface +// 0x00000001: Lock word clock on BNC interface +// +// The pattern for rate bits: +// 0x00: 32.0 kHz +// 0x01: 44.1 kHz +// 0x02: 48.0 kHz +// 0x04: 64.0 kHz +// 0x05: 88.2 kHz +// 0x06: 96.0 kHz +// 0x08: 128.0 kHz +// 0x09: 176.4 kHz +// 0x0a: 192.0 kHz static int parse_clock_bits(u32 data, unsigned int *rate, enum snd_ff_clock_src *src, enum snd_ff_unit_version unit_version) @@ -23,35 +78,48 @@ static int parse_clock_bits(u32 data, un unsigned int rate; u32 flag; } *rate_entry, rate_entries[] = { - { 32000, 0x00000000, }, - { 44100, 0x01000000, }, - { 48000, 0x02000000, }, - { 64000, 0x04000000, }, - { 88200, 0x05000000, }, - { 96000, 0x06000000, }, - { 128000, 0x08000000, }, - { 176400, 0x09000000, }, - { 192000, 0x0a000000, }, + { 32000, 0x00, }, + { 44100, 0x01, }, + { 48000, 0x02, }, + { 64000, 0x04, }, + { 88200, 0x05, }, + { 96000, 0x06, }, + { 128000, 0x08, }, + { 176400, 0x09, }, + { 192000, 0x0a, }, }; static const struct { enum snd_ff_clock_src src; u32 flag; - } *clk_entry, clk_entries[] = { + } *clk_entry, *clk_entries, ucx_clk_entries[] = { { SND_FF_CLOCK_SRC_SPDIF, 0x00000200, }, { SND_FF_CLOCK_SRC_ADAT1, 0x00000400, }, { SND_FF_CLOCK_SRC_WORD, 0x00000600, }, { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, }, + }, ufx_ff802_clk_entries[] = { + { SND_FF_CLOCK_SRC_WORD, 0x00000200, }, + { SND_FF_CLOCK_SRC_SPDIF, 0x00000400, }, + { SND_FF_CLOCK_SRC_ADAT1, 0x00000600, }, + { SND_FF_CLOCK_SRC_ADAT2, 0x00000800, }, + { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, }, }; + u32 rate_bits; + unsigned int clk_entry_count; int i;
- if (unit_version != SND_FF_UNIT_VERSION_UCX) { - // e.g. 0x00fe0f20 but expected 0x00eff002. - data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4); + if (unit_version == SND_FF_UNIT_VERSION_UCX) { + rate_bits = (data & 0x0f000000) >> 24; + clk_entries = ucx_clk_entries; + clk_entry_count = ARRAY_SIZE(ucx_clk_entries); + } else { + rate_bits = (data & 0xf0000000) >> 28; + clk_entries = ufx_ff802_clk_entries; + clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries); }
for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) { rate_entry = rate_entries + i; - if ((data & 0x0f000000) == rate_entry->flag) { + if (rate_bits == rate_entry->flag) { *rate = rate_entry->rate; break; } @@ -59,14 +127,14 @@ static int parse_clock_bits(u32 data, un if (i == ARRAY_SIZE(rate_entries)) return -EIO;
- for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { + for (i = 0; i < clk_entry_count; ++i) { clk_entry = clk_entries + i; if ((data & 0x000e00) == clk_entry->flag) { *src = clk_entry->src; break; } } - if (i == ARRAY_SIZE(clk_entries)) + if (i == clk_entry_count) return -EIO;
return 0; @@ -249,16 +317,22 @@ static void latter_dump_status(struct sn char *const label; u32 locked_mask; u32 synced_mask; - } *clk_entry, clk_entries[] = { + } *clk_entry, *clk_entries, ucx_clk_entries[] = { { "S/PDIF", 0x00000001, 0x00000010, }, { "ADAT", 0x00000002, 0x00000020, }, { "WDClk", 0x00000004, 0x00000040, }, + }, ufx_ff802_clk_entries[] = { + { "WDClk", 0x00000001, 0x00000010, }, + { "AES/EBU", 0x00000002, 0x00000020, }, + { "ADAT-A", 0x00000004, 0x00000040, }, + { "ADAT-B", 0x00000008, 0x00000080, }, }; __le32 reg; u32 data; unsigned int rate; enum snd_ff_clock_src src; const char *label; + unsigned int clk_entry_count; int i; int err;
@@ -270,7 +344,15 @@ static void latter_dump_status(struct sn
snd_iprintf(buffer, "External source detection:\n");
- for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { + if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) { + clk_entries = ucx_clk_entries; + clk_entry_count = ARRAY_SIZE(ucx_clk_entries); + } else { + clk_entries = ufx_ff802_clk_entries; + clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries); + } + + for (i = 0; i < clk_entry_count; ++i) { clk_entry = clk_entries + i; snd_iprintf(buffer, "%s: ", clk_entry->label); if (data & clk_entry->locked_mask) {
From: Kai Vehmanen kai.vehmanen@linux.intel.com
commit 0d3070f5e6551d8a759619e85736e49a3bf40398 upstream.
Add one more HD Audio PCI ID for CometLake-H PCH.
Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210212151022.2568567-1-kai.vehmanen@linux.intel.... Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2481,6 +2481,8 @@ static const struct pci_device_id azx_id /* CometLake-H */ { PCI_DEVICE(0x8086, 0x06C8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + { PCI_DEVICE(0x8086, 0xf1c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* CometLake-S */ { PCI_DEVICE(0x8086, 0xa3f0), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
From: Takashi Iwai tiwai@suse.de
commit 056a3da5d07fc5d3ceacfa2cdf013c9d8df630bd upstream.
Some users reported the kernel WARNING with stack traces from hdmi_pcm_close(), and it's the line checking the per_cvt->assigned flag. This used to be a valid check in the past because the flag was turned on/off only at opening and closing a PCM stream. Meanwhile, since the introduction of the silent-stream mode, this flag may be turned on/off at the monitor connection/disconnection time, which isn't always associated with the PCM open/close. Hence this may lead to the inconsistent per_cvt->assigned flag at closing.
As the check itself became almost useless and confuses users as if it were a serious problem, just drop the check.
Fixes: b1a5039759cb ("ALSA: hda/hdmi: fix silent stream for first playback to DP") Cc: stable@vger.kernel.org BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=210987 Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210211083139.29531-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/patch_hdmi.c | 1 - 1 file changed, 1 deletion(-)
--- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2130,7 +2130,6 @@ static int hdmi_pcm_close(struct hda_pcm goto unlock; } per_cvt = get_cvt(spec, cvt_idx); - snd_BUG_ON(!per_cvt->assigned); per_cvt->assigned = 0; hinfo->nid = 0;
From: PeiSen Hou pshou@realtek.com
commit 4841b8e6318a7f0ae57c4e5ec09032ea057c97a8 upstream.
Modify 0x20 index 7 bit 5 to 1, make the 0x15 EAPD the same as 0x14.
Signed-off-by: PeiSen Hou pshou@realtek.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/e62c5058957f48d8b8953e97135ff108@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
--- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1905,6 +1905,7 @@ enum { ALC889_FIXUP_FRONT_HP_NO_PRESENCE, ALC889_FIXUP_VAIO_TT, ALC888_FIXUP_EEE1601, + ALC886_FIXUP_EAPD, ALC882_FIXUP_EAPD, ALC883_FIXUP_EAPD, ALC883_FIXUP_ACER_EAPD, @@ -2238,6 +2239,15 @@ static const struct hda_fixup alc882_fix { } } }, + [ALC886_FIXUP_EAPD] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* change to EAPD mode */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 }, + { } + } + }, [ALC882_FIXUP_EAPD] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -2510,6 +2520,7 @@ static const struct snd_pci_quirk alc882 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
From: Takashi Iwai tiwai@suse.de
commit c3bb2b521944ffbbc8c24b849f81977a9915fb5e upstream.
HP Spectre x360 14 model (PCI SSID 103c:87f7) seems requiring a unique setup for its external amp: the GPIO0 needs to be toggled on and off shortly at each device initialization via runtime PM.
This patch implements that workaround as well as the model option string, so that users with other devices may try the same workaround more easily.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=210633 Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210215082540.4520-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/hda/patch_realtek.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
--- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4291,6 +4291,28 @@ static void alc280_fixup_hp_gpio4(struct } }
+/* HP Spectre x360 14 model needs a unique workaround for enabling the amp; + * it needs to toggle the GPIO0 once on and off at each time (bko#210633) + */ +static void alc245_fixup_hp_x360_amp(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + spec->gpio_mask |= 0x01; + spec->gpio_dir |= 0x01; + break; + case HDA_FIXUP_ACT_INIT: + /* need to toggle GPIO to enable the amp */ + alc_update_gpio_data(codec, 0x01, true); + msleep(100); + alc_update_gpio_data(codec, 0x01, false); + break; + } +} + static void alc_update_coef_led(struct hda_codec *codec, struct alc_coef_led *led, bool polarity, bool on) @@ -6277,6 +6299,7 @@ enum { ALC280_FIXUP_HP_DOCK_PINS, ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, ALC280_FIXUP_HP_9480M, + ALC245_FIXUP_HP_X360_AMP, ALC288_FIXUP_DELL_HEADSET_MODE, ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, ALC288_FIXUP_DELL_XPS_13, @@ -6982,6 +7005,10 @@ static const struct hda_fixup alc269_fix .type = HDA_FIXUP_FUNC, .v.func = alc280_fixup_hp_9480m, }, + [ALC245_FIXUP_HP_X360_AMP] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_x360_amp, + }, [ALC288_FIXUP_DELL_HEADSET_MODE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_dell_alc288, @@ -7996,6 +8023,7 @@ static const struct snd_pci_quirk alc269 SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -8368,6 +8396,7 @@ static const struct hda_model_fixup alc2 {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"}, {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"}, {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"}, + {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"}, {} }; #define ALC225_STANDARD_PINS \
From: Paul Cercueil paul@crapouillou.net
commit a5360958a3cd1d876aae1f504ae014658513e1af upstream.
The JZ4760 has the HPTLB as well, but has a XBurst CPU with a D0 CPUID.
Disable the HPTLB for all XBurst CPUs with a D0 CPUID. In the case where there is no HPTLB (e.g. for older SoCs), this won't have any side effect.
Fixes: b02efeb05699 ("MIPS: Ingenic: Disable abandoned HPTLB function.") Cc: stable@vger.kernel.org # 5.4 Signed-off-by: Paul Cercueil paul@crapouillou.net Reviewed-by: 周琰杰 (Zhou Yanjie) zhouyanjie@wanyeetech.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/kernel/cpu-probe.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
--- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1830,16 +1830,17 @@ static inline void cpu_probe_ingenic(str */ case PRID_COMP_INGENIC_D0: c->isa_level &= ~MIPS_CPU_ISA_M32R2; - break; + fallthrough;
/* * The config0 register in the XBurst CPUs with a processor ID of - * PRID_COMP_INGENIC_D1 has an abandoned huge page tlb mode, this - * mode is not compatible with the MIPS standard, it will cause - * tlbmiss and into an infinite loop (line 21 in the tlb-funcs.S) - * when starting the init process. After chip reset, the default - * is HPTLB mode, Write 0xa9000000 to cp0 register 5 sel 4 to - * switch back to VTLB mode to prevent getting stuck. + * PRID_COMP_INGENIC_D0 or PRID_COMP_INGENIC_D1 has an abandoned + * huge page tlb mode, this mode is not compatible with the MIPS + * standard, it will cause tlbmiss and into an infinite loop + * (line 21 in the tlb-funcs.S) when starting the init process. + * After chip reset, the default is HPTLB mode, Write 0xa9000000 + * to cp0 register 5 sel 4 to switch back to VTLB mode to prevent + * getting stuck. */ case PRID_COMP_INGENIC_D1: write_c0_page_ctrl(XBURST_PAGECTRL_HPTLB_DIS);
From: Aurelien Jarno aurelien@aurel32.net
commit 5373ae67c3aad1ab306cc722b5a80b831eb4d4d1 upstream.
From version 2.35, binutils can be configured with
--enable-mips-fix-loongson3-llsc=yes, which means it defaults to -mfix-loongson3-llsc. This breaks labels which might then point at the wrong instruction.
The workaround to explicitly pass -mno-fix-loongson3-llsc has been added in Linux version 5.1, but is only enabled when building a Loongson 64 kernel. As vendors might use a common toolchain for building Loongson and non-Loongson kernels, just move that workaround to arch/mips/Makefile. At the same time update the comments to reflect the current status.
Cc: stable@vger.kernel.org # 5.1+ Cc: YunQiang Su syq@debian.org Signed-off-by: Aurelien Jarno aurelien@aurel32.net Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/Makefile | 19 +++++++++++++++++++ arch/mips/loongson64/Platform | 22 ---------------------- 2 files changed, 19 insertions(+), 22 deletions(-)
--- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -136,6 +136,25 @@ cflags-$(CONFIG_SB1XXX_CORELIS) += $(cal # cflags-y += -fno-stack-check
+# binutils from v2.35 when built with --enable-mips-fix-loongson3-llsc=yes, +# supports an -mfix-loongson3-llsc flag which emits a sync prior to each ll +# instruction to work around a CPU bug (see __SYNC_loongson3_war in asm/sync.h +# for a description). +# +# We disable this in order to prevent the assembler meddling with the +# instruction that labels refer to, ie. if we label an ll instruction: +# +# 1: ll v0, 0(a0) +# +# ...then with the assembler fix applied the label may actually point at a sync +# instruction inserted by the assembler, and if we were using the label in an +# exception table the table would no longer contain the address of the ll +# instruction. +# +# Avoid this by explicitly disabling that assembler behaviour. +# +cflags-y += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,) + # # CPU-dependent compiler/assembler options for optimization. # --- a/arch/mips/loongson64/Platform +++ b/arch/mips/loongson64/Platform @@ -6,28 +6,6 @@ cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap
# -# Some versions of binutils, not currently mainline as of 2019/02/04, support -# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction -# to work around a CPU bug (see __SYNC_loongson3_war in asm/sync.h for a -# description). -# -# We disable this in order to prevent the assembler meddling with the -# instruction that labels refer to, ie. if we label an ll instruction: -# -# 1: ll v0, 0(a0) -# -# ...then with the assembler fix applied the label may actually point at a sync -# instruction inserted by the assembler, and if we were using the label in an -# exception table the table would no longer contain the address of the ll -# instruction. -# -# Avoid this by explicitly disabling that assembler behaviour. If upstream -# binutils does not merge support for the flag then we can revisit & remove -# this later - for now it ensures vendor toolchains don't cause problems. -# -cflags-$(CONFIG_CPU_LOONGSON64) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,) - -# # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a # as MIPS64 R2; older versions as just R1. This leaves the possibility open # that GCC might generate R2 code for -march=loongson3a which then is rejected
From: Nathan Chancellor natechancellor@gmail.com
commit 76d7fff22be3e4185ee5f9da2eecbd8188e76b2c upstream.
Commit ee67855ecd9d ("MIPS: vdso: Allow clang's --target flag in VDSO cflags") allowed the '--target=' flag from the main Makefile to filter through to the vDSO. However, it did not bring any of the other clang specific flags for controlling the integrated assembler and the GNU tools locations (--prefix=, --gcc-toolchain=, and -no-integrated-as). Without these, we will get a warning (visible with tinyconfig):
arch/mips/vdso/elf.S:14:1: warning: DWARF2 only supports one section per compilation unit .pushsection .note.Linux, "a",@note ; .balign 4 ; .long 2f - 1f ; .long 4484f - 3f ; .long 0 ; 1:.asciz "Linux" ; 2:.balign 4 ; 3: ^ arch/mips/vdso/elf.S:34:2: warning: DWARF2 only supports one section per compilation unit .section .mips_abiflags, "a" ^
All of these flags are bundled up under CLANG_FLAGS in the main Makefile and exported so that they can be added to Makefiles that set their own CFLAGS. Use this value instead of filtering out '--target=' so there is no warning and all of the tools are properly used.
Cc: stable@vger.kernel.org Fixes: ee67855ecd9d ("MIPS: vdso: Allow clang's --target flag in VDSO cflags") Link: https://github.com/ClangBuiltLinux/linux/issues/1256 Reported-by: Anders Roxell anders.roxell@linaro.org Signed-off-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Anders Roxell anders.roxell@linaro.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/vdso/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
--- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile @@ -16,16 +16,13 @@ ccflags-vdso := \ $(filter -march=%,$(KBUILD_CFLAGS)) \ $(filter -m%-float,$(KBUILD_CFLAGS)) \ $(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \ + $(CLANG_FLAGS) \ -D__VDSO__
ifndef CONFIG_64BIT ccflags-vdso += -DBUILD_VDSO32 endif
-ifdef CONFIG_CC_IS_CLANG -ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) -endif - # # The -fno-jump-tables flag only prevents the compiler from generating # jump tables but does not prevent the compiler from emitting absolute
From: Kevin Hao haokexin@gmail.com
commit fe82de91af83a9212b6c704b1ce6cf6d129a108b upstream.
This reverts commit d9df9fb901d25b941ab2cfb5b570d91fb2abf7a3.
For the OCTEON boards, it need to patch the built-in DTB before using it. Previously it judges if it is a built-in DTB by checking fw_passed_dtb. But after commit 37e5c69ffd41 ("MIPS: head.S: Init fw_passed_dtb to builtin DTB", the fw_passed_dtb is initialized even when using built-in DTB. This causes the OCTEON boards boot broken due to an unpatched built-in DTB is used. Revert the commit d9df9fb901d2 to restore the codes before the fw_passed_dtb is used and then fix this issue.
Fixed: 37e5c69ffd41 ("MIPS: head.S: Init fw_passed_dtb to builtin DTB") Cc: stable@vger.kernel.org Suggested-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Kevin Hao haokexin@gmail.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/cavium-octeon/setup.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1149,12 +1149,15 @@ void __init device_tree_init(void) bool do_prune; bool fill_mac;
- if (fw_passed_dtb) { - fdt = (void *)fw_passed_dtb; +#ifdef CONFIG_MIPS_ELF_APPENDED_DTB + if (!fdt_check_header(&__appended_dtb)) { + fdt = &__appended_dtb; do_prune = false; fill_mac = true; pr_info("Using appended Device Tree.\n"); - } else if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { + } else +#endif + if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { fdt = phys_to_virt(octeon_bootinfo->fdt_addr); if (fdt_check_header(fdt)) panic("Corrupt Device Tree passed to kernel.");
From: Alexander Lobakin alobakin@pm.me
commit fc4cac4cfc437659ce445c3c47b807e1cc625b66 upstream.
Commit 1e35918ad9d1 ("MIPS: Enable Undefined Behavior Sanitizer UBSAN") added a possibility to build the entire kernel with UBSAN instrumentation for MIPS, with the exception for VDSO. However, self-extracting head wasn't been added to exceptions, so this occurs:
mips-alpine-linux-musl-ld: arch/mips/boot/compressed/decompress.o: in function `FSE_buildDTable_wksp': decompress.c:(.text.FSE_buildDTable_wksp+0x278): undefined reference to `__ubsan_handle_shift_out_of_bounds' mips-alpine-linux-musl-ld: decompress.c:(.text.FSE_buildDTable_wksp+0x2a8): undefined reference to `__ubsan_handle_shift_out_of_bounds' mips-alpine-linux-musl-ld: decompress.c:(.text.FSE_buildDTable_wksp+0x2c4): undefined reference to `__ubsan_handle_shift_out_of_bounds' mips-alpine-linux-musl-ld: arch/mips/boot/compressed/decompress.o: decompress.c:(.text.FSE_buildDTable_raw+0x9c): more undefined references to `__ubsan_handle_shift_out_of_bounds' follow
Add UBSAN_SANITIZE := n to mips/boot/compressed/Makefile to exclude it from instrumentation scope and fix this issue.
Fixes: 1e35918ad9d1 ("MIPS: Enable Undefined Behavior Sanitizer UBSAN") Cc: stable@vger.kernel.org # 5.0+ Signed-off-by: Alexander Lobakin alobakin@pm.me Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/mips/boot/compressed/Makefile | 1 + 1 file changed, 1 insertion(+)
--- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -37,6 +37,7 @@ KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__AS # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. KCOV_INSTRUMENT := n GCOV_PROFILE := n +UBSAN_SANITIZE := n
# decompressor objects (linked with vmlinuz) vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o
From: Kai Krakow kai@kaishome.de
commit 9f233ffe02e5cef611100cd8c5bcf4de26ca7bef upstream.
This reverts commit 56b30770b27d54d68ad51eccc6d888282b568cee.
With the btree using the `system_wq`, I seem to see a lot more desktop latency than I should.
After some more investigation, it looks like the original assumption of 56b3077 no longer is true, and bcache has a very high potential of congesting the `system_wq`. In turn, this introduces laggy desktop performance, IO stalls (at least with btrfs), and input events may be delayed.
So let's revert this. It's important to note that the semantics of using `system_wq` previously mean that `btree_io_wq` should be created before and destroyed after other bcache wqs to keep the same assumptions.
Cc: Coly Li colyli@suse.de Cc: stable@vger.kernel.org # 5.4+ Signed-off-by: Kai Krakow kai@kaishome.de Signed-off-by: Coly Li colyli@suse.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/bcache/bcache.h | 2 ++ drivers/md/bcache/btree.c | 21 +++++++++++++++++++-- drivers/md/bcache/super.c | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-)
--- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -1042,5 +1042,7 @@ void bch_debug_exit(void); void bch_debug_init(void); void bch_request_exit(void); int bch_request_init(void); +void bch_btree_exit(void); +int bch_btree_init(void);
#endif /* _BCACHE_H */ --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -99,6 +99,8 @@ #define PTR_HASH(c, k) \ (((k)->ptr[0] >> c->bucket_bits) | PTR_GEN(k, 0))
+static struct workqueue_struct *btree_io_wq; + #define insert_lock(s, b) ((b)->level <= (s)->lock)
@@ -308,7 +310,7 @@ static void __btree_node_write_done(stru btree_complete_write(b, w);
if (btree_node_dirty(b)) - schedule_delayed_work(&b->work, 30 * HZ); + queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
closure_return_with_destructor(cl, btree_node_write_unlock); } @@ -481,7 +483,7 @@ static void bch_btree_leaf_dirty(struct BUG_ON(!i->keys);
if (!btree_node_dirty(b)) - schedule_delayed_work(&b->work, 30 * HZ); + queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
set_btree_node_dirty(b);
@@ -2764,3 +2766,18 @@ void bch_keybuf_init(struct keybuf *buf) spin_lock_init(&buf->lock); array_allocator_init(&buf->freelist); } + +void bch_btree_exit(void) +{ + if (btree_io_wq) + destroy_workqueue(btree_io_wq); +} + +int __init bch_btree_init(void) +{ + btree_io_wq = create_singlethread_workqueue("bch_btree_io"); + if (!btree_io_wq) + return -ENOMEM; + + return 0; +} --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -2821,6 +2821,7 @@ static void bcache_exit(void) destroy_workqueue(bcache_wq); if (bch_journal_wq) destroy_workqueue(bch_journal_wq); + bch_btree_exit();
if (bcache_major) unregister_blkdev(bcache_major, "bcache"); @@ -2876,6 +2877,9 @@ static int __init bcache_init(void) return bcache_major; }
+ if (bch_btree_init()) + goto err; + bcache_wq = alloc_workqueue("bcache", WQ_MEM_RECLAIM, 0); if (!bcache_wq) goto err;
From: Kai Krakow kai@kaishome.de
commit d797bd9897e3559eb48d68368550d637d32e468c upstream.
Before killing `btree_io_wq`, the queue was allocated using `create_singlethread_workqueue()` which has `WQ_MEM_RECLAIM`. After killing it, it no longer had this property but `system_wq` is not single threaded.
Let's combine both worlds and make it multi threaded but able to reclaim memory.
Cc: Coly Li colyli@suse.de Cc: stable@vger.kernel.org # 5.4+ Signed-off-by: Kai Krakow kai@kaishome.de Signed-off-by: Coly Li colyli@suse.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/bcache/btree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -2775,7 +2775,7 @@ void bch_btree_exit(void)
int __init bch_btree_init(void) { - btree_io_wq = create_singlethread_workqueue("bch_btree_io"); + btree_io_wq = alloc_workqueue("bch_btree_io", WQ_MEM_RECLAIM, 0); if (!btree_io_wq) return -ENOMEM;
From: Kai Krakow kai@kaishome.de
commit afe78ab46f638ecdf80a35b122ffc92c20d9ae5d upstream.
This is potentially long running and not latency sensitive, let's get it out of the way of other latency sensitive events.
As observed in the previous commit, the `system_wq` comes easily congested by bcache, and this fixes a few more stalls I was observing every once in a while.
Let's not make this `WQ_MEM_RECLAIM` as it showed to reduce performance of boot and file system operations in my tests. Also, without `WQ_MEM_RECLAIM`, I no longer see desktop stalls. This matches the previous behavior as `system_wq` also does no memory reclaim:
// workqueue.c: system_wq = alloc_workqueue("events", 0, 0);
Cc: Coly Li colyli@suse.de Cc: stable@vger.kernel.org # 5.4+ Signed-off-by: Kai Krakow kai@kaishome.de Signed-off-by: Coly Li colyli@suse.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/bcache/bcache.h | 1 + drivers/md/bcache/journal.c | 4 ++-- drivers/md/bcache/super.c | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-)
--- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -1001,6 +1001,7 @@ void bch_write_bdev_super(struct cached_
extern struct workqueue_struct *bcache_wq; extern struct workqueue_struct *bch_journal_wq; +extern struct workqueue_struct *bch_flush_wq; extern struct mutex bch_register_lock; extern struct list_head bch_cache_sets;
--- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -932,8 +932,8 @@ atomic_t *bch_journal(struct cache_set * journal_try_write(c); } else if (!w->dirty) { w->dirty = true; - schedule_delayed_work(&c->journal.work, - msecs_to_jiffies(c->journal_delay_ms)); + queue_delayed_work(bch_flush_wq, &c->journal.work, + msecs_to_jiffies(c->journal_delay_ms)); spin_unlock(&c->journal.lock); } else { spin_unlock(&c->journal.lock); --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -49,6 +49,7 @@ static int bcache_major; static DEFINE_IDA(bcache_device_idx); static wait_queue_head_t unregister_wait; struct workqueue_struct *bcache_wq; +struct workqueue_struct *bch_flush_wq; struct workqueue_struct *bch_journal_wq;
@@ -2821,6 +2822,8 @@ static void bcache_exit(void) destroy_workqueue(bcache_wq); if (bch_journal_wq) destroy_workqueue(bch_journal_wq); + if (bch_flush_wq) + destroy_workqueue(bch_flush_wq); bch_btree_exit();
if (bcache_major) @@ -2884,6 +2887,19 @@ static int __init bcache_init(void) if (!bcache_wq) goto err;
+ /* + * Let's not make this `WQ_MEM_RECLAIM` for the following reasons: + * + * 1. It used `system_wq` before which also does no memory reclaim. + * 2. With `WQ_MEM_RECLAIM` desktop stalls, increased boot times, and + * reduced throughput can be observed. + * + * We still want to user our own queue to not congest the `system_wq`. + */ + bch_flush_wq = alloc_workqueue("bch_flush", 0, 0); + if (!bch_flush_wq) + goto err; + bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0); if (!bch_journal_wq) goto err;
From: Alex Deucher alexander.deucher@amd.com
commit 910f1601addae3e430fc7d3cd589d7622c5df693 upstream.
This reverts commit 4a3dea8932d3b1199680d2056dd91d31d94d70b7.
This causes blank screens for some users.
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1388 Cc: Alvin Lee alvin.lee2@amd.com Cc: Jun Lei Jun.Lei@amd.com Cc: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Reviewed-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/dc/dcn20/dcn20_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -408,8 +408,8 @@ static struct _vcs_dpi_soc_bounding_box_ }, }, .num_states = 5, - .sr_exit_time_us = 11.6, - .sr_enter_plus_exit_time_us = 13.9, + .sr_exit_time_us = 8.6, + .sr_enter_plus_exit_time_us = 10.9, .urgent_latency_us = 4.0, .urgent_latency_pixel_data_only_us = 4.0, .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
From: Jan Kokemüller jan.kokemueller@gmail.com
commit 41401ac67791810dd880345962339aa1bedd3c0d upstream.
dcn21_validate_bandwidth() calls functions that use floating point math. On my machine this sometimes results in simd exceptions when there are other FPU users such as KVM virtual machines running. The screen freezes completely in this case.
Wrapping the function with DC_FP_START()/DC_FP_END() seems to solve the problem. This mirrors the approach used for dcn20_validate_bandwidth.
Tested on a AMD Ryzen 7 PRO 4750U (Renoir).
Bug: https://bugzilla.kernel.org/show_bug.cgi?id=206987 Signed-off-by: Jan Kokemüller jan.kokemueller@gmail.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/dc/dcn20/dcn20_resource.c | 2 - drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 ++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3245,7 +3245,7 @@ restore_dml_state: bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate) { - bool voltage_supported = false; + bool voltage_supported; DC_FP_START(); voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate); DC_FP_END(); --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1329,8 +1329,8 @@ validate_out: return out; }
-bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) +static noinline bool dcn21_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, bool fast_validate) { bool out = false;
@@ -1383,6 +1383,22 @@ validate_out:
return out; } + +/* + * Some of the functions further below use the FPU, so we need to wrap this + * with DC_FP_START()/DC_FP_END(). Use the same approach as for + * dcn20_validate_bandwidth in dcn20_resource.c. + */ +bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported; + DC_FP_START(); + voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate); + DC_FP_END(); + return voltage_supported; +} + static void dcn21_destroy_resource_pool(struct resource_pool **pool) { struct dcn21_resource_pool *dcn21_pool = TO_DCN21_RES_POOL(*pool);
From: Eric Bernstein eric.bernstein@amd.com
commit 83e6667b675f101fb66659dfa72e45d08773d763 upstream.
[Why] In some cases, this function is called when DIG BE is not connected to DIG FE, in which case a value of zero isn't invalid and assert should not be hit.
[How] Remove assert and handle ENGINE_ID_UNKNOWN result in calling function.
Signed-off-by: Eric Bernstein eric.bernstein@amd.com Acked-by: Bindu Ramamurthy bindu.r@amd.com Tested-by: Daniel Wheeler daniel.wheeler@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/dc/dcn10/dcn10_link_encoder.c | 1 - drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -480,7 +480,6 @@ unsigned int dcn10_get_dig_frontend(stru break; default: // invalid source select DIG - ASSERT(false); result = ENGINE_ID_UNKNOWN; }
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -539,6 +539,8 @@ void dcn30_init_hw(struct dc *dc)
fe = dc->links[i]->link_enc->funcs->get_dig_frontend( dc->links[i]->link_enc); + if (fe == ENGINE_ID_UNKNOWN) + continue;
for (j = 0; j < dc->res_pool->stream_enc_count; j++) { if (fe == dc->res_pool->stream_enc[j]->id) {
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
commit 688f97ed3f5e339c0c2c09d9ee7ff23d5807b0a7 upstream.
When run igt@kms_vrr in a device that uses DCN2.1 architecture, we noticed multiple failures. Furthermore, when we tested a VRR demo, we noticed a system hang where the mouse pointer still works, but the entire system freezes; in this case, we don't see any dmesg warning or failure messages kernel. This happens due to a lack of vupdate_no_lock interrupt, making the userspace wait eternally to get the event back. For fixing this issue, we need to add the vupdate_no_lock interrupt in the interrupt list.
Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Acked-by: Bindu Ramamurthy bindu.r@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/dc/irq/dcn21/irq_service_dcn21.c | 22 +++++++++++ 1 file changed, 22 insertions(+)
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -168,6 +168,11 @@ static const struct irq_source_info_func .ack = NULL };
+static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + #undef BASE_INNER #define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
@@ -230,6 +235,17 @@ static const struct irq_source_info_func .funcs = &vblank_irq_info_funcs\ }
+/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic + * of DCE's DC_IRQ_SOURCE_VUPDATEx. + */ +#define vupdate_no_lock_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\ + .funcs = &vupdate_no_lock_irq_info_funcs\ + } + #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ IRQ_REG_ENTRY(OTG, reg_num,\ @@ -338,6 +354,12 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NU vupdate_int_entry(3), vupdate_int_entry(4), vupdate_int_entry(5), + vupdate_no_lock_int_entry(0), + vupdate_no_lock_int_entry(1), + vupdate_no_lock_int_entry(2), + vupdate_no_lock_int_entry(3), + vupdate_no_lock_int_entry(4), + vupdate_no_lock_int_entry(5), vblank_int_entry(0), vblank_int_entry(1), vblank_int_entry(2),
From: Anson Jacob Anson.Jacob@amd.com
commit efc8278eecfd5e6fa36c5d41e71d038f534fe107 upstream.
This reverts commit 8866a67ab86cc0812e65c04f1ef02bcc41e24d68.
Reason for revert: This breaks hotplug of HDMI on some systems, resulting in a blank screen. Caused general hangs on boot/hotplugs.
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1487 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1492 Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211649 Signed-off-by: Anson Jacob Anson.Jacob@amd.com Reviewed-by: Bhawanpreet Lakha bhawanpreet.lakha@amd.com Acked-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/display/amdgpu_dm/amdgpu_dm.c | 23 ++++++++++-------- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 ++++++---------------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 3 +- 3 files changed, 23 insertions(+), 30 deletions(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1934,7 +1934,7 @@ static void dm_gpureset_commit_state(str dc_commit_updates_for_stream( dm->dc, bundle->surface_updates, dc_state->stream_status->plane_count, - dc_state->streams[k], &bundle->stream_update); + dc_state->streams[k], &bundle->stream_update, dc_state); }
cleanup: @@ -1965,7 +1965,8 @@ static void dm_set_dpms_off(struct dc_li
stream_update.stream = stream_state; dc_commit_updates_for_stream(stream_state->ctx->dc, NULL, 0, - stream_state, &stream_update); + stream_state, &stream_update, + stream_state->ctx->dc->current_state); mutex_unlock(&adev->dm.dc_lock); }
@@ -7548,7 +7549,7 @@ static void amdgpu_dm_commit_planes(stru struct drm_crtc *pcrtc, bool wait_for_vblank) { - int i; + uint32_t i; uint64_t timestamp_ns; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; @@ -7589,7 +7590,7 @@ static void amdgpu_dm_commit_planes(stru amdgpu_dm_commit_cursors(state);
/* update planes when needed */ - for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { struct drm_crtc *crtc = new_plane_state->crtc; struct drm_crtc_state *new_crtc_state; struct drm_framebuffer *fb = new_plane_state->fb; @@ -7812,7 +7813,8 @@ static void amdgpu_dm_commit_planes(stru bundle->surface_updates, planes_count, acrtc_state->stream, - &bundle->stream_update); + &bundle->stream_update, + dc_state);
/** * Enable or disable the interrupts on the backend. @@ -8148,13 +8150,13 @@ static void amdgpu_dm_atomic_commit_tail struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); - struct dc_surface_update surface_updates[MAX_SURFACES]; + struct dc_surface_update dummy_updates[MAX_SURFACES]; struct dc_stream_update stream_update; struct dc_info_packet hdr_packet; struct dc_stream_status *status = NULL; bool abm_changed, hdr_changed, scaling_changed;
- memset(&surface_updates, 0, sizeof(surface_updates)); + memset(&dummy_updates, 0, sizeof(dummy_updates)); memset(&stream_update, 0, sizeof(stream_update));
if (acrtc) { @@ -8211,15 +8213,16 @@ static void amdgpu_dm_atomic_commit_tail * To fix this, DC should permit updating only stream properties. */ for (j = 0; j < status->plane_count; j++) - surface_updates[j].surface = status->plane_states[j]; + dummy_updates[j].surface = status->plane_states[0];
mutex_lock(&dm->dc_lock); dc_commit_updates_for_stream(dm->dc, - surface_updates, + dummy_updates, status->plane_count, dm_new_crtc_state->stream, - &stream_update); + &stream_update, + dc_state); mutex_unlock(&dm->dc_lock); }
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2679,7 +2679,8 @@ void dc_commit_updates_for_stream(struct struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update) + struct dc_stream_update *stream_update, + struct dc_state *state) { const struct dc_stream_status *stream_status; enum surface_update_type update_type; @@ -2698,12 +2699,6 @@ void dc_commit_updates_for_stream(struct
if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_planes[MAX_SURFACES]; - - memset(new_planes, 0, sizeof(new_planes)); - - for (i = 0; i < surface_count; i++) - new_planes[i] = srf_updates[i].surface;
/* initialize scratch memory for building context */ context = dc_create_state(dc); @@ -2712,21 +2707,15 @@ void dc_commit_updates_for_stream(struct return; }
- dc_resource_state_copy_construct( - dc->current_state, context); + dc_resource_state_copy_construct(state, context);
- /*remove old surfaces from context */ - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { - DC_ERROR("Failed to remove streams for new validate context!\n"); - return; - } + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- /* add surface to context */ - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { - DC_ERROR("Failed to add streams for new validate context!\n"); - return; + if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state) + new_pipe->plane_state->force_full_update = true; } - }
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -283,7 +283,8 @@ void dc_commit_updates_for_stream(struct struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update); + struct dc_stream_update *stream_update, + struct dc_state *state); /* * Log the current stream state. */
From: Felix Kuehling Felix.Kuehling@amd.com
commit 1fb8b1fc4dd1035a264c81d15d41f05884cc8058 upstream.
memalloc_nofs_save/restore are no longer sufficient to prevent recursive lock warnings when holding locks that can be taken in MMU notifiers. Use memalloc_noreclaim_save/restore instead.
Fixes: f920e413ff9c ("mm: track mmu notifiers in fs_reclaim_acquire/release") CC: Daniel Vetter daniel.vetter@ffwll.ch Reviewed-by: Philip Yang Philip.Yang@amd.com Signed-off-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org # 5.10.x Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -243,11 +243,11 @@ get_sh_mem_bases_nybble_64(struct kfd_pr static inline void dqm_lock(struct device_queue_manager *dqm) { mutex_lock(&dqm->lock_hidden); - dqm->saved_flags = memalloc_nofs_save(); + dqm->saved_flags = memalloc_noreclaim_save(); } static inline void dqm_unlock(struct device_queue_manager *dqm) { - memalloc_nofs_restore(dqm->saved_flags); + memalloc_noreclaim_restore(dqm->saved_flags); mutex_unlock(&dqm->lock_hidden); }
From: Marek Olšák marek.olsak@amd.com
commit 4112c00354004cbb1bf56f0114fa9951bf6b13ed upstream.
This fixes incorrect TCC harvesting info reported to userspace. The impact was a very very tiny performance degradation (unnecessary GL2 cache flushes).
Signed-off-by: Marek Olšák marek.olsak@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@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/gfx_v10_0.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -71,6 +71,11 @@ #define GB_ADDR_CONFIG__NUM_PKRS__SHIFT 0x8 #define GB_ADDR_CONFIG__NUM_PKRS_MASK 0x00000700L
+#define mmCGTS_TCC_DISABLE_gc_10_3 0x5006 +#define mmCGTS_TCC_DISABLE_gc_10_3_BASE_IDX 1 +#define mmCGTS_USER_TCC_DISABLE_gc_10_3 0x5007 +#define mmCGTS_USER_TCC_DISABLE_gc_10_3_BASE_IDX 1 + #define mmCP_MEC_CNTL_Sienna_Cichlid 0x0f55 #define mmCP_MEC_CNTL_Sienna_Cichlid_BASE_IDX 0 #define mmRLC_SAFE_MODE_Sienna_Cichlid 0x4ca0 @@ -99,10 +104,6 @@ #define mmGCR_GENERAL_CNTL_Sienna_Cichlid 0x1580 #define mmGCR_GENERAL_CNTL_Sienna_Cichlid_BASE_IDX 0
-#define mmCGTS_TCC_DISABLE_Vangogh 0x5006 -#define mmCGTS_TCC_DISABLE_Vangogh_BASE_IDX 1 -#define mmCGTS_USER_TCC_DISABLE_Vangogh 0x5007 -#define mmCGTS_USER_TCC_DISABLE_Vangogh_BASE_IDX 1 #define mmGOLDEN_TSC_COUNT_UPPER_Vangogh 0x0025 #define mmGOLDEN_TSC_COUNT_UPPER_Vangogh_BASE_IDX 1 #define mmGOLDEN_TSC_COUNT_LOWER_Vangogh 0x0026 @@ -4942,15 +4943,12 @@ static void gfx_v10_0_get_tcc_info(struc /* TCCs are global (not instanced). */ uint32_t tcc_disable;
- switch (adev->asic_type) { - case CHIP_VANGOGH: - tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE_Vangogh) | - RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE_Vangogh); - break; - default: + if (adev->asic_type >= CHIP_SIENNA_CICHLID) { + tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE_gc_10_3) | + RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE_gc_10_3); + } else { tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE) | - RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE); - break; + RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE); }
adev->gfx.config.tcc_disabled_mask =
From: Alex Deucher alexander.deucher@amd.com
commit 6e80fb8ab04f6c4f377e2fd422bdd1855beb7371 upstream.
Fixes the rlc reference clock used for GPU timestamps. Value is 100Mhz. Confirmed with hardware team.
v2: reword commit message.
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1480 Acked-by: Christian König christian.koenig@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/soc15.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -241,6 +241,8 @@ static u32 soc15_get_xclk(struct amdgpu_ { u32 reference_clock = adev->clock.spll.reference_freq;
+ if (adev->asic_type == CHIP_RENOIR) + return 10000; if (adev->asic_type == CHIP_RAVEN) return reference_clock / 4;
From: Prike Liang Prike.Liang@amd.com
commit b092b19602cfd47de1eeeb3a1b03822afd86b136 upstream.
In the shutdown and poweroff opt on the s0i3 system we still need un-gate the gfx clock gating and power gating before destory amdgpu device.
Fixes: 628c36d7b238e2 ("drm/amdgpu: update amdgpu device suspend/resume sequence for s0i3 support") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1499 Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Prike Liang Prike.Liang@amd.com Reviewed-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.h | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 ++++++++- 3 files changed, 18 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1003,6 +1003,12 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate;
+ /* + * The combination flag in_poweroff_reboot_com used to identify the poweroff + * and reboot opt in the s0i3 system-wide suspend. + */ + bool in_poweroff_reboot_com; + atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; struct rw_semaphore reset_sem; --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2666,7 +2666,8 @@ static int amdgpu_device_ip_suspend_phas { int i, r;
- if (!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) { + if (adev->in_poweroff_reboot_com || + !amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) { amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); } @@ -3726,7 +3727,8 @@ int amdgpu_device_suspend(struct drm_dev
amdgpu_fence_driver_suspend(adev);
- if (!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) + if (adev->in_poweroff_reboot_com || + !amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) r = amdgpu_device_ip_suspend_phase2(adev); else amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry); --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1266,7 +1266,9 @@ amdgpu_pci_shutdown(struct pci_dev *pdev */ if (!amdgpu_passthrough(adev)) adev->mp1_state = PP_MP1_STATE_UNLOAD; + adev->in_poweroff_reboot_com = true; amdgpu_device_ip_suspend(adev); + adev->in_poweroff_reboot_com = false; adev->mp1_state = PP_MP1_STATE_NONE; }
@@ -1308,8 +1310,13 @@ static int amdgpu_pmops_thaw(struct devi static int amdgpu_pmops_poweroff(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + int r;
- return amdgpu_device_suspend(drm_dev, true); + adev->in_poweroff_reboot_com = true; + r = amdgpu_device_suspend(drm_dev, true); + adev->in_poweroff_reboot_com = false; + return r; }
static int amdgpu_pmops_restore(struct device *dev)
From: xinhui pan xinhui.pan@amd.com
commit 7a8a4b0729a8807e37196e44629b31ee03f88872 upstream.
Free the memory on failure. Also no need to re-alloc memory on retry.
Signed-off-by: xinhui pan xinhui.pan@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20210219042547.44855-1-xinhui.... Reviewed-by: Christian König christian.koenig@amd.com CC: stable@vger.kernel.org # 5.11 Signed-off-by: Christian König christian.koenig@amd.com Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/ttm/ttm_bo.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -967,8 +967,10 @@ static int ttm_bo_bounce_temp_buffer(str return ret; /* move to the bounce domain */ ret = ttm_bo_handle_move_mem(bo, &hop_mem, false, ctx, NULL); - if (ret) + if (ret) { + ttm_resource_free(bo, &hop_mem); return ret; + } return 0; }
@@ -1000,18 +1002,19 @@ static int ttm_bo_move_buffer(struct ttm * stop and the driver will be called to make * the second hop. */ -bounce: ret = ttm_bo_mem_space(bo, placement, &mem, ctx); if (ret) return ret; +bounce: ret = ttm_bo_handle_move_mem(bo, &mem, false, ctx, &hop); if (ret == -EMULTIHOP) { ret = ttm_bo_bounce_temp_buffer(bo, &mem, ctx, &hop); if (ret) - return ret; + goto out; /* try and move to final place now. */ goto bounce; } +out: if (ret) ttm_resource_free(bo, &mem); return ret;
From: Karol Herbst kherbst@redhat.com
commit d1f5a3fc85566e9ddce9361ef180f070367e6eab upstream.
In some cases we have the handle those explicitly as the fallback connector type detection fails and marks those as eDP connectors.
Attempting to use such a connector with mutter leads to a crash of mutter as it ends up with two eDP displays.
Information is taken from the official DCB documentation.
Cc: stable@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: Ben Skeggs bskeggs@redhat.com Reported-by: Mark Pearson markpearson@lenovo.com Tested-by: Mark Pearson markpearson@lenovo.com Signed-off-by: Karol Herbst kherbst@redhat.com Signed-off-by: Ben Skeggs bskeggs@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 + drivers/gpu/drm/nouveau/nouveau_connector.c | 1 + 2 files changed, 2 insertions(+)
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h @@ -14,6 +14,7 @@ enum dcb_connector_type { DCB_CONNECTOR_LVDS_SPWG = 0x41, DCB_CONNECTOR_DP = 0x46, DCB_CONNECTOR_eDP = 0x47, + DCB_CONNECTOR_mDP = 0x48, DCB_CONNECTOR_HDMI_0 = 0x60, DCB_CONNECTOR_HDMI_1 = 0x61, DCB_CONNECTOR_HDMI_C = 0x63, --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1210,6 +1210,7 @@ drm_conntype_from_dcb(enum dcb_connector case DCB_CONNECTOR_DMS59_DP0: case DCB_CONNECTOR_DMS59_DP1: case DCB_CONNECTOR_DP : + case DCB_CONNECTOR_mDP : case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort; case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; case DCB_CONNECTOR_HDMI_0 :
From: Ville Syrjälä ville.syrjala@linux.intel.com
commit 5b34ab52401f0f1f191bcb83a182c83b506f4763 upstream.
The new >8k CEA modes have dotclocks reaching 5.94 GHz, which means our clock*1000 will now overflow the 32bit unsigned integer. Switch to 64bit maths to avoid it.
Cc: stable@vger.kernel.org Reported-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20201022194256.30978-1-ville.s... Tested-by: Randy Dunlap rdunlap@infradead.org Reviewed-by: Chris Wilson chris@chris-wilson.co.uk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/drm_modes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -762,7 +762,7 @@ int drm_mode_vrefresh(const struct drm_d if (mode->htotal == 0 || mode->vtotal == 0) return 0;
- num = mode->clock * 1000; + num = mode->clock; den = mode->htotal * mode->vtotal;
if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -772,7 +772,7 @@ int drm_mode_vrefresh(const struct drm_d if (mode->vscan > 1) den *= mode->vscan;
- return DIV_ROUND_CLOSEST(num, den); + return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den); } EXPORT_SYMBOL(drm_mode_vrefresh);
From: Andrey Grodzovsky andrey.grodzovsky@amd.com
commit e582951baabba3e278c97169d0acc1e09b24a72e upstream.
To avoid any possible use after free.
Signed-off-by: Andrey Grodzovsky andrey.grodzovsky@amd.com Reviewed-by: Christian König christian.koenig@amd.com Link: https://patchwork.freedesktop.org/patch/414814/ CC: stable@vger.kernel.org Signed-off-by: Christian König christian.koenig@amd.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/scheduler/sched_main.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -891,6 +891,9 @@ void drm_sched_fini(struct drm_gpu_sched if (sched->thread) kthread_stop(sched->thread);
+ /* Confirm no work left behind accessing device structures */ + cancel_delayed_work_sync(&sched->work_tdr); + sched->ready = false; } EXPORT_SYMBOL(drm_sched_fini);
From: Heiko Stuebner heiko@sntech.de
commit d922d58fedcd98ba625e89b625a98e222b090b10 upstream.
The panel is able to work when dsi clock is non-continuous, thus the system power consumption can be reduced using such feature.
Add MIPI_DSI_CLOCK_NON_CONTINUOUS to panel's mode_flags.
Also the flag actually becomes necessary after commit c6d94e37bdbb ("drm/bridge/synopsys: dsi: add support for non-continuous HS clock") and without it the panel only emits stripes instead of output.
Fixes: c6d94e37bdbb ("drm/bridge/synopsys: dsi: add support for non-continuous HS clock") Cc: stable@vger.kernel.org # 5.10+ Signed-off-by: Heiko Stuebner heiko@sntech.de Tested-by: Ezequiel Garcia ezequiel@collabora.com Reviewed-by: Christopher Morgan macromorgan@hotmail.com Link: https://patchwork.freedesktop.org/patch/msgid/20210206135020.1991820-1-heiko... Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -265,7 +265,8 @@ static int kd35t133_probe(struct mipi_ds dsi->lanes = 1; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET; + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET | + MIPI_DSI_CLOCK_NON_CONTINUOUS;
drm_panel_init(&ctx->panel, &dsi->dev, &kd35t133_funcs, DRM_MODE_CONNECTOR_DSI);
From: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com
commit 5f94e3571459abb626077aedb65d71264c2a58c0 upstream.
The AFBC decoder used in the Rockchip VOP assumes the use of the YUV-like colourspace transform (YTR). YTR is lossless for RGB(A) buffers, which covers the RGBA8 and RGB565 formats supported in vop_convert_afbc_format. Use of YTR is signaled with the AFBC_FORMAT_MOD_YTR modifier, which prior to this commit was missing. As such, a producer would have to generate buffers that do not use YTR, which the VOP would erroneously decode as YTR, leading to severe visual corruption.
The upstream AFBC support was developed against a captured frame, which failed to exercise modifier support. Prior to bring-up of AFBC in Mesa (in the Panfrost driver), no open userspace respected modifier reporting. As such, this change is not expected to affect broken userspaces.
Tested on RK3399 with Panfrost and Weston.
Fixes: 7707f7227f09 ("drm/rockchip: Add support for afbc") Cc: stable@vger.kernel.org Signed-off-by: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com Acked-by: Daniel Stone daniels@collabora.com Signed-off-by: Heiko Stuebner heiko@sntech.de Link: https://patchwork.freedesktop.org/patch/msgid/20200811202631.3603-1-alyssa.r... Signed-off-by: Maarten Lankhorst maarten.lankhorst@linux.intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -17,9 +17,20 @@
#define NUM_YUV2YUV_COEFFICIENTS 12
+/* AFBC supports a number of configurable modes. Relevant to us is block size + * (16x16 or 32x8), storage modifiers (SPARSE, SPLIT), and the YUV-like + * colourspace transform (YTR). 16x16 SPARSE mode is always used. SPLIT mode + * could be enabled via the hreg_block_split register, but is not currently + * handled. The colourspace transform is implicitly always assumed by the + * decoder, so consumers must use this transform as well. + * + * Failure to match modifiers will cause errors displaying AFBC buffers + * produced by conformant AFBC producers, including Mesa. + */ #define ROCKCHIP_AFBC_MOD \ DRM_FORMAT_MOD_ARM_AFBC( \ AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE \ + | AFBC_FORMAT_MOD_YTR \ )
enum vop_data_format {
From: Takashi Iwai tiwai@suse.de
commit ae07f5c7c5e9ebca5b9d6471bb4b99a9da5c6d88 upstream.
A const prefix was put wrongly in the middle at the code refactoring commit 932eaf7c7904 ("ASoC: sh: siu_pcm: remove snd_pcm_ops"), which leads to a build error as: sound/soc/sh/siu_pcm.c:546:8: error: expected '{' before 'const'
Also, another inconsistency is that the declaration of siu_component misses the const prefix.
This patch corrects both failures.
Fixes: 932eaf7c7904 ("ASoC: sh: siu_pcm: remove snd_pcm_ops") Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de Link: https://lore.kernel.org/r/20210126154702.3974-1-tiwai@suse.de Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/soc/sh/siu.h | 2 +- sound/soc/sh/siu_pcm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
--- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h @@ -169,7 +169,7 @@ static inline u32 siu_read32(u32 __iomem #define SIU_BRGBSEL (0x108 / sizeof(u32)) #define SIU_BRRB (0x10c / sizeof(u32))
-extern struct snd_soc_component_driver siu_component; +extern const struct snd_soc_component_driver siu_component; extern struct siu_info *siu_i2s_data;
int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -543,7 +543,7 @@ static void siu_pcm_free(struct snd_soc_ dev_dbg(pcm->card->dev, "%s\n", __func__); }
-struct const snd_soc_component_driver siu_component = { +const struct snd_soc_component_driver siu_component = { .name = DRV_NAME, .open = siu_pcm_open, .close = siu_pcm_close,
From: Amir Goldstein amir73il@gmail.com
commit a9ffe682c58aaff643764547f5420e978b6e0830 upstream.
When inode has no listxattr op of its own (e.g. squashfs) vfs_listxattr calls the LSM inode_listsecurity hooks to list the xattrs that LSMs will intercept in inode_getxattr hooks.
When selinux LSM is installed but not initialized, it will list the security.selinux xattr in inode_listsecurity, but will not intercept it in inode_getxattr. This results in -ENODATA for a getxattr call for an xattr returned by listxattr.
This situation was manifested as overlayfs failure to copy up lower files from squashfs when selinux is built-in but not initialized, because ovl_copy_xattr() iterates the lower inode xattrs by vfs_listxattr() and vfs_getxattr().
Match the logic of inode_listsecurity to that of inode_getxattr and do not list the security.selinux xattr if selinux is not initialized.
Reported-by: Michael Labriola michael.d.labriola@gmail.com Tested-by: Michael Labriola michael.d.labriola@gmail.com Link: https://lore.kernel.org/linux-unionfs/2nv9d47zt7.fsf@aldarion.sourceruckus.o... Fixes: c8e222616c7e ("selinux: allow reading labels before policy is loaded") Cc: stable@vger.kernel.org#v5.9+ Signed-off-by: Amir Goldstein amir73il@gmail.com Reviewed-by: Ondrej Mosnacek omosnace@redhat.com Signed-off-by: Paul Moore paul@paul-moore.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/selinux/hooks.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3413,6 +3413,10 @@ static int selinux_inode_setsecurity(str static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) { const int len = sizeof(XATTR_NAME_SELINUX); + + if (!selinux_initialized(&selinux_state)) + return 0; + if (buffer && len <= buffer_size) memcpy(buffer, XATTR_NAME_SELINUX, len); return len;
From: Gao Xiang hsiangkao@redhat.com
commit ce063129181312f8781a047a50be439c5859747b upstream.
Currently, although set_bit() & test_bit() pairs are used as a fast- path for initialized configurations. However, these atomic ops are actually relaxed forms. Instead, load-acquire & store-release form is needed to make sure uninitialized fields won't be observed in advance here (yet no such corresponding bitops so use full barriers instead.)
Link: https://lore.kernel.org/r/20210209130618.15838-1-hsiangkao@aol.com Fixes: 62dc45979f3f ("staging: erofs: fix race of initializing xattrs of a inode at the same time") Fixes: 152a333a5895 ("staging: erofs: add compacted compression indexes support") Cc: stable@vger.kernel.org # 5.3+ Reported-by: Huang Jianan huangjianan@oppo.com Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Gao Xiang hsiangkao@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/erofs/xattr.c | 10 +++++++++- fs/erofs/zmap.c | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-)
--- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -48,8 +48,14 @@ static int init_inode_xattrs(struct inod int ret = 0;
/* the most case is that xattrs of this inode are initialized. */ - if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) { + /* + * paired with smp_mb() at the end of the function to ensure + * fields will only be observed after the bit is set. + */ + smp_mb(); return 0; + }
if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_XATTR_BIT, TASK_KILLABLE)) return -ERESTARTSYS; @@ -137,6 +143,8 @@ static int init_inode_xattrs(struct inod } xattr_iter_end(&it, atomic_map);
+ /* paired with smp_mb() at the beginning of the function. */ + smp_mb(); set_bit(EROFS_I_EA_INITED_BIT, &vi->flags);
out_unlock: --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -36,8 +36,14 @@ static int z_erofs_fill_inode_lazy(struc void *kaddr; struct z_erofs_map_header *h;
- if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) + if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) { + /* + * paired with smp_mb() at the end of the function to ensure + * fields will only be observed after the bit is set. + */ + smp_mb(); return 0; + }
if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE)) return -ERESTARTSYS; @@ -83,6 +89,8 @@ static int z_erofs_fill_inode_lazy(struc
vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + ((h->h_clusterbits >> 5) & 7); + /* paired with smp_mb() at the beginning of the function */ + smp_mb(); set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); unmap_done: kunmap_atomic(kaddr);
From: James Bottomley James.Bottomley@HansenPartnership.com
commit 3d9ae54af1d02a7c0edc55c77d7df2b921e58a87 upstream.
The TPM TIS specification says the TPM signals the acquisition of locality when the TMP_ACCESS_REQUEST_USE bit goes to one *and* the TPM_ACCESS_REQUEST_USE bit goes to zero. Currently we only check the former not the latter, so check both. Adding the check on TPM_ACCESS_REQUEST_USE should fix the case where the locality is re-requested before the TPM has released it. In this case the locality may get released briefly before it is reacquired, which causes all sorts of problems. However, with the added check, TPM_ACCESS_REQUEST_USE should remain 1 until the second request for the locality is granted.
Cc: stable@ger.kernel.org Fixes: 27084efee0c3 ("[PATCH] tpm: driver for next generation TPM chips") Signed-off-by: James Bottomley James.Bottomley@HansenPartnership.com Reviewed-by: Jerry Snitselaar jsnitsel@redhat.com Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm_tis_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -125,7 +125,8 @@ static bool check_locality(struct tpm_ch if (rc < 0) return false;
- if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID + | TPM_ACCESS_REQUEST_USE)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { priv->locality = l; return true;
From: James Bottomley James.Bottomley@HansenPartnership.com
commit e42acf104d6e0bd7ccd2f09103d5be5e6d3c637c upstream.
The current release locality code seems to be based on the misunderstanding that the TPM interrupts when a locality is released: it doesn't, only when the locality is acquired.
Furthermore, there seems to be no point in waiting for the locality to be released. All it does is penalize the last TPM user. However, if there's no next TPM user, this is a pointless wait and if there is a next TPM user, they'll pay the penalty waiting for the new locality (or possibly not if it's the same as the old locality).
Fix the code by making release_locality as simple write to release with no waiting for completion.
Cc: stable@ger.kernel.org Fixes: 33bafe90824b ("tpm_tis: verify locality released before returning from release_locality") Signed-off-by: James Bottomley James.Bottomley@HansenPartnership.com Reviewed-by: Jerry Snitselaar jsnitsel@redhat.com Reviewed-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm_tis_core.c | 47 ---------------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-)
--- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -135,58 +135,13 @@ static bool check_locality(struct tpm_ch return false; }
-static bool locality_inactive(struct tpm_chip *chip, int l) -{ - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - int rc; - u8 access; - - rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); - if (rc < 0) - return false; - - if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) - == TPM_ACCESS_VALID) - return true; - - return false; -} - static int release_locality(struct tpm_chip *chip, int l) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - unsigned long stop, timeout; - long rc;
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
- stop = jiffies + chip->timeout_a; - - if (chip->flags & TPM_CHIP_FLAG_IRQ) { -again: - timeout = stop - jiffies; - if ((long)timeout <= 0) - return -1; - - rc = wait_event_interruptible_timeout(priv->int_queue, - (locality_inactive(chip, l)), - timeout); - - if (rc > 0) - return 0; - - if (rc == -ERESTARTSYS && freezing(current)) { - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - } else { - do { - if (locality_inactive(chip, l)) - return 0; - tpm_msleep(TPM_TIMEOUT); - } while (time_before(jiffies, stop)); - } - return -1; + return 0; }
static int request_locality(struct tpm_chip *chip, int l)
From: Jarkko Sakkinen jarkko@kernel.org
commit 5df16caada3fba3b21cb09b85cdedf99507f4ec1 upstream.
When tpm_get_random() was introduced, it defined the following API for the return value:
1. A positive value tells how many bytes of random data was generated. 2. A negative value on error.
However, in the call sites the API was used incorrectly, i.e. as it would only return negative values and otherwise zero. Returning he positive read counts to the user space does not make any possible sense.
Fix this by returning -EIO when tpm_get_random() returns a positive value.
Fixes: 41ab999c80f1 ("tpm: Move tpm_get_random api into the TPM device driver") Cc: stable@vger.kernel.org Cc: Mimi Zohar zohar@linux.ibm.com Cc: "James E.J. Bottomley" James.Bottomley@HansenPartnership.com Cc: David Howells dhowells@redhat.com Cc: Kent Yoder key@linux.vnet.ibm.com Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Reviewed-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/keys/trusted-keys/trusted_tpm1.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
--- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -403,9 +403,12 @@ static int osap(struct tpm_buf *tb, stru int ret;
ret = tpm_get_random(chip, ononce, TPM_NONCE_SIZE); - if (ret != TPM_NONCE_SIZE) + if (ret < 0) return ret;
+ if (ret != TPM_NONCE_SIZE) + return -EIO; + tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); tpm_buf_append_u16(tb, type); tpm_buf_append_u32(tb, handle); @@ -496,8 +499,12 @@ static int tpm_seal(struct tpm_buf *tb, goto out;
ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE); + if (ret < 0) + return ret; + if (ret != TPM_NONCE_SIZE) - goto out; + return -EIO; + ordinal = htonl(TPM_ORD_SEAL); datsize = htonl(datalen); pcrsize = htonl(pcrinfosize); @@ -601,9 +608,12 @@ static int tpm_unseal(struct tpm_buf *tb
ordinal = htonl(TPM_ORD_UNSEAL); ret = tpm_get_random(chip, nonceodd, TPM_NONCE_SIZE); + if (ret < 0) + return ret; + if (ret != TPM_NONCE_SIZE) { pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); - return ret; + return -EIO; } ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, enonce1, nonceodd, cont, sizeof(uint32_t), @@ -1013,8 +1023,12 @@ static int trusted_instantiate(struct ke case Opt_new: key_len = payload->key_len; ret = tpm_get_random(chip, payload->key, key_len); + if (ret < 0) + goto out; + if (ret != key_len) { pr_info("trusted_key: key_create failed (%d)\n", ret); + ret = -EIO; goto out; } if (tpm2)
From: Jarkko Sakkinen jarkko@kernel.org
commit 8da7520c80468c48f981f0b81fc1be6599e3b0ad upstream.
Consider the following transcript:
$ keyctl add trusted kmk "new 32 blobauth=helloworld keyhandle=80000000 migratable=1" @u add_key: Invalid argument
The documentation has the following description:
migratable= 0|1 indicating permission to reseal to new PCR values, default 1 (resealing allowed)
The consequence is that "migratable=1" should succeed. Fix this by allowing this condition to pass instead of return -EINVAL.
[*] Documentation/security/keys/trusted-encrypted.rst
Cc: stable@vger.kernel.org Cc: "James E.J. Bottomley" jejb@linux.ibm.com Cc: Mimi Zohar zohar@linux.ibm.com Cc: David Howells dhowells@redhat.com Fixes: d00a1c72f7f4 ("keys: add new trusted key-type") Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/keys/trusted-keys/trusted_tpm1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -801,7 +801,7 @@ static int getoptions(char *c, struct tr case Opt_migratable: if (*args[0].from == '0') pay->migratable = 0; - else + else if (*args[0].from != '1') return -EINVAL; break; case Opt_pcrlock:
From: Jarkko Sakkinen jarkko@kernel.org
commit 8c657a0590de585b1115847c17b34a58025f2f4b upstream.
When TPM 2.0 trusted keys code was moved to the trusted keys subsystem, the operations were unwrapped from tpm_try_get_ops() and tpm_put_ops(), which are used to take temporarily the ownership of the TPM chip. The ownership is only taken inside tpm_send(), but this is not sufficient, as in the key load TPM2_CC_LOAD, TPM2_CC_UNSEAL and TPM2_FLUSH_CONTEXT need to be done as a one single atom.
Take the TPM chip ownership before sending anything with tpm_try_get_ops() and tpm_put_ops(), and use tpm_transmit_cmd() to send TPM commands instead of tpm_send(), reverting back to the old behaviour.
Fixes: 2e19e10131a0 ("KEYS: trusted: Move TPM2 trusted keys code") Reported-by: "James E.J. Bottomley" James.Bottomley@HansenPartnership.com Cc: stable@vger.kernel.org Cc: David Howells dhowells@redhat.com Cc: Mimi Zohar zohar@linux.ibm.com Cc: Sumit Garg sumit.garg@linaro.org Acked-by Sumit Garg sumit.garg@linaro.org Tested-by: Mimi Zohar zohar@linux.ibm.com Signed-off-by: Jarkko Sakkinen jarkko@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/char/tpm/tpm.h | 4 ---- include/linux/tpm.h | 5 ++++- security/keys/trusted-keys/trusted_tpm2.c | 22 ++++++++++++++++++---- 3 files changed, 22 insertions(+), 9 deletions(-)
--- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -164,8 +164,6 @@ extern const struct file_operations tpmr extern struct idr dev_nums_idr;
ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz); -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, - size_t min_rsp_body_length, const char *desc); int tpm_get_timeouts(struct tpm_chip *); int tpm_auto_startup(struct tpm_chip *chip);
@@ -194,8 +192,6 @@ static inline void tpm_msleep(unsigned i int tpm_chip_start(struct tpm_chip *chip); void tpm_chip_stop(struct tpm_chip *chip); struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); -__must_check int tpm_try_get_ops(struct tpm_chip *chip); -void tpm_put_ops(struct tpm_chip *chip);
struct tpm_chip *tpm_chip_alloc(struct device *dev, const struct tpm_class_ops *ops); --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -397,6 +397,10 @@ static inline u32 tpm2_rc_value(u32 rc) #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
extern int tpm_is_tpm2(struct tpm_chip *chip); +extern __must_check int tpm_try_get_ops(struct tpm_chip *chip); +extern void tpm_put_ops(struct tpm_chip *chip); +extern ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf, + size_t min_rsp_body_length, const char *desc); extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest); extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, @@ -410,7 +414,6 @@ static inline int tpm_is_tpm2(struct tpm { return -ENODEV; } - static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, struct tpm_digest *digest) { --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -83,6 +83,12 @@ int tpm2_seal_trusted(struct tpm_chip *c if (rc) return rc;
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); + if (rc) { + tpm_put_ops(chip); + return rc; + } + tpm_buf_append_u32(&buf, options->keyhandle); tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL /* nonce */, 0, @@ -130,7 +136,7 @@ int tpm2_seal_trusted(struct tpm_chip *c goto out; }
- rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); + rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); if (rc) goto out;
@@ -157,6 +163,7 @@ out: rc = -EPERM; }
+ tpm_put_ops(chip); return rc; }
@@ -211,7 +218,7 @@ static int tpm2_load_cmd(struct tpm_chip goto out; }
- rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); + rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); if (!rc) *blob_handle = be32_to_cpup( (__be32 *) &buf.data[TPM_HEADER_SIZE]); @@ -260,7 +267,7 @@ static int tpm2_unseal_cmd(struct tpm_ch options->blobauth /* hmac */, TPM_DIGEST_SIZE);
- rc = tpm_send(chip, buf.data, tpm_buf_length(&buf)); + rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); if (rc > 0) rc = -EPERM;
@@ -304,12 +311,19 @@ int tpm2_unseal_trusted(struct tpm_chip u32 blob_handle; int rc;
- rc = tpm2_load_cmd(chip, payload, options, &blob_handle); + rc = tpm_try_get_ops(chip); if (rc) return rc;
+ rc = tpm2_load_cmd(chip, payload, options, &blob_handle); + if (rc) + goto out; + rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); tpm2_flush_context(chip, blob_handle);
+out: + tpm_put_ops(chip); + return rc; }
From: Josef Bacik josef@toxicpanda.com
commit 7e2a870a599d4699a626ec26430c7a1ab14a2a49 upstream.
Zygo reported the following panic when testing my error handling patches for relocation:
kernel BUG at fs/btrfs/backref.c:2545! invalid opcode: 0000 [#1] SMP KASAN PTI CPU: 3 PID: 8472 Comm: btrfs Tainted: G W 14 Hardware name: QEMU Standard PC (i440FX + PIIX,
Call Trace: btrfs_backref_error_cleanup+0x4df/0x530 build_backref_tree+0x1a5/0x700 ? _raw_spin_unlock+0x22/0x30 ? release_extent_buffer+0x225/0x280 ? free_extent_buffer.part.52+0xd7/0x140 relocate_tree_blocks+0x2a6/0xb60 ? kasan_unpoison_shadow+0x35/0x50 ? do_relocation+0xc10/0xc10 ? kasan_kmalloc+0x9/0x10 ? kmem_cache_alloc_trace+0x6a3/0xcb0 ? free_extent_buffer.part.52+0xd7/0x140 ? rb_insert_color+0x342/0x360 ? add_tree_block.isra.36+0x236/0x2b0 relocate_block_group+0x2eb/0x780 ? merge_reloc_roots+0x470/0x470 btrfs_relocate_block_group+0x26e/0x4c0 btrfs_relocate_chunk+0x52/0x120 btrfs_balance+0xe2e/0x18f0 ? pvclock_clocksource_read+0xeb/0x190 ? btrfs_relocate_chunk+0x120/0x120 ? lock_contended+0x620/0x6e0 ? do_raw_spin_lock+0x1e0/0x1e0 ? do_raw_spin_unlock+0xa8/0x140 btrfs_ioctl_balance+0x1f9/0x460 btrfs_ioctl+0x24c8/0x4380 ? __kasan_check_read+0x11/0x20 ? check_chain_key+0x1f4/0x2f0 ? __asan_loadN+0xf/0x20 ? btrfs_ioctl_get_supported_features+0x30/0x30 ? kvm_sched_clock_read+0x18/0x30 ? check_chain_key+0x1f4/0x2f0 ? lock_downgrade+0x3f0/0x3f0 ? handle_mm_fault+0xad6/0x2150 ? do_vfs_ioctl+0xfc/0x9d0 ? ioctl_file_clone+0xe0/0xe0 ? check_flags.part.50+0x6c/0x1e0 ? check_flags.part.50+0x6c/0x1e0 ? check_flags+0x26/0x30 ? lock_is_held_type+0xc3/0xf0 ? syscall_enter_from_user_mode+0x1b/0x60 ? do_syscall_64+0x13/0x80 ? rcu_read_lock_sched_held+0xa1/0xd0 ? __kasan_check_read+0x11/0x20 ? __fget_light+0xae/0x110 __x64_sys_ioctl+0xc3/0x100 do_syscall_64+0x37/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9
This occurs because of this check
if (RB_EMPTY_NODE(&upper->rb_node)) BUG_ON(!list_empty(&node->upper));
As we are dropping the backref node, if we discover that our upper node in the edge we just cleaned up isn't linked into the cache that we are now done with this node, thus the BUG_ON().
However this is an erroneous assumption, as we will look up all the references for a node first, and then process the pending edges. All of the 'upper' nodes in our pending edges won't be in the cache's rb_tree yet, because they haven't been processed. We could very well have many edges still left to cleanup on this node.
The fact is we simply do not need this check, we can just process all of the edges only for this node, because below this check we do the following
if (list_empty(&upper->lower)) { list_add_tail(&upper->lower, &cache->leaves); upper->lowest = 1; }
If the upper node truly isn't used yet, then we add it to the cache->leaves list to be cleaned up later. If it is still used then the last child node that has it linked into its node will add it to the leaves list and then it will be cleaned up.
Fix this problem by dropping this logic altogether. With this fix I no longer see the panic when testing with error injection in the backref code.
CC: stable@vger.kernel.org # 4.4+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Josef Bacik josef@toxicpanda.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/backref.c | 7 ------- 1 file changed, 7 deletions(-)
--- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -2541,13 +2541,6 @@ void btrfs_backref_cleanup_node(struct b list_del(&edge->list[UPPER]); btrfs_backref_free_edge(cache, edge);
- if (RB_EMPTY_NODE(&upper->rb_node)) { - BUG_ON(!list_empty(&node->upper)); - btrfs_backref_drop_node(cache, node); - node = upper; - node->lowest = 1; - continue; - } /* * Add the node to leaf node list if no other child block * cached.
From: Josef Bacik josef@toxicpanda.com
commit f78743fbdae1bb31bc9c9233c3590a5048782381 upstream.
The backref code is looking for a reloc_root that corresponds to the given fs root. However any number of things could have gone wrong while initializing that reloc_root, like ENOMEM while trying to allocate the root itself, or EIO while trying to write the root item. This would result in no corresponding reloc_root being in the reloc root cache, and thus would return NULL when we do the find_reloc_root() call.
Because of this we do not want to WARN_ON(). This presumably was meant to catch developer errors, cases where we messed up adding the reloc root. However we can easily hit this case with error injection, and thus should not do a WARN_ON().
CC: stable@vger.kernel.org # 5.10+ Reported-by: Zygo Blaxell ce3g8jdj@umail.furryterror.org Signed-off-by: Josef Bacik josef@toxicpanda.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/backref.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -2617,7 +2617,7 @@ static int handle_direct_tree_backref(st /* Only reloc backref cache cares about a specific root */ if (cache->is_reloc) { root = find_reloc_root(cache->fs_info, cur->bytenr); - if (WARN_ON(!root)) + if (!root) return -ENOENT; cur->root = root; } else {
From: Josef Bacik josef@toxicpanda.com
commit eddda68d97732ce05ca145f8e85e8a447f65cdad upstream.
A weird KASAN problem that Zygo reported could have been easily caught if we checked for basic things in our backref freeing code. We have two methods of freeing a backref node
- btrfs_backref_free_node: this just is kfree() essentially. - btrfs_backref_drop_node: this actually unlinks the node and cleans up everything and then calls btrfs_backref_free_node().
We should mostly be using btrfs_backref_drop_node(), to make sure the node is properly unlinked from the backref cache, and only use btrfs_backref_free_node() when we know the node isn't actually linked to the backref cache. We made a mistake here and thus got the KASAN splat.
Make this style of issue easier to find by adding some ASSERT()'s to btrfs_backref_free_node() and adjusting our deletion stuff to properly init the list so we can rely on list_empty() checks working properly.
BUG: KASAN: use-after-free in btrfs_backref_cleanup_node+0x18a/0x420 Read of size 8 at addr ffff888112402950 by task btrfs/28836
CPU: 0 PID: 28836 Comm: btrfs Tainted: G W 5.10.0-e35f27394290-for-next+ #23 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 Call Trace: dump_stack+0xbc/0xf9 ? btrfs_backref_cleanup_node+0x18a/0x420 print_address_description.constprop.8+0x21/0x210 ? record_print_text.cold.34+0x11/0x11 ? btrfs_backref_cleanup_node+0x18a/0x420 ? btrfs_backref_cleanup_node+0x18a/0x420 kasan_report.cold.10+0x20/0x37 ? btrfs_backref_cleanup_node+0x18a/0x420 __asan_load8+0x69/0x90 btrfs_backref_cleanup_node+0x18a/0x420 btrfs_backref_release_cache+0x83/0x1b0 relocate_block_group+0x394/0x780 ? merge_reloc_roots+0x4a0/0x4a0 btrfs_relocate_block_group+0x26e/0x4c0 btrfs_relocate_chunk+0x52/0x120 btrfs_balance+0xe2e/0x1900 ? check_flags.part.50+0x6c/0x1e0 ? btrfs_relocate_chunk+0x120/0x120 ? kmem_cache_alloc_trace+0xa06/0xcb0 ? _copy_from_user+0x83/0xc0 btrfs_ioctl_balance+0x3a7/0x460 btrfs_ioctl+0x24c8/0x4360 ? __kasan_check_read+0x11/0x20 ? check_chain_key+0x1f4/0x2f0 ? __asan_loadN+0xf/0x20 ? btrfs_ioctl_get_supported_features+0x30/0x30 ? kvm_sched_clock_read+0x18/0x30 ? check_chain_key+0x1f4/0x2f0 ? lock_downgrade+0x3f0/0x3f0 ? handle_mm_fault+0xad6/0x2150 ? do_vfs_ioctl+0xfc/0x9d0 ? ioctl_file_clone+0xe0/0xe0 ? check_flags.part.50+0x6c/0x1e0 ? check_flags.part.50+0x6c/0x1e0 ? check_flags+0x26/0x30 ? lock_is_held_type+0xc3/0xf0 ? syscall_enter_from_user_mode+0x1b/0x60 ? do_syscall_64+0x13/0x80 ? rcu_read_lock_sched_held+0xa1/0xd0 ? __kasan_check_read+0x11/0x20 ? __fget_light+0xae/0x110 __x64_sys_ioctl+0xc3/0x100 do_syscall_64+0x37/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f4c4bdfe427 RSP: 002b:00007fff33ee6df8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007fff33ee6e98 RCX: 00007f4c4bdfe427 RDX: 00007fff33ee6e98 RSI: 00000000c4009420 RDI: 0000000000000003 RBP: 0000000000000003 R08: 0000000000000003 R09: 0000000000000078 R10: fffffffffffff59d R11: 0000000000000202 R12: 0000000000000001 R13: 0000000000000000 R14: 00007fff33ee8a34 R15: 0000000000000001
Allocated by task 28836: kasan_save_stack+0x21/0x50 __kasan_kmalloc.constprop.18+0xbe/0xd0 kasan_kmalloc+0x9/0x10 kmem_cache_alloc_trace+0x410/0xcb0 btrfs_backref_alloc_node+0x46/0xf0 btrfs_backref_add_tree_node+0x60d/0x11d0 build_backref_tree+0xc5/0x700 relocate_tree_blocks+0x2be/0xb90 relocate_block_group+0x2eb/0x780 btrfs_relocate_block_group+0x26e/0x4c0 btrfs_relocate_chunk+0x52/0x120 btrfs_balance+0xe2e/0x1900 btrfs_ioctl_balance+0x3a7/0x460 btrfs_ioctl+0x24c8/0x4360 __x64_sys_ioctl+0xc3/0x100 do_syscall_64+0x37/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 28836: kasan_save_stack+0x21/0x50 kasan_set_track+0x20/0x30 kasan_set_free_info+0x1f/0x30 __kasan_slab_free+0xf3/0x140 kasan_slab_free+0xe/0x10 kfree+0xde/0x200 btrfs_backref_error_cleanup+0x452/0x530 build_backref_tree+0x1a5/0x700 relocate_tree_blocks+0x2be/0xb90 relocate_block_group+0x2eb/0x780 btrfs_relocate_block_group+0x26e/0x4c0 btrfs_relocate_chunk+0x52/0x120 btrfs_balance+0xe2e/0x1900 btrfs_ioctl_balance+0x3a7/0x460 btrfs_ioctl+0x24c8/0x4360 __x64_sys_ioctl+0xc3/0x100 do_syscall_64+0x37/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9
The buggy address belongs to the object at ffff888112402900 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 80 bytes inside of 128-byte region [ffff888112402900, ffff888112402980) The buggy address belongs to the page: page:0000000028b1cd08 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888131c810c0 pfn:0x112402 flags: 0x17ffe0000000200(slab) raw: 017ffe0000000200 ffffea000424f308 ffffea0007d572c8 ffff888100040440 raw: ffff888131c810c0 ffff888112402000 0000000100000009 0000000000000000 page dumped because: kasan: bad access detected
Memory state around the buggy address: ffff888112402800: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888112402880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888112402900: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^ ffff888112402980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff888112402a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Link: https://lore.kernel.org/linux-btrfs/20201208194607.GI31381@hungrycats.org/ CC: stable@vger.kernel.org # 5.10+ Signed-off-by: Josef Bacik josef@toxicpanda.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/backref.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
--- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -296,6 +296,9 @@ static inline void btrfs_backref_free_no struct btrfs_backref_node *node) { if (node) { + ASSERT(list_empty(&node->list)); + ASSERT(list_empty(&node->lower)); + ASSERT(node->eb == NULL); cache->nr_nodes--; btrfs_put_root(node->root); kfree(node); @@ -340,11 +343,11 @@ static inline void btrfs_backref_drop_no static inline void btrfs_backref_drop_node(struct btrfs_backref_cache *tree, struct btrfs_backref_node *node) { - BUG_ON(!list_empty(&node->upper)); + ASSERT(list_empty(&node->upper));
btrfs_backref_drop_node_buffer(node); - list_del(&node->list); - list_del(&node->lower); + list_del_init(&node->list); + list_del_init(&node->lower); if (!RB_EMPTY_NODE(&node->rb_node)) rb_erase(&node->rb_node, &tree->rb_root); btrfs_backref_free_node(tree, node);
From: Josef Bacik josef@toxicpanda.com
commit 867ed321f90d06aaba84e2c91de51cd3038825ef upstream.
While testing my error handling patches, I added a error injection site at btrfs_inc_extent_ref, to validate the error handling I added was doing the correct thing. However I hit a pretty ugly corruption while doing this check, with the following error injection stack trace:
btrfs_inc_extent_ref btrfs_copy_root create_reloc_root btrfs_init_reloc_root btrfs_record_root_in_trans btrfs_start_transaction btrfs_update_inode btrfs_update_time touch_atime file_accessed btrfs_file_mmap
This is because we do not catch the error from btrfs_inc_extent_ref, which in practice would be ENOMEM, which means we lose the extent references for a root that has already been allocated and inserted, which is the problem. Fix this by aborting the transaction if we fail to do the reference modification.
CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Josef Bacik josef@toxicpanda.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/ctree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -221,9 +221,10 @@ int btrfs_copy_root(struct btrfs_trans_h ret = btrfs_inc_ref(trans, root, cow, 1); else ret = btrfs_inc_ref(trans, root, cow, 0); - - if (ret) + if (ret) { + btrfs_abort_transaction(trans, ret); return ret; + }
btrfs_mark_buffer_dirty(cow); *cow_ret = cow;
From: Josef Bacik josef@toxicpanda.com
commit c78a10aebb275c38d0cfccae129a803fe622e305 upstream.
When recovering a relocation, if we run into a reloc root that has 0 refs we simply add it to the reloc_control->reloc_roots list, and then clean it up later. The problem with this is __del_reloc_root() doesn't do anything if the root isn't in the radix tree, which in this case it won't be because we never call __add_reloc_root() on the reloc_root.
This exit condition simply isn't correct really. During normal operation we can remove ourselves from the rb tree and then we're meant to clean up later at merge_reloc_roots() time, and this happens correctly. During recovery we're depending on free_reloc_roots() to drop our references, but we're short-circuiting.
Fix this by continuing to check if we're on the list and dropping ourselves from the reloc_control root list and dropping our reference appropriately. Change the corresponding BUG_ON() to an ASSERT() that does the correct thing if we aren't in the rb tree.
CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Josef Bacik josef@toxicpanda.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/relocation.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
--- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -668,9 +668,7 @@ static void __del_reloc_root(struct btrf RB_CLEAR_NODE(&node->rb_node); } spin_unlock(&rc->reloc_root_tree.lock); - if (!node) - return; - BUG_ON((struct btrfs_root *)node->data != root); + ASSERT(!node || (struct btrfs_root *)node->data == root); }
/*
From: Josef Bacik josef@toxicpanda.com
commit 938fcbfb0cbcf532a1869efab58e6009446b1ced upstream.
While doing error injection testing with my relocation patches I hit the following assert:
assertion failed: list_empty(&block_group->dirty_list), in fs/btrfs/block-group.c:3356 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ctree.h:3357! invalid opcode: 0000 [#1] SMP NOPTI CPU: 0 PID: 24351 Comm: umount Tainted: G W 5.10.0-rc3+ #193 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 RIP: 0010:assertfail.constprop.0+0x18/0x1a RSP: 0018:ffffa09b019c7e00 EFLAGS: 00010282 RAX: 0000000000000056 RBX: ffff8f6492c18000 RCX: 0000000000000000 RDX: ffff8f64fbc27c60 RSI: ffff8f64fbc19050 RDI: ffff8f64fbc19050 RBP: ffff8f6483bbdc00 R08: 0000000000000000 R09: 0000000000000000 R10: ffffa09b019c7c38 R11: ffffffff85d70928 R12: ffff8f6492c18100 R13: ffff8f6492c18148 R14: ffff8f6483bbdd70 R15: dead000000000100 FS: 00007fbfda4cdc40(0000) GS:ffff8f64fbc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fbfda666fd0 CR3: 000000013cf66002 CR4: 0000000000370ef0 Call Trace: btrfs_free_block_groups.cold+0x55/0x55 close_ctree+0x2c5/0x306 ? fsnotify_destroy_marks+0x14/0x100 generic_shutdown_super+0x6c/0x100 kill_anon_super+0x14/0x30 btrfs_kill_super+0x12/0x20 deactivate_locked_super+0x36/0xa0 cleanup_mnt+0x12d/0x190 task_work_run+0x5c/0xa0 exit_to_user_mode_prepare+0x1b1/0x1d0 syscall_exit_to_user_mode+0x54/0x280 entry_SYSCALL_64_after_hwframe+0x44/0xa9
This happened because I injected an error in btrfs_cow_block() while running the dirty block groups. When we run the dirty block groups, we splice the list onto a local list to process. However if an error occurs, we only cleanup the transactions dirty block group list, not any pending block groups we have on our locally spliced list.
In fact if we fail to allocate a path in this function we'll also fail to clean up the splice list.
Fix this by splicing the list back onto the transaction dirty block group list so that the block groups are cleaned up. Then add a 'out' label and have the error conditions jump to out so that the errors are handled properly. This also has the side-effect of fixing a problem where we would clear 'ret' on error because we unconditionally ran btrfs_run_delayed_refs().
CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Josef Bacik josef@toxicpanda.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/block-group.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
--- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -2564,8 +2564,10 @@ again:
if (!path) { path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out; + } }
/* @@ -2659,16 +2661,14 @@ again: btrfs_put_block_group(cache); if (drop_reserve) btrfs_delayed_refs_rsv_release(fs_info, 1); - - if (ret) - break; - /* * Avoid blocking other tasks for too long. It might even save * us from writing caches for block groups that are going to be * removed. */ mutex_unlock(&trans->transaction->cache_write_mutex); + if (ret) + goto out; mutex_lock(&trans->transaction->cache_write_mutex); } mutex_unlock(&trans->transaction->cache_write_mutex); @@ -2692,7 +2692,12 @@ again: goto again; } spin_unlock(&cur_trans->dirty_bgs_lock); - } else if (ret < 0) { + } +out: + if (ret < 0) { + spin_lock(&cur_trans->dirty_bgs_lock); + list_splice_init(&dirty, &cur_trans->dirty_bgs); + spin_unlock(&cur_trans->dirty_bgs_lock); btrfs_cleanup_dirty_bgs(cur_trans, fs_info); }
From: Josef Bacik josef@toxicpanda.com
commit 2187374f35fe9cadbddaa9fcf0c4121365d914e8 upstream.
Currently we pass things around to figure out if we maybe freeing data based on the state of the delayed refs head. This makes the accounting sort of confusing and hard to follow, as it's distinctly separate from the delayed ref heads stuff, but also depends on it entirely.
Fix this by explicitly adjusting the space_info->total_bytes_pinned in the delayed refs code. We now have two places where we modify this counter, once where we create the delayed and destroy the delayed refs, and once when we pin and unpin the extents. This means there is a slight overlap between delayed refs and the pin/unpin mechanisms, but this is simply used by the ENOSPC infrastructure to determine if we need to commit the transaction, so there's no adverse affect from this, we might simply commit thinking it will give us enough space when it might not.
CC: stable@vger.kernel.org # 5.10 Reviewed-by: Nikolay Borisov nborisov@suse.com Signed-off-by: Josef Bacik josef@toxicpanda.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/block-group.c | 10 +---- fs/btrfs/delayed-ref.c | 51 +++++++++++++++---------- fs/btrfs/delayed-ref.h | 16 ++++++-- fs/btrfs/extent-tree.c | 97 ++++++------------------------------------------- fs/btrfs/space-info.h | 17 ++++++++ 5 files changed, 74 insertions(+), 117 deletions(-)
--- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1371,9 +1371,7 @@ void btrfs_delete_unused_bgs(struct btrf btrfs_space_info_update_bytes_pinned(fs_info, space_info, -block_group->pinned); space_info->bytes_readonly += block_group->pinned; - percpu_counter_add_batch(&space_info->total_bytes_pinned, - -block_group->pinned, - BTRFS_TOTAL_BYTES_PINNED_BATCH); + __btrfs_mod_total_bytes_pinned(space_info, -block_group->pinned); block_group->pinned = 0;
spin_unlock(&block_group->lock); @@ -2901,10 +2899,8 @@ int btrfs_update_block_group(struct btrf spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock);
- percpu_counter_add_batch( - &cache->space_info->total_bytes_pinned, - num_bytes, - BTRFS_TOTAL_BYTES_PINNED_BATCH); + __btrfs_mod_total_bytes_pinned(cache->space_info, + num_bytes); set_extent_dirty(&trans->transaction->pinned_extents, bytenr, bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL); --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -648,12 +648,12 @@ inserted: */ static noinline void update_existing_head_ref(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *existing, - struct btrfs_delayed_ref_head *update, - int *old_ref_mod_ret) + struct btrfs_delayed_ref_head *update) { struct btrfs_delayed_ref_root *delayed_refs = &trans->transaction->delayed_refs; struct btrfs_fs_info *fs_info = trans->fs_info; + u64 flags = btrfs_ref_head_to_space_flags(existing); int old_ref_mod;
BUG_ON(existing->is_data != update->is_data); @@ -701,8 +701,6 @@ static noinline void update_existing_hea * currently, for refs we just added we know we're a-ok. */ old_ref_mod = existing->total_ref_mod; - if (old_ref_mod_ret) - *old_ref_mod_ret = old_ref_mod; existing->ref_mod += update->ref_mod; existing->total_ref_mod += update->ref_mod;
@@ -724,6 +722,22 @@ static noinline void update_existing_hea trans->delayed_ref_updates += csum_leaves; } } + + /* + * This handles the following conditions: + * + * 1. We had a ref mod of 0 or more and went negative, indicating that + * we may be freeing space, so add our space to the + * total_bytes_pinned counter. + * 2. We were negative and went to 0 or positive, so no longer can say + * that the space would be pinned, decrement our counter from the + * total_bytes_pinned counter. + */ + if (existing->total_ref_mod < 0 && old_ref_mod >= 0) + btrfs_mod_total_bytes_pinned(fs_info, flags, existing->num_bytes); + else if (existing->total_ref_mod >= 0 && old_ref_mod < 0) + btrfs_mod_total_bytes_pinned(fs_info, flags, -existing->num_bytes); + spin_unlock(&existing->lock); }
@@ -798,8 +812,7 @@ static noinline struct btrfs_delayed_ref add_delayed_ref_head(struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *head_ref, struct btrfs_qgroup_extent_record *qrecord, - int action, int *qrecord_inserted_ret, - int *old_ref_mod, int *new_ref_mod) + int action, int *qrecord_inserted_ret) { struct btrfs_delayed_ref_head *existing; struct btrfs_delayed_ref_root *delayed_refs; @@ -821,8 +834,7 @@ add_delayed_ref_head(struct btrfs_trans_ existing = htree_insert(&delayed_refs->href_root, &head_ref->href_node); if (existing) { - update_existing_head_ref(trans, existing, head_ref, - old_ref_mod); + update_existing_head_ref(trans, existing, head_ref); /* * we've updated the existing ref, free the newly * allocated ref @@ -830,14 +842,17 @@ add_delayed_ref_head(struct btrfs_trans_ kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref); head_ref = existing; } else { - if (old_ref_mod) - *old_ref_mod = 0; + u64 flags = btrfs_ref_head_to_space_flags(head_ref); + if (head_ref->is_data && head_ref->ref_mod < 0) { delayed_refs->pending_csums += head_ref->num_bytes; trans->delayed_ref_updates += btrfs_csum_bytes_to_leaves(trans->fs_info, head_ref->num_bytes); } + if (head_ref->ref_mod < 0) + btrfs_mod_total_bytes_pinned(trans->fs_info, flags, + head_ref->num_bytes); delayed_refs->num_heads++; delayed_refs->num_heads_ready++; atomic_inc(&delayed_refs->num_entries); @@ -845,8 +860,6 @@ add_delayed_ref_head(struct btrfs_trans_ } if (qrecord_inserted_ret) *qrecord_inserted_ret = qrecord_inserted; - if (new_ref_mod) - *new_ref_mod = head_ref->total_ref_mod;
return head_ref; } @@ -909,8 +922,7 @@ static void init_delayed_ref_common(stru */ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref, - struct btrfs_delayed_extent_op *extent_op, - int *old_ref_mod, int *new_ref_mod) + struct btrfs_delayed_extent_op *extent_op) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_delayed_tree_ref *ref; @@ -977,8 +989,7 @@ int btrfs_add_delayed_tree_ref(struct bt * the spin lock */ head_ref = add_delayed_ref_head(trans, head_ref, record, - action, &qrecord_inserted, - old_ref_mod, new_ref_mod); + action, &qrecord_inserted);
ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); spin_unlock(&delayed_refs->lock); @@ -1006,8 +1017,7 @@ int btrfs_add_delayed_tree_ref(struct bt */ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref, - u64 reserved, int *old_ref_mod, - int *new_ref_mod) + u64 reserved) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_delayed_data_ref *ref; @@ -1073,8 +1083,7 @@ int btrfs_add_delayed_data_ref(struct bt * the spin lock */ head_ref = add_delayed_ref_head(trans, head_ref, record, - action, &qrecord_inserted, - old_ref_mod, new_ref_mod); + action, &qrecord_inserted);
ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); spin_unlock(&delayed_refs->lock); @@ -1117,7 +1126,7 @@ int btrfs_add_delayed_extent_op(struct b spin_lock(&delayed_refs->lock);
add_delayed_ref_head(trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD, - NULL, NULL, NULL); + NULL);
spin_unlock(&delayed_refs->lock);
--- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h @@ -326,6 +326,16 @@ static inline void btrfs_put_delayed_ref } }
+static inline u64 btrfs_ref_head_to_space_flags( + struct btrfs_delayed_ref_head *head_ref) +{ + if (head_ref->is_data) + return BTRFS_BLOCK_GROUP_DATA; + else if (head_ref->is_system) + return BTRFS_BLOCK_GROUP_SYSTEM; + return BTRFS_BLOCK_GROUP_METADATA; +} + static inline void btrfs_put_delayed_ref_head(struct btrfs_delayed_ref_head *head) { if (refcount_dec_and_test(&head->refs)) @@ -334,12 +344,10 @@ static inline void btrfs_put_delayed_ref
int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref, - struct btrfs_delayed_extent_op *extent_op, - int *old_ref_mod, int *new_ref_mod); + struct btrfs_delayed_extent_op *extent_op); int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans, struct btrfs_ref *generic_ref, - u64 reserved, int *old_ref_mod, - int *new_ref_mod); + u64 reserved); int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans, u64 bytenr, u64 num_bytes, struct btrfs_delayed_extent_op *extent_op); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -82,41 +82,6 @@ void btrfs_free_excluded_extents(struct EXTENT_UPTODATE); }
-static u64 generic_ref_to_space_flags(struct btrfs_ref *ref) -{ - if (ref->type == BTRFS_REF_METADATA) { - if (ref->tree_ref.root == BTRFS_CHUNK_TREE_OBJECTID) - return BTRFS_BLOCK_GROUP_SYSTEM; - else - return BTRFS_BLOCK_GROUP_METADATA; - } - return BTRFS_BLOCK_GROUP_DATA; -} - -static void add_pinned_bytes(struct btrfs_fs_info *fs_info, - struct btrfs_ref *ref) -{ - struct btrfs_space_info *space_info; - u64 flags = generic_ref_to_space_flags(ref); - - space_info = btrfs_find_space_info(fs_info, flags); - ASSERT(space_info); - percpu_counter_add_batch(&space_info->total_bytes_pinned, ref->len, - BTRFS_TOTAL_BYTES_PINNED_BATCH); -} - -static void sub_pinned_bytes(struct btrfs_fs_info *fs_info, - struct btrfs_ref *ref) -{ - struct btrfs_space_info *space_info; - u64 flags = generic_ref_to_space_flags(ref); - - space_info = btrfs_find_space_info(fs_info, flags); - ASSERT(space_info); - percpu_counter_add_batch(&space_info->total_bytes_pinned, -ref->len, - BTRFS_TOTAL_BYTES_PINNED_BATCH); -} - /* simple helper to search for an existing data extent at a given offset */ int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) { @@ -1388,7 +1353,6 @@ int btrfs_inc_extent_ref(struct btrfs_tr struct btrfs_ref *generic_ref) { struct btrfs_fs_info *fs_info = trans->fs_info; - int old_ref_mod, new_ref_mod; int ret;
ASSERT(generic_ref->type != BTRFS_REF_NOT_SET && @@ -1397,17 +1361,12 @@ int btrfs_inc_extent_ref(struct btrfs_tr generic_ref->tree_ref.root == BTRFS_TREE_LOG_OBJECTID);
if (generic_ref->type == BTRFS_REF_METADATA) - ret = btrfs_add_delayed_tree_ref(trans, generic_ref, - NULL, &old_ref_mod, &new_ref_mod); + ret = btrfs_add_delayed_tree_ref(trans, generic_ref, NULL); else - ret = btrfs_add_delayed_data_ref(trans, generic_ref, 0, - &old_ref_mod, &new_ref_mod); + ret = btrfs_add_delayed_data_ref(trans, generic_ref, 0);
btrfs_ref_tree_mod(fs_info, generic_ref);
- if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0) - sub_pinned_bytes(fs_info, generic_ref); - return ret; }
@@ -1796,20 +1755,9 @@ void btrfs_cleanup_ref_head_accounting(s int nr_items = 1; /* Dropping this ref head update. */
if (head->total_ref_mod < 0) { - struct btrfs_space_info *space_info; - u64 flags; + u64 flags = btrfs_ref_head_to_space_flags(head);
- if (head->is_data) - flags = BTRFS_BLOCK_GROUP_DATA; - else if (head->is_system) - flags = BTRFS_BLOCK_GROUP_SYSTEM; - else - flags = BTRFS_BLOCK_GROUP_METADATA; - space_info = btrfs_find_space_info(fs_info, flags); - ASSERT(space_info); - percpu_counter_add_batch(&space_info->total_bytes_pinned, - -head->num_bytes, - BTRFS_TOTAL_BYTES_PINNED_BATCH); + btrfs_mod_total_bytes_pinned(fs_info, flags, -head->num_bytes);
/* * We had csum deletions accounted for in our delayed refs rsv, @@ -2572,8 +2520,7 @@ static int pin_down_extent(struct btrfs_ spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock);
- percpu_counter_add_batch(&cache->space_info->total_bytes_pinned, - num_bytes, BTRFS_TOTAL_BYTES_PINNED_BATCH); + __btrfs_mod_total_bytes_pinned(cache->space_info, num_bytes); set_extent_dirty(&trans->transaction->pinned_extents, bytenr, bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL); return 0; @@ -2784,8 +2731,7 @@ static int unpin_extent_range(struct btr cache->pinned -= len; btrfs_space_info_update_bytes_pinned(fs_info, space_info, -len); space_info->max_extent_size = 0; - percpu_counter_add_batch(&space_info->total_bytes_pinned, - -len, BTRFS_TOTAL_BYTES_PINNED_BATCH); + __btrfs_mod_total_bytes_pinned(space_info, -len); if (cache->ro) { space_info->bytes_readonly += len; readonly = true; @@ -3318,7 +3264,6 @@ void btrfs_free_tree_block(struct btrfs_ { struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_ref generic_ref = { 0 }; - int pin = 1; int ret;
btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF, @@ -3327,13 +3272,9 @@ void btrfs_free_tree_block(struct btrfs_ root->root_key.objectid);
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { - int old_ref_mod, new_ref_mod; - btrfs_ref_tree_mod(fs_info, &generic_ref); - ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL, - &old_ref_mod, &new_ref_mod); + ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL); BUG_ON(ret); /* -ENOMEM */ - pin = old_ref_mod >= 0 && new_ref_mod < 0; }
if (last_ref && btrfs_header_generation(buf) == trans->transid) { @@ -3345,7 +3286,6 @@ void btrfs_free_tree_block(struct btrfs_ goto out; }
- pin = 0; cache = btrfs_lookup_block_group(fs_info, buf->start);
if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { @@ -3362,9 +3302,6 @@ void btrfs_free_tree_block(struct btrfs_ trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); } out: - if (pin) - add_pinned_bytes(fs_info, &generic_ref); - if (last_ref) { /* * Deleting the buffer, clear the corrupt flag since it doesn't @@ -3378,7 +3315,6 @@ out: int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref) { struct btrfs_fs_info *fs_info = trans->fs_info; - int old_ref_mod, new_ref_mod; int ret;
if (btrfs_is_testing(fs_info)) @@ -3394,14 +3330,11 @@ int btrfs_free_extent(struct btrfs_trans ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID)) { /* unlocks the pinned mutex */ btrfs_pin_extent(trans, ref->bytenr, ref->len, 1); - old_ref_mod = new_ref_mod = 0; ret = 0; } else if (ref->type == BTRFS_REF_METADATA) { - ret = btrfs_add_delayed_tree_ref(trans, ref, NULL, - &old_ref_mod, &new_ref_mod); + ret = btrfs_add_delayed_tree_ref(trans, ref, NULL); } else { - ret = btrfs_add_delayed_data_ref(trans, ref, 0, - &old_ref_mod, &new_ref_mod); + ret = btrfs_add_delayed_data_ref(trans, ref, 0); }
if (!((ref->type == BTRFS_REF_METADATA && @@ -3410,9 +3343,6 @@ int btrfs_free_extent(struct btrfs_trans ref->data_ref.ref_root == BTRFS_TREE_LOG_OBJECTID))) btrfs_ref_tree_mod(fs_info, ref);
- if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0) - add_pinned_bytes(fs_info, ref); - return ret; }
@@ -4528,7 +4458,6 @@ int btrfs_alloc_reserved_file_extent(str struct btrfs_key *ins) { struct btrfs_ref generic_ref = { 0 }; - int ret;
BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
@@ -4536,9 +4465,8 @@ int btrfs_alloc_reserved_file_extent(str ins->objectid, ins->offset, 0); btrfs_init_data_ref(&generic_ref, root->root_key.objectid, owner, offset); btrfs_ref_tree_mod(root->fs_info, &generic_ref); - ret = btrfs_add_delayed_data_ref(trans, &generic_ref, - ram_bytes, NULL, NULL); - return ret; + + return btrfs_add_delayed_data_ref(trans, &generic_ref, ram_bytes); }
/* @@ -4730,8 +4658,7 @@ struct extent_buffer *btrfs_alloc_tree_b generic_ref.real_root = root->root_key.objectid; btrfs_init_tree_ref(&generic_ref, level, root_objectid); btrfs_ref_tree_mod(fs_info, &generic_ref); - ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, - extent_op, NULL, NULL); + ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, extent_op); if (ret) goto out_free_delayed; } --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -152,4 +152,21 @@ static inline void btrfs_space_info_free int btrfs_reserve_data_bytes(struct btrfs_fs_info *fs_info, u64 bytes, enum btrfs_reserve_flush_enum flush);
+static inline void __btrfs_mod_total_bytes_pinned( + struct btrfs_space_info *space_info, + s64 mod) +{ + percpu_counter_add_batch(&space_info->total_bytes_pinned, mod, + BTRFS_TOTAL_BYTES_PINNED_BATCH); +} + +static inline void btrfs_mod_total_bytes_pinned(struct btrfs_fs_info *fs_info, + u64 flags, s64 mod) +{ + struct btrfs_space_info *space_info = btrfs_find_space_info(fs_info, flags); + + ASSERT(space_info); + __btrfs_mod_total_bytes_pinned(space_info, mod); +} + #endif /* BTRFS_SPACE_INFO_H */
From: Josef Bacik josef@toxicpanda.com
commit 81e75ac74ecba929d1e922bf93f9fc467232e39f upstream.
My recent patch set "A variety of lock contention fixes", found here
https://lore.kernel.org/linux-btrfs/cover.1608319304.git.josef@toxicpanda.co... (Tracked in https://github.com/btrfs/linux/issues/86)
that reduce lock contention on the extent root by running delayed refs less often resulted in a regression in generic/371. This test fallocate()'s the fs until it's full, deletes all the files, and then tries to fallocate() until full again.
Before these patches we would run all of the delayed refs during flushing, and then would commit the transaction because we had plenty of pinned space to recover in order to allocate. However my patches made it so we weren't running the delayed refs as aggressively, which meant that we appeared to have less pinned space when we were deciding to commit the transaction.
We use the space_info->total_bytes_pinned to approximate how much space we have pinned. It's approximate because if we remove a reference to an extent we may free it, but there may be more references to it than we know of at that point, but we account it as pinned at the creation time, and then it's properly accounted when the delayed ref runs.
The way we account for pinned space is if the delayed_ref_head->total_ref_mod is < 0, because that is clearly a freeing option. However there is another case, and that is where ->total_ref_mod == 0 && ->must_insert_reserved == 1.
When we allocate a new extent, we have ->total_ref_mod == 1 and we have ->must_insert_reserved == 1. This is used to indicate that it is a brand new extent and will need to have its extent entry added before we modify any references on the delayed ref head. But if we subsequently remove that extent reference, our ->total_ref_mod will be 0, and that space will be pinned and freed. Accounting for this case properly allows for generic/371 to pass with my delayed refs patches applied.
It's important to note that this problem exists without the referenced patches, it just was uncovered by them.
CC: stable@vger.kernel.org # 5.10 Reviewed-by: Nikolay Borisov nborisov@suse.com Signed-off-by: Josef Bacik josef@toxicpanda.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/delayed-ref.c | 5 +++++ fs/btrfs/extent-tree.c | 33 +++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 14 deletions(-)
--- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -732,11 +732,16 @@ static noinline void update_existing_hea * 2. We were negative and went to 0 or positive, so no longer can say * that the space would be pinned, decrement our counter from the * total_bytes_pinned counter. + * 3. We are now at 0 and have ->must_insert_reserved set, which means + * this was a new allocation and then we dropped it, and thus must + * add our space to the total_bytes_pinned counter. */ if (existing->total_ref_mod < 0 && old_ref_mod >= 0) btrfs_mod_total_bytes_pinned(fs_info, flags, existing->num_bytes); else if (existing->total_ref_mod >= 0 && old_ref_mod < 0) btrfs_mod_total_bytes_pinned(fs_info, flags, -existing->num_bytes); + else if (existing->total_ref_mod == 0 && existing->must_insert_reserved) + btrfs_mod_total_bytes_pinned(fs_info, flags, existing->num_bytes);
spin_unlock(&existing->lock); } --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1754,23 +1754,28 @@ void btrfs_cleanup_ref_head_accounting(s { int nr_items = 1; /* Dropping this ref head update. */
- if (head->total_ref_mod < 0) { + /* + * We had csum deletions accounted for in our delayed refs rsv, we need + * to drop the csum leaves for this update from our delayed_refs_rsv. + */ + if (head->total_ref_mod < 0 && head->is_data) { + spin_lock(&delayed_refs->lock); + delayed_refs->pending_csums -= head->num_bytes; + spin_unlock(&delayed_refs->lock); + nr_items += btrfs_csum_bytes_to_leaves(fs_info, head->num_bytes); + } + + /* + * We were dropping refs, or had a new ref and dropped it, and thus must + * adjust down our total_bytes_pinned, the space may or may not have + * been pinned and so is accounted for properly in the pinned space by + * now. + */ + if (head->total_ref_mod < 0 || + (head->total_ref_mod == 0 && head->must_insert_reserved)) { u64 flags = btrfs_ref_head_to_space_flags(head);
btrfs_mod_total_bytes_pinned(fs_info, flags, -head->num_bytes); - - /* - * We had csum deletions accounted for in our delayed refs rsv, - * we need to drop the csum leaves for this update from our - * delayed_refs_rsv. - */ - if (head->is_data) { - spin_lock(&delayed_refs->lock); - delayed_refs->pending_csums -= head->num_bytes; - spin_unlock(&delayed_refs->lock); - nr_items += btrfs_csum_bytes_to_leaves(fs_info, - head->num_bytes); - } }
btrfs_delayed_refs_rsv_release(fs_info, nr_items);
From: Filipe Manana fdmanana@suse.com
commit 72c9925f87c8b74f36f8e75a4cd93d964538d3ca upstream.
At btrfs_copy_root(), if the call to btrfs_inc_ref() fails we end up returning without unlocking and releasing our reference on the extent buffer named "cow" we previously allocated with btrfs_alloc_tree_block().
So fix that by unlocking the extent buffer and dropping our reference on it before returning.
Fixes: be20aa9dbadc8c ("Btrfs: Add mount option to turn off data cow") 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/ctree.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -222,6 +222,8 @@ int btrfs_copy_root(struct btrfs_trans_h else ret = btrfs_inc_ref(trans, root, cow, 0); if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); btrfs_abort_transaction(trans, ret); return ret; }
From: Chris Wilson chris@chris-wilson.co.uk
commit d5109f739c9f14a3bda249cb48b16de1065932f0 upstream.
Flush; invalidate; change registers; invalidate; flush.
Will this finally work on every device? Or will Baytrail complain again?
On the positive side, we immediately see the benefit of having hsw-gt1 in CI.
Fixes: ace44e13e577 ("drm/i915/gt: Clear CACHE_MODE prior to clearing residuals") Testcase: igt/gem_render_tiled_blits # hsw-gt1 Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Mika Kuoppala mika.kuoppala@linux.intel.com Cc: Akeem G Abodunrin akeem.g.abodunrin@intel.com Acked-by: Mika Kuoppala mika.kuoppala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210125220247.31701-1-chris@c... (cherry picked from commit d30bbd62b1bfd9e0a33c3583c5a9e5d66f60cbd7) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Cc: Diego Calleja diegocg@gmail.com Cc: Hans de Goede hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/gen7_renderclear.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/i915/gt/gen7_renderclear.c +++ b/drivers/gpu/drm/i915/gt/gen7_renderclear.c @@ -393,6 +393,7 @@ static void emit_batch(struct i915_vma * desc_count);
/* Reset inherited context registers */ + gen7_emit_pipeline_flush(&cmds); gen7_emit_pipeline_invalidate(&cmds); batch_add(&cmds, MI_LOAD_REGISTER_IMM(2)); batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_0_GEN7));
From: Chris Wilson chris@chris-wilson.co.uk
commit 81ce8f04aa96f7f6cae05770f68b5d15be91f5a2 upstream.
The surface_state_base is an offset into the batch, so we need to pass the correct batch address for STATE_BASE_ADDRESS.
Fixes: 47f8253d2b89 ("drm/i915/gen7: Clear all EU/L3 residual contexts") Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Mika Kuoppala mika.kuoppala@linux.intel.com Cc: Prathap Kumar Valsan prathap.kumar.valsan@intel.com Cc: Akeem G Abodunrin akeem.g.abodunrin@intel.com Cc: Hans de Goede hdegoede@redhat.com Cc: Hans de Goede hdegoede@redhat.com Reviewed-by: Mika Kuoppala mika.kuoppala@linux.intel.com Cc: stable@vger.kernel.org # v5.7+ Link: https://patchwork.freedesktop.org/patch/msgid/20210210122728.20097-1-chris@c... (cherry picked from commit 1914911f4aa08ddc05bae71d3516419463e0c567) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/gt/gen7_renderclear.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/gt/gen7_renderclear.c +++ b/drivers/gpu/drm/i915/gt/gen7_renderclear.c @@ -240,7 +240,7 @@ gen7_emit_state_base_address(struct batc /* general */ *cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY; /* surface */ - *cs++ = batch_addr(batch) | surface_state_base | BASE_ADDRESS_MODIFY; + *cs++ = (batch_addr(batch) + surface_state_base) | BASE_ADDRESS_MODIFY; /* dynamic */ *cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY; /* indirect */
From: Ard Biesheuvel ardb@kernel.org
commit 0df07d8117c3576f1603b05b84089742a118d10a upstream.
The accelerated, instruction based implementations of SHA1, SHA2 and SHA3 are autoloaded based on CPU capabilities, given that the code is modest in size, and widely used, which means that resolving the algo name, loading all compatible modules and picking the one with the highest priority is taken to be suboptimal.
However, if these algorithms are requested before this CPU feature based matching and autoloading occurs, these modules are not even considered, and we end up with suboptimal performance.
So add the missing module aliases for the various SHA implementations.
Cc: stable@vger.kernel.org Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/crypto/sha1-ce-glue.c | 1 + arch/arm64/crypto/sha2-ce-glue.c | 2 ++ arch/arm64/crypto/sha3-ce-glue.c | 4 ++++ arch/arm64/crypto/sha512-ce-glue.c | 2 ++ 4 files changed, 9 insertions(+)
--- a/arch/arm64/crypto/sha1-ce-glue.c +++ b/arch/arm64/crypto/sha1-ce-glue.c @@ -19,6 +19,7 @@ MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel ard.biesheuvel@linaro.org"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha1");
struct sha1_ce_state { struct sha1_state sst; --- a/arch/arm64/crypto/sha2-ce-glue.c +++ b/arch/arm64/crypto/sha2-ce-glue.c @@ -19,6 +19,8 @@ MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel ard.biesheuvel@linaro.org"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha224"); +MODULE_ALIAS_CRYPTO("sha256");
struct sha256_ce_state { struct sha256_state sst; --- a/arch/arm64/crypto/sha3-ce-glue.c +++ b/arch/arm64/crypto/sha3-ce-glue.c @@ -23,6 +23,10 @@ MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel ard.biesheuvel@linaro.org"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha3-224"); +MODULE_ALIAS_CRYPTO("sha3-256"); +MODULE_ALIAS_CRYPTO("sha3-384"); +MODULE_ALIAS_CRYPTO("sha3-512");
asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks, int md_len); --- a/arch/arm64/crypto/sha512-ce-glue.c +++ b/arch/arm64/crypto/sha512-ce-glue.c @@ -23,6 +23,8 @@ MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel ard.biesheuvel@linaro.org"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha384"); +MODULE_ALIAS_CRYPTO("sha512");
asmlinkage void sha512_ce_transform(struct sha512_state *sst, u8 const *src, int blocks);
From: Ard Biesheuvel ardb@kernel.org
commit a13ed1d15b07a04b1f74b2df61ff7a5e47f45dd8 upstream.
The GCM mode driver uses 16 byte aligned buffers on the stack to pass the IV to the asm helpers, but unfortunately, the x86 port does not guarantee that the stack pointer is 16 byte aligned upon entry in the first place. Since the compiler is not aware of this, it will not emit the additional stack realignment sequence that is needed, and so the alignment is not guaranteed to be more than 8 bytes.
So instead, allocate some padding on the stack, and realign the IV pointer by hand.
Cc: stable@vger.kernel.org Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/crypto/aesni-intel_glue.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
--- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -686,7 +686,8 @@ static int gcmaes_crypt_by_sg(bool enc, struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned long auth_tag_len = crypto_aead_authsize(tfm); const struct aesni_gcm_tfm_s *gcm_tfm = aesni_gcm_tfm; - struct gcm_context_data data AESNI_ALIGN_ATTR; + u8 databuf[sizeof(struct gcm_context_data) + (AESNI_ALIGN - 8)] __aligned(8); + struct gcm_context_data *data = PTR_ALIGN((void *)databuf, AESNI_ALIGN); struct scatter_walk dst_sg_walk = {}; unsigned long left = req->cryptlen; unsigned long len, srclen, dstlen; @@ -735,8 +736,7 @@ static int gcmaes_crypt_by_sg(bool enc, }
kernel_fpu_begin(); - gcm_tfm->init(aes_ctx, &data, iv, - hash_subkey, assoc, assoclen); + gcm_tfm->init(aes_ctx, data, iv, hash_subkey, assoc, assoclen); if (req->src != req->dst) { while (left) { src = scatterwalk_map(&src_sg_walk); @@ -746,10 +746,10 @@ static int gcmaes_crypt_by_sg(bool enc, len = min(srclen, dstlen); if (len) { if (enc) - gcm_tfm->enc_update(aes_ctx, &data, + gcm_tfm->enc_update(aes_ctx, data, dst, src, len); else - gcm_tfm->dec_update(aes_ctx, &data, + gcm_tfm->dec_update(aes_ctx, data, dst, src, len); } left -= len; @@ -767,10 +767,10 @@ static int gcmaes_crypt_by_sg(bool enc, len = scatterwalk_clamp(&src_sg_walk, left); if (len) { if (enc) - gcm_tfm->enc_update(aes_ctx, &data, + gcm_tfm->enc_update(aes_ctx, data, src, src, len); else - gcm_tfm->dec_update(aes_ctx, &data, + gcm_tfm->dec_update(aes_ctx, data, src, src, len); } left -= len; @@ -779,7 +779,7 @@ static int gcmaes_crypt_by_sg(bool enc, scatterwalk_done(&src_sg_walk, 1, left); } } - gcm_tfm->finalize(aes_ctx, &data, authTag, auth_tag_len); + gcm_tfm->finalize(aes_ctx, data, authTag, auth_tag_len); kernel_fpu_end();
if (!assocmem) @@ -828,7 +828,8 @@ static int helper_rfc4106_encrypt(struct struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); void *aes_ctx = &(ctx->aes_key_expanded); - u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); + u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8); + u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN); unsigned int i; __be32 counter = cpu_to_be32(1);
@@ -855,7 +856,8 @@ static int helper_rfc4106_decrypt(struct struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); void *aes_ctx = &(ctx->aes_key_expanded); - u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); + u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8); + u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN); unsigned int i;
if (unlikely(req->assoclen != 16 && req->assoclen != 20)) @@ -985,7 +987,8 @@ static int generic_gcmaes_encrypt(struct struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm); void *aes_ctx = &(ctx->aes_key_expanded); - u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); + u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8); + u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN); __be32 counter = cpu_to_be32(1);
memcpy(iv, req->iv, 12); @@ -1001,7 +1004,8 @@ static int generic_gcmaes_decrypt(struct struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm); void *aes_ctx = &(ctx->aes_key_expanded); - u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN))); + u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8); + u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
memcpy(iv, req->iv, 12); *((__be32 *)(iv+12)) = counter;
From: Ard Biesheuvel ardb@kernel.org
commit e1b2d980f03b833442768c1987d5ad0b9a58cfe7 upstream.
The Michael MIC driver uses the cra_alignmask to ensure that pointers presented to its update and finup/final methods are 32-bit aligned. However, due to the way the shash API works, this is no guarantee that the 32-bit reads occurring in the update method are also aligned, as the size of the buffer presented to update may be of uneven length. For instance, an update() of 3 bytes followed by a misaligned update() of 4 or more bytes will result in a misaligned access using an accessor that is not suitable for this.
On most architectures, this does not matter, and so setting the cra_alignmask is pointless. On architectures where this does matter, setting the cra_alignmask does not actually solve the problem.
So let's get rid of the cra_alignmask, and use unaligned accessors instead, where appropriate.
Cc: stable@vger.kernel.org Signed-off-by: Ard Biesheuvel ardb@kernel.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- crypto/michael_mic.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-)
--- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -7,7 +7,7 @@ * Copyright (c) 2004 Jouni Malinen j@w1.fi */ #include <crypto/internal/hash.h> -#include <asm/byteorder.h> +#include <asm/unaligned.h> #include <linux/init.h> #include <linux/module.h> #include <linux/string.h> @@ -19,7 +19,7 @@ struct michael_mic_ctx { };
struct michael_mic_desc_ctx { - u8 pending[4]; + __le32 pending; size_t pending_len;
u32 l, r; @@ -60,13 +60,12 @@ static int michael_update(struct shash_d unsigned int len) { struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc); - const __le32 *src;
if (mctx->pending_len) { int flen = 4 - mctx->pending_len; if (flen > len) flen = len; - memcpy(&mctx->pending[mctx->pending_len], data, flen); + memcpy((u8 *)&mctx->pending + mctx->pending_len, data, flen); mctx->pending_len += flen; data += flen; len -= flen; @@ -74,23 +73,21 @@ static int michael_update(struct shash_d if (mctx->pending_len < 4) return 0;
- src = (const __le32 *)mctx->pending; - mctx->l ^= le32_to_cpup(src); + mctx->l ^= le32_to_cpu(mctx->pending); michael_block(mctx->l, mctx->r); mctx->pending_len = 0; }
- src = (const __le32 *)data; - while (len >= 4) { - mctx->l ^= le32_to_cpup(src++); + mctx->l ^= get_unaligned_le32(data); michael_block(mctx->l, mctx->r); + data += 4; len -= 4; }
if (len > 0) { mctx->pending_len = len; - memcpy(mctx->pending, src, len); + memcpy(&mctx->pending, data, len); }
return 0; @@ -100,8 +97,7 @@ static int michael_update(struct shash_d static int michael_final(struct shash_desc *desc, u8 *out) { struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc); - u8 *data = mctx->pending; - __le32 *dst = (__le32 *)out; + u8 *data = (u8 *)&mctx->pending;
/* Last block and padding (0x5a, 4..7 x 0) */ switch (mctx->pending_len) { @@ -123,8 +119,8 @@ static int michael_final(struct shash_de /* l ^= 0; */ michael_block(mctx->l, mctx->r);
- dst[0] = cpu_to_le32(mctx->l); - dst[1] = cpu_to_le32(mctx->r); + put_unaligned_le32(mctx->l, out); + put_unaligned_le32(mctx->r, out + 4);
return 0; } @@ -135,13 +131,11 @@ static int michael_setkey(struct crypto_ { struct michael_mic_ctx *mctx = crypto_shash_ctx(tfm);
- const __le32 *data = (const __le32 *)key; - if (keylen != 8) return -EINVAL;
- mctx->l = le32_to_cpu(data[0]); - mctx->r = le32_to_cpu(data[1]); + mctx->l = get_unaligned_le32(key); + mctx->r = get_unaligned_le32(key + 4); return 0; }
@@ -156,7 +150,6 @@ static struct shash_alg alg = { .cra_name = "michael_mic", .cra_driver_name = "michael_mic-generic", .cra_blocksize = 8, - .cra_alignmask = 3, .cra_ctxsize = sizeof(struct michael_mic_ctx), .cra_module = THIS_MODULE, }
From: Corentin Labbe clabbe@baylibre.com
commit 7bdcd851fa7eb66e8922aa7f6cba9e2f2427a7cf upstream.
The optimized cipher function need length multiple of 4 bytes. But it get sometimes odd length. This is due to SG data could be stored with an offset.
So the fix is to check also if the offset is aligned with 4 bytes. Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator") Cc: stable@vger.kernel.org Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -201,12 +201,12 @@ static int sun4i_ss_cipher_poll(struct s * we can use the SS optimized function */ while (in_sg && no_chunk == 1) { - if (in_sg->length % 4) + if ((in_sg->length | in_sg->offset) & 3u) no_chunk = 0; in_sg = sg_next(in_sg); } while (out_sg && no_chunk == 1) { - if (out_sg->length % 4) + if ((out_sg->length | out_sg->offset) & 3u) no_chunk = 0; out_sg = sg_next(out_sg); }
From: Corentin Labbe clabbe@baylibre.com
commit b756f1c8fc9d84e3f546d7ffe056c5352f4aab05 upstream.
Allwinner A10 and A13 SoC have a version of the SS which produce invalid IV in IVx register.
Instead of adding a variant for those, let's convert SS to produce IV directly from data. Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator") Cc: stable@vger.kernel.org Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 34 ++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-)
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -20,6 +20,7 @@ static int noinline_for_stack sun4i_ss_o unsigned int ivsize = crypto_skcipher_ivsize(tfm); struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); u32 mode = ctx->mode; + void *backup_iv = NULL; /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ u32 rx_cnt = SS_RX_DEFAULT; u32 tx_cnt = 0; @@ -44,6 +45,13 @@ static int noinline_for_stack sun4i_ss_o return -EINVAL; }
+ if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { + backup_iv = kzalloc(ivsize, GFP_KERNEL); + if (!backup_iv) + return -ENOMEM; + scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); + } + spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4) @@ -117,9 +125,12 @@ static int noinline_for_stack sun4i_ss_o } while (oleft);
if (areq->iv) { - for (i = 0; i < 4 && i < ivsize / 4; i++) { - v = readl(ss->base + SS_IV0 + i * 4); - *(u32 *)(areq->iv + i * 4) = v; + if (mode & SS_DECRYPTION) { + memcpy(areq->iv, backup_iv, ivsize); + kfree_sensitive(backup_iv); + } else { + scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, + ivsize, 0); } }
@@ -174,6 +185,7 @@ static int sun4i_ss_cipher_poll(struct s unsigned int ileft = areq->cryptlen; unsigned int oleft = areq->cryptlen; unsigned int todo; + void *backup_iv = NULL; struct sg_mapping_iter mi, mo; unsigned long pi = 0, po = 0; /* progress for in and out */ bool miter_err; @@ -217,6 +229,13 @@ static int sun4i_ss_cipher_poll(struct s if (need_fallback) return sun4i_ss_cipher_poll_fallback(areq);
+ if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { + backup_iv = kzalloc(ivsize, GFP_KERNEL); + if (!backup_iv) + return -ENOMEM; + scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); + } + spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4) @@ -345,9 +364,12 @@ static int sun4i_ss_cipher_poll(struct s sg_miter_stop(&mo); } if (areq->iv) { - for (i = 0; i < 4 && i < ivsize / 4; i++) { - v = readl(ss->base + SS_IV0 + i * 4); - *(u32 *)(areq->iv + i * 4) = v; + if (mode & SS_DECRYPTION) { + memcpy(areq->iv, backup_iv, ivsize); + kfree_sensitive(backup_iv); + } else { + scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, + ivsize, 0); } }
From: Corentin Labbe clabbe@baylibre.com
commit 5ab6177fa02df15cd8a02a1f1fb361d2d5d8b946 upstream.
Ciphers produce invalid results on BE. Key and IV need to be written in LE.
Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator") Cc: stable@vger.kernel.org Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -54,13 +54,13 @@ static int noinline_for_stack sun4i_ss_o
spin_lock_irqsave(&ss->slock, flags);
- for (i = 0; i < op->keylen; i += 4) - writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); + for (i = 0; i < op->keylen / 4; i++) + writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { v = *(u32 *)(areq->iv + i * 4); - writel(v, ss->base + SS_IV0 + i * 4); + writesl(ss->base + SS_IV0 + i * 4, &v, 1); } } writel(mode, ss->base + SS_CTL); @@ -238,13 +238,13 @@ static int sun4i_ss_cipher_poll(struct s
spin_lock_irqsave(&ss->slock, flags);
- for (i = 0; i < op->keylen; i += 4) - writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); + for (i = 0; i < op->keylen / 4; i++) + writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { v = *(u32 *)(areq->iv + i * 4); - writel(v, ss->base + SS_IV0 + i * 4); + writesl(ss->base + SS_IV0 + i * 4, &v, 1); } } writel(mode, ss->base + SS_CTL);
From: Corentin Labbe clabbe@baylibre.com
commit 4ec8977b921fd9d512701e009ce8082cb94b5c1c upstream.
The need_fallback is never initialized and seem to be always true at runtime. So all hardware operations are always bypassed.
Fixes: 0ae1f46c55f87 ("crypto: sun4i-ss - fallback when length is not multiple of blocksize") Cc: stable@vger.kernel.org Signed-off-by: Corentin Labbe clabbe@baylibre.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -194,7 +194,7 @@ static int sun4i_ss_cipher_poll(struct s unsigned int obo = 0; /* offset in bufo*/ unsigned int obl = 0; /* length of data in bufo */ unsigned long flags; - bool need_fallback; + bool need_fallback = false;
if (!areq->cryptlen) return 0;
From: Marek Szyprowski m.szyprowski@samsung.com
commit 0458b88267c637fb872b0359da9ff0b243081e9e upstream.
Check if the SoC is really supported before gathering the needed resources. This fixes endless deferred probe on some SoCs other than Exynos5422 (like Exynos5410).
Fixes: 5ea428595cc5 ("soc: samsung: Add Exynos Adaptive Supply Voltage driver") Cc: stable@vger.kernel.org Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com Reviewed-by: Pankaj Dubey pankaj.dubey@samsung.com Link: https://lore.kernel.org/r/20201207190517.262051-2-krzk@kernel.org Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/samsung/exynos-asv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -119,11 +119,6 @@ static int exynos_asv_probe(struct platf u32 product_id = 0; int ret, i;
- cpu_dev = get_cpu_device(0); - ret = dev_pm_opp_get_opp_count(cpu_dev); - if (ret < 0) - return -EPROBE_DEFER; - asv = devm_kzalloc(&pdev->dev, sizeof(*asv), GFP_KERNEL); if (!asv) return -ENOMEM; @@ -144,6 +139,11 @@ static int exynos_asv_probe(struct platf return -ENODEV; }
+ cpu_dev = get_cpu_device(0); + ret = dev_pm_opp_get_opp_count(cpu_dev); + if (ret < 0) + return -EPROBE_DEFER; + ret = of_property_read_u32(pdev->dev.of_node, "samsung,asv-bin", &asv->of_bin); if (ret < 0)
From: Krzysztof Kozlowski krzk@kernel.org
commit 4561560dfb4f847a0b327d48bdd1f45bf1b6261f upstream.
If regmap_read() fails, the product_id local variable will contain random value from the stack. Do not try to parse such value and fail the ASV driver probe.
Fixes: 5ea428595cc5 ("soc: samsung: Add Exynos Adaptive Supply Voltage driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzk@kernel.org Reviewed-by: Pankaj Dubey pankaj.dubey@samsung.com Link: https://lore.kernel.org/r/20201207190517.262051-3-krzk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/soc/samsung/exynos-asv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/soc/samsung/exynos-asv.c +++ b/drivers/soc/samsung/exynos-asv.c @@ -129,7 +129,13 @@ static int exynos_asv_probe(struct platf return PTR_ERR(asv->chipid_regmap); }
- regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id); + ret = regmap_read(asv->chipid_regmap, EXYNOS_CHIPID_REG_PRO_ID, + &product_id); + if (ret < 0) { + dev_err(&pdev->dev, "Cannot read revision from ChipID: %d\n", + ret); + return -ENODEV; + }
switch (product_id & EXYNOS_MASK) { case 0xE5422000:
From: Paul Cercueil paul@crapouillou.net
commit 04b38d012556199ba4c31195940160e0c44c64f0 upstream.
We don't actually care about the value, since the kernel will panic before that; but a value should nonetheless be returned, otherwise the compiler will complain.
Fixes: 8112c4f140fa ("seccomp: remove 2-phase API") Cc: stable@vger.kernel.org # 4.7+ Signed-off-by: Paul Cercueil paul@crapouillou.net Signed-off-by: Kees Cook keescook@chromium.org Link: https://lore.kernel.org/r/20210111172839.640914-1-paul@crapouillou.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/seccomp.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -1284,6 +1284,8 @@ static int __seccomp_filter(int this_sys const bool recheck_after_trace) { BUG(); + + return -1; } #endif
From: Timothy E Baldwin T.E.Baldwin99@members.leeds.ac.uk
commit df84fe94708985cdfb78a83148322bcd0a699472 upstream.
Since commit f086f67485c5 ("arm64: ptrace: add support for syscall emulation"), if system call number -1 is called and the process is being traced with PTRACE_SYSCALL, for example by strace, the seccomp check is skipped and -ENOSYS is returned unconditionally (unless altered by the tracer) rather than carrying out action specified in the seccomp filter.
The consequence of this is that it is not possible to reliably strace a seccomp based implementation of a foreign system call interface in which r7/x8 is permitted to be -1 on entry to a system call.
Also trace_sys_enter and audit_syscall_entry are skipped if a system call is skipped.
Fix by removing the in_syscall(regs) check restoring the previous behaviour which is like AArch32, x86 (which uses generic code) and everything else.
Cc: Oleg Nesterov oleg@redhat.com Cc: Catalin Marinascatalin.marinas@arm.com Cc: stable@vger.kernel.org Fixes: f086f67485c5 ("arm64: ptrace: add support for syscall emulation") Reviewed-by: Kees Cook keescook@chromium.org Reviewed-by: Sudeep Holla sudeep.holla@arm.com Tested-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Timothy E Baldwin T.E.Baldwin99@members.leeds.ac.uk Link: https://lore.kernel.org/r/90edd33b-6353-1228-791f-0336d94d5f8c@majoroak.me.u... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -1796,7 +1796,7 @@ int syscall_trace_enter(struct pt_regs *
if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) { tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); - if (!in_syscall(regs) || (flags & _TIF_SYSCALL_EMU)) + if (flags & _TIF_SYSCALL_EMU) return NO_SYSCALL; }
From: Ricky Wu ricky_wu@realtek.com
commit 920fd8a70619074eac7687352c8f1c6f3c2a64a5 upstream.
Power down OCP for power consumption when no SD/MMC card is present
Cc: stable@vger.kernel.org Signed-off-by: Ricky Wu ricky_wu@realtek.com Link: https://lore.kernel.org/r/20210204083115.9471-1-ricky_wu@realtek.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/cardreader/rts5227.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/drivers/misc/cardreader/rts5227.c +++ b/drivers/misc/cardreader/rts5227.c @@ -398,6 +398,11 @@ static int rts522a_extra_init_hw(struct { rts5227_extra_init_hw(pcr);
+ /* Power down OCP for power consumption */ + if (!pcr->card_exist) + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, + OC_POWER_DOWN); + rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG, FUNC_FORCE_UPME_XMT_DBG); rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
From: Sabyrzhan Tasbolatov snovitoll@gmail.com
commit 2fd10bcf0310b9525b2af9e1f7aa9ddd87c3772e upstream.
syzbot found WARNING in qp_broker_alloc[1] in qp_host_alloc_queue() when num_pages is 0x100001, giving queue_size + queue_page_size bigger than KMALLOC_MAX_SIZE for kzalloc(), resulting order >= MAX_ORDER condition.
queue_size + queue_page_size=0x8000d8, where KMALLOC_MAX_SIZE=0x400000.
[1] Call Trace: alloc_pages include/linux/gfp.h:547 [inline] kmalloc_order+0x40/0x130 mm/slab_common.c:837 kmalloc_order_trace+0x15/0x70 mm/slab_common.c:853 kmalloc_large include/linux/slab.h:481 [inline] __kmalloc+0x257/0x330 mm/slub.c:3959 kmalloc include/linux/slab.h:557 [inline] kzalloc include/linux/slab.h:682 [inline] qp_host_alloc_queue drivers/misc/vmw_vmci/vmci_queue_pair.c:540 [inline] qp_broker_create drivers/misc/vmw_vmci/vmci_queue_pair.c:1351 [inline] qp_broker_alloc+0x936/0x2740 drivers/misc/vmw_vmci/vmci_queue_pair.c:1739
Reported-by: syzbot+15ec7391f3d6a1a7cc7d@syzkaller.appspotmail.com Signed-off-by: Sabyrzhan Tasbolatov snovitoll@gmail.com Link: https://lore.kernel.org/r/20210209102612.2112247-1-snovitoll@gmail.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/vmw_vmci/vmci_queue_pair.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -537,6 +537,9 @@ static struct vmci_queue *qp_host_alloc_
queue_page_size = num_pages * sizeof(*queue->kernel_if->u.h.page);
+ if (queue_size + queue_page_size > KMALLOC_MAX_SIZE) + return NULL; + queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL); if (queue) { queue->q_header = NULL;
From: Jiri Bohac jbohac@suse.cz
commit 19d8e9149c27b689c6224f5c84b96a159342195a upstream.
Both pstore_compress() and decompress_record() use a mistyped config option name ("PSTORE_COMPRESSION" instead of "PSTORE_COMPRESS"). As a result compression and decompression of pstore records was always disabled.
Use the correct config option name.
Signed-off-by: Jiri Bohac jbohac@suse.cz Fixes: fd49e03280e5 ("pstore: Fix linking when crypto API disabled") Acked-by: Matteo Croce mcroce@microsoft.com Signed-off-by: Kees Cook keescook@chromium.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210218111547.johvp5klpv3xrpnn@dwarf.suse.cz Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/pstore/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -269,7 +269,7 @@ static int pstore_compress(const void *i { int ret;
- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION)) + if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS)) return -EINVAL;
ret = crypto_comp_compress(tfm, in, inlen, out, &outlen); @@ -671,7 +671,7 @@ static void decompress_record(struct pst int unzipped_len; char *unzipped, *workspace;
- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION) || !record->compressed) + if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed) return;
/* Only PSTORE_TYPE_DMESG support compression. */
From: Frank Wunderlich frank-w@public-files.de
commit dc2e76175417e69c41d927dba75a966399f18354 upstream.
Fix extreme slow speed (200MB takes ~20 min) on writing sdcard on bananapi-r64 by adding reset-control for mmc1 like it's done for mmc0/emmc.
Fixes: 2c002a3049f7 ("arm64: dts: mt7622: add mmc related device nodes") Signed-off-by: Frank Wunderlich frank-w@public-files.de Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210113180919.49523-1-linux@fw-web.de Signed-off-by: Matthias Brugger matthias.bgg@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 ++ 1 file changed, 2 insertions(+)
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -698,6 +698,8 @@ clocks = <&pericfg CLK_PERI_MSDC30_1_PD>, <&topckgen CLK_TOP_AXI_SEL>; clock-names = "source", "hclk"; + resets = <&pericfg MT7622_PERI_MSDC1_SW_RST>; + reset-names = "hrst"; status = "disabled"; };
From: Dinh Nguyen dinguyen@kernel.org
commit b7ff3a447d100c999d9848353ef8a4046831d893 upstream.
The shift for the phy_intf_sel bit in the system manager for gmac1 and gmac2 should be 0.
Fixes: 2f804ba7aa9ee ("arm64: dts: agilex: Add SysMgr to Ethernet nodes") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen dinguyen@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi +++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi @@ -166,7 +166,7 @@ rx-fifo-depth = <16384>; snps,multicast-filter-bins = <256>; iommus = <&smmu 2>; - altr,sysmgr-syscon = <&sysmgr 0x48 8>; + altr,sysmgr-syscon = <&sysmgr 0x48 0>; clocks = <&clkmgr AGILEX_EMAC1_CLK>, <&clkmgr AGILEX_EMAC_PTP_CLK>; clock-names = "stmmaceth", "ptp_ref"; status = "disabled"; @@ -184,7 +184,7 @@ rx-fifo-depth = <16384>; snps,multicast-filter-bins = <256>; iommus = <&smmu 3>; - altr,sysmgr-syscon = <&sysmgr 0x4c 16>; + altr,sysmgr-syscon = <&sysmgr 0x4c 0>; clocks = <&clkmgr AGILEX_EMAC2_CLK>, <&clkmgr AGILEX_EMAC_PTP_CLK>; clock-names = "stmmaceth", "ptp_ref"; status = "disabled";
From: Ilya Lipnitskiy ilya.lipnitskiy@gmail.com
commit 1f92798cbe7fe923479cff754dd06dd23d352e36 upstream.
Also use KBUILD_MODNAME for module name.
This driver is only used by RALINK MIPS MT7621 SoCs. Tested by building against that target using OpenWrt with Linux 5.10.10.
Fixes the following error: error: the following would cause module name conflict: drivers/dma/mediatek/mtk-hsdma.ko drivers/staging/mt7621-dma/mtk-hsdma.ko
Cc: stable@vger.kernel.org Cc: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Ilya Lipnitskiy ilya.lipnitskiy@gmail.com Link: https://lore.kernel.org/r/20210130034507.2115280-1-ilya.lipnitskiy@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/mt7621-dma/Makefile | 2 drivers/staging/mt7621-dma/hsdma-mt7621.c | 760 ++++++++++++++++++++++++++++++ drivers/staging/mt7621-dma/mtk-hsdma.c | 760 ------------------------------ 3 files changed, 761 insertions(+), 761 deletions(-) rename drivers/staging/mt7621-dma/{mtk-hsdma.c => hsdma-mt7621.c} (99%)
--- a/drivers/staging/mt7621-dma/Makefile +++ b/drivers/staging/mt7621-dma/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o +obj-$(CONFIG_MTK_HSDMA) += hsdma-mt7621.o
ccflags-y += -I$(srctree)/drivers/dma --- /dev/null +++ b/drivers/staging/mt7621-dma/hsdma-mt7621.c @@ -0,0 +1,760 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015, Michael Lee igvtee@gmail.com + * MTK HSDMA support + */ + +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/irq.h> +#include <linux/of_dma.h> +#include <linux/reset.h> +#include <linux/of_device.h> + +#include "virt-dma.h" + +#define HSDMA_BASE_OFFSET 0x800 + +#define HSDMA_REG_TX_BASE 0x00 +#define HSDMA_REG_TX_CNT 0x04 +#define HSDMA_REG_TX_CTX 0x08 +#define HSDMA_REG_TX_DTX 0x0c +#define HSDMA_REG_RX_BASE 0x100 +#define HSDMA_REG_RX_CNT 0x104 +#define HSDMA_REG_RX_CRX 0x108 +#define HSDMA_REG_RX_DRX 0x10c +#define HSDMA_REG_INFO 0x200 +#define HSDMA_REG_GLO_CFG 0x204 +#define HSDMA_REG_RST_CFG 0x208 +#define HSDMA_REG_DELAY_INT 0x20c +#define HSDMA_REG_FREEQ_THRES 0x210 +#define HSDMA_REG_INT_STATUS 0x220 +#define HSDMA_REG_INT_MASK 0x228 +#define HSDMA_REG_SCH_Q01 0x280 +#define HSDMA_REG_SCH_Q23 0x284 + +#define HSDMA_DESCS_MAX 0xfff +#define HSDMA_DESCS_NUM 8 +#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1) +#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK) + +/* HSDMA_REG_INFO */ +#define HSDMA_INFO_INDEX_MASK 0xf +#define HSDMA_INFO_INDEX_SHIFT 24 +#define HSDMA_INFO_BASE_MASK 0xff +#define HSDMA_INFO_BASE_SHIFT 16 +#define HSDMA_INFO_RX_MASK 0xff +#define HSDMA_INFO_RX_SHIFT 8 +#define HSDMA_INFO_TX_MASK 0xff +#define HSDMA_INFO_TX_SHIFT 0 + +/* HSDMA_REG_GLO_CFG */ +#define HSDMA_GLO_TX_2B_OFFSET BIT(31) +#define HSDMA_GLO_CLK_GATE BIT(30) +#define HSDMA_GLO_BYTE_SWAP BIT(29) +#define HSDMA_GLO_MULTI_DMA BIT(10) +#define HSDMA_GLO_TWO_BUF BIT(9) +#define HSDMA_GLO_32B_DESC BIT(8) +#define HSDMA_GLO_BIG_ENDIAN BIT(7) +#define HSDMA_GLO_TX_DONE BIT(6) +#define HSDMA_GLO_BT_MASK 0x3 +#define HSDMA_GLO_BT_SHIFT 4 +#define HSDMA_GLO_RX_BUSY BIT(3) +#define HSDMA_GLO_RX_DMA BIT(2) +#define HSDMA_GLO_TX_BUSY BIT(1) +#define HSDMA_GLO_TX_DMA BIT(0) + +#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT) +#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT) +#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT) +#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT) + +#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \ + HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES) + +/* HSDMA_REG_RST_CFG */ +#define HSDMA_RST_RX_SHIFT 16 +#define HSDMA_RST_TX_SHIFT 0 + +/* HSDMA_REG_DELAY_INT */ +#define HSDMA_DELAY_INT_EN BIT(15) +#define HSDMA_DELAY_PEND_OFFSET 8 +#define HSDMA_DELAY_TIME_OFFSET 0 +#define HSDMA_DELAY_TX_OFFSET 16 +#define HSDMA_DELAY_RX_OFFSET 0 + +#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \ + ((x) << HSDMA_DELAY_PEND_OFFSET)) +#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \ + HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x)) + +/* HSDMA_REG_INT_STATUS */ +#define HSDMA_INT_DELAY_RX_COH BIT(31) +#define HSDMA_INT_DELAY_RX_INT BIT(30) +#define HSDMA_INT_DELAY_TX_COH BIT(29) +#define HSDMA_INT_DELAY_TX_INT BIT(28) +#define HSDMA_INT_RX_MASK 0x3 +#define HSDMA_INT_RX_SHIFT 16 +#define HSDMA_INT_RX_Q0 BIT(16) +#define HSDMA_INT_TX_MASK 0xf +#define HSDMA_INT_TX_SHIFT 0 +#define HSDMA_INT_TX_Q0 BIT(0) + +/* tx/rx dma desc flags */ +#define HSDMA_PLEN_MASK 0x3fff +#define HSDMA_DESC_DONE BIT(31) +#define HSDMA_DESC_LS0 BIT(30) +#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16) +#define HSDMA_DESC_TAG BIT(15) +#define HSDMA_DESC_LS1 BIT(14) +#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK) + +/* align 4 bytes */ +#define HSDMA_ALIGN_SIZE 3 +/* align size 128bytes */ +#define HSDMA_MAX_PLEN 0x3f80 + +struct hsdma_desc { + u32 addr0; + u32 flags; + u32 addr1; + u32 unused; +}; + +struct mtk_hsdma_sg { + dma_addr_t src_addr; + dma_addr_t dst_addr; + u32 len; +}; + +struct mtk_hsdma_desc { + struct virt_dma_desc vdesc; + unsigned int num_sgs; + struct mtk_hsdma_sg sg[1]; +}; + +struct mtk_hsdma_chan { + struct virt_dma_chan vchan; + unsigned int id; + dma_addr_t desc_addr; + int tx_idx; + int rx_idx; + struct hsdma_desc *tx_ring; + struct hsdma_desc *rx_ring; + struct mtk_hsdma_desc *desc; + unsigned int next_sg; +}; + +struct mtk_hsdam_engine { + struct dma_device ddev; + struct device_dma_parameters dma_parms; + void __iomem *base; + struct tasklet_struct task; + volatile unsigned long chan_issued; + + struct mtk_hsdma_chan chan[1]; +}; + +static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev( + struct mtk_hsdma_chan *chan) +{ + return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine, + ddev); +} + +static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c) +{ + return container_of(c, struct mtk_hsdma_chan, vchan.chan); +} + +static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc( + struct virt_dma_desc *vdesc) +{ + return container_of(vdesc, struct mtk_hsdma_desc, vdesc); +} + +static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg) +{ + return readl(hsdma->base + reg); +} + +static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma, + unsigned int reg, u32 val) +{ + writel(val, hsdma->base + reg); +} + +static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + chan->tx_idx = 0; + chan->rx_idx = HSDMA_DESCS_NUM - 1; + + mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); + mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); + + mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, + 0x1 << (chan->id + HSDMA_RST_TX_SHIFT)); + mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, + 0x1 << (chan->id + HSDMA_RST_RX_SHIFT)); +} + +static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma) +{ + dev_dbg(hsdma->ddev.dev, + "tbase %08x, tcnt %08x, tctx %08x, tdtx: %08x, rbase %08x, rcnt %08x, rctx %08x, rdtx %08x\n", + mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE), + mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT), + mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX), + mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX), + mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE), + mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT), + mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX), + mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX)); + + dev_dbg(hsdma->ddev.dev, + "info %08x, glo %08x, delay %08x, intr_stat %08x, intr_mask %08x\n", + mtk_hsdma_read(hsdma, HSDMA_REG_INFO), + mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG), + mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT), + mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS), + mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK)); +} + +static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + struct hsdma_desc *tx_desc; + struct hsdma_desc *rx_desc; + int i; + + dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n", + chan->tx_idx, chan->rx_idx); + + for (i = 0; i < HSDMA_DESCS_NUM; i++) { + tx_desc = &chan->tx_ring[i]; + rx_desc = &chan->rx_ring[i]; + + dev_dbg(hsdma->ddev.dev, + "%d tx addr0: %08x, flags %08x, tx addr1: %08x, rx addr0 %08x, flags %08x\n", + i, tx_desc->addr0, tx_desc->flags, + tx_desc->addr1, rx_desc->addr0, rx_desc->flags); + } +} + +static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + int i; + + /* disable dma */ + mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); + + /* disable intr */ + mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); + + /* init desc value */ + for (i = 0; i < HSDMA_DESCS_NUM; i++) { + chan->tx_ring[i].addr0 = 0; + chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; + } + for (i = 0; i < HSDMA_DESCS_NUM; i++) { + chan->rx_ring[i].addr0 = 0; + chan->rx_ring[i].flags = 0; + } + + /* reset */ + mtk_hsdma_reset_chan(hsdma, chan); + + /* enable intr */ + mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); + + /* enable dma */ + mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); +} + +static int mtk_hsdma_terminate_all(struct dma_chan *c) +{ + struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); + struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); + unsigned long timeout; + LIST_HEAD(head); + + spin_lock_bh(&chan->vchan.lock); + chan->desc = NULL; + clear_bit(chan->id, &hsdma->chan_issued); + vchan_get_all_descriptors(&chan->vchan, &head); + spin_unlock_bh(&chan->vchan.lock); + + vchan_dma_desc_free_list(&chan->vchan, &head); + + /* wait dma transfer complete */ + timeout = jiffies + msecs_to_jiffies(2000); + while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) & + (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) { + if (time_after_eq(jiffies, timeout)) { + hsdma_dump_desc(hsdma, chan); + mtk_hsdma_reset(hsdma, chan); + dev_err(hsdma->ddev.dev, "timeout, reset it\n"); + break; + } + cpu_relax(); + } + + return 0; +} + +static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + dma_addr_t src, dst; + size_t len, tlen; + struct hsdma_desc *tx_desc, *rx_desc; + struct mtk_hsdma_sg *sg; + unsigned int i; + int rx_idx; + + sg = &chan->desc->sg[0]; + len = sg->len; + chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN); + + /* tx desc */ + src = sg->src_addr; + for (i = 0; i < chan->desc->num_sgs; i++) { + tx_desc = &chan->tx_ring[chan->tx_idx]; + + if (len > HSDMA_MAX_PLEN) + tlen = HSDMA_MAX_PLEN; + else + tlen = len; + + if (i & 0x1) { + tx_desc->addr1 = src; + tx_desc->flags |= HSDMA_DESC_PLEN1(tlen); + } else { + tx_desc->addr0 = src; + tx_desc->flags = HSDMA_DESC_PLEN0(tlen); + + /* update index */ + chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx); + } + + src += tlen; + len -= tlen; + } + if (i & 0x1) + tx_desc->flags |= HSDMA_DESC_LS0; + else + tx_desc->flags |= HSDMA_DESC_LS1; + + /* rx desc */ + rx_idx = HSDMA_NEXT_DESC(chan->rx_idx); + len = sg->len; + dst = sg->dst_addr; + for (i = 0; i < chan->desc->num_sgs; i++) { + rx_desc = &chan->rx_ring[rx_idx]; + if (len > HSDMA_MAX_PLEN) + tlen = HSDMA_MAX_PLEN; + else + tlen = len; + + rx_desc->addr0 = dst; + rx_desc->flags = HSDMA_DESC_PLEN0(tlen); + + dst += tlen; + len -= tlen; + + /* update index */ + rx_idx = HSDMA_NEXT_DESC(rx_idx); + } + + /* make sure desc and index all up to date */ + wmb(); + mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); + + return 0; +} + +static int gdma_next_desc(struct mtk_hsdma_chan *chan) +{ + struct virt_dma_desc *vdesc; + + vdesc = vchan_next_desc(&chan->vchan); + if (!vdesc) { + chan->desc = NULL; + return 0; + } + chan->desc = to_mtk_hsdma_desc(vdesc); + chan->next_sg = 0; + + return 1; +} + +static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + struct mtk_hsdma_desc *desc; + int chan_issued; + + chan_issued = 0; + spin_lock_bh(&chan->vchan.lock); + desc = chan->desc; + if (likely(desc)) { + if (chan->next_sg == desc->num_sgs) { + list_del(&desc->vdesc.node); + vchan_cookie_complete(&desc->vdesc); + chan_issued = gdma_next_desc(chan); + } + } else { + dev_dbg(hsdma->ddev.dev, "no desc to complete\n"); + } + + if (chan_issued) + set_bit(chan->id, &hsdma->chan_issued); + spin_unlock_bh(&chan->vchan.lock); +} + +static irqreturn_t mtk_hsdma_irq(int irq, void *devid) +{ + struct mtk_hsdam_engine *hsdma = devid; + u32 status; + + status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS); + if (unlikely(!status)) + return IRQ_NONE; + + if (likely(status & HSDMA_INT_RX_Q0)) + tasklet_schedule(&hsdma->task); + else + dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", status); + /* clean intr bits */ + mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status); + + return IRQ_HANDLED; +} + +static void mtk_hsdma_issue_pending(struct dma_chan *c) +{ + struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); + struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); + + spin_lock_bh(&chan->vchan.lock); + if (vchan_issue_pending(&chan->vchan) && !chan->desc) { + if (gdma_next_desc(chan)) { + set_bit(chan->id, &hsdma->chan_issued); + tasklet_schedule(&hsdma->task); + } else { + dev_dbg(hsdma->ddev.dev, "no desc to issue\n"); + } + } + spin_unlock_bh(&chan->vchan.lock); +} + +static struct dma_async_tx_descriptor *mtk_hsdma_prep_dma_memcpy( + struct dma_chan *c, dma_addr_t dest, dma_addr_t src, + size_t len, unsigned long flags) +{ + struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); + struct mtk_hsdma_desc *desc; + + if (len <= 0) + return NULL; + + desc = kzalloc(sizeof(*desc), GFP_ATOMIC); + if (!desc) { + dev_err(c->device->dev, "alloc memcpy decs error\n"); + return NULL; + } + + desc->sg[0].src_addr = src; + desc->sg[0].dst_addr = dest; + desc->sg[0].len = len; + + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); +} + +static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, + dma_cookie_t cookie, + struct dma_tx_state *state) +{ + return dma_cookie_status(c, cookie, state); +} + +static void mtk_hsdma_free_chan_resources(struct dma_chan *c) +{ + vchan_free_chan_resources(to_virt_chan(c)); +} + +static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc) +{ + kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc)); +} + +static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma) +{ + struct mtk_hsdma_chan *chan; + + if (test_and_clear_bit(0, &hsdma->chan_issued)) { + chan = &hsdma->chan[0]; + if (chan->desc) + mtk_hsdma_start_transfer(hsdma, chan); + else + dev_dbg(hsdma->ddev.dev, "chan 0 no desc to issue\n"); + } +} + +static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma) +{ + struct mtk_hsdma_chan *chan; + int next_idx, drx_idx, cnt; + + chan = &hsdma->chan[0]; + next_idx = HSDMA_NEXT_DESC(chan->rx_idx); + drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX); + + cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK; + if (!cnt) + return; + + chan->next_sg += cnt; + chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK; + + /* update rx crx */ + wmb(); + mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); + + mtk_hsdma_chan_done(hsdma, chan); +} + +static void mtk_hsdma_tasklet(struct tasklet_struct *t) +{ + struct mtk_hsdam_engine *hsdma = from_tasklet(hsdma, t, task); + + mtk_hsdma_rx(hsdma); + mtk_hsdma_tx(hsdma); +} + +static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + int i; + + chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev, + 2 * HSDMA_DESCS_NUM * + sizeof(*chan->tx_ring), + &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO); + if (!chan->tx_ring) + goto no_mem; + + chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM]; + + /* init tx ring value */ + for (i = 0; i < HSDMA_DESCS_NUM; i++) + chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; + + return 0; +no_mem: + return -ENOMEM; +} + +static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma, + struct mtk_hsdma_chan *chan) +{ + if (chan->tx_ring) { + dma_free_coherent(hsdma->ddev.dev, + 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), + chan->tx_ring, chan->desc_addr); + chan->tx_ring = NULL; + chan->rx_ring = NULL; + } +} + +static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma) +{ + struct mtk_hsdma_chan *chan; + int ret; + u32 reg; + + /* init desc */ + chan = &hsdma->chan[0]; + ret = mtk_hsdam_alloc_desc(hsdma, chan); + if (ret) + return ret; + + /* tx */ + mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr); + mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM); + /* rx */ + mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr + + (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM)); + mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM); + /* reset */ + mtk_hsdma_reset_chan(hsdma, chan); + + /* enable rx intr */ + mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); + + /* enable dma */ + mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); + + /* hardware info */ + reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO); + dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n", + (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK, + (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK); + + hsdma_dump_reg(hsdma); + + return ret; +} + +static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma) +{ + struct mtk_hsdma_chan *chan; + + /* disable dma */ + mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); + + /* disable intr */ + mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); + + /* free desc */ + chan = &hsdma->chan[0]; + mtk_hsdam_free_desc(hsdma, chan); + + /* tx */ + mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0); + mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0); + /* rx */ + mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0); + mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0); + /* reset */ + mtk_hsdma_reset_chan(hsdma, chan); +} + +static const struct of_device_id mtk_hsdma_of_match[] = { + { .compatible = "mediatek,mt7621-hsdma" }, + { }, +}; + +static int mtk_hsdma_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct mtk_hsdma_chan *chan; + struct mtk_hsdam_engine *hsdma; + struct dma_device *dd; + int ret; + int irq; + void __iomem *base; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + match = of_match_device(mtk_hsdma_of_match, &pdev->dev); + if (!match) + return -EINVAL; + + hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); + if (!hsdma) + return -EINVAL; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + hsdma->base = base + HSDMA_BASE_OFFSET; + tasklet_setup(&hsdma->task, mtk_hsdma_tasklet); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -EINVAL; + ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, + 0, dev_name(&pdev->dev), hsdma); + if (ret) { + dev_err(&pdev->dev, "failed to request irq\n"); + return ret; + } + + device_reset(&pdev->dev); + + dd = &hsdma->ddev; + dma_cap_set(DMA_MEMCPY, dd->cap_mask); + dd->copy_align = HSDMA_ALIGN_SIZE; + dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; + dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; + dd->device_terminate_all = mtk_hsdma_terminate_all; + dd->device_tx_status = mtk_hsdma_tx_status; + dd->device_issue_pending = mtk_hsdma_issue_pending; + dd->dev = &pdev->dev; + dd->dev->dma_parms = &hsdma->dma_parms; + dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN); + INIT_LIST_HEAD(&dd->channels); + + chan = &hsdma->chan[0]; + chan->id = 0; + chan->vchan.desc_free = mtk_hsdma_desc_free; + vchan_init(&chan->vchan, dd); + + /* init hardware */ + ret = mtk_hsdma_init(hsdma); + if (ret) { + dev_err(&pdev->dev, "failed to alloc ring descs\n"); + return ret; + } + + ret = dma_async_device_register(dd); + if (ret) { + dev_err(&pdev->dev, "failed to register dma device\n"); + goto err_uninit_hsdma; + } + + ret = of_dma_controller_register(pdev->dev.of_node, + of_dma_xlate_by_chan_id, hsdma); + if (ret) { + dev_err(&pdev->dev, "failed to register of dma controller\n"); + goto err_unregister; + } + + platform_set_drvdata(pdev, hsdma); + + return 0; + +err_unregister: + dma_async_device_unregister(dd); +err_uninit_hsdma: + mtk_hsdma_uninit(hsdma); + return ret; +} + +static int mtk_hsdma_remove(struct platform_device *pdev) +{ + struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev); + + mtk_hsdma_uninit(hsdma); + + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(&hsdma->ddev); + + return 0; +} + +static struct platform_driver mtk_hsdma_driver = { + .probe = mtk_hsdma_probe, + .remove = mtk_hsdma_remove, + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = mtk_hsdma_of_match, + }, +}; +module_platform_driver(mtk_hsdma_driver); + +MODULE_AUTHOR("Michael Lee igvtee@gmail.com"); +MODULE_DESCRIPTION("MTK HSDMA driver"); +MODULE_LICENSE("GPL v2"); --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ /dev/null @@ -1,760 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2015, Michael Lee igvtee@gmail.com - * MTK HSDMA support - */ - -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/irq.h> -#include <linux/of_dma.h> -#include <linux/reset.h> -#include <linux/of_device.h> - -#include "virt-dma.h" - -#define HSDMA_BASE_OFFSET 0x800 - -#define HSDMA_REG_TX_BASE 0x00 -#define HSDMA_REG_TX_CNT 0x04 -#define HSDMA_REG_TX_CTX 0x08 -#define HSDMA_REG_TX_DTX 0x0c -#define HSDMA_REG_RX_BASE 0x100 -#define HSDMA_REG_RX_CNT 0x104 -#define HSDMA_REG_RX_CRX 0x108 -#define HSDMA_REG_RX_DRX 0x10c -#define HSDMA_REG_INFO 0x200 -#define HSDMA_REG_GLO_CFG 0x204 -#define HSDMA_REG_RST_CFG 0x208 -#define HSDMA_REG_DELAY_INT 0x20c -#define HSDMA_REG_FREEQ_THRES 0x210 -#define HSDMA_REG_INT_STATUS 0x220 -#define HSDMA_REG_INT_MASK 0x228 -#define HSDMA_REG_SCH_Q01 0x280 -#define HSDMA_REG_SCH_Q23 0x284 - -#define HSDMA_DESCS_MAX 0xfff -#define HSDMA_DESCS_NUM 8 -#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1) -#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK) - -/* HSDMA_REG_INFO */ -#define HSDMA_INFO_INDEX_MASK 0xf -#define HSDMA_INFO_INDEX_SHIFT 24 -#define HSDMA_INFO_BASE_MASK 0xff -#define HSDMA_INFO_BASE_SHIFT 16 -#define HSDMA_INFO_RX_MASK 0xff -#define HSDMA_INFO_RX_SHIFT 8 -#define HSDMA_INFO_TX_MASK 0xff -#define HSDMA_INFO_TX_SHIFT 0 - -/* HSDMA_REG_GLO_CFG */ -#define HSDMA_GLO_TX_2B_OFFSET BIT(31) -#define HSDMA_GLO_CLK_GATE BIT(30) -#define HSDMA_GLO_BYTE_SWAP BIT(29) -#define HSDMA_GLO_MULTI_DMA BIT(10) -#define HSDMA_GLO_TWO_BUF BIT(9) -#define HSDMA_GLO_32B_DESC BIT(8) -#define HSDMA_GLO_BIG_ENDIAN BIT(7) -#define HSDMA_GLO_TX_DONE BIT(6) -#define HSDMA_GLO_BT_MASK 0x3 -#define HSDMA_GLO_BT_SHIFT 4 -#define HSDMA_GLO_RX_BUSY BIT(3) -#define HSDMA_GLO_RX_DMA BIT(2) -#define HSDMA_GLO_TX_BUSY BIT(1) -#define HSDMA_GLO_TX_DMA BIT(0) - -#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT) -#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT) -#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT) -#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT) - -#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \ - HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES) - -/* HSDMA_REG_RST_CFG */ -#define HSDMA_RST_RX_SHIFT 16 -#define HSDMA_RST_TX_SHIFT 0 - -/* HSDMA_REG_DELAY_INT */ -#define HSDMA_DELAY_INT_EN BIT(15) -#define HSDMA_DELAY_PEND_OFFSET 8 -#define HSDMA_DELAY_TIME_OFFSET 0 -#define HSDMA_DELAY_TX_OFFSET 16 -#define HSDMA_DELAY_RX_OFFSET 0 - -#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \ - ((x) << HSDMA_DELAY_PEND_OFFSET)) -#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \ - HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x)) - -/* HSDMA_REG_INT_STATUS */ -#define HSDMA_INT_DELAY_RX_COH BIT(31) -#define HSDMA_INT_DELAY_RX_INT BIT(30) -#define HSDMA_INT_DELAY_TX_COH BIT(29) -#define HSDMA_INT_DELAY_TX_INT BIT(28) -#define HSDMA_INT_RX_MASK 0x3 -#define HSDMA_INT_RX_SHIFT 16 -#define HSDMA_INT_RX_Q0 BIT(16) -#define HSDMA_INT_TX_MASK 0xf -#define HSDMA_INT_TX_SHIFT 0 -#define HSDMA_INT_TX_Q0 BIT(0) - -/* tx/rx dma desc flags */ -#define HSDMA_PLEN_MASK 0x3fff -#define HSDMA_DESC_DONE BIT(31) -#define HSDMA_DESC_LS0 BIT(30) -#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16) -#define HSDMA_DESC_TAG BIT(15) -#define HSDMA_DESC_LS1 BIT(14) -#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK) - -/* align 4 bytes */ -#define HSDMA_ALIGN_SIZE 3 -/* align size 128bytes */ -#define HSDMA_MAX_PLEN 0x3f80 - -struct hsdma_desc { - u32 addr0; - u32 flags; - u32 addr1; - u32 unused; -}; - -struct mtk_hsdma_sg { - dma_addr_t src_addr; - dma_addr_t dst_addr; - u32 len; -}; - -struct mtk_hsdma_desc { - struct virt_dma_desc vdesc; - unsigned int num_sgs; - struct mtk_hsdma_sg sg[1]; -}; - -struct mtk_hsdma_chan { - struct virt_dma_chan vchan; - unsigned int id; - dma_addr_t desc_addr; - int tx_idx; - int rx_idx; - struct hsdma_desc *tx_ring; - struct hsdma_desc *rx_ring; - struct mtk_hsdma_desc *desc; - unsigned int next_sg; -}; - -struct mtk_hsdam_engine { - struct dma_device ddev; - struct device_dma_parameters dma_parms; - void __iomem *base; - struct tasklet_struct task; - volatile unsigned long chan_issued; - - struct mtk_hsdma_chan chan[1]; -}; - -static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev( - struct mtk_hsdma_chan *chan) -{ - return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine, - ddev); -} - -static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c) -{ - return container_of(c, struct mtk_hsdma_chan, vchan.chan); -} - -static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc( - struct virt_dma_desc *vdesc) -{ - return container_of(vdesc, struct mtk_hsdma_desc, vdesc); -} - -static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg) -{ - return readl(hsdma->base + reg); -} - -static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma, - unsigned int reg, u32 val) -{ - writel(val, hsdma->base + reg); -} - -static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - chan->tx_idx = 0; - chan->rx_idx = HSDMA_DESCS_NUM - 1; - - mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); - mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); - - mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, - 0x1 << (chan->id + HSDMA_RST_TX_SHIFT)); - mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, - 0x1 << (chan->id + HSDMA_RST_RX_SHIFT)); -} - -static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma) -{ - dev_dbg(hsdma->ddev.dev, - "tbase %08x, tcnt %08x, tctx %08x, tdtx: %08x, rbase %08x, rcnt %08x, rctx %08x, rdtx %08x\n", - mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE), - mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT), - mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX), - mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX), - mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE), - mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT), - mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX), - mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX)); - - dev_dbg(hsdma->ddev.dev, - "info %08x, glo %08x, delay %08x, intr_stat %08x, intr_mask %08x\n", - mtk_hsdma_read(hsdma, HSDMA_REG_INFO), - mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG), - mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT), - mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS), - mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK)); -} - -static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - struct hsdma_desc *tx_desc; - struct hsdma_desc *rx_desc; - int i; - - dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n", - chan->tx_idx, chan->rx_idx); - - for (i = 0; i < HSDMA_DESCS_NUM; i++) { - tx_desc = &chan->tx_ring[i]; - rx_desc = &chan->rx_ring[i]; - - dev_dbg(hsdma->ddev.dev, - "%d tx addr0: %08x, flags %08x, tx addr1: %08x, rx addr0 %08x, flags %08x\n", - i, tx_desc->addr0, tx_desc->flags, - tx_desc->addr1, rx_desc->addr0, rx_desc->flags); - } -} - -static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - int i; - - /* disable dma */ - mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); - - /* disable intr */ - mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); - - /* init desc value */ - for (i = 0; i < HSDMA_DESCS_NUM; i++) { - chan->tx_ring[i].addr0 = 0; - chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; - } - for (i = 0; i < HSDMA_DESCS_NUM; i++) { - chan->rx_ring[i].addr0 = 0; - chan->rx_ring[i].flags = 0; - } - - /* reset */ - mtk_hsdma_reset_chan(hsdma, chan); - - /* enable intr */ - mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); - - /* enable dma */ - mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); -} - -static int mtk_hsdma_terminate_all(struct dma_chan *c) -{ - struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); - struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); - unsigned long timeout; - LIST_HEAD(head); - - spin_lock_bh(&chan->vchan.lock); - chan->desc = NULL; - clear_bit(chan->id, &hsdma->chan_issued); - vchan_get_all_descriptors(&chan->vchan, &head); - spin_unlock_bh(&chan->vchan.lock); - - vchan_dma_desc_free_list(&chan->vchan, &head); - - /* wait dma transfer complete */ - timeout = jiffies + msecs_to_jiffies(2000); - while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) & - (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) { - if (time_after_eq(jiffies, timeout)) { - hsdma_dump_desc(hsdma, chan); - mtk_hsdma_reset(hsdma, chan); - dev_err(hsdma->ddev.dev, "timeout, reset it\n"); - break; - } - cpu_relax(); - } - - return 0; -} - -static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - dma_addr_t src, dst; - size_t len, tlen; - struct hsdma_desc *tx_desc, *rx_desc; - struct mtk_hsdma_sg *sg; - unsigned int i; - int rx_idx; - - sg = &chan->desc->sg[0]; - len = sg->len; - chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN); - - /* tx desc */ - src = sg->src_addr; - for (i = 0; i < chan->desc->num_sgs; i++) { - tx_desc = &chan->tx_ring[chan->tx_idx]; - - if (len > HSDMA_MAX_PLEN) - tlen = HSDMA_MAX_PLEN; - else - tlen = len; - - if (i & 0x1) { - tx_desc->addr1 = src; - tx_desc->flags |= HSDMA_DESC_PLEN1(tlen); - } else { - tx_desc->addr0 = src; - tx_desc->flags = HSDMA_DESC_PLEN0(tlen); - - /* update index */ - chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx); - } - - src += tlen; - len -= tlen; - } - if (i & 0x1) - tx_desc->flags |= HSDMA_DESC_LS0; - else - tx_desc->flags |= HSDMA_DESC_LS1; - - /* rx desc */ - rx_idx = HSDMA_NEXT_DESC(chan->rx_idx); - len = sg->len; - dst = sg->dst_addr; - for (i = 0; i < chan->desc->num_sgs; i++) { - rx_desc = &chan->rx_ring[rx_idx]; - if (len > HSDMA_MAX_PLEN) - tlen = HSDMA_MAX_PLEN; - else - tlen = len; - - rx_desc->addr0 = dst; - rx_desc->flags = HSDMA_DESC_PLEN0(tlen); - - dst += tlen; - len -= tlen; - - /* update index */ - rx_idx = HSDMA_NEXT_DESC(rx_idx); - } - - /* make sure desc and index all up to date */ - wmb(); - mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); - - return 0; -} - -static int gdma_next_desc(struct mtk_hsdma_chan *chan) -{ - struct virt_dma_desc *vdesc; - - vdesc = vchan_next_desc(&chan->vchan); - if (!vdesc) { - chan->desc = NULL; - return 0; - } - chan->desc = to_mtk_hsdma_desc(vdesc); - chan->next_sg = 0; - - return 1; -} - -static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - struct mtk_hsdma_desc *desc; - int chan_issued; - - chan_issued = 0; - spin_lock_bh(&chan->vchan.lock); - desc = chan->desc; - if (likely(desc)) { - if (chan->next_sg == desc->num_sgs) { - list_del(&desc->vdesc.node); - vchan_cookie_complete(&desc->vdesc); - chan_issued = gdma_next_desc(chan); - } - } else { - dev_dbg(hsdma->ddev.dev, "no desc to complete\n"); - } - - if (chan_issued) - set_bit(chan->id, &hsdma->chan_issued); - spin_unlock_bh(&chan->vchan.lock); -} - -static irqreturn_t mtk_hsdma_irq(int irq, void *devid) -{ - struct mtk_hsdam_engine *hsdma = devid; - u32 status; - - status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS); - if (unlikely(!status)) - return IRQ_NONE; - - if (likely(status & HSDMA_INT_RX_Q0)) - tasklet_schedule(&hsdma->task); - else - dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", status); - /* clean intr bits */ - mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status); - - return IRQ_HANDLED; -} - -static void mtk_hsdma_issue_pending(struct dma_chan *c) -{ - struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); - struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); - - spin_lock_bh(&chan->vchan.lock); - if (vchan_issue_pending(&chan->vchan) && !chan->desc) { - if (gdma_next_desc(chan)) { - set_bit(chan->id, &hsdma->chan_issued); - tasklet_schedule(&hsdma->task); - } else { - dev_dbg(hsdma->ddev.dev, "no desc to issue\n"); - } - } - spin_unlock_bh(&chan->vchan.lock); -} - -static struct dma_async_tx_descriptor *mtk_hsdma_prep_dma_memcpy( - struct dma_chan *c, dma_addr_t dest, dma_addr_t src, - size_t len, unsigned long flags) -{ - struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); - struct mtk_hsdma_desc *desc; - - if (len <= 0) - return NULL; - - desc = kzalloc(sizeof(*desc), GFP_ATOMIC); - if (!desc) { - dev_err(c->device->dev, "alloc memcpy decs error\n"); - return NULL; - } - - desc->sg[0].src_addr = src; - desc->sg[0].dst_addr = dest; - desc->sg[0].len = len; - - return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -} - -static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, - dma_cookie_t cookie, - struct dma_tx_state *state) -{ - return dma_cookie_status(c, cookie, state); -} - -static void mtk_hsdma_free_chan_resources(struct dma_chan *c) -{ - vchan_free_chan_resources(to_virt_chan(c)); -} - -static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc) -{ - kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc)); -} - -static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma) -{ - struct mtk_hsdma_chan *chan; - - if (test_and_clear_bit(0, &hsdma->chan_issued)) { - chan = &hsdma->chan[0]; - if (chan->desc) - mtk_hsdma_start_transfer(hsdma, chan); - else - dev_dbg(hsdma->ddev.dev, "chan 0 no desc to issue\n"); - } -} - -static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma) -{ - struct mtk_hsdma_chan *chan; - int next_idx, drx_idx, cnt; - - chan = &hsdma->chan[0]; - next_idx = HSDMA_NEXT_DESC(chan->rx_idx); - drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX); - - cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK; - if (!cnt) - return; - - chan->next_sg += cnt; - chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK; - - /* update rx crx */ - wmb(); - mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); - - mtk_hsdma_chan_done(hsdma, chan); -} - -static void mtk_hsdma_tasklet(struct tasklet_struct *t) -{ - struct mtk_hsdam_engine *hsdma = from_tasklet(hsdma, t, task); - - mtk_hsdma_rx(hsdma); - mtk_hsdma_tx(hsdma); -} - -static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - int i; - - chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev, - 2 * HSDMA_DESCS_NUM * - sizeof(*chan->tx_ring), - &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO); - if (!chan->tx_ring) - goto no_mem; - - chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM]; - - /* init tx ring value */ - for (i = 0; i < HSDMA_DESCS_NUM; i++) - chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; - - return 0; -no_mem: - return -ENOMEM; -} - -static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma, - struct mtk_hsdma_chan *chan) -{ - if (chan->tx_ring) { - dma_free_coherent(hsdma->ddev.dev, - 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), - chan->tx_ring, chan->desc_addr); - chan->tx_ring = NULL; - chan->rx_ring = NULL; - } -} - -static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma) -{ - struct mtk_hsdma_chan *chan; - int ret; - u32 reg; - - /* init desc */ - chan = &hsdma->chan[0]; - ret = mtk_hsdam_alloc_desc(hsdma, chan); - if (ret) - return ret; - - /* tx */ - mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr); - mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM); - /* rx */ - mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr + - (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM)); - mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM); - /* reset */ - mtk_hsdma_reset_chan(hsdma, chan); - - /* enable rx intr */ - mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); - - /* enable dma */ - mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); - - /* hardware info */ - reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO); - dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n", - (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK, - (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK); - - hsdma_dump_reg(hsdma); - - return ret; -} - -static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma) -{ - struct mtk_hsdma_chan *chan; - - /* disable dma */ - mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); - - /* disable intr */ - mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); - - /* free desc */ - chan = &hsdma->chan[0]; - mtk_hsdam_free_desc(hsdma, chan); - - /* tx */ - mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0); - mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0); - /* rx */ - mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0); - mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0); - /* reset */ - mtk_hsdma_reset_chan(hsdma, chan); -} - -static const struct of_device_id mtk_hsdma_of_match[] = { - { .compatible = "mediatek,mt7621-hsdma" }, - { }, -}; - -static int mtk_hsdma_probe(struct platform_device *pdev) -{ - const struct of_device_id *match; - struct mtk_hsdma_chan *chan; - struct mtk_hsdam_engine *hsdma; - struct dma_device *dd; - int ret; - int irq; - void __iomem *base; - - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - - match = of_match_device(mtk_hsdma_of_match, &pdev->dev); - if (!match) - return -EINVAL; - - hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); - if (!hsdma) - return -EINVAL; - - base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); - hsdma->base = base + HSDMA_BASE_OFFSET; - tasklet_setup(&hsdma->task, mtk_hsdma_tasklet); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -EINVAL; - ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, - 0, dev_name(&pdev->dev), hsdma); - if (ret) { - dev_err(&pdev->dev, "failed to request irq\n"); - return ret; - } - - device_reset(&pdev->dev); - - dd = &hsdma->ddev; - dma_cap_set(DMA_MEMCPY, dd->cap_mask); - dd->copy_align = HSDMA_ALIGN_SIZE; - dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; - dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; - dd->device_terminate_all = mtk_hsdma_terminate_all; - dd->device_tx_status = mtk_hsdma_tx_status; - dd->device_issue_pending = mtk_hsdma_issue_pending; - dd->dev = &pdev->dev; - dd->dev->dma_parms = &hsdma->dma_parms; - dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN); - INIT_LIST_HEAD(&dd->channels); - - chan = &hsdma->chan[0]; - chan->id = 0; - chan->vchan.desc_free = mtk_hsdma_desc_free; - vchan_init(&chan->vchan, dd); - - /* init hardware */ - ret = mtk_hsdma_init(hsdma); - if (ret) { - dev_err(&pdev->dev, "failed to alloc ring descs\n"); - return ret; - } - - ret = dma_async_device_register(dd); - if (ret) { - dev_err(&pdev->dev, "failed to register dma device\n"); - goto err_uninit_hsdma; - } - - ret = of_dma_controller_register(pdev->dev.of_node, - of_dma_xlate_by_chan_id, hsdma); - if (ret) { - dev_err(&pdev->dev, "failed to register of dma controller\n"); - goto err_unregister; - } - - platform_set_drvdata(pdev, hsdma); - - return 0; - -err_unregister: - dma_async_device_unregister(dd); -err_uninit_hsdma: - mtk_hsdma_uninit(hsdma); - return ret; -} - -static int mtk_hsdma_remove(struct platform_device *pdev) -{ - struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev); - - mtk_hsdma_uninit(hsdma); - - of_dma_controller_free(pdev->dev.of_node); - dma_async_device_unregister(&hsdma->ddev); - - return 0; -} - -static struct platform_driver mtk_hsdma_driver = { - .probe = mtk_hsdma_probe, - .remove = mtk_hsdma_remove, - .driver = { - .name = "hsdma-mt7621", - .of_match_table = mtk_hsdma_of_match, - }, -}; -module_platform_driver(mtk_hsdma_driver); - -MODULE_AUTHOR("Michael Lee igvtee@gmail.com"); -MODULE_DESCRIPTION("MTK HSDMA driver"); -MODULE_LICENSE("GPL v2");
From: Amey Narkhede ameynarkhede03@gmail.com
commit 7c3a0635cd008eaca9a734dc802709ee0b81cac5 upstream.
Stack allocated buffers cannot be used for DMA on all architectures so allocate hci_packet buffer using kmalloc.
Reviewed-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Amey Narkhede ameynarkhede03@gmail.com Link: https://lore.kernel.org/r/20210211053819.34858-1-ameynarkhede03@gmail.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/gdm724x/gdm_usb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -56,20 +56,24 @@ static int gdm_usb_recv(void *priv_dev,
static int request_mac_address(struct lte_udev *udev) { - u8 buf[16] = {0,}; - struct hci_packet *hci = (struct hci_packet *)buf; + struct hci_packet *hci; struct usb_device *usbdev = udev->usbdev; int actual; int ret = -1;
+ hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL); + if (!hci) + return -ENOMEM; + hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION); hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1); hci->data[0] = MAC_ADDRESS;
- ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5, + ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5, &actual, 1000);
udev->request_mac_addr = 1; + kfree(hci);
return ret; }
From: Martin Kaiser martin@kaiser.cx
commit 7a8d2f1908a59003e55ef8691d09efb7fbc51625 upstream.
The Edimax EW-7811UN V2 uses an RTL8188EU chipset and works with this driver.
Signed-off-by: Martin Kaiser martin@kaiser.cx Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20210204085217.9743-1-martin@kaiser.cx Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -41,6 +41,7 @@ static const struct usb_device_id rtw_us {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */ {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811UN V2 */ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ {} /* Terminating entry */ };
From: Jiri Kosina jkosina@suse.cz
commit 8a0c014cd20516ade9654fc13b51345ec58e7be8 upstream.
This issue was originally fixed in 09954bad4 ("floppy: refactor open() flags handling").
The fix as a side-effect, however, introduce issue for open(O_ACCMODE) that is being used for ioctl-only open. I wrote a fix for that, but instead of it being merged, full revert of 09954bad4 was performed, re-introducing the O_NDELAY / O_NONBLOCK issue, and it strikes again.
This is a forward-port of the original fix to current codebase; the original submission had the changelog below:
==== Commit 09954bad4 ("floppy: refactor open() flags handling"), as a side-effect, causes open(/dev/fdX, O_ACCMODE) to fail. It turns out that this is being used setfdprm userspace for ioctl-only open().
Reintroduce back the original behavior wrt !(FMODE_READ|FMODE_WRITE) modes, while still keeping the original O_NDELAY bug fixed.
Link: https://lore.kernel.org/r/nycvar.YFH.7.76.2101221209060.5622@cbobk.fhfr.pm Cc: stable@vger.kernel.org Reported-by: Wim Osterholt wim@djo.tudelft.nl Tested-by: Wim Osterholt wim@djo.tudelft.nl Reported-and-tested-by: Kurt Garloff kurt@garloff.de Fixes: 09954bad4 ("floppy: refactor open() flags handling") Fixes: f2791e7ead ("Revert "floppy: refactor open() flags handling"") Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Denis Efremov efremov@linux.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/block/floppy.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
--- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4121,23 +4121,23 @@ static int floppy_open(struct block_devi if (fdc_state[FDC(drive)].rawcmd == 1) fdc_state[FDC(drive)].rawcmd = 2;
- if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - drive_state[drive].last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, - &drive_state[drive].flags); - if (bdev_check_media_change(bdev)) - floppy_revalidate(bdev->bd_disk); - if (test_bit(FD_DISK_CHANGED_BIT, &drive_state[drive].flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &drive_state[drive].flags)) + if (mode & (FMODE_READ|FMODE_WRITE)) { + drive_state[drive].last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags); + if (bdev_check_media_change(bdev)) + floppy_revalidate(bdev->bd_disk); + if (test_bit(FD_DISK_CHANGED_BIT, &drive_state[drive].flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &drive_state[drive].flags)) goto out; } + + res = -EROFS; + + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &drive_state[drive].flags)) + goto out; + mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); return 0;
From: Tomi Valkeinen tomi.valkeinen@ideasonboard.com
commit e88ccf09e79cf33cac40316ba69c820d9eebc82b upstream.
The asd allocated with v4l2_async_notifier_add_fwnode_subdev() must be of size max9286_asd, otherwise access to max9286_asd->source will go to unallocated memory.
Fixes: 86d37bf31af6 ("media: i2c: max9286: Allocate v4l2_async_subdev dynamically") Signed-off-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Cc: stable@vger.kernel.org # v5.10+ Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com Tested-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/i2c/max9286.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -580,7 +580,7 @@ static int max9286_v4l2_notifier_registe
asd = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier, source->fwnode, - sizeof(*asd)); + sizeof(struct max9286_asd)); if (IS_ERR(asd)) { dev_err(dev, "Failed to add subdev for source %u: %ld", i, PTR_ERR(asd));
From: Sakari Ailus sakari.ailus@linux.intel.com
commit fb18802a338b36f675a388fc03d2aa504a0d0899 upstream.
When an IOCTL with argument size larger than 128 that also used array arguments were handled, two memory allocations were made but alas, only the latter one of them was released. This happened because there was only a single local variable to hold such a temporary allocation.
Fix this by adding separate variables to hold the pointers to the temporary allocations.
Reported-by: Arnd Bergmann arnd@kernel.org Reported-by: syzbot+1115e79c8df6472c612b@syzkaller.appspotmail.com Fixes: d14e6d76ebf7 ("[media] v4l: Add multi-planar ioctl handling code") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Acked-by: Arnd Bergmann arnd@arndb.de Acked-by: Hans Verkuil hverkuil-cisco@xs4all.nl Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/v4l2-core/v4l2-ioctl.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-)
--- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -3283,7 +3283,7 @@ video_usercopy(struct file *file, unsign v4l2_kioctl func) { char sbuf[128]; - void *mbuf = NULL; + void *mbuf = NULL, *array_buf = NULL; void *parg = (void *)arg; long err = -EINVAL; bool has_array_args; @@ -3318,27 +3318,21 @@ video_usercopy(struct file *file, unsign has_array_args = err;
if (has_array_args) { - /* - * When adding new types of array args, make sure that the - * parent argument to ioctl (which contains the pointer to the - * array) fits into sbuf (so that mbuf will still remain - * unused up to here). - */ - mbuf = kvmalloc(array_size, GFP_KERNEL); + array_buf = kvmalloc(array_size, GFP_KERNEL); err = -ENOMEM; - if (NULL == mbuf) + if (array_buf == NULL) goto out_array_args; err = -EFAULT; if (in_compat_syscall()) - err = v4l2_compat_get_array_args(file, mbuf, user_ptr, - array_size, orig_cmd, - parg); + err = v4l2_compat_get_array_args(file, array_buf, + user_ptr, array_size, + orig_cmd, parg); else - err = copy_from_user(mbuf, user_ptr, array_size) ? + err = copy_from_user(array_buf, user_ptr, array_size) ? -EFAULT : 0; if (err) goto out_array_args; - *kernel_ptr = mbuf; + *kernel_ptr = array_buf; }
/* Handles IOCTL */ @@ -3360,12 +3354,13 @@ video_usercopy(struct file *file, unsign if (in_compat_syscall()) { int put_err;
- put_err = v4l2_compat_put_array_args(file, user_ptr, mbuf, - array_size, orig_cmd, - parg); + put_err = v4l2_compat_put_array_args(file, user_ptr, + array_buf, + array_size, + orig_cmd, parg); if (put_err) err = put_err; - } else if (copy_to_user(user_ptr, mbuf, array_size)) { + } else if (copy_to_user(user_ptr, array_buf, array_size)) { err = -EFAULT; } goto out_array_args; @@ -3381,6 +3376,7 @@ out_array_args: if (video_put_user((void __user *)arg, parg, cmd, orig_cmd)) err = -EFAULT; out: + kvfree(array_buf); kvfree(mbuf); return err; }
From: Sean Young sean@mess.org
commit 4487e0215560392bd11c9de08d60824d72c89cd9 upstream.
This device is also supported.
Cc: stable@vger.kernel.org Tested-by: Georgi Bakalski georgi.bakalski@gmail.com Reported-by: Georgi Bakalski georgi.bakalski@gmail.com Signed-off-by: Sean Young sean@mess.org Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/rc/ir_toy.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/media/rc/ir_toy.c +++ b/drivers/media/rc/ir_toy.c @@ -491,6 +491,7 @@ static void irtoy_disconnect(struct usb_
static const struct usb_device_id irtoy_table[] = { { USB_DEVICE_INTERFACE_CLASS(0x04d8, 0xfd08, USB_CLASS_CDC_DATA) }, + { USB_DEVICE_INTERFACE_CLASS(0x04d8, 0xf58b, USB_CLASS_CDC_DATA) }, { } };
From: Pavel Machek pavel@denx.de
commit 334de4b45892f7e67074e1b1b2ac36fd3e091118 upstream.
Loop was useless as it would always exit on the first iteration. Fix it with right condition.
Signed-off-by: Pavel Machek (CIP) pavel@denx.de Fixes: a86cf9b29e8b ("media: ipu3-cio2: Validate mbus format in setting subdev format") Tested-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Cc: stable@vger.kernel.org # v4.16 and up Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1269,7 +1269,7 @@ static int cio2_subdev_set_fmt(struct v4 fmt->format.code = formats[0].mbus_code;
for (i = 0; i < ARRAY_SIZE(formats); i++) { - if (formats[i].mbus_code == fmt->format.code) { + if (formats[i].mbus_code == mbus_code) { fmt->format.code = mbus_code; break; }
From: Lubomir Rintel lkundrak@v3.sk
commit 655ae29da72a693cf294bba3c3322e662ff75bd3 upstream.
Writing to REG_CLKCTRL with the power off causes a hang. Enable the device first.
Cc: stable@vger.kernel.org # 5.10+ Signed-off-by: Lubomir Rintel lkundrak@v3.sk Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/platform/marvell-ccic/mcam-core.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -931,6 +931,7 @@ static int mclk_enable(struct clk_hw *hw mclk_div = 2; }
+ pm_runtime_get_sync(cam->dev); clk_enable(cam->clk[0]); mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div); mcam_ctlr_power_up(cam); @@ -944,6 +945,7 @@ static void mclk_disable(struct clk_hw *
mcam_ctlr_power_down(cam); clk_disable(cam->clk[0]); + pm_runtime_put(cam->dev); }
static unsigned long mclk_recalc_rate(struct clk_hw *hw,
From: Sean Young sean@mess.org
commit 6532923237b427ed30cc7b4486f6f1ccdee3c647 upstream.
After the first IR message, interrupts are no longer received. In addition, the code generates a timeout IR message of 10ms but sets the timeout value to 100ms, so no timeout was ever generated.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=204317
Fixes: a49a7a4635de ("media: smipcie: add universal ir capability") Tested-by: Laz Lev lazlev@web.de Cc: stable@vger.kernel.org # v5.1+ Signed-off-by: Sean Young sean@mess.org Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/pci/smipcie/smipcie-ir.c | 48 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-)
--- a/drivers/media/pci/smipcie/smipcie-ir.c +++ b/drivers/media/pci/smipcie/smipcie-ir.c @@ -60,38 +60,44 @@ static void smi_ir_decode(struct smi_rc { struct smi_dev *dev = ir->dev; struct rc_dev *rc_dev = ir->rc_dev; - u32 dwIRControl, dwIRData; - u8 index, ucIRCount, readLoop; + u32 control, data; + u8 index, ir_count, read_loop;
- dwIRControl = smi_read(IR_Init_Reg); + control = smi_read(IR_Init_Reg);
- if (dwIRControl & rbIRVld) { - ucIRCount = (u8) smi_read(IR_Data_Cnt); + dev_dbg(&rc_dev->dev, "ircontrol: 0x%08x\n", control);
- readLoop = ucIRCount/4; - if (ucIRCount % 4) - readLoop += 1; - for (index = 0; index < readLoop; index++) { - dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index * 4)); - - ir->irData[index*4 + 0] = (u8)(dwIRData); - ir->irData[index*4 + 1] = (u8)(dwIRData >> 8); - ir->irData[index*4 + 2] = (u8)(dwIRData >> 16); - ir->irData[index*4 + 3] = (u8)(dwIRData >> 24); + if (control & rbIRVld) { + ir_count = (u8)smi_read(IR_Data_Cnt); + + dev_dbg(&rc_dev->dev, "ircount %d\n", ir_count); + + read_loop = ir_count / 4; + if (ir_count % 4) + read_loop += 1; + for (index = 0; index < read_loop; index++) { + data = smi_read(IR_DATA_BUFFER_BASE + (index * 4)); + dev_dbg(&rc_dev->dev, "IRData 0x%08x\n", data); + + ir->irData[index * 4 + 0] = (u8)(data); + ir->irData[index * 4 + 1] = (u8)(data >> 8); + ir->irData[index * 4 + 2] = (u8)(data >> 16); + ir->irData[index * 4 + 3] = (u8)(data >> 24); } - smi_raw_process(rc_dev, ir->irData, ucIRCount); - smi_set(IR_Init_Reg, rbIRVld); + smi_raw_process(rc_dev, ir->irData, ir_count); }
- if (dwIRControl & rbIRhighidle) { + if (control & rbIRhighidle) { struct ir_raw_event rawir = {};
+ dev_dbg(&rc_dev->dev, "high idle\n"); + rawir.pulse = 0; rawir.duration = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN; ir_raw_event_store_with_filter(rc_dev, &rawir); - smi_set(IR_Init_Reg, rbIRhighidle); }
+ smi_set(IR_Init_Reg, rbIRVld); ir_raw_event_handle(rc_dev); }
@@ -150,7 +156,7 @@ int smi_ir_init(struct smi_dev *dev) rc_dev->dev.parent = &dev->pci_dev->dev;
rc_dev->map_name = dev->info->rc_map; - rc_dev->timeout = MS_TO_US(100); + rc_dev->timeout = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN; rc_dev->rx_resolution = SMI_SAMPLE_PERIOD;
ir->rc_dev = rc_dev; @@ -173,7 +179,7 @@ void smi_ir_exit(struct smi_dev *dev) struct smi_rc *ir = &dev->ir; struct rc_dev *rc_dev = ir->rc_dev;
- smi_ir_stop(ir); rc_unregister_device(rc_dev); + smi_ir_stop(ir); ir->rc_dev = NULL; }
From: Sean Christopherson seanjc@google.com
commit aec511ad153556640fb1de38bfe00c69464f997f upstream.
Silently ignore all faults on VMXOFF in the reboot flows as such faults are all but guaranteed to be due to the CPU not being in VMX root. Because (a) VMXOFF may be executed in NMI context, e.g. after VMXOFF but before CR4.VMXE is cleared, (b) there's no way to query the CPU's VMX state without faulting, and (c) the whole point is to get out of VMX root, eating faults is the simplest way to achieve the desired behaior.
Technically, VMXOFF can fault (or fail) for other reasons, but all other fault and failure scenarios are mode related, i.e. the kernel would have to magically end up in RM, V86, compat mode, at CPL>0, or running with the SMI Transfer Monitor active. The kernel is beyond hosed if any of those scenarios are encountered; trying to do something fancy in the error path to handle them cleanly is pointless.
Fixes: 1e9931146c74 ("x86: asm/virtext.h: add cpu_vmxoff() inline function") Reported-by: David P. Reed dpreed@deepplum.com Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20201231002702.2223707-2-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/include/asm/virtext.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
--- a/arch/x86/include/asm/virtext.h +++ b/arch/x86/include/asm/virtext.h @@ -30,15 +30,22 @@ static inline int cpu_has_vmx(void) }
-/** Disable VMX on the current CPU +/** + * cpu_vmxoff() - Disable VMX on the current CPU * - * vmxoff causes a undefined-opcode exception if vmxon was not run - * on the CPU previously. Only call this function if you know VMX - * is enabled. + * Disable VMX and clear CR4.VMXE (even if VMXOFF faults) + * + * Note, VMXOFF causes a #UD if the CPU is !post-VMXON, but it's impossible to + * atomically track post-VMXON state, e.g. this may be called in NMI context. + * Eat all faults as all other faults on VMXOFF faults are mode related, i.e. + * faults are guaranteed to be due to the !post-VMXON check unless the CPU is + * magically in RM, VM86, compat mode, or at CPL>0. */ static inline void cpu_vmxoff(void) { - asm volatile ("vmxoff"); + asm_volatile_goto("1: vmxoff\n\t" + _ASM_EXTABLE(1b, %l[fault]) :::: fault); +fault: cr4_clear_bits(X86_CR4_VMXE); }
From: Sean Christopherson seanjc@google.com
commit ed72736183c45a413a8d6974dd04be90f514cb6b upstream.
Force all CPUs to do VMXOFF (via NMI shootdown) during an emergency reboot if VMX is _supported_, as VMX being off on the current CPU does not prevent other CPUs from being in VMX root (post-VMXON). This fixes a bug where a crash/panic reboot could leave other CPUs in VMX root and prevent them from being woken via INIT-SIPI-SIPI in the new kernel.
Fixes: d176720d34c7 ("x86: disable VMX on all CPUs on reboot") Cc: stable@vger.kernel.org Suggested-by: Sean Christopherson seanjc@google.com Signed-off-by: David P. Reed dpreed@deepplum.com [sean: reworked changelog and further tweaked comment] Signed-off-by: Sean Christopherson seanjc@google.com Message-Id: 20201231002702.2223707-3-seanjc@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kernel/reboot.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-)
--- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -538,31 +538,21 @@ static void emergency_vmx_disable_all(vo local_irq_disable();
/* - * We need to disable VMX on all CPUs before rebooting, otherwise - * we risk hanging up the machine, because the CPU ignores INIT - * signals when VMX is enabled. + * Disable VMX on all CPUs before rebooting, otherwise we risk hanging + * the machine, because the CPU blocks INIT when it's in VMX root. * - * We can't take any locks and we may be on an inconsistent - * state, so we use NMIs as IPIs to tell the other CPUs to disable - * VMX and halt. + * We can't take any locks and we may be on an inconsistent state, so + * use NMIs as IPIs to tell the other CPUs to exit VMX root and halt. * - * For safety, we will avoid running the nmi_shootdown_cpus() - * stuff unnecessarily, but we don't have a way to check - * if other CPUs have VMX enabled. So we will call it only if the - * CPU we are running on has VMX enabled. - * - * We will miss cases where VMX is not enabled on all CPUs. This - * shouldn't do much harm because KVM always enable VMX on all - * CPUs anyway. But we can miss it on the small window where KVM - * is still enabling VMX. + * Do the NMI shootdown even if VMX if off on _this_ CPU, as that + * doesn't prevent a different CPU from being in VMX root operation. */ - if (cpu_has_vmx() && cpu_vmx_enabled()) { - /* Disable VMX on this CPU. */ - cpu_vmxoff(); + if (cpu_has_vmx()) { + /* Safely force _this_ CPU out of VMX root operation. */ + __cpu_emergency_vmxoff();
- /* Halt and disable VMX on the other CPUs */ + /* Halt and exit VMX root operation on the other CPUs. */ nmi_shootdown_cpus(vmxoff_nmi); - } }
From: Andy Lutomirski luto@kernel.org
commit 35f1c89b0cce247bf0213df243ed902989b1dcda upstream.
The recent rework of probe_kernel_address() and its conversion to get_kernel_nofault() inadvertently broke is_prefetch(). Before this change, probe_kernel_address() was used as a sloppy "read user or kernel memory" helper, but it doesn't do that any more. The new get_kernel_nofault() reads *kernel* memory only, which completely broke is_prefetch() for user access.
Adjust the code to the correct accessor based on access mode. The manual address bounds check is no longer necessary, since the accessor helpers (get_user() / get_kernel_nofault()) do the right thing all by themselves. As a bonus, by using the correct accessor, the open-coded address bounds check is not needed anymore.
[ bp: Massage commit message. ]
Fixes: eab0c6089b68 ("maccess: unify the probe kernel arch hooks") Signed-off-by: Andy Lutomirski luto@kernel.org Signed-off-by: Borislav Petkov bp@suse.de Reviewed-by: Christoph Hellwig hch@lst.de Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/b91f7f92f3367d2d3a88eec3b09c6aab1b2dc8ef.161292425... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/mm/fault.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
--- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -54,7 +54,7 @@ kmmio_fault(struct pt_regs *regs, unsign * 32-bit mode: * * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch. - * Check that here and ignore it. + * Check that here and ignore it. This is AMD erratum #91. * * 64-bit mode: * @@ -83,11 +83,7 @@ check_prefetch_opcode(struct pt_regs *re #ifdef CONFIG_X86_64 case 0x40: /* - * In AMD64 long mode 0x40..0x4F are valid REX prefixes - * Need to figure out under what instruction mode the - * instruction was issued. Could check the LDT for lm, - * but for now it's good enough to assume that long - * mode only uses well known segments or kernel. + * In 64-bit mode 0x40..0x4F are valid REX prefixes */ return (!user_mode(regs) || user_64bit_mode(regs)); #endif @@ -127,20 +123,31 @@ is_prefetch(struct pt_regs *regs, unsign instr = (void *)convert_ip_to_linear(current, regs); max_instr = instr + 15;
- if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE_MAX) - return 0; + /* + * This code has historically always bailed out if IP points to a + * not-present page (e.g. due to a race). No one has ever + * complained about this. + */ + pagefault_disable();
while (instr < max_instr) { unsigned char opcode;
- if (get_kernel_nofault(opcode, instr)) - break; + if (user_mode(regs)) { + if (get_user(opcode, instr)) + break; + } else { + if (get_kernel_nofault(opcode, instr)) + break; + }
instr++;
if (!check_prefetch_opcode(regs, instr, opcode, &prefetch)) break; } + + pagefault_enable(); return prefetch; }
From: Thomas Gleixner tglx@linutronix.de
commit 15f720aabe71a5662c4198b22532d95bbeec80ef upstream.
Embracing a callout into instrumentation_begin() / instrumentation_begin() does not really make sense. Make the latter instrumentation_end().
Fixes: 2f6474e4636b ("x86/entry: Switch XEN/PV hypercall entry to IDTENTRY") Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Kees Cook keescook@chromium.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210210002512.106502464@linutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/entry/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -270,7 +270,7 @@ __visible noinstr void xen_pv_evtchn_do_
instrumentation_begin(); run_on_irqstack_cond(__xen_pv_evtchn_do_upcall, regs); - instrumentation_begin(); + instrumentation_end();
set_irq_regs(old_regs);
From: Cédric Le Goater clg@kaod.org
commit ed5b00a05c2ae95b59adc3442f45944ec632e794 upstream.
The "ibm,arch-vec-5-platform-support" property is a list of pairs of bytes representing the options and values supported by the platform firmware. At boot time, Linux scans this list and activates the available features it recognizes : Radix and XIVE.
A recent change modified the number of entries to loop on and 8 bytes, 4 pairs of { options, values } entries are always scanned. This is fine on KVM but not on PowerVM which can advertises less. As a consequence on this platform, Linux reads extra entries pointing to random data, interprets these as available features and tries to activate them, leading to a firmware crash in ibm,client-architecture-support.
Fix that by using the property length of "ibm,arch-vec-5-platform-support".
Fixes: ab91239942a9 ("powerpc/prom: Remove VLA in prom_check_platform_support()") Cc: stable@vger.kernel.org # v4.20+ Signed-off-by: Cédric Le Goater clg@kaod.org Reviewed-by: Fabiano Rosas farosas@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/20210122075029.797013-1-clg@kaod.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/kernel/prom_init.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
--- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1331,14 +1331,10 @@ static void __init prom_check_platform_s if (prop_len > sizeof(vec)) prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n", prop_len); - prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", - &vec, sizeof(vec)); - for (i = 0; i < sizeof(vec); i += 2) { - prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 - , vec[i] - , vec[i + 1]); - prom_parse_platform_support(vec[i], vec[i + 1], - &supported); + prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", &vec, sizeof(vec)); + for (i = 0; i < prop_len; i += 2) { + prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2, vec[i], vec[i + 1]); + prom_parse_platform_support(vec[i], vec[i + 1], &supported); } }
From: Frederic Weisbecker frederic@kernel.org
commit 54b7429efffc99e845ba9381bee3244f012a06c2 upstream.
Deferred wakeup of rcuog kthreads upon RCU idle mode entry is going to be handled differently whether initiated by idle, user or guest. Prepare with pulling that control up to rcu_eqs_enter() callers.
Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-2-frederic@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/rcu/tree.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
--- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -644,7 +644,6 @@ static noinstr void rcu_eqs_enter(bool u trace_rcu_dyntick(TPS("Start"), rdp->dynticks_nesting, 0, atomic_read(&rdp->dynticks)); WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !user && !is_idle_task(current)); rdp = this_cpu_ptr(&rcu_data); - do_nocb_deferred_wakeup(rdp); rcu_prepare_for_idle(); rcu_preempt_deferred_qs(current);
@@ -672,7 +671,10 @@ static noinstr void rcu_eqs_enter(bool u */ void rcu_idle_enter(void) { + struct rcu_data *rdp = this_cpu_ptr(&rcu_data); + lockdep_assert_irqs_disabled(); + do_nocb_deferred_wakeup(rdp); rcu_eqs_enter(false); } EXPORT_SYMBOL_GPL(rcu_idle_enter); @@ -691,7 +693,14 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter); */ noinstr void rcu_user_enter(void) { + struct rcu_data *rdp = this_cpu_ptr(&rcu_data); + lockdep_assert_irqs_disabled(); + + instrumentation_begin(); + do_nocb_deferred_wakeup(rdp); + instrumentation_end(); + rcu_eqs_enter(true); } #endif /* CONFIG_NO_HZ_FULL */
From: Frederic Weisbecker frederic@kernel.org
commit 43789ef3f7d61aa7bed0cb2764e588fc990c30ef upstream.
Entering RCU idle mode may cause a deferred wake up of an RCU NOCB_GP kthread (rcuog) to be serviced.
Usually a local wake up happening while running the idle task is handled in one of the need_resched() checks carefully placed within the idle loop that can break to the scheduler.
Unfortunately the call to rcu_idle_enter() is already beyond the last generic need_resched() check and we may halt the CPU with a resched request unhandled, leaving the task hanging.
Fix this with splitting the rcuog wakeup handling from rcu_idle_enter() and place it before the last generic need_resched() check in the idle loop. It is then assumed that no call to call_rcu() will be performed after that in the idle loop until the CPU is put in low power mode.
Fixes: 96d3fd0d315a (rcu: Break call_rcu() deadlock involving scheduler and perf) Reported-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-3-frederic@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/rcupdate.h | 2 ++ kernel/rcu/tree.c | 3 --- kernel/rcu/tree_plugin.h | 5 +++++ kernel/sched/idle.c | 1 + 4 files changed, 8 insertions(+), 3 deletions(-)
--- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -110,8 +110,10 @@ static inline void rcu_user_exit(void) {
#ifdef CONFIG_RCU_NOCB_CPU void rcu_init_nohz(void); +void rcu_nocb_flush_deferred_wakeup(void); #else /* #ifdef CONFIG_RCU_NOCB_CPU */ static inline void rcu_init_nohz(void) { } +static inline void rcu_nocb_flush_deferred_wakeup(void) { } #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
/** --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -671,10 +671,7 @@ static noinstr void rcu_eqs_enter(bool u */ void rcu_idle_enter(void) { - struct rcu_data *rdp = this_cpu_ptr(&rcu_data); - lockdep_assert_irqs_disabled(); - do_nocb_deferred_wakeup(rdp); rcu_eqs_enter(false); } EXPORT_SYMBOL_GPL(rcu_idle_enter); --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -2187,6 +2187,11 @@ static void do_nocb_deferred_wakeup(stru do_nocb_deferred_wakeup_common(rdp); }
+void rcu_nocb_flush_deferred_wakeup(void) +{ + do_nocb_deferred_wakeup(this_cpu_ptr(&rcu_data)); +} + void __init rcu_init_nohz(void) { int cpu; --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -285,6 +285,7 @@ static void do_idle(void) }
arch_cpu_idle_enter(); + rcu_nocb_flush_deferred_wakeup();
/* * In poll mode we reenable interrupts and spin. Also if we
From: Frederic Weisbecker frederic@kernel.org
commit f8bb5cae9616224a39cbb399de382d36ac41df10 upstream.
Entering RCU idle mode may cause a deferred wake up of an RCU NOCB_GP kthread (rcuog) to be serviced.
Unfortunately the call to rcu_user_enter() is already past the last rescheduling opportunity before we resume to userspace or to guest mode. We may escape there with the woken task ignored.
The ultimate resort to fix every callsites is to trigger a self-IPI (nohz_full depends on arch to implement arch_irq_work_raise()) that will trigger a reschedule on IRQ tail or guest exit.
Eventually every site that want a saner treatment will need to carefully place a call to rcu_nocb_flush_deferred_wakeup() before the last explicit need_resched() check upon resume.
Fixes: 96d3fd0d315a (rcu: Break call_rcu() deadlock involving scheduler and perf) Reported-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-4-frederic@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/rcu/tree.c | 21 ++++++++++++++++++++- kernel/rcu/tree.h | 2 +- kernel/rcu/tree_plugin.h | 25 ++++++++++++++++--------- 3 files changed, 37 insertions(+), 11 deletions(-)
--- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -677,6 +677,18 @@ void rcu_idle_enter(void) EXPORT_SYMBOL_GPL(rcu_idle_enter);
#ifdef CONFIG_NO_HZ_FULL + +/* + * An empty function that will trigger a reschedule on + * IRQ tail once IRQs get re-enabled on userspace resume. + */ +static void late_wakeup_func(struct irq_work *work) +{ +} + +static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) = + IRQ_WORK_INIT(late_wakeup_func); + /** * rcu_user_enter - inform RCU that we are resuming userspace. * @@ -694,12 +706,19 @@ noinstr void rcu_user_enter(void)
lockdep_assert_irqs_disabled();
+ /* + * We may be past the last rescheduling opportunity in the entry code. + * Trigger a self IPI that will fire and reschedule once we resume to + * user/guest mode. + */ instrumentation_begin(); - do_nocb_deferred_wakeup(rdp); + if (do_nocb_deferred_wakeup(rdp) && need_resched()) + irq_work_queue(this_cpu_ptr(&late_wakeup_work)); instrumentation_end();
rcu_eqs_enter(true); } + #endif /* CONFIG_NO_HZ_FULL */
/** --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -433,7 +433,7 @@ static bool rcu_nocb_try_bypass(struct r static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty, unsigned long flags); static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp); -static void do_nocb_deferred_wakeup(struct rcu_data *rdp); +static bool do_nocb_deferred_wakeup(struct rcu_data *rdp); static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); static void rcu_spawn_cpu_nocb_kthread(int cpu); static void __init rcu_spawn_nocb_kthreads(void); --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -1631,8 +1631,8 @@ bool rcu_is_nocb_cpu(int cpu) * Kick the GP kthread for this NOCB group. Caller holds ->nocb_lock * and this function releases it. */ -static void wake_nocb_gp(struct rcu_data *rdp, bool force, - unsigned long flags) +static bool wake_nocb_gp(struct rcu_data *rdp, bool force, + unsigned long flags) __releases(rdp->nocb_lock) { bool needwake = false; @@ -1643,7 +1643,7 @@ static void wake_nocb_gp(struct rcu_data trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("AlreadyAwake")); rcu_nocb_unlock_irqrestore(rdp, flags); - return; + return false; } del_timer(&rdp->nocb_timer); rcu_nocb_unlock_irqrestore(rdp, flags); @@ -1656,6 +1656,8 @@ static void wake_nocb_gp(struct rcu_data raw_spin_unlock_irqrestore(&rdp_gp->nocb_gp_lock, flags); if (needwake) wake_up_process(rdp_gp->nocb_gp_kthread); + + return needwake; }
/* @@ -2152,20 +2154,23 @@ static int rcu_nocb_need_deferred_wakeup }
/* Do a deferred wakeup of rcu_nocb_kthread(). */ -static void do_nocb_deferred_wakeup_common(struct rcu_data *rdp) +static bool do_nocb_deferred_wakeup_common(struct rcu_data *rdp) { unsigned long flags; int ndw; + int ret;
rcu_nocb_lock_irqsave(rdp, flags); if (!rcu_nocb_need_deferred_wakeup(rdp)) { rcu_nocb_unlock_irqrestore(rdp, flags); - return; + return false; } ndw = READ_ONCE(rdp->nocb_defer_wakeup); WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT); - wake_nocb_gp(rdp, ndw == RCU_NOCB_WAKE_FORCE, flags); + ret = wake_nocb_gp(rdp, ndw == RCU_NOCB_WAKE_FORCE, flags); trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("DeferredWake")); + + return ret; }
/* Do a deferred wakeup of rcu_nocb_kthread() from a timer handler. */ @@ -2181,10 +2186,11 @@ static void do_nocb_deferred_wakeup_time * This means we do an inexact common-case check. Note that if * we miss, ->nocb_timer will eventually clean things up. */ -static void do_nocb_deferred_wakeup(struct rcu_data *rdp) +static bool do_nocb_deferred_wakeup(struct rcu_data *rdp) { if (rcu_nocb_need_deferred_wakeup(rdp)) - do_nocb_deferred_wakeup_common(rdp); + return do_nocb_deferred_wakeup_common(rdp); + return false; }
void rcu_nocb_flush_deferred_wakeup(void) @@ -2523,8 +2529,9 @@ static int rcu_nocb_need_deferred_wakeup return false; }
-static void do_nocb_deferred_wakeup(struct rcu_data *rdp) +static bool do_nocb_deferred_wakeup(struct rcu_data *rdp) { + return false; }
static void rcu_spawn_cpu_nocb_kthread(int cpu)
From: Frederic Weisbecker frederic@kernel.org
commit 47b8ff194c1fd73d58dc339b597d466fe48c8958 upstream.
Following the idle loop model, cleanly check for pending rcuog wakeup before the last rescheduling point on resuming to user mode. This way we can avoid to do it from rcu_user_enter() with the last resort self-IPI hack that enforces rescheduling.
Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-5-frederic@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/entry/common.c | 7 +++++++ kernel/rcu/tree.c | 12 +++++++----- 2 files changed, 14 insertions(+), 5 deletions(-)
--- a/kernel/entry/common.c +++ b/kernel/entry/common.c @@ -184,6 +184,10 @@ static unsigned long exit_to_user_mode_l * enabled above. */ local_irq_disable_exit_to_user(); + + /* Check if any of the above work has queued a deferred wakeup */ + rcu_nocb_flush_deferred_wakeup(); + ti_work = READ_ONCE(current_thread_info()->flags); }
@@ -197,6 +201,9 @@ static void exit_to_user_mode_prepare(st
lockdep_assert_irqs_disabled();
+ /* Flush pending rcuog wakeup before the last need_resched() check */ + rcu_nocb_flush_deferred_wakeup(); + if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK)) ti_work = exit_to_user_mode_loop(regs, ti_work);
--- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -707,13 +707,15 @@ noinstr void rcu_user_enter(void) lockdep_assert_irqs_disabled();
/* - * We may be past the last rescheduling opportunity in the entry code. - * Trigger a self IPI that will fire and reschedule once we resume to - * user/guest mode. + * Other than generic entry implementation, we may be past the last + * rescheduling opportunity in the entry code. Trigger a self IPI + * that will fire and reschedule once we resume in user/guest mode. */ instrumentation_begin(); - if (do_nocb_deferred_wakeup(rdp) && need_resched()) - irq_work_queue(this_cpu_ptr(&late_wakeup_work)); + if (!IS_ENABLED(CONFIG_GENERIC_ENTRY) || (current->flags & PF_VCPU)) { + if (do_nocb_deferred_wakeup(rdp) && need_resched()) + irq_work_queue(this_cpu_ptr(&late_wakeup_work)); + } instrumentation_end();
rcu_eqs_enter(true);
From: Frederic Weisbecker frederic@kernel.org
commit 4ae7dc97f726ea95c58ac58af71cc034ad22d7de upstream.
Following the idle loop model, cleanly check for pending rcuog wakeup before the last rescheduling point upon resuming to guest mode. This way we can avoid to do it from rcu_user_enter() with the last resort self-IPI hack that enforces rescheduling.
Suggested-by: Peter Zijlstra peterz@infradead.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Ingo Molnar mingo@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-6-frederic@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/x86.c | 1 + include/linux/entry-kvm.h | 14 ++++++++++++++ kernel/rcu/tree.c | 44 ++++++++++++++++++++++++++++++++++---------- kernel/rcu/tree_plugin.h | 1 + 4 files changed, 50 insertions(+), 10 deletions(-)
--- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1782,6 +1782,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr);
bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu) { + xfer_to_guest_mode_prepare(); return vcpu->mode == EXITING_GUEST_MODE || kvm_request_pending(vcpu) || xfer_to_guest_mode_work_pending(); } --- a/include/linux/entry-kvm.h +++ b/include/linux/entry-kvm.h @@ -47,6 +47,20 @@ static inline int arch_xfer_to_guest_mod int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu);
/** + * xfer_to_guest_mode_prepare - Perform last minute preparation work that + * need to be handled while IRQs are disabled + * upon entering to guest. + * + * Has to be invoked with interrupts disabled before the last call + * to xfer_to_guest_mode_work_pending(). + */ +static inline void xfer_to_guest_mode_prepare(void) +{ + lockdep_assert_irqs_disabled(); + rcu_nocb_flush_deferred_wakeup(); +} + +/** * __xfer_to_guest_mode_work_pending - Check if work is pending * * Returns: True if work pending, False otherwise. --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -678,9 +678,10 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter);
#ifdef CONFIG_NO_HZ_FULL
+#if !defined(CONFIG_GENERIC_ENTRY) || !defined(CONFIG_KVM_XFER_TO_GUEST_WORK) /* * An empty function that will trigger a reschedule on - * IRQ tail once IRQs get re-enabled on userspace resume. + * IRQ tail once IRQs get re-enabled on userspace/guest resume. */ static void late_wakeup_func(struct irq_work *work) { @@ -689,6 +690,37 @@ static void late_wakeup_func(struct irq_ static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) = IRQ_WORK_INIT(late_wakeup_func);
+/* + * If either: + * + * 1) the task is about to enter in guest mode and $ARCH doesn't support KVM generic work + * 2) the task is about to enter in user mode and $ARCH doesn't support generic entry. + * + * In these cases the late RCU wake ups aren't supported in the resched loops and our + * last resort is to fire a local irq_work that will trigger a reschedule once IRQs + * get re-enabled again. + */ +noinstr static void rcu_irq_work_resched(void) +{ + struct rcu_data *rdp = this_cpu_ptr(&rcu_data); + + if (IS_ENABLED(CONFIG_GENERIC_ENTRY) && !(current->flags & PF_VCPU)) + return; + + if (IS_ENABLED(CONFIG_KVM_XFER_TO_GUEST_WORK) && (current->flags & PF_VCPU)) + return; + + instrumentation_begin(); + if (do_nocb_deferred_wakeup(rdp) && need_resched()) { + irq_work_queue(this_cpu_ptr(&late_wakeup_work)); + } + instrumentation_end(); +} + +#else +static inline void rcu_irq_work_resched(void) { } +#endif + /** * rcu_user_enter - inform RCU that we are resuming userspace. * @@ -702,8 +734,6 @@ static DEFINE_PER_CPU(struct irq_work, l */ noinstr void rcu_user_enter(void) { - struct rcu_data *rdp = this_cpu_ptr(&rcu_data); - lockdep_assert_irqs_disabled();
/* @@ -711,13 +741,7 @@ noinstr void rcu_user_enter(void) * rescheduling opportunity in the entry code. Trigger a self IPI * that will fire and reschedule once we resume in user/guest mode. */ - instrumentation_begin(); - if (!IS_ENABLED(CONFIG_GENERIC_ENTRY) || (current->flags & PF_VCPU)) { - if (do_nocb_deferred_wakeup(rdp) && need_resched()) - irq_work_queue(this_cpu_ptr(&late_wakeup_work)); - } - instrumentation_end(); - + rcu_irq_work_resched(); rcu_eqs_enter(true); }
--- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -2197,6 +2197,7 @@ void rcu_nocb_flush_deferred_wakeup(void { do_nocb_deferred_wakeup(this_cpu_ptr(&rcu_data)); } +EXPORT_SYMBOL_GPL(rcu_nocb_flush_deferred_wakeup);
void __init rcu_init_nohz(void) {
From: Masami Hiramatsu mhiramat@kernel.org
commit c85c9a2c6e368dc94907e63babb18a9788e5c9b6 upstream.
Commit 36dadef23fcc ("kprobes: Init kprobes in early_initcall") moved the kprobe setup in early_initcall(), which includes kprobe jump optimization. The kprobes jump optimizer involves synchronize_rcu_tasks() which depends on the ksoftirqd and rcu_spawn_tasks_*(). However, since those are setup in core_initcall(), kprobes jump optimizer can not run at the early_initcall().
To avoid this issue, make the kprobe optimization disabled in the early_initcall() and enables it in subsys_initcall().
Note that non-optimized kprobes is still available after early_initcall(). Only jump optimization is delayed.
Link: https://lkml.kernel.org/r/161365856280.719838.12423085451287256713.stgit@dev...
Fixes: 36dadef23fcc ("kprobes: Init kprobes in early_initcall") Cc: Ingo Molnar mingo@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Thomas Gleixner tglx@linutronix.de Cc: RCU rcu@vger.kernel.org Cc: Michael Ellerman mpe@ellerman.id.au Cc: Andrew Morton akpm@linux-foundation.org Cc: Daniel Axtens dja@axtens.net Cc: Frederic Weisbecker frederic@kernel.org Cc: Neeraj Upadhyay neeraju@codeaurora.org Cc: Joel Fernandes joel@joelfernandes.org Cc: Michal Hocko mhocko@suse.com Cc: "Theodore Y . Ts'o" tytso@mit.edu Cc: Oleksiy Avramchenko oleksiy.avramchenko@sonymobile.com Cc: stable@vger.kernel.org Reported-by: Paul E. McKenney paulmck@kernel.org Reported-by: Sebastian Andrzej Siewior bigeasy@linutronix.de Reported-by: Uladzislau Rezki urezki@gmail.com Acked-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Signed-off-by: Steven Rostedt (VMware) rostedt@goodmis.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/kprobes.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
--- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -861,7 +861,6 @@ out: cpus_read_unlock(); }
-#ifdef CONFIG_SYSCTL static void optimize_all_kprobes(void) { struct hlist_head *head; @@ -887,6 +886,7 @@ out: mutex_unlock(&kprobe_mutex); }
+#ifdef CONFIG_SYSCTL static void unoptimize_all_kprobes(void) { struct hlist_head *head; @@ -2497,18 +2497,14 @@ static int __init init_kprobes(void) } }
-#if defined(CONFIG_OPTPROBES) -#if defined(__ARCH_WANT_KPROBES_INSN_SLOT) - /* Init kprobe_optinsn_slots */ - kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE; -#endif - /* By default, kprobes can be optimized */ - kprobes_allow_optimization = true; -#endif - /* By default, kprobes are armed */ kprobes_all_disarmed = false;
+#if defined(CONFIG_OPTPROBES) && defined(__ARCH_WANT_KPROBES_INSN_SLOT) + /* Init kprobe_optinsn_slots for allocation */ + kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE; +#endif + err = arch_init_kprobes(); if (!err) err = register_die_notifier(&kprobe_exceptions_nb); @@ -2523,6 +2519,21 @@ static int __init init_kprobes(void) } early_initcall(init_kprobes);
+#if defined(CONFIG_OPTPROBES) +static int __init init_optprobes(void) +{ + /* + * Enable kprobe optimization - this kicks the optimizer which + * depends on synchronize_rcu_tasks() and ksoftirqd, that is + * not spawned in early initcall. So delay the optimization. + */ + optimize_all_kprobes(); + + return 0; +} +subsys_initcall(init_optprobes); +#endif + #ifdef CONFIG_DEBUG_FS static void report_probe(struct seq_file *pi, struct kprobe *p, const char *sym, int offset, char *modname, struct kprobe *pp)
From: Suzuki K Poulose suzuki.poulose@arm.com
commit c0b15c25d25171db4b70cc0b7dbc1130ee94017d upstream.
The erratum 1024718 affects Cortex-A55 r0p0 to r2p0. However we apply the work around for r0p0 - r1p0. Unfortunately this won't be fixed for the future revisions for the CPU. Thus extend the work around for all versions of A55, to cover for r2p0 and any future revisions.
Cc: stable@vger.kernel.org Cc: Catalin Marinas catalin.marinas@arm.com Cc: Will Deacon will@kernel.org Cc: James Morse james.morse@arm.com Cc: Kunihiko Hayashi hayashi.kunihiko@socionext.com Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Link: https://lore.kernel.org/r/20210203230057.3961239-1-suzuki.poulose@arm.com [will: Update Kconfig help text] Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/Kconfig | 2 +- arch/arm64/kernel/cpufeature.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -522,7 +522,7 @@ config ARM64_ERRATUM_1024718 help This option adds a workaround for ARM Cortex-A55 Erratum 1024718.
- Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect + Affected Cortex-A55 cores (all revisions) could cause incorrect update of the hardware dirty bit when the DBM/AP bits are updated without a break-before-make. The workaround is to disable the usage of hardware DBM locally on the affected cores. CPUs not affected by --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1455,7 +1455,7 @@ static bool cpu_has_broken_dbm(void) /* List of CPUs which have broken DBM support. */ static const struct midr_range cpus[] = { #ifdef CONFIG_ARM64_ERRATUM_1024718 - MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0), // A55 r0p0 -r1p0 + MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), /* Kryo4xx Silver (rdpe => r1p0) */ MIDR_REV(MIDR_QCOM_KRYO_4XX_SILVER, 0xd, 0xe), #endif
From: Isaac J. Manjarres isaacm@codeaurora.org
commit dead723e6f049e9fb6b05e5b93456982798ea961 upstream.
When extracting the mask for a SMR that was programmed by the bootloader, the SMR's valid bit is also extracted and is treated as part of the mask, which is not correct. Consider the scenario where an SMMU master whose context is determined by a bootloader programmed SMR is removed (omitting parts of device/driver core):
->iommu_release_device() -> arm_smmu_release_device() -> arm_smmu_master_free_smes() -> arm_smmu_free_sme() /* Assume that the SME is now free */ -> arm_smmu_write_sme() -> arm_smmu_write_smr() /* Construct SMR value using mask and SID */
Since the valid bit was considered as part of the mask, the SMR will be programmed as valid.
Fix the SMR mask extraction step for bootloader programmed SMRs by masking out the valid bit when we know that we're already working with a valid SMR.
Fixes: 07a7f2caaa5a ("iommu/arm-smmu-qcom: Read back stream mappings") Signed-off-by: Isaac J. Manjarres isaacm@codeaurora.org Cc: stable@vger.kernel.org Reviewed-by: Robin Murphy robin.murphy@arm.com Link: https://lore.kernel.org/r/1611611545-19055-1-git-send-email-isaacm@codeauror... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -206,6 +206,8 @@ static int qcom_smmu_cfg_probe(struct ar smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) { + /* Ignore valid bit for SMR mask extraction. */ + smr &= ~ARM_SMMU_SMR_VALID; smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr); smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr); smmu->smrs[i].valid = true;
From: Viresh Kumar viresh.kumar@linaro.org
commit 6b50df2b8c208a04d44b8df5b7baaf668ceb8fc3 upstream.
It is possible that 'data' passed to kfree() is set to a error value instead of allocated space. Make sure it doesn't get called with invalid pointer.
Fixes: 5a6338cce9f4 ("mailbox: arm_mhuv2: Add driver") Cc: v5.11 stable@vger.kernel.org # v5.11 Reported-by: kernel test robot lkp@intel.com Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Jassi Brar jaswinder.singh@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mailbox/arm_mhuv2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/mailbox/arm_mhuv2.c +++ b/drivers/mailbox/arm_mhuv2.c @@ -699,7 +699,9 @@ static irqreturn_t mhuv2_receiver_interr ret = IRQ_HANDLED; }
- kfree(data); + if (!IS_ERR(data)) + kfree(data); + return ret; }
From: qiuguorui1 qiuguorui1@huawei.com
commit 656d1d58d8e0958d372db86c24f0b2ea36f50888 upstream.
in function create_dtb(), if fdt_open_into() fails, we need to vfree buf before return.
Fixes: 52b2a8af7436 ("arm64: kexec_file: load initrd and device-tree") Cc: stable@vger.kernel.org # v5.0 Signed-off-by: qiuguorui1 qiuguorui1@huawei.com Link: https://lore.kernel.org/r/20210218125900.6810-1-qiuguorui1@huawei.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/kernel/machine_kexec_file.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -182,8 +182,10 @@ static int create_dtb(struct kimage *ima
/* duplicate a device tree blob */ ret = fdt_open_into(initial_boot_params, buf, buf_size); - if (ret) + if (ret) { + vfree(buf); return -EINVAL; + }
ret = setup_dtb(image, initrd_load_addr, initrd_len, cmdline, buf);
From: He Zhe zhe.he@windriver.com
commit d47422d953e258ad587b5edf2274eb95d08bdc7d upstream.
As stated in linux/errno.h, ENOTSUPP should never be seen by user programs. When we set up uprobe with 32-bit perf and arm64 kernel, we would see the following vague error without useful hint.
The sys_perf_event_open() syscall returned with 524 (INTERNAL ERROR: strerror_r(524, [buf], 128)=22)
Use EOPNOTSUPP instead to indicate such cases.
Signed-off-by: He Zhe zhe.he@windriver.com Link: https://lore.kernel.org/r/20210223082535.48730-1-zhe.he@windriver.com Cc: stable@vger.kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/kernel/probes/uprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm64/kernel/probes/uprobes.c +++ b/arch/arm64/kernel/probes/uprobes.c @@ -38,7 +38,7 @@ int arch_uprobe_analyze_insn(struct arch
/* TODO: Currently we do not support AARCH32 instruction probing */ if (mm->context.flags & MMCF_AARCH32) - return -ENOTSUPP; + return -EOPNOTSUPP; else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) return -EINVAL;
From: Shaoying Xu shaoyi@amazon.com
commit f5c6d0fcf90ce07ee0d686d465b19b247ebd5ed7 upstream.
These plt* and .text.ftrace_trampoline sections specified for arm64 have non-zero addressses. Non-zero section addresses in a relocatable ELF would confuse GDB when it tries to compute the section offsets and it ends up printing wrong symbol addresses. Therefore, set them to zero, which mirrors the change in commit 5d8591bc0fba ("module: set ksymtab/kcrctab* section addresses to 0x0").
Reported-by: Frank van der Linden fllinden@amazon.com Signed-off-by: Shaoying Xu shaoyi@amazon.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210216183234.GA23876@amazon.com Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/include/asm/module.lds.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/arm64/include/asm/module.lds.h +++ b/arch/arm64/include/asm/module.lds.h @@ -1,7 +1,7 @@ #ifdef CONFIG_ARM64_MODULE_PLTS SECTIONS { - .plt (NOLOAD) : { BYTE(0) } - .init.plt (NOLOAD) : { BYTE(0) } - .text.ftrace_trampoline (NOLOAD) : { BYTE(0) } + .plt 0 (NOLOAD) : { BYTE(0) } + .init.plt 0 (NOLOAD) : { BYTE(0) } + .text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) } } #endif
From: Will Deacon will@kernel.org
commit a2c42bbabbe260b7626d8459093631a6e16ee0ee upstream.
The Spectre-v4 workaround is re-configured when resuming from suspend, as the firmware may have re-enabled the mitigation despite the user previously asking for it to be disabled.
Enabling or disabling the workaround can result in an undefined instruction exception on CPUs which implement PSTATE.SSBS but only allow it to be configured by adjusting the SPSR on exception return. We handle this by installing an 'undef hook' which effectively emulates the access.
Installing this hook requires us to take a couple of spinlocks both to avoid corrupting the internal list of hooks but also to ensure that we don't run into an unhandled exception. Unfortunately, when resuming from suspend, we haven't yet called rcu_idle_exit() and so lockdep gets angry about "suspicious RCU usage". In doing so, it tries to print a warning, which leads it to get even more suspicious, this time about itself:
| rcu_scheduler_active = 2, debug_locks = 1 | RCU used illegally from extended quiescent state! | 1 lock held by swapper/0: | #0: (logbuf_lock){-.-.}-{2:2}, at: vprintk_emit+0x88/0x198 | | Call trace: | dump_backtrace+0x0/0x1d8 | show_stack+0x18/0x24 | dump_stack+0xe0/0x17c | lockdep_rcu_suspicious+0x11c/0x134 | trace_lock_release+0xa0/0x160 | lock_release+0x3c/0x290 | _raw_spin_unlock+0x44/0x80 | vprintk_emit+0xbc/0x198 | vprintk_default+0x44/0x6c | vprintk_func+0x1f4/0x1fc | printk+0x54/0x7c | lockdep_rcu_suspicious+0x30/0x134 | trace_lock_acquire+0xa0/0x188 | lock_acquire+0x50/0x2fc | _raw_spin_lock+0x68/0x80 | spectre_v4_enable_mitigation+0xa8/0x30c | __cpu_suspend_exit+0xd4/0x1a8 | cpu_suspend+0xa0/0x104 | psci_cpu_suspend_enter+0x3c/0x5c | psci_enter_idle_state+0x44/0x74 | cpuidle_enter_state+0x148/0x2f8 | cpuidle_enter+0x38/0x50 | do_idle+0x1f0/0x2b4
Prevent these splats by running __cpu_suspend_exit() with RCU watching.
Cc: Mark Rutland mark.rutland@arm.com Cc: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Boqun Feng boqun.feng@gmail.com Cc: Marc Zyngier maz@kernel.org Cc: Saravana Kannan saravanak@google.com Suggested-by: "Paul E . McKenney" paulmck@kernel.org Reported-by: Sami Tolvanen samitolvanen@google.com Fixes: c28762070ca6 ("arm64: Rewrite Spectre-v4 mitigation code") Cc: stable@vger.kernel.org Acked-by: Paul E. McKenney paulmck@kernel.org Acked-by: Marc Zyngier maz@kernel.org Acked-by: Mark Rutland mark.rutland@arm.com Link: https://lore.kernel.org/r/20210218140346.5224-1-will@kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/kernel/suspend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c @@ -119,7 +119,7 @@ int cpu_suspend(unsigned long arg, int ( if (!ret) ret = -EOPNOTSUPP; } else { - __cpu_suspend_exit(); + RCU_NONIDLE(__cpu_suspend_exit()); }
unpause_graph_tracing();
From: Tobias Klauser tklauser@distanz.ch
commit f3d60f2a25e4417e1676161fe42115de3e3f98a2 upstream.
We use the generic C VDSO implementations of a handful of clock-related functions. When kasan is enabled this results in asan stub calls that are unlikely to be resolved by userspace, this just disables KASAN when building the VDSO.
Verified the fix on a kernel with KASAN enabled using vDSO selftests.
Link: https://lore.kernel.org/lkml/CACT4Y+ZNJBnkKHXUf=tm_yuowvZvHwN=0rmJ=7J+xFd+9r... Tested-by: Tobias Klauser tklauser@distanz.ch Signed-off-by: Tobias Klauser tklauser@distanz.ch Tested-by: Dmitry Vyukov dvyukov@google.com [Palmer: commit text] Fixes: ad5d1122b82f ("riscv: use vDSO common flow to reduce the latency of the time-related functions") Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt palmerdabbelt@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/riscv/kernel/vdso/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile @@ -32,9 +32,10 @@ CPPFLAGS_vdso.lds += -P -C -U$(ARCH) # Disable -pg to prevent insert call site CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os
-# Disable gcov profiling for VDSO code +# Disable profiling and instrumentation for VDSO code GCOV_PROFILE := n KCOV_INSTRUMENT := n +KASAN_SANITIZE := n
# Force dependency $(obj)/vdso.o: $(obj)/vdso.so
From: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org
commit a4f3407c41605d14f09e490045d0609990cd5d94 upstream.
As per register documentation, QCOM_WDT_ENABLE_IRQ which is BIT(1) of watchdog control register is wakeup interrupt enable bit and not related to bark interrupt at all, BIT(0) is used for that. So remove incorrect usage of this bit when supporting bark irq for pre-timeout notification. Currently with this bit set and bark interrupt specified, pre-timeout notification and/or watchdog reset/bite does not occur.
Fixes: 36375491a439 ("watchdog: qcom: support pre-timeout when the bark irq is available") Cc: stable@vger.kernel.org Signed-off-by: Sai Prakash Ranjan saiprakash.ranjan@codeaurora.org Reviewed-by: Guenter Roeck linux@roeck-us.net Reviewed-by: Stephen Boyd swboyd@chromium.org Link: https://lore.kernel.org/r/20210126150241.10009-1-saiprakash.ranjan@codeauror... Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Wim Van Sebroeck wim@linux-watchdog.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/watchdog/qcom-wdt.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)
--- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -22,7 +22,6 @@ enum wdt_reg { };
#define QCOM_WDT_ENABLE BIT(0) -#define QCOM_WDT_ENABLE_IRQ BIT(1)
static const u32 reg_offset_data_apcs_tmr[] = { [WDT_RST] = 0x38, @@ -63,16 +62,6 @@ struct qcom_wdt *to_qcom_wdt(struct watc return container_of(wdd, struct qcom_wdt, wdd); }
-static inline int qcom_get_enable(struct watchdog_device *wdd) -{ - int enable = QCOM_WDT_ENABLE; - - if (wdd->pretimeout) - enable |= QCOM_WDT_ENABLE_IRQ; - - return enable; -} - static irqreturn_t qcom_wdt_isr(int irq, void *arg) { struct watchdog_device *wdd = arg; @@ -91,7 +80,7 @@ static int qcom_wdt_start(struct watchdo writel(1, wdt_addr(wdt, WDT_RST)); writel(bark * wdt->rate, wdt_addr(wdt, WDT_BARK_TIME)); writel(wdd->timeout * wdt->rate, wdt_addr(wdt, WDT_BITE_TIME)); - writel(qcom_get_enable(wdd), wdt_addr(wdt, WDT_EN)); + writel(QCOM_WDT_ENABLE, wdt_addr(wdt, WDT_EN)); return 0; }
From: Alexander Usyskin alexander.usyskin@intel.com
commit 740c0a57b8f1e36301218bf549f3c9cc833a60be upstream.
The MEI bus has a special behavior on suspend it destroys all the attached devices, this is due to the fact that also firmware context is not persistent across power flows.
If watchdog on MEI bus is ticking before suspending the firmware times out and reports that the OS is missing watchdog tick. Send the stop command to the firmware on watchdog unregistered to eliminate the false event on suspend. This does not make the things worse from the user-space perspective as a user-space should re-open watchdog device after suspending before this patch.
Cc: stable@vger.kernel.org Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Reviewed-by: Guenter Roeck linux@roeck-us.net Link: https://lore.kernel.org/r/20210124114938.373885-1-tomas.winkler@intel.com Signed-off-by: Guenter Roeck linux@roeck-us.net Signed-off-by: Wim Van Sebroeck wim@linux-watchdog.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/watchdog/mei_wdt.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -382,6 +382,7 @@ static int mei_wdt_register(struct mei_w
watchdog_set_drvdata(&wdt->wdd, wdt); watchdog_stop_on_reboot(&wdt->wdd); + watchdog_stop_on_unregister(&wdt->wdd);
ret = watchdog_register_device(&wdt->wdd); if (ret)
From: Suzuki K Poulose suzuki.poulose@arm.com
commit f72896063396b0cb205cbf0fd76ec6ab3ca11c8a upstream.
TRCSTALLCTLR register is only implemented if
TRCIDR3.STALLCTL == 0b1
Make sure the driver touches the register only it is implemented.
Link: https://lore.kernel.org/r/20210127184617.3684379-1-suzuki.poulose@arm.com Cc: stable@vger.kernel.org Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Cc: Leo Yan leo.yan@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Signed-off-by: Mathieu Poirier mathieu.poirier@linaro.org Link: https://lore.kernel.org/r/20210201181351.1475223-32-mathieu.poirier@linaro.o... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/hwtracing/coresight/coresight-etm4x-core.c | 9 ++++++--- drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -226,7 +226,8 @@ static int etm4_enable_hw(struct etmv4_d writel_relaxed(0x0, drvdata->base + TRCAUXCTLR); writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R); writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R); - writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR); + if (drvdata->stallctl) + writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR); writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR); writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR); writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR); @@ -1288,7 +1289,8 @@ static int etm4_cpu_save(struct etmv4_dr state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR); state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R); state->trceventctl1r = readl(drvdata->base + TRCEVENTCTL1R); - state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR); + if (drvdata->stallctl) + state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR); state->trctsctlr = readl(drvdata->base + TRCTSCTLR); state->trcsyncpr = readl(drvdata->base + TRCSYNCPR); state->trcccctlr = readl(drvdata->base + TRCCCCTLR); @@ -1398,7 +1400,8 @@ static void etm4_cpu_restore(struct etmv writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR); writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R); writel_relaxed(state->trceventctl1r, drvdata->base + TRCEVENTCTL1R); - writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR); + if (drvdata->stallctl) + writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR); writel_relaxed(state->trctsctlr, drvdata->base + TRCTSCTLR); writel_relaxed(state->trcsyncpr, drvdata->base + TRCSYNCPR); writel_relaxed(state->trcccctlr, drvdata->base + TRCCCCTLR); --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -389,7 +389,7 @@ static ssize_t mode_store(struct device config->eventctrl1 &= ~BIT(12);
/* bit[8], Instruction stall bit */ - if (config->mode & ETM_MODE_ISTALL_EN) + if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl == true)) config->stall_ctrl |= BIT(8); else config->stall_ctrl &= ~BIT(8);
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
commit 9166f4af32db74e1544a2149aef231ff24515ea3 upstream.
The place of spi_nor_region_mark_end() must be moved, because 'i' is re-used for the index of erase[].
Fixes: b038e8e3be72 ("mtd: spi-nor: parse SFDP Sector Map Parameter Table") Cc: stable@vger.kernel.org Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com [ta: Add Fixes tag and Cc to stable] Signed-off-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/02ce8d84b7989ebee33382f6494df53778dd508e.160161287... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/sfdp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -858,6 +858,7 @@ spi_nor_init_non_uniform_erase_map(struc offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + region[i].size; } + spi_nor_region_mark_end(®ion[i - 1]);
save_uniform_erase_type = map->uniform_erase_type; map->uniform_erase_type = spi_nor_sort_erase_mask(map, @@ -881,8 +882,6 @@ spi_nor_init_non_uniform_erase_map(struc if (!(regions_erase_type & BIT(erase[i].idx))) spi_nor_set_erase_type(&erase[i], 0, 0xFF);
- spi_nor_region_mark_end(®ion[i - 1]); - return 0; }
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
commit abdf5a5ef9652bad4d58058bc22ddf23543ba3e1 upstream.
At the time spi_nor_region_check_overlay() is called, the erase types are sorted in ascending order of erase size. The 'erase_type' should be masked with 'BIT(erase[i].idx)' instead of 'BIT(i)'.
Fixes: b038e8e3be72 ("mtd: spi-nor: parse SFDP Sector Map Parameter Table") Cc: stable@vger.kernel.org Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com [ta: Add Fixes tag and Cc to stable] Signed-off-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/fd90c40d5b626a1319a78fc2bcee79a8871d4d57.160161287... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/sfdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -788,7 +788,7 @@ spi_nor_region_check_overlay(struct spi_ int i;
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { - if (!(erase_type & BIT(i))) + if (!(erase[i].size && erase_type & BIT(erase[i].idx))) continue; if (region->size & erase[i].size_mask) { spi_nor_region_mark_overlay(region);
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
commit 969b276718de37dfe66fce3a5633f611e8cd58fd upstream.
In case of overlaid regions in which their biggest erase size command overpasses in size the region's size, only the non-overlaid portion of the sector gets erased. For example, if a Sector Erase command is applied to a 256-kB range that is overlaid by 4-kB sectors, the overlaid 4-kB sectors are not affected by the erase. For overlaid regions, 'region->size' is assigned to 'cmd->size' later in spi_nor_init_erase_cmd(), so 'erase->size' can be greater than 'len'.
Fixes: 5390a8df769e ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories") Cc: stable@vger.kernel.org Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com [ta: Update commit description, add Fixes tag and Cc to stable] Signed-off-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/fa5d8b944a5cca488ac54ba37c95e775ac2deb34.160161287... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1364,14 +1364,15 @@ spi_nor_find_best_erase_type(const struc
erase = &map->erase_type[i];
+ /* Alignment is not mandatory for overlaid regions */ + if (region->offset & SNOR_OVERLAID_REGION && + region->size <= len) + return erase; + /* Don't erase more than what the user has asked for. */ if (erase->size > len) continue;
- /* Alignment is not mandatory for overlaid regions */ - if (region->offset & SNOR_OVERLAID_REGION) - return erase; - spi_nor_div_by_erase_size(erase, addr, &rem); if (rem) continue;
From: Takahiro Kuwano Takahiro.Kuwano@infineon.com
commit 58fa22f68fcaff20ce4d08a6adffa64f65ccd37d upstream.
Even if erase type is same as previous region, erase size can be different if the previous region is overlaid region. Since 'region->size' is assigned to 'cmd->size' for overlaid region, comparing 'erase->size' and 'cmd->size' can detect previous overlaid region.
Fixes: 5390a8df769e ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories") Cc: stable@vger.kernel.org Signed-off-by: Takahiro Kuwano Takahiro.Kuwano@infineon.com [ta: Add Fixes tag and Cc to stable] Signed-off-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/13d47e8d8991b8a7fd8cc7b9e2a5319c56df35cc.160161287... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/core.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1516,6 +1516,7 @@ static int spi_nor_init_erase_cmd_list(s goto destroy_erase_cmd_list;
if (prev_erase != erase || + erase->size != cmd->size || region->offset & SNOR_OVERLAID_REGION) { cmd = spi_nor_init_erase_cmd(region, erase); if (IS_ERR(cmd)) {
From: Pan Bian bianpan2016@163.com
commit fe6653460ee7a7dbe0cd5fd322992af862ce5ab0 upstream.
Put the child node np when it fails to get or register device.
Fixes: e523f11141bd ("mtd: spi-nor: add hisilicon spi-nor flash controller driver") Cc: stable@vger.kernel.org Signed-off-by: Pan Bian bianpan2016@163.com [ta: Add Fixes tag and Cc stable] Signed-off-by: Tudor Ambarus tudor.ambarus@microchip.com Link: https://lore.kernel.org/r/20210121091847.85362-1-bianpan2016@163.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/mtd/spi-nor/controllers/hisi-sfc.c +++ b/drivers/mtd/spi-nor/controllers/hisi-sfc.c @@ -399,8 +399,10 @@ static int hisi_spi_nor_register_all(str
for_each_available_child_of_node(dev->of_node, np) { ret = hisi_spi_nor_register(np, host); - if (ret) + if (ret) { + of_node_put(np); goto fail; + }
if (host->num_chip == HIFMC_MAX_CHIP_NUM) { dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n");
From: Pan Bian bianpan2016@163.com
commit 70779b897395b330ba5a47bed84f94178da599f9 upstream.
The reference count of the old buffer head should be decremented on path that fails to get the new buffer head.
Fixes: 6b4657667ba0 ("fs/affs: add rename exchange") CC: stable@vger.kernel.org # 4.14+ Signed-off-by: Pan Bian bianpan2016@163.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/affs/namei.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -460,8 +460,10 @@ affs_xrename(struct inode *old_dir, stru return -EIO;
bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino); - if (!bh_new) + if (!bh_new) { + affs_brelse(bh_old); return -EIO; + }
/* Remove old header from its parent directory. */ affs_lock_dir(old_dir);
From: NeilBrown neilb@suse.de
commit b3656d8227f4c45812c6b40815d8f4e446ed372a upstream.
Patch series "Fix some seq_file users that were recently broken".
A recent change to seq_file broke some users which were using seq_file in a non-"standard" way ... though the "standard" isn't documented, so they can be excused. The result is a possible leak - of memory in one case, of references to a 'transport' in the other.
These three patches: 1/ document and explain the problem 2/ fix the problem user in x86 3/ fix the problem user in net/sctp
This patch (of 3):
Users of seq_file will sometimes find it convenient to take a resource, such as a lock or memory allocation, in the ->start or ->next operations. These are per-entry resources, distinct from per-session resources which are taken in ->start and released in ->stop.
The preferred management of these is release the resource on the subsequent call to ->next or ->stop.
However prior to Commit 1f4aace60b0e ("fs/seq_file.c: simplify seq_file iteration code and interface") it happened that ->show would always be called after ->start or ->next, and a few users chose to release the resource in ->show.
This is no longer reliable. Since the mentioned commit, ->next will always come after a successful ->show (to ensure m->index is updated correctly), so the original ordering cannot be maintained.
This patch updates the documentation to clearly state the required behaviour. Other patches will fix the few problematic users.
[akpm@linux-foundation.org: fix typo, per Willy]
Link: https://lkml.kernel.org/r/161248518659.21478.2484341937387294998.stgit@noble... Link: https://lkml.kernel.org/r/161248539020.21478.3147971477400875336.stgit@noble... Fixes: 1f4aace60b0e ("fs/seq_file.c: simplify seq_file iteration code and interface") Signed-off-by: NeilBrown neilb@suse.de Cc: Xin Long lucien.xin@gmail.com Cc: Alexander Viro viro@zeniv.linux.org.uk Cc: Jonathan Corbet corbet@lwn.net Cc: Ingo Molnar mingo@redhat.com Cc: Dave Hansen dave.hansen@linux.intel.com Cc: Andy Lutomirski luto@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Vlad Yasevich vyasevich@gmail.com Cc: Neil Horman nhorman@tuxdriver.com Cc: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Cc: "David S. Miller" davem@davemloft.net Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/filesystems/seq_file.rst | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/Documentation/filesystems/seq_file.rst +++ b/Documentation/filesystems/seq_file.rst @@ -217,6 +217,12 @@ between the calls to start() and stop(), is a reasonable thing to do. The seq_file code will also avoid taking any other locks while the iterator is active.
+The iterater value returned by start() or next() is guaranteed to be +passed to a subsequent next() or stop() call. This allows resources +such as locks that were taken to be reliably released. There is *no* +guarantee that the iterator will be passed to show(), though in practice +it often will be. +
Formatted output ================
From: NeilBrown neilb@suse.de
commit 3d2fc4c082448e9c05792f9b2a11c1d5db408b85 upstream.
The memtype seq_file iterator allocates a buffer in the ->start and ->next functions and frees it in the ->show function. The preferred handling for such resources is to free them in the subsequent ->next or ->stop function call.
Since Commit 1f4aace60b0e ("fs/seq_file.c: simplify seq_file iteration code and interface") there is no guarantee that ->show will be called after ->next, so this function can now leak memory.
So move the freeing of the buffer to ->next and ->stop.
Link: https://lkml.kernel.org/r/161248539022.21478.13874455485854739066.stgit@nobl... Fixes: 1f4aace60b0e ("fs/seq_file.c: simplify seq_file iteration code and interface") Signed-off-by: NeilBrown neilb@suse.de Cc: Xin Long lucien.xin@gmail.com Cc: Alexander Viro viro@zeniv.linux.org.uk Cc: Andy Lutomirski luto@kernel.org Cc: Dave Hansen dave.hansen@linux.intel.com Cc: "David S. Miller" davem@davemloft.net Cc: Ingo Molnar mingo@redhat.com Cc: Jonathan Corbet corbet@lwn.net Cc: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Cc: Neil Horman nhorman@tuxdriver.com Cc: Peter Zijlstra peterz@infradead.org Cc: Vlad Yasevich vyasevich@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/mm/pat/memtype.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/x86/mm/pat/memtype.c +++ b/arch/x86/mm/pat/memtype.c @@ -1164,12 +1164,14 @@ static void *memtype_seq_start(struct se
static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos) { + kfree(v); ++*pos; return memtype_get_idx(*pos); }
static void memtype_seq_stop(struct seq_file *seq, void *v) { + kfree(v); }
static int memtype_seq_show(struct seq_file *seq, void *v) @@ -1181,8 +1183,6 @@ static int memtype_seq_show(struct seq_f entry_print->end, cattr_name(entry_print->type));
- kfree(entry_print); - return 0; }
From: Muchun Song songmuchun@bytedance.com
commit cae3af62b33aa931427a0f211e04347b22180b36 upstream.
When pages are swapped in, the VM may retain the swap copy to avoid repeated writes in the future. It's also retained if shared pages are faulted back in some processes, but not in others. During that time we have an in-memory copy of the page, as well as an on-swap copy. Cgroup1 and cgroup2 handle these overlapping lifetimes slightly differently due to the nature of how they account memory and swap:
Cgroup1 has a unified memory+swap counter that tracks a data page regardless whether it's in-core or swapped out. On swapin, we transfer the charge from the swap entry to the newly allocated swapcache page, even though the swap entry might stick around for a while. That's why we have a mem_cgroup_uncharge_swap() call inside mem_cgroup_charge().
Cgroup2 tracks memory and swap as separate, independent resources and thus has split memory and swap counters. On swapin, we charge the newly allocated swapcache page as memory, while the swap slot in turn must remain charged to the swap counter as long as its allocated too.
The cgroup2 logic was broken by commit 2d1c498072de ("mm: memcontrol: make swap tracking an integral part of memory control"), because it accidentally removed the do_memsw_account() check in the branch inside mem_cgroup_uncharge() that was supposed to tell the difference between the charge transfer in cgroup1 and the separate counters in cgroup2.
As a result, cgroup2 currently undercounts retained swap to varying degrees: swap slots are cached up to 50% of the configured limit or total available swap space; partially faulted back shared pages are only limited by physical capacity. This in turn allows cgroups to significantly overconsume their alloted swap space.
Add the do_memsw_account() check back to fix this problem.
Link: https://lkml.kernel.org/r/20210217153237.92484-1-songmuchun@bytedance.com Fixes: 2d1c498072de ("mm: memcontrol: make swap tracking an integral part of memory control") Signed-off-by: Muchun Song songmuchun@bytedance.com Acked-by: Johannes Weiner hannes@cmpxchg.org Reviewed-by: Shakeel Butt shakeelb@google.com Acked-by: Michal Hocko mhocko@suse.com Cc: Vladimir Davydov vdavydov.dev@gmail.com Cc: stable@vger.kernel.org [5.8+] Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/memcontrol.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
--- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6758,7 +6758,19 @@ int mem_cgroup_charge(struct page *page, memcg_check_events(memcg, page); local_irq_enable();
- if (PageSwapCache(page)) { + /* + * Cgroup1's unified memory+swap counter has been charged with the + * new swapcache page, finish the transfer by uncharging the swap + * slot. The swap slot would also get uncharged when it dies, but + * it can stick around indefinitely and we'd count the page twice + * the entire time. + * + * Cgroup2 has separate resource counters for memory and swap, + * so this is a non-issue here. Memory and swap charge lifetimes + * correspond 1:1 to page and swap slot lifetimes: we charge the + * page to memory here, and uncharge swap when the slot is freed. + */ + if (do_memsw_account() && PageSwapCache(page)) { swp_entry_t entry = { .val = page_private(page) }; /* * The swap entry might not get freed for a long time,
From: Muchun Song songmuchun@bytedance.com
commit 1685bde6b9af55923180a76152036c7fb7176db0 upstream.
We use a global percpu int_active_memcg variable to store the remote memcg when we are in the interrupt context. But get_active_memcg always return the current->active_memcg or root_mem_cgroup. The remote memcg (set in the interrupt context) is ignored. This is not what we want. So fix it.
Link: https://lkml.kernel.org/r/20210223091101.42150-1-songmuchun@bytedance.com Fixes: 37d5985c003d ("mm: kmem: prepare remote memcg charging infra for interrupt contexts") Signed-off-by: Muchun Song songmuchun@bytedance.com Reviewed-by: Shakeel Butt shakeelb@google.com Reviewed-by: Roman Gushchin guro@fb.com Cc: Johannes Weiner hannes@cmpxchg.org Cc: Michal Hocko mhocko@kernel.org Cc: Vladimir Davydov vdavydov.dev@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/memcontrol.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
--- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1080,13 +1080,9 @@ static __always_inline struct mem_cgroup
rcu_read_lock(); memcg = active_memcg(); - if (memcg) { - /* current->active_memcg must hold a ref. */ - if (WARN_ON_ONCE(!css_tryget(&memcg->css))) - memcg = root_mem_cgroup; - else - memcg = current->active_memcg; - } + /* remote memcg must hold a ref. */ + if (memcg && WARN_ON_ONCE(!css_tryget(&memcg->css))) + memcg = root_mem_cgroup; rcu_read_unlock();
return memcg;
From: Mike Kravetz mike.kravetz@oracle.com
commit dbfee5aee7e54f83d96ceb8e3e80717fac62ad63 upstream.
page structs are not guaranteed to be contiguous for gigantic pages. The routine update_and_free_page can encounter a gigantic page, yet it assumes page structs are contiguous when setting page flags in subpages.
If update_and_free_page encounters non-contiguous page structs, we can see “BUG: Bad page state in process …” errors.
Non-contiguous page structs are generally not an issue. However, they can exist with a specific kernel configuration and hotplug operations. For example: Configure the kernel with CONFIG_SPARSEMEM and !CONFIG_SPARSEMEM_VMEMMAP. Then, hotplug add memory for the area where the gigantic page will be allocated. Zi Yan outlined steps to reproduce here [1].
[1] https://lore.kernel.org/linux-mm/16F7C58B-4D79-41C5-9B64-A1A1628F4AF2@nvidia...
Link: https://lkml.kernel.org/r/20210217184926.33567-1-mike.kravetz@oracle.com Fixes: 944d9fec8d7a ("hugetlb: add support for gigantic page allocation at runtime") Signed-off-by: Zi Yan ziy@nvidia.com Signed-off-by: Mike Kravetz mike.kravetz@oracle.com Cc: Zi Yan ziy@nvidia.com Cc: Davidlohr Bueso dbueso@suse.de Cc: "Kirill A . Shutemov" kirill.shutemov@linux.intel.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Matthew Wilcox willy@infradead.org Cc: Oscar Salvador osalvador@suse.de Cc: Joao Martins joao.m.martins@oracle.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/hugetlb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1312,14 +1312,16 @@ static inline void destroy_compound_giga static void update_and_free_page(struct hstate *h, struct page *page) { int i; + struct page *subpage = page;
if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) return;
h->nr_huge_pages--; h->nr_huge_pages_node[page_to_nid(page)]--; - for (i = 0; i < pages_per_huge_page(h); i++) { - page[i].flags &= ~(1 << PG_locked | 1 << PG_error | + for (i = 0; i < pages_per_huge_page(h); + i++, subpage = mem_map_next(subpage, page, i)) { + subpage->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | 1 << PG_dirty | 1 << PG_active | 1 << PG_private | 1 << PG_writeback);
From: Mike Kravetz mike.kravetz@oracle.com
commit 3272cfc2525b3a2810a59312d7a1e6f04a0ca3ef upstream.
page structs are not guaranteed to be contiguous for gigantic pages. The routine copy_huge_page_from_user can encounter gigantic pages, yet it assumes page structs are contiguous when copying pages from user space.
Since page structs for the target gigantic page are not contiguous, the data copied from user space could overwrite other pages not associated with the gigantic page and cause data corruption.
Non-contiguous page structs are generally not an issue. However, they can exist with a specific kernel configuration and hotplug operations. For example: Configure the kernel with CONFIG_SPARSEMEM and !CONFIG_SPARSEMEM_VMEMMAP. Then, hotplug add memory for the area where the gigantic page will be allocated.
Link: https://lkml.kernel.org/r/20210217184926.33567-2-mike.kravetz@oracle.com Fixes: 8fb5debc5fcd ("userfaultfd: hugetlbfs: add hugetlb_mcopy_atomic_pte for userfaultfd support") Signed-off-by: Mike Kravetz mike.kravetz@oracle.com Cc: Zi Yan ziy@nvidia.com Cc: Davidlohr Bueso dbueso@suse.de Cc: "Kirill A . Shutemov" kirill.shutemov@linux.intel.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Matthew Wilcox willy@infradead.org Cc: Oscar Salvador osalvador@suse.de Cc: Joao Martins joao.m.martins@oracle.com Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/memory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
--- a/mm/memory.c +++ b/mm/memory.c @@ -5204,17 +5204,19 @@ long copy_huge_page_from_user(struct pag void *page_kaddr; unsigned long i, rc = 0; unsigned long ret_val = pages_per_huge_page * PAGE_SIZE; + struct page *subpage = dst_page;
- for (i = 0; i < pages_per_huge_page; i++) { + for (i = 0; i < pages_per_huge_page; + i++, subpage = mem_map_next(subpage, dst_page, i)) { if (allow_pagefault) - page_kaddr = kmap(dst_page + i); + page_kaddr = kmap(subpage); else - page_kaddr = kmap_atomic(dst_page + i); + page_kaddr = kmap_atomic(subpage); rc = copy_from_user(page_kaddr, (const void __user *)(src + i * PAGE_SIZE), PAGE_SIZE); if (allow_pagefault) - kunmap(dst_page + i); + kunmap(subpage); else kunmap_atomic(page_kaddr);
From: Dave Hansen dave.hansen@linux.intel.com
commit 519983645a9f2ec339cabfa0c6ef7b09be985dd0 upstream.
I went to go add a new RECLAIM_* mode for the zone_reclaim_mode sysctl. Like a good kernel developer, I also went to go update the documentation. I noticed that the bits in the documentation didn't match the bits in the #defines.
The VM never explicitly checks the RECLAIM_ZONE bit. The bit is, however implicitly checked when checking 'node_reclaim_mode==0'. The RECLAIM_ZONE #define was removed in a cleanup. That, by itself is fine.
But, when the bit was removed (bit 0) the _other_ bit locations also got changed. That's not OK because the bit values are documented to mean one specific thing. Users surely do not expect the meaning to change from kernel to kernel.
The end result is that if someone had a script that did:
sysctl vm.zone_reclaim_mode=1
it would have gone from enabling node reclaim for clean unmapped pages to writing out pages during node reclaim after the commit in question. That's not great.
Put the bits back the way they were and add a comment so something like this is a bit harder to do again. Update the documentation to make it clear that the first bit is ignored.
Link: https://lkml.kernel.org/r/20210219172555.FF0CDF23@viggo.jf.intel.com Signed-off-by: Dave Hansen dave.hansen@linux.intel.com Fixes: 648b5cf368e0 ("mm/vmscan: remove unused RECLAIM_OFF/RECLAIM_ZONE") Reviewed-by: Ben Widawsky ben.widawsky@intel.com Reviewed-by: Oscar Salvador osalvador@suse.de Acked-by: David Rientjes rientjes@google.com Acked-by: Christoph Lameter cl@linux.com Cc: Alex Shi alex.shi@linux.alibaba.com Cc: Daniel Wagner dwagner@suse.de Cc: "Tobin C. Harding" tobin@kernel.org Cc: Christoph Lameter cl@linux.com Cc: Andrew Morton akpm@linux-foundation.org Cc: Huang Ying ying.huang@intel.com Cc: Dan Williams dan.j.williams@intel.com Cc: Qian Cai cai@lca.pw Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- Documentation/admin-guide/sysctl/vm.rst | 10 +++++----- mm/vmscan.c | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-)
--- a/Documentation/admin-guide/sysctl/vm.rst +++ b/Documentation/admin-guide/sysctl/vm.rst @@ -983,11 +983,11 @@ that benefit from having their data cach left disabled as the caching effect is likely to be more important than data locality.
-zone_reclaim may be enabled if it's known that the workload is partitioned -such that each partition fits within a NUMA node and that accessing remote -memory would cause a measurable performance reduction. The page allocator -will then reclaim easily reusable pages (those page cache pages that are -currently not used) before allocating off node pages. +Consider enabling one or more zone_reclaim mode bits if it's known that the +workload is partitioned such that each partition fits within a NUMA node +and that accessing remote memory would cause a measurable performance +reduction. The page allocator will take additional actions before +allocating off node pages.
Allowing zone reclaim to write out pages stops processes that are writing large amounts of data from dirtying pages on other nodes. Zone --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4095,8 +4095,13 @@ module_init(kswapd_init) */ int node_reclaim_mode __read_mostly;
-#define RECLAIM_WRITE (1<<0) /* Writeout pages during reclaim */ -#define RECLAIM_UNMAP (1<<1) /* Unmap pages during reclaim */ +/* + * These bit locations are exposed in the vm.zone_reclaim_mode sysctl + * ABI. New bits are OK, but existing bits can never change. + */ +#define RECLAIM_ZONE (1<<0) /* Run shrink_inactive_list on the zone */ +#define RECLAIM_WRITE (1<<1) /* Writeout pages during reclaim */ +#define RECLAIM_UNMAP (1<<2) /* Unmap pages during reclaim */
/* * Priority for NODE_RECLAIM. This determines the fraction of pages
From: Vlastimil Babka vbabka@suse.cz
commit 6e2b7044c199229a3d20cefbd3184968238c4184 upstream.
Compaction always operates on pages from a single given zone when isolating both pages to migrate and freepages. Pageblock boundaries are intersected with zone boundaries to be safe in case zone starts or ends in the middle of pageblock. The use of pageblock_pfn_to_page() protects against non-contiguous pageblocks.
The functions fast_isolate_freepages() and fast_isolate_around() don't currently protect the fast freepage isolation thoroughly enough against these corner cases, and can result in freepage isolation operate outside of zone boundaries:
- in fast_isolate_freepages() if we get a pfn from the first pageblock of a zone that starts in the middle of that pageblock, 'highest' can be a pfn outside of the zone.
If we fail to isolate anything in this function, we may then call fast_isolate_around() on a pfn outside of the zone and there effectively do a set_pageblock_skip(page_to_pfn(highest)) which may currently hit a VM_BUG_ON() in some configurations
- fast_isolate_around() checks only the zone end boundary and not beginning, nor that the pageblock is contiguous (with pageblock_pfn_to_page()) so it's possible that we end up calling isolate_freepages_block() on a range of pfn's from two different zones and end up e.g. isolating freepages under the wrong zone's lock.
This patch should fix the above issues.
Link: https://lkml.kernel.org/r/20210217173300.6394-1-vbabka@suse.cz Fixes: 5a811889de10 ("mm, compaction: use free lists to quickly locate a migration target") Signed-off-by: Vlastimil Babka vbabka@suse.cz Acked-by: David Rientjes rientjes@google.com Acked-by: Mel Gorman mgorman@techsingularity.net Cc: Andrea Arcangeli aarcange@redhat.com Cc: David Hildenbrand david@redhat.com Cc: Michal Hocko mhocko@kernel.org Cc: Mike Rapoport rppt@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/compaction.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
--- a/mm/compaction.c +++ b/mm/compaction.c @@ -1288,7 +1288,7 @@ static void fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long nr_isolated) { unsigned long start_pfn, end_pfn; - struct page *page = pfn_to_page(pfn); + struct page *page;
/* Do not search around if there are enough pages already */ if (cc->nr_freepages >= cc->nr_migratepages) @@ -1299,8 +1299,12 @@ fast_isolate_around(struct compact_contr return;
/* Pageblock boundaries */ - start_pfn = pageblock_start_pfn(pfn); - end_pfn = min(pageblock_end_pfn(pfn), zone_end_pfn(cc->zone)) - 1; + start_pfn = max(pageblock_start_pfn(pfn), cc->zone->zone_start_pfn); + end_pfn = min(pageblock_end_pfn(pfn), zone_end_pfn(cc->zone)); + + page = pageblock_pfn_to_page(start_pfn, end_pfn, cc->zone); + if (!page) + return;
/* Scan before */ if (start_pfn != pfn) { @@ -1402,7 +1406,8 @@ fast_isolate_freepages(struct compact_co pfn = page_to_pfn(freepage);
if (pfn >= highest) - highest = pageblock_start_pfn(pfn); + highest = max(pageblock_start_pfn(pfn), + cc->zone->zone_start_pfn);
if (pfn >= low_pfn) { cc->fast_search_fail = 0; @@ -1472,7 +1477,8 @@ fast_isolate_freepages(struct compact_co } else { if (cc->direct_compaction && pfn_valid(min_pfn)) { page = pageblock_pfn_to_page(min_pfn, - pageblock_end_pfn(min_pfn), + min(pageblock_end_pfn(min_pfn), + zone_end_pfn(cc->zone)), cc->zone); cc->free_pfn = min_pfn; }
From: Paolo Bonzini pbonzini@redhat.com
commit a04aead144fd938c2d9869eb187e5b9ea0009bae upstream.
In case of npt=0 on host, nSVM needs the same .inject_page_fault tweak as VMX has, to make sure that shadow mmu faults are injected as vmexits.
It is not clear why this is needed at all, but for now keep the same code as VMX and we'll fix it for both.
Based on a patch by Maxim Levitsky mlevitsk@redhat.com.
Fixes: 7c86663b68ba ("KVM: nSVM: inject exceptions via svm_check_nested_events") Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/x86/kvm/svm/nested.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
--- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -51,6 +51,23 @@ static void nested_svm_inject_npf_exit(s nested_svm_vmexit(svm); }
+static void svm_inject_page_fault_nested(struct kvm_vcpu *vcpu, struct x86_exception *fault) +{ + struct vcpu_svm *svm = to_svm(vcpu); + WARN_ON(!is_guest_mode(vcpu)); + + if (vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_EXCEPTION_OFFSET + PF_VECTOR) && + !svm->nested.nested_run_pending) { + svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + PF_VECTOR; + svm->vmcb->control.exit_code_hi = 0; + svm->vmcb->control.exit_info_1 = fault->error_code; + svm->vmcb->control.exit_info_2 = fault->address; + nested_svm_vmexit(svm); + } else { + kvm_inject_page_fault(vcpu, fault); + } +} + static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index) { struct vcpu_svm *svm = to_svm(vcpu); @@ -446,6 +463,9 @@ int enter_svm_guest_mode(struct vcpu_svm if (ret) return ret;
+ if (!npt_enabled) + svm->vcpu.arch.mmu->inject_page_fault = svm_inject_page_fault_nested; + svm_set_gif(svm, true);
return 0;
From: Subbaraman Narayanamurthy subbaram@codeaurora.org
commit e2057ee29973b9741d43d3f475a6b02fb46a0e61 upstream.
"sdam->pdev" is uninitialized and it is used to print error logs. Fix it. Since device pointer can be used from sdam_config, use it directly thereby removing pdev pointer.
Fixes: 40ce9798794f ("nvmem: add QTI SDAM driver") Cc: stable@vger.kernel.org Signed-off-by: Subbaraman Narayanamurthy subbaram@codeaurora.org Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Link: https://lore.kernel.org/r/20210205100853.32372-3-srinivas.kandagatla@linaro.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/nvmem/qcom-spmi-sdam.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/nvmem/qcom-spmi-sdam.c +++ b/drivers/nvmem/qcom-spmi-sdam.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2020-2021, The Linux Foundation. All rights reserved. */
#include <linux/device.h> @@ -18,7 +18,6 @@ #define SDAM_PBS_TRIG_CLR 0xE6
struct sdam_chip { - struct platform_device *pdev; struct regmap *regmap; struct nvmem_config sdam_config; unsigned int base; @@ -65,7 +64,7 @@ static int sdam_read(void *priv, unsigne size_t bytes) { struct sdam_chip *sdam = priv; - struct device *dev = &sdam->pdev->dev; + struct device *dev = sdam->sdam_config.dev; int rc;
if (!sdam_is_valid(sdam, offset, bytes)) { @@ -86,7 +85,7 @@ static int sdam_write(void *priv, unsign size_t bytes) { struct sdam_chip *sdam = priv; - struct device *dev = &sdam->pdev->dev; + struct device *dev = sdam->sdam_config.dev; int rc;
if (!sdam_is_valid(sdam, offset, bytes)) {
From: Fangrui Song maskray@google.com
commit ebfac7b778fac8b0e8e92ec91d0b055f046b4604 upstream.
clang-12 -fno-pic (since https://github.com/llvm/llvm-project/commit/a084c0388e2a59b9556f2de008333323...) can emit `call __stack_chk_fail@PLT` instead of `call __stack_chk_fail` on x86. The two forms should have identical behaviors on x86-64 but the former causes GNU as<2.37 to produce an unreferenced undefined symbol _GLOBAL_OFFSET_TABLE_.
(On x86-32, there is an R_386_PC32 vs R_386_PLT32 difference but the linker behavior is identical as far as Linux kernel is concerned.)
Simply ignore _GLOBAL_OFFSET_TABLE_ for now, like what scripts/mod/modpost.c:ignore_undef_symbol does. This also fixes the problem for gcc/clang -fpie and -fpic, which may emit `call foo@PLT` for external function calls on x86.
Note: ld -z defs and dynamic loaders do not error for unreferenced undefined symbols so the module loader is reading too much. If we ever need to ignore more symbols, the code should be refactored to ignore unreferenced symbols.
Cc: stable@vger.kernel.org Link: https://github.com/ClangBuiltLinux/linux/issues/1250 Link: https://sourceware.org/bugzilla/show_bug.cgi?id=27178 Reported-by: Marco Elver elver@google.com Reviewed-by: Nick Desaulniers ndesaulniers@google.com Reviewed-by: Nathan Chancellor natechancellor@gmail.com Tested-by: Marco Elver elver@google.com Signed-off-by: Fangrui Song maskray@google.com Signed-off-by: Jessica Yu jeyu@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/module.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
--- a/kernel/module.c +++ b/kernel/module.c @@ -2348,6 +2348,21 @@ static int verify_exported_symbols(struc return 0; }
+static bool ignore_undef_symbol(Elf_Half emachine, const char *name) +{ + /* + * On x86, PIC code and Clang non-PIC code may have call foo@PLT. GNU as + * before 2.37 produces an unreferenced _GLOBAL_OFFSET_TABLE_ on x86-64. + * i386 has a similar problem but may not deserve a fix. + * + * If we ever have to ignore many symbols, consider refactoring the code to + * only warn if referenced by a relocation. + */ + if (emachine == EM_386 || emachine == EM_X86_64) + return !strcmp(name, "_GLOBAL_OFFSET_TABLE_"); + return false; +} + /* Change all symbols so that st_value encodes the pointer directly. */ static int simplify_symbols(struct module *mod, const struct load_info *info) { @@ -2395,8 +2410,10 @@ static int simplify_symbols(struct modul break; }
- /* Ok if weak. */ - if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK) + /* Ok if weak or ignored. */ + if (!ksym && + (ELF_ST_BIND(sym[i].st_info) == STB_WEAK || + ignore_undef_symbol(info->hdr->e_machine, name))) break;
ret = PTR_ERR(ksym) ?: -ENOENT;
From: Frank Li Frank.Li@nxp.com
commit a56f44138a2c57047f1ea94ea121af31c595132b upstream.
In sdhci_esdhc_imx_remove() the SDHCI_INT_STATUS in read. Under some circumstances, this may be done while the device is runtime suspended, triggering the below splat.
Fix the problem by adding a pm_runtime_get_sync(), before reading the register, which will turn on clocks etc making the device accessible again.
[ 1811.323148] mmc1: card aaaa removed [ 1811.347483] Internal error: synchronous external abort: 96000210 [#1] PREEMPT SMP [ 1811.354988] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci cqhci mmc_block mmc_core [last unloaded: mmc_core] [ 1811.365726] CPU: 0 PID: 3464 Comm: rmmod Not tainted 5.10.1-sd-99871-g53835a2e8186 #5 [ 1811.373559] Hardware name: Freescale i.MX8DXL EVK (DT) [ 1811.378705] pstate: 60000005 (nZCv daif -PAN -UAO -TCO BTYPE=--) [ 1811.384723] pc : sdhci_esdhc_imx_remove+0x28/0x15c [sdhci_esdhc_imx] [ 1811.391090] lr : platform_drv_remove+0x2c/0x50 [ 1811.395536] sp : ffff800012c7bcb0 [ 1811.398855] x29: ffff800012c7bcb0 x28: ffff00002c72b900 [ 1811.404181] x27: 0000000000000000 x26: 0000000000000000 [ 1811.409497] x25: 0000000000000000 x24: 0000000000000000 [ 1811.414814] x23: ffff0000042b3890 x22: ffff800009127120 [ 1811.420131] x21: ffff00002c4c9580 x20: ffff0000042d0810 [ 1811.425456] x19: ffff0000042d0800 x18: 0000000000000020 [ 1811.430773] x17: 0000000000000000 x16: 0000000000000000 [ 1811.436089] x15: 0000000000000004 x14: ffff000004019c10 [ 1811.441406] x13: 0000000000000000 x12: 0000000000000020 [ 1811.446723] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f [ 1811.452040] x9 : fefefeff6364626d x8 : 7f7f7f7f7f7f7f7f [ 1811.457356] x7 : 78725e6473607372 x6 : 0000000080808080 [ 1811.462673] x5 : 0000000000000000 x4 : 0000000000000000 [ 1811.467990] x3 : ffff800011ac1cb0 x2 : 0000000000000000 [ 1811.473307] x1 : ffff8000091214d4 x0 : ffff8000133a0030 [ 1811.478624] Call trace: [ 1811.481081] sdhci_esdhc_imx_remove+0x28/0x15c [sdhci_esdhc_imx] [ 1811.487098] platform_drv_remove+0x2c/0x50 [ 1811.491198] __device_release_driver+0x188/0x230 [ 1811.495818] driver_detach+0xc0/0x14c [ 1811.499487] bus_remove_driver+0x5c/0xb0 [ 1811.503413] driver_unregister+0x30/0x60 [ 1811.507341] platform_driver_unregister+0x14/0x20 [ 1811.512048] sdhci_esdhc_imx_driver_exit+0x1c/0x3a8 [sdhci_esdhc_imx] [ 1811.518495] __arm64_sys_delete_module+0x19c/0x230 [ 1811.523291] el0_svc_common.constprop.0+0x78/0x1a0 [ 1811.528086] do_el0_svc+0x24/0x90 [ 1811.531405] el0_svc+0x14/0x20 [ 1811.534461] el0_sync_handler+0x1a4/0x1b0 [ 1811.538474] el0_sync+0x174/0x180 [ 1811.541801] Code: a9025bf5 f9403e95 f9400ea0 9100c000 (b9400000) [ 1811.547902] ---[ end trace 3fb1a3bd48ff7be5 ]---
Signed-off-by: Frank Li Frank.Li@nxp.com Cc: stable@vger.kernel.org # v4.0+ Link: https://lore.kernel.org/r/20210210181933.29263-1-Frank.Li@nxp.com [Ulf: Clarified the commit message a bit] Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-esdhc-imx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1666,9 +1666,10 @@ static int sdhci_esdhc_imx_remove(struct struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); - int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); + int dead;
pm_runtime_get_sync(&pdev->dev); + dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
From: Shirley Her shirley.her@bayhubtech.com
commit 1ad9f88014ae1d5abccb6fe930bc4c5c311bdc05 upstream.
Force chip enter L0 power state during SDR104 HW tuning to avoid tuning failure
Signed-off-by: Shirley Her shirley.her@bayhubtech.com Link: https://lore.kernel.org/r/20210206014051.3418-1-shirley.her@bayhubtech.com Fixes: 7b7d897e8898 ("mmc: sdhci-pci-o2micro: Add HW tuning for SDR104 mode") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
--- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -33,6 +33,8 @@ #define O2_SD_ADMA2 0xE7 #define O2_SD_INF_MOD 0xF1 #define O2_SD_MISC_CTRL4 0xFC +#define O2_SD_MISC_CTRL 0x1C0 +#define O2_SD_PWR_FORCE_L0 0x0002 #define O2_SD_TUNING_CTRL 0x300 #define O2_SD_PLL_SETTING 0x304 #define O2_SD_MISC_SETTING 0x308 @@ -300,6 +302,8 @@ static int sdhci_o2_execute_tuning(struc { struct sdhci_host *host = mmc_priv(mmc); int current_bus_width = 0; + u32 scratch32 = 0; + u16 scratch = 0;
/* * This handler only implements the eMMC tuning that is specific to @@ -312,6 +316,17 @@ static int sdhci_o2_execute_tuning(struc if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) && (opcode != MMC_SEND_TUNING_BLOCK))) return -EINVAL; + + /* Force power mode enter L0 */ + scratch = sdhci_readw(host, O2_SD_MISC_CTRL); + scratch |= O2_SD_PWR_FORCE_L0; + sdhci_writew(host, scratch, O2_SD_MISC_CTRL); + + /* wait DLL lock, timeout value 5ms */ + if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host, + scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000)) + pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n", + mmc_hostname(host->mmc)); /* * Judge the tuning reason, whether caused by dll shift * If cause by dll shift, should call sdhci_o2_dll_recovery @@ -344,6 +359,11 @@ static int sdhci_o2_execute_tuning(struc sdhci_set_bus_width(host, current_bus_width); }
+ /* Cancel force power mode enter L0 */ + scratch = sdhci_readw(host, O2_SD_MISC_CTRL); + scratch &= ~(O2_SD_PWR_FORCE_L0); + sdhci_writew(host, scratch, O2_SD_MISC_CTRL); + sdhci_reset(host, SDHCI_RESET_CMD); sdhci_reset(host, SDHCI_RESET_DATA);
From: Christophe Leroy christophe.leroy@csgroup.eu
commit 3642eb21256a317ac14e9ed560242c6d20cf06d9 upstream.
THREAD_ALIGN_SHIFT = THREAD_SHIFT + 1 = PAGE_SHIFT + 1 Maximum PAGE_SHIFT is 18 for 256k pages so THREAD_ALIGN_SHIFT is 19 at the maximum.
No need to clobber cr1, it can be preserved when moving r1 into CR when we check stack overflow.
This reduces the number of instructions in Machine Check Exception prolog and fixes a build failure reported by the kernel test robot on v5.10 stable when building with RTAS + VMAP_STACK + KVM. That build failure is due to too many instructions in the prolog hence not fitting between 0x200 and 0x300. Allthough the problem doesn't show up in mainline, it is still worth the change.
Fixes: 98bf2d3f4970 ("powerpc/32s: Fix RTAS machine check with VMAP stack") Cc: stable@vger.kernel.org Reported-by: kernel test robot lkp@intel.com Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/5ae4d545e3ac58e133d2599e0deb88843cb494fc.161276862... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/kernel/head_32.h | 2 +- arch/powerpc/kernel/head_book3s_32.S | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-)
--- a/arch/powerpc/kernel/head_32.h +++ b/arch/powerpc/kernel/head_32.h @@ -47,7 +47,7 @@ lwz r1,TASK_STACK-THREAD(r1) addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE 1: - mtcrf 0x7f, r1 + mtcrf 0x3f, r1 bt 32 - THREAD_ALIGN_SHIFT, stack_overflow #else subi r11, r1, INT_FRAME_SIZE /* use r1 if kernel */ --- a/arch/powerpc/kernel/head_book3s_32.S +++ b/arch/powerpc/kernel/head_book3s_32.S @@ -278,12 +278,6 @@ MachineCheck: 7: EXCEPTION_PROLOG_2 addi r3,r1,STACK_FRAME_OVERHEAD #ifdef CONFIG_PPC_CHRP -#ifdef CONFIG_VMAP_STACK - mfspr r4, SPRN_SPRG_THREAD - tovirt(r4, r4) - lwz r4, RTAS_SP(r4) - cmpwi cr1, r4, 0 -#endif beq cr1, machine_check_tramp twi 31, 0, 0 #else
From: Hari Bathini hbathini@linux.ibm.com
commit 2377c92e37fe97bc5b365f55cf60f56dfc4849f5 upstream.
On systems with large amount of memory, loading kdump kernel through kexec_file_load syscall may fail with the below error:
"Failed to update fdt with linux,drconf-usable-memory property"
This happens because the size estimation for kdump kernel's FDT does not account for the additional space needed to setup usable memory properties. Fix it by accounting for the space needed to include linux,usable-memory & linux,drconf-usable-memory properties while estimating kdump kernel's FDT size.
Fixes: 6ecd0163d360 ("powerpc/kexec_file: Add appropriate regions for memory reserve map") Cc: stable@vger.kernel.org # v5.9+ Signed-off-by: Hari Bathini hbathini@linux.ibm.com Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/161243826811.119001.14083048209224609814.stgit@hba... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/include/asm/kexec.h | 1 + arch/powerpc/kexec/elf_64.c | 2 +- arch/powerpc/kexec/file_load_64.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-)
--- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h @@ -136,6 +136,7 @@ int load_crashdump_segments_ppc64(struct int setup_purgatory_ppc64(struct kimage *image, const void *slave_code, const void *fdt, unsigned long kernel_load_addr, unsigned long fdt_load_addr); +unsigned int kexec_fdt_totalsize_ppc64(struct kimage *image); int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, unsigned long initrd_load_addr, unsigned long initrd_len, const char *cmdline); --- a/arch/powerpc/kexec/elf_64.c +++ b/arch/powerpc/kexec/elf_64.c @@ -102,7 +102,7 @@ static void *elf64_load(struct kimage *i pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr); }
- fdt_size = fdt_totalsize(initial_boot_params) * 2; + fdt_size = kexec_fdt_totalsize_ppc64(image); fdt = kmalloc(fdt_size, GFP_KERNEL); if (!fdt) { pr_err("Not enough memory for the device tree.\n"); --- a/arch/powerpc/kexec/file_load_64.c +++ b/arch/powerpc/kexec/file_load_64.c @@ -21,6 +21,7 @@ #include <linux/memblock.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <asm/setup.h> #include <asm/drmem.h> #include <asm/kexec_ranges.h> #include <asm/crashdump-ppc64.h> @@ -926,6 +927,40 @@ out: }
/** + * kexec_fdt_totalsize_ppc64 - Return the estimated size needed to setup FDT + * for kexec/kdump kernel. + * @image: kexec image being loaded. + * + * Returns the estimated size needed for kexec/kdump kernel FDT. + */ +unsigned int kexec_fdt_totalsize_ppc64(struct kimage *image) +{ + unsigned int fdt_size; + u64 usm_entries; + + /* + * The below estimate more than accounts for a typical kexec case where + * the additional space is to accommodate things like kexec cmdline, + * chosen node with properties for initrd start & end addresses and + * a property to indicate kexec boot.. + */ + fdt_size = fdt_totalsize(initial_boot_params) + (2 * COMMAND_LINE_SIZE); + if (image->type != KEXEC_TYPE_CRASH) + return fdt_size; + + /* + * For kdump kernel, also account for linux,usable-memory and + * linux,drconf-usable-memory properties. Get an approximate on the + * number of usable memory entries and use for FDT size estimation. + */ + usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) + + (2 * (resource_size(&crashk_res) / drmem_lmb_size()))); + fdt_size += (unsigned int)(usm_entries * sizeof(u64)); + + return fdt_size; +} + +/** * setup_new_fdt_ppc64 - Update the flattend device-tree of the kernel * being loaded. * @image: kexec image being loaded.
From: Christophe Leroy christophe.leroy@csgroup.eu
commit 57fdfbce89137ae85cd5cef48be168040a47dd13 upstream.
Userspace Execution protection and fast syscall entry were implemented independently from each other and were both merged in kernel 5.2, leading to syscall entry missing userspace execution protection.
On syscall entry, execution of user space memory must be locked in the same way as on exception entry.
Fixes: b86fb88855ea ("powerpc/32: implement fast entry for syscalls on non BOOKE") Cc: stable@vger.kernel.org Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/c65e105b63aaf74f91a14f845bc77192350b84a6.161279661... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/powerpc/kernel/entry_32.S | 3 +++ 1 file changed, 3 insertions(+)
--- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -356,6 +356,9 @@ trace_syscall_entry_irq_off:
.globl transfer_to_syscall transfer_to_syscall: +#ifdef CONFIG_PPC_BOOK3S_32 + kuep_lock r11, r12 +#endif #ifdef CONFIG_TRACE_IRQFLAGS andi. r12,r9,MSR_EE beq- trace_syscall_entry_irq_off
From: Subbaraman Narayanamurthy subbaram@codeaurora.org
commit d19db80a366576d3ffadf2508ed876b4c1faf959 upstream.
Currently, when handling the SPMI summary interrupt, the hw_irq number is calculated based on SID, Peripheral ID, IRQ index and APID. This is then passed to irq_find_mapping() to see if a mapping exists for this hw_irq and if available, invoke the interrupt handler. Since the IRQ index uses an "int" type, hw_irq which is of unsigned long data type can take a large value when SID has its MSB set to 1 and the type conversion happens. Because of this, irq_find_mapping() returns 0 as there is no mapping for this hw_irq. This ends up invoking cleanup_irq() as if the interrupt is spurious whereas it is actually a valid interrupt. Fix this by using the proper data type (u32) for id.
Cc: stable@vger.kernel.org Signed-off-by: Subbaraman Narayanamurthy subbaram@codeaurora.org Link: https://lore.kernel.org/r/1612812784-26369-1-git-send-email-subbaram@codeaur... Signed-off-by: Stephen Boyd sboyd@kernel.org Link: https://lore.kernel.org/r/20210212031417.3148936-1-sboyd@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/spmi/spmi-pmic-arb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015, 2017, 2021, The Linux Foundation. All rights reserved. */ #include <linux/bitmap.h> #include <linux/delay.h> @@ -505,8 +505,7 @@ static void cleanup_irq(struct spmi_pmic static void periph_interrupt(struct spmi_pmic_arb *pmic_arb, u16 apid) { unsigned int irq; - u32 status; - int id; + u32 status, id; u8 sid = (pmic_arb->apid_data[apid].ppid >> 8) & 0xF; u8 per = pmic_arb->apid_data[apid].ppid & 0xFF;
From: Alexander Usyskin alexander.usyskin@intel.com
commit b398d53cd421454d64850f8b1f6d609ede9042d9 upstream.
Block data send with vtag if either transport layer or FW client are not supporting vtags.
Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210208150649.141358-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/mei/bus.c | 7 +++++++ 1 file changed, 7 insertions(+)
--- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -60,6 +60,13 @@ ssize_t __mei_cl_send(struct mei_cl *cl, goto out; }
+ if (vtag) { + /* Check if vtag is supported by client */ + rets = mei_cl_vt_support_check(cl); + if (rets) + goto out; + } + if (length > mei_cl_mtu(cl)) { rets = -EFBIG; goto out;
From: Alexander Usyskin alexander.usyskin@intel.com
commit 1309ecc90f16ee9cc3077761e7f4474369747e6e upstream.
The size in header field for packet transferred over DMA includes size of the extended header. Include extended header in size check. Add size and sanity checks on extended header.
Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210129120752.850325-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/mei/interrupt.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
--- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -295,12 +295,17 @@ static inline bool hdr_is_fixed(struct m static inline int hdr_is_valid(u32 msg_hdr) { struct mei_msg_hdr *mei_hdr; + u32 expected_len = 0;
mei_hdr = (struct mei_msg_hdr *)&msg_hdr; if (!msg_hdr || mei_hdr->reserved) return -EBADMSG;
- if (mei_hdr->dma_ring && mei_hdr->length != MEI_SLOT_SIZE) + if (mei_hdr->dma_ring) + expected_len += MEI_SLOT_SIZE; + if (mei_hdr->extended) + expected_len += MEI_SLOT_SIZE; + if (mei_hdr->length < expected_len) return -EBADMSG;
return 0; @@ -324,6 +329,8 @@ int mei_irq_read_handler(struct mei_devi struct mei_cl *cl; int ret; u32 ext_meta_hdr_u32; + u32 hdr_size_left; + u32 hdr_size_ext; int i; int ext_hdr_end;
@@ -353,6 +360,7 @@ int mei_irq_read_handler(struct mei_devi }
ext_hdr_end = 1; + hdr_size_left = mei_hdr->length;
if (mei_hdr->extended) { if (!dev->rd_msg_hdr[1]) { @@ -363,8 +371,21 @@ int mei_irq_read_handler(struct mei_devi dev_dbg(dev->dev, "extended header is %08x\n", ext_meta_hdr_u32); } - meta_hdr = ((struct mei_ext_meta_hdr *) - dev->rd_msg_hdr + 1); + meta_hdr = ((struct mei_ext_meta_hdr *)dev->rd_msg_hdr + 1); + if (check_add_overflow((u32)sizeof(*meta_hdr), + mei_slots2data(meta_hdr->size), + &hdr_size_ext)) { + dev_err(dev->dev, "extended message size too big %d\n", + meta_hdr->size); + return -EBADMSG; + } + if (hdr_size_left < hdr_size_ext) { + dev_err(dev->dev, "corrupted message header len %d\n", + mei_hdr->length); + return -EBADMSG; + } + hdr_size_left -= hdr_size_ext; + ext_hdr_end = meta_hdr->size + 2; for (i = dev->rd_msg_hdr_count; i < ext_hdr_end; i++) { dev->rd_msg_hdr[i] = mei_read_hdr(dev); @@ -376,6 +397,12 @@ int mei_irq_read_handler(struct mei_devi }
if (mei_hdr->dma_ring) { + if (hdr_size_left != sizeof(dev->rd_msg_hdr[ext_hdr_end])) { + dev_err(dev->dev, "corrupted message header len %d\n", + mei_hdr->length); + return -EBADMSG; + } + dev->rd_msg_hdr[ext_hdr_end] = mei_read_hdr(dev); dev->rd_msg_hdr_count++; (*slots)--;
From: Tomas Winkler tomas.winkler@intel.com
commit 372726cb3957dbd69ded9a4e3419d5c6c3bc648e upstream.
Add Emmitsburg workstation DID.
Cc: stable@vger.kernel.org Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210129120752.850325-5-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/mei/hw-me-regs.h | 2 ++ drivers/misc/mei/pci-me.c | 2 ++ 2 files changed, 4 insertions(+)
--- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -101,6 +101,8 @@ #define MEI_DEV_ID_MCC 0x4B70 /* Mule Creek Canyon (EHL) */ #define MEI_DEV_ID_MCC_4 0x4B75 /* Mule Creek Canyon 4 (EHL) */
+#define MEI_DEV_ID_EBG 0x1BE0 /* Emmitsburg WS */ + /* * MEI HW Section */ --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -107,6 +107,8 @@ static const struct pci_device_id mei_me
{MEI_PCI_DEVICE(MEI_DEV_ID_CDF, MEI_ME_PCH8_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_EBG, MEI_ME_PCH15_SPS_CFG)}, + /* required last entry */ {0, } };
From: Alexander Usyskin alexander.usyskin@intel.com
commit f7545efaf7950b240de6b8a20b9c3ffd7278538e upstream.
Add Adler Lake S device id.
Cc: stable@vger.kernel.org Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210129120752.850325-6-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/mei/hw-me-regs.h | 2 ++ drivers/misc/mei/pci-me.c | 2 ++ 2 files changed, 4 insertions(+)
--- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -103,6 +103,8 @@
#define MEI_DEV_ID_EBG 0x1BE0 /* Emmitsburg WS */
+#define MEI_DEV_ID_ADP_S 0x7AE8 /* Alder Lake Point S */ + /* * MEI HW Section */ --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -109,6 +109,8 @@ static const struct pci_device_id mei_me
{MEI_PCI_DEVICE(MEI_DEV_ID_EBG, MEI_ME_PCH15_SPS_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_S, MEI_ME_PCH15_CFG)}, + /* required last entry */ {0, } };
From: Alexander Usyskin alexander.usyskin@intel.com
commit 930c922a987a02936000f15ea62988b7a39c27f5 upstream.
Add Adler Lake LP device id.
Cc: stable@vger.kernel.org Signed-off-by: Alexander Usyskin alexander.usyskin@intel.com Signed-off-by: Tomas Winkler tomas.winkler@intel.com Link: https://lore.kernel.org/r/20210129120752.850325-7-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/misc/mei/hw-me-regs.h | 1 + drivers/misc/mei/pci-me.c | 1 + 2 files changed, 2 insertions(+)
--- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -104,6 +104,7 @@ #define MEI_DEV_ID_EBG 0x1BE0 /* Emmitsburg WS */
#define MEI_DEV_ID_ADP_S 0x7AE8 /* Alder Lake Point S */ +#define MEI_DEV_ID_ADP_LP 0x7A60 /* Alder Lake Point LP */
/* * MEI HW Section --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -110,6 +110,7 @@ static const struct pci_device_id mei_me {MEI_PCI_DEVICE(MEI_DEV_ID_EBG, MEI_ME_PCH15_SPS_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_ADP_S, MEI_ME_PCH15_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_LP, MEI_ME_PCH15_CFG)},
/* required last entry */ {0, }
From: Maxim Kiselev bigunclemax@gmail.com
commit a8002a35935aaefcd6a42ad3289f62bab947f2ca upstream.
If no n_latch value will be provided at driver probe then all pins will be used as an input:
gpio->out = ~n_latch;
In that case initial state for all pins is "one":
gpio->status = gpio->out;
So if pcf857x IRQ happens with change pin value from "zero" to "one" then we miss it, because of "one" from IRQ and "one" from initial state leaves corresponding pin unchanged: change = (gpio->status ^ status) & gpio->irq_enabled;
The right solution will be to read actual state at driver probe.
Cc: stable@vger.kernel.org Fixes: 6e20a0a429bd ("gpio: pcf857x: enable gpio_to_irq() support") Signed-off-by: Maxim Kiselev bigunclemax@gmail.com Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpio/gpio-pcf857x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -332,7 +332,7 @@ static int pcf857x_probe(struct i2c_clie * reset state. Otherwise it flags pins to be driven low. */ gpio->out = ~n_latch; - gpio->status = gpio->out; + gpio->status = gpio->read(gpio->client);
/* Enable irqchip if we have an interrupt */ if (client->irq) {
From: Tim Harvey tharvey@gateworks.com
commit 8d9bf3c3e1451fc8de7b590040a868ade26d6b22 upstream.
The Gateworks System Controller has an active-low interrupt. Fix the interrupt request type.
Cc: stable@vger.kernel.org Fixes: d85234994b2f ("mfd: Add Gateworks System Controller core driver") Signed-off-by: Tim Harvey tharvey@gateworks.com Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mfd/gateworks-gsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mfd/gateworks-gsc.c +++ b/drivers/mfd/gateworks-gsc.c @@ -234,7 +234,7 @@ static int gsc_probe(struct i2c_client *
ret = devm_regmap_add_irq_chip(dev, gsc->regmap, client->irq, IRQF_ONESHOT | IRQF_SHARED | - IRQF_TRIGGER_FALLING, 0, + IRQF_TRIGGER_LOW, 0, &gsc_irq_chip, &irq_data); if (ret) return ret;
From: Muchun Song songmuchun@bytedance.com
commit 8a8109f303e25a27f92c1d8edd67d7cbbc60a4eb upstream.
printk_safe_flush_on_panic() caused the following deadlock on our server:
CPU0: CPU1: panic rcu_dump_cpu_stacks kdump_nmi_shootdown_cpus nmi_trigger_cpumask_backtrace register_nmi_handler(crash_nmi_callback) printk_safe_flush __printk_safe_flush raw_spin_lock_irqsave(&read_lock) // send NMI to other processors apic_send_IPI_allbutself(NMI_VECTOR) // NMI interrupt, dead loop crash_nmi_callback printk_safe_flush_on_panic printk_safe_flush __printk_safe_flush // deadlock raw_spin_lock_irqsave(&read_lock)
DEADLOCK: read_lock is taken on CPU1 and will never get released.
It happens when panic() stops a CPU by NMI while it has been in the middle of printk_safe_flush().
Handle the lock the same way as logbuf_lock. The printk_safe buffers are flushed only when both locks can be safely taken. It can avoid the deadlock _in this particular case_ at expense of losing contents of printk_safe buffers.
Note: It would actually be safe to re-init the locks when all CPUs were stopped by NMI. But it would require passing this information from arch-specific code. It is not worth the complexity. Especially because logbuf_lock and printk_safe buffers have been obsoleted by the lockless ring buffer.
Fixes: cf9b1106c81c ("printk/nmi: flush NMI messages on the system panic") Signed-off-by: Muchun Song songmuchun@bytedance.com Reviewed-by: Petr Mladek pmladek@suse.com Cc: stable@vger.kernel.org Acked-by: Sergey Senozhatsky sergey.senozhatsky@gmail.com Signed-off-by: Petr Mladek pmladek@suse.com Link: https://lore.kernel.org/r/20210210034823.64867-1-songmuchun@bytedance.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/printk/printk_safe.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
--- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -45,6 +45,8 @@ struct printk_safe_seq_buf { static DEFINE_PER_CPU(struct printk_safe_seq_buf, safe_print_seq); static DEFINE_PER_CPU(int, printk_context);
+static DEFINE_RAW_SPINLOCK(safe_read_lock); + #ifdef CONFIG_PRINTK_NMI static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq); #endif @@ -180,8 +182,6 @@ static void report_message_lost(struct p */ static void __printk_safe_flush(struct irq_work *work) { - static raw_spinlock_t read_lock = - __RAW_SPIN_LOCK_INITIALIZER(read_lock); struct printk_safe_seq_buf *s = container_of(work, struct printk_safe_seq_buf, work); unsigned long flags; @@ -195,7 +195,7 @@ static void __printk_safe_flush(struct i * different CPUs. This is especially important when printing * a backtrace. */ - raw_spin_lock_irqsave(&read_lock, flags); + raw_spin_lock_irqsave(&safe_read_lock, flags);
i = 0; more: @@ -232,7 +232,7 @@ more:
out: report_message_lost(s); - raw_spin_unlock_irqrestore(&read_lock, flags); + raw_spin_unlock_irqrestore(&safe_read_lock, flags); }
/** @@ -278,6 +278,14 @@ void printk_safe_flush_on_panic(void) raw_spin_lock_init(&logbuf_lock); }
+ if (raw_spin_is_locked(&safe_read_lock)) { + if (num_online_cpus() > 1) + return; + + debug_locks_off(); + raw_spin_lock_init(&safe_read_lock); + } + printk_safe_flush(); }
From: Namjae Jeon namjae.jeon@samsung.com
commit 78c276f5495aa53a8beebb627e5bf6a54f0af34f upstream.
syzbot reported a warning which could cause shift-out-of-bounds issue.
Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x183/0x22e lib/dump_stack.c:120 ubsan_epilogue lib/ubsan.c:148 [inline] __ubsan_handle_shift_out_of_bounds+0x432/0x4d0 lib/ubsan.c:395 exfat_read_boot_sector fs/exfat/super.c:471 [inline] __exfat_fill_super fs/exfat/super.c:556 [inline] exfat_fill_super+0x2acb/0x2d00 fs/exfat/super.c:624 get_tree_bdev+0x406/0x630 fs/super.c:1291 vfs_get_tree+0x86/0x270 fs/super.c:1496 do_new_mount fs/namespace.c:2881 [inline] path_mount+0x1937/0x2c50 fs/namespace.c:3211 do_mount fs/namespace.c:3224 [inline] __do_sys_mount fs/namespace.c:3432 [inline] __se_sys_mount+0x2f9/0x3b0 fs/namespace.c:3409 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
exfat specification describe sect_per_clus_bits field of boot sector could be at most 25 - sect_size_bits and at least 0. And sect_size_bits can also affect this calculation, It also needs validation. This patch add validation for sect_per_clus_bits and sect_size_bits field of boot sector.
Fixes: 719c1e182916 ("exfat: add super block operations") Cc: stable@vger.kernel.org # v5.9+ Reported-by: syzbot+da4fe66aaadd3c2e2d1c@syzkaller.appspotmail.com Reviewed-by: Sungjong Seo sj1557.seo@samsung.com Tested-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Namjae Jeon namjae.jeon@samsung.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/exfat/exfat_raw.h | 4 ++++ fs/exfat/super.c | 31 ++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-)
--- a/fs/exfat/exfat_raw.h +++ b/fs/exfat/exfat_raw.h @@ -77,6 +77,10 @@
#define EXFAT_FILE_NAME_LEN 15
+#define EXFAT_MIN_SECT_SIZE_BITS 9 +#define EXFAT_MAX_SECT_SIZE_BITS 12 +#define EXFAT_MAX_SECT_PER_CLUS_BITS(x) (25 - (x)->sect_size_bits) + /* EXFAT: Main and Backup Boot Sector (512 bytes) */ struct boot_sector { __u8 jmp_boot[BOOTSEC_JUMP_BOOT_LEN]; --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -381,8 +381,7 @@ static int exfat_calibrate_blocksize(str { struct exfat_sb_info *sbi = EXFAT_SB(sb);
- if (!is_power_of_2(logical_sect) || - logical_sect < 512 || logical_sect > 4096) { + if (!is_power_of_2(logical_sect)) { exfat_err(sb, "bogus logical sector size %u", logical_sect); return -EIO; } @@ -451,6 +450,25 @@ static int exfat_read_boot_sector(struct return -EINVAL; }
+ /* + * sect_size_bits could be at least 9 and at most 12. + */ + if (p_boot->sect_size_bits < EXFAT_MIN_SECT_SIZE_BITS || + p_boot->sect_size_bits > EXFAT_MAX_SECT_SIZE_BITS) { + exfat_err(sb, "bogus sector size bits : %u\n", + p_boot->sect_size_bits); + return -EINVAL; + } + + /* + * sect_per_clus_bits could be at least 0 and at most 25 - sect_size_bits. + */ + if (p_boot->sect_per_clus_bits > EXFAT_MAX_SECT_PER_CLUS_BITS(p_boot)) { + exfat_err(sb, "bogus sectors bits per cluster : %u\n", + p_boot->sect_per_clus_bits); + return -EINVAL; + } + sbi->sect_per_clus = 1 << p_boot->sect_per_clus_bits; sbi->sect_per_clus_bits = p_boot->sect_per_clus_bits; sbi->cluster_size_bits = p_boot->sect_per_clus_bits + @@ -477,16 +495,19 @@ static int exfat_read_boot_sector(struct sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
/* check consistencies */ - if (sbi->num_FAT_sectors << p_boot->sect_size_bits < - sbi->num_clusters * 4) { + if ((u64)sbi->num_FAT_sectors << p_boot->sect_size_bits < + (u64)sbi->num_clusters * 4) { exfat_err(sb, "bogus fat length"); return -EINVAL; } + if (sbi->data_start_sector < - sbi->FAT1_start_sector + sbi->num_FAT_sectors * p_boot->num_fats) { + (u64)sbi->FAT1_start_sector + + (u64)sbi->num_FAT_sectors * p_boot->num_fats) { exfat_err(sb, "bogus data start sector"); return -EINVAL; } + if (sbi->vol_flags & VOLUME_DIRTY) exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck."); if (sbi->vol_flags & MEDIA_FAILURE)
From: Shin'ichiro Kawasaki shinichiro.kawasaki@wdc.com
commit 059c01039c0185dbee7ed080f1f2bd22cb1e4dab upstream.
Per ZBC/ZAC/ZNS specifications, write pointers may not have valid values when zones are in full condition. However, when zonefs mounts a zoned block device, zonefs refers write pointers to set file size even when the zones are in full condition. This results in wrong file size. To fix this, refer maximum file size in place of write pointers for zones in full condition.
Signed-off-by: Shin'ichiro Kawasaki shinichiro.kawasaki@wdc.com Fixes: 8dcc1a9d90c1 ("fs: New zonefs file system") Cc: stable@vger.kernel.org # 5.6+ Signed-off-by: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/zonefs/super.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -250,6 +250,9 @@ static loff_t zonefs_check_zone_conditio } inode->i_mode &= ~0222; return i_size_read(inode); + case BLK_ZONE_COND_FULL: + /* The write pointer of full zones is invalid. */ + return zi->i_max_size; default: if (zi->i_ztype == ZONEFS_ZTYPE_CNV) return zi->i_max_size;
From: Chris Wilson chris@chris-wilson.co.uk
commit bfe3911a91047557eb0e620f95a370aee6a248c7 upstream.
Userspace has discovered the functionality offered by SYS_kcmp and has started to depend upon it. In particular, Mesa uses SYS_kcmp for os_same_file_description() in order to identify when two fd (e.g. device or dmabuf) point to the same struct file. Since they depend on it for core functionality, lift SYS_kcmp out of the non-default CONFIG_CHECKPOINT_RESTORE into the selectable syscall category.
Rasmus Villemoes also pointed out that systemd uses SYS_kcmp to deduplicate the per-service file descriptor store.
Note that some distributions such as Ubuntu are already enabling CHECKPOINT_RESTORE in their configs and so, by extension, SYS_kcmp.
Signed-off-by: Chris Wilson chris@chris-wilson.co.uk Cc: Kees Cook keescook@chromium.org Cc: Andy Lutomirski luto@amacapital.net Cc: Will Drewry wad@chromium.org Cc: Andrew Morton akpm@linux-foundation.org Cc: Dave Airlie airlied@gmail.com Cc: Daniel Vetter daniel@ffwll.ch Cc: Lucas Stach l.stach@pengutronix.de Cc: Rasmus Villemoes linux@rasmusvillemoes.dk Cc: Cyrill Gorcunov gorcunov@gmail.com Cc: stable@vger.kernel.org Acked-by: Daniel Vetter daniel.vetter@ffwll.ch # DRM depends on kcmp Acked-by: Rasmus Villemoes linux@rasmusvillemoes.dk # systemd uses kcmp Reviewed-by: Cyrill Gorcunov gorcunov@gmail.com Reviewed-by: Kees Cook keescook@chromium.org Acked-by: Thomas Zimmermann tzimmermann@suse.de Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20210205220012.1983-1-chris@ch... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/Kconfig | 3 +++ fs/eventpoll.c | 4 ++-- include/linux/eventpoll.h | 2 +- init/Kconfig | 11 +++++++++++ kernel/Makefile | 2 +- tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -15,6 +15,9 @@ menuconfig DRM select I2C_ALGOBIT select DMA_SHARED_BUFFER select SYNC_FILE +# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate +# device and dmabuf fd. Let's make sure that is available for our userspace. + select KCMP help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -979,7 +979,7 @@ static struct epitem *ep_find(struct eve return epir; }
-#ifdef CONFIG_CHECKPOINT_RESTORE +#ifdef CONFIG_KCMP static struct epitem *ep_find_tfd(struct eventpoll *ep, int tfd, unsigned long toff) { struct rb_node *rbp; @@ -1021,7 +1021,7 @@ struct file *get_epoll_tfile_raw_ptr(str
return file_raw; } -#endif /* CONFIG_CHECKPOINT_RESTORE */ +#endif /* CONFIG_KCMP */
/** * Adds a new entry to the tail of the list in a lockless way, i.e. --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -18,7 +18,7 @@ struct file;
#ifdef CONFIG_EPOLL
-#ifdef CONFIG_CHECKPOINT_RESTORE +#ifdef CONFIG_KCMP struct file *get_epoll_tfile_raw_ptr(struct file *file, int tfd, unsigned long toff); #endif
--- a/init/Kconfig +++ b/init/Kconfig @@ -1193,6 +1193,7 @@ endif # NAMESPACES config CHECKPOINT_RESTORE bool "Checkpoint/restore support" select PROC_CHILDREN + select KCMP default n help Enables additional kernel features in a sake of checkpoint/restore. @@ -1736,6 +1737,16 @@ config ARCH_HAS_MEMBARRIER_CALLBACKS config ARCH_HAS_MEMBARRIER_SYNC_CORE bool
+config KCMP + bool "Enable kcmp() system call" if EXPERT + help + Enable the kernel resource comparison system call. It provides + user-space with the ability to compare two processes to see if they + share a common resource, such as a file descriptor or even virtual + memory space. + + If unsure, say N. + config RSEQ bool "Enable rseq() system call" if EXPERT default y --- a/kernel/Makefile +++ b/kernel/Makefile @@ -51,7 +51,7 @@ obj-y += livepatch/ obj-y += dma/ obj-y += entry/
-obj-$(CONFIG_CHECKPOINT_RESTORE) += kcmp.o +obj-$(CONFIG_KCMP) += kcmp.o obj-$(CONFIG_FREEZER) += freezer.o obj-$(CONFIG_PROFILING) += profile.o obj-$(CONFIG_STACKTRACE) += stacktrace.o --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -315,7 +315,7 @@ TEST(kcmp) ret = __filecmp(getpid(), getpid(), 1, 1); EXPECT_EQ(ret, 0); if (ret != 0 && errno == ENOSYS) - SKIP(return, "Kernel does not support kcmp() (missing CONFIG_CHECKPOINT_RESTORE?)"); + SKIP(return, "Kernel does not support kcmp() (missing CONFIG_KCMP?)"); }
TEST(mode_strict_support)
From: Viresh Kumar viresh.kumar@linaro.org
commit a51afb13311cd85b2f638c691b2734622277d8f5 upstream.
freq_qos_update_request() returns 1 if the effective constraint value has changed, 0 if the effective constraint value has not changed, or a negative error code on failures.
The frequency constraints for CPUs can be set by different parts of the kernel. If the maximum frequency constraint set by other parts of the kernel are set at a lower value than the one corresponding to cooling state 0, then we will never be able to cool down the system as freq_qos_update_request() will keep on returning 0 and we will skip updating cpufreq_state and thermal pressure.
Fix that by doing the updates even in the case where freq_qos_update_request() returns 0, as we have effectively set the constraint to a new value even if the consolidated value of the actual constraint is unchanged because of external factors.
Cc: v5.7+ stable@vger.kernel.org # v5.7+ Reported-by: Thara Gopinath thara.gopinath@linaro.org Fixes: f12e4f66ab6a ("thermal/cpu-cooling: Update thermal pressure in case of a maximum frequency capping") Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Reviewed-by: Lukasz Luba lukasz.luba@arm.com Tested-by: Lukasz Luba lukasz.luba@arm.com Reviewed-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Tested-by: Thara Gopinaththara.gopinath@linaro.org Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org Link: https://lore.kernel.org/r/b2b7e84944937390256669df5a48ce5abba0c1ef.161354071... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/thermal/cpufreq_cooling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/thermal/cpufreq_cooling.c +++ b/drivers/thermal/cpufreq_cooling.c @@ -441,7 +441,7 @@ static int cpufreq_set_cur_state(struct frequency = get_state_freq(cpufreq_cdev, state);
ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency); - if (ret > 0) { + if (ret >= 0) { cpufreq_cdev->cpufreq_state = state; cpus = cpufreq_cdev->policy->cpus; max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus));
From: Shawn Guo shawn.guo@linaro.org
commit 67fc209b527d023db4d087c68e44e9790aa089ef upstream.
Commit f17b3e44320b ("cpufreq: qcom-hw: Use devm_platform_ioremap_resource() to simplify code") introduces a regression on platforms using the driver, by failing to initialise a policy, when one is created post hotplug.
When all the CPUs of a policy are hoptplugged out, the call to .exit() and later to devm_iounmap() does not release the memory region that was requested during devm_platform_ioremap_resource(). Therefore, a subsequent call to .init() will result in the following error, which will prevent a new policy to be initialised:
[ 3395.915416] CPU4: shutdown [ 3395.938185] psci: CPU4 killed (polled 0 ms) [ 3399.071424] CPU5: shutdown [ 3399.094316] psci: CPU5 killed (polled 0 ms) [ 3402.139358] CPU6: shutdown [ 3402.161705] psci: CPU6 killed (polled 0 ms) [ 3404.742939] CPU7: shutdown [ 3404.765592] psci: CPU7 killed (polled 0 ms) [ 3411.492274] Detected VIPT I-cache on CPU4 [ 3411.492337] GICv3: CPU4: found redistributor 400 region 0:0x0000000017ae0000 [ 3411.492448] CPU4: Booted secondary processor 0x0000000400 [0x516f802d] [ 3411.503654] qcom-cpufreq-hw 17d43000.cpufreq: can't request region for resource [mem 0x17d45800-0x17d46bff]
With that being said, the original code was tricky and skipping memory region request intentionally to hide this issue. The true cause is that those devm_xxx() device managed functions shouldn't be used for cpufreq init/exit hooks, because &pdev->dev is alive across the hooks and will not trigger auto resource free-up. Let's drop the use of device managed functions and manually allocate/free resources, so that the issue can be fixed properly.
Cc: v5.10+ stable@vger.kernel.org # v5.10+ Fixes: f17b3e44320b ("cpufreq: qcom-hw: Use devm_platform_ioremap_resource() to simplify code") Suggested-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Shawn Guo shawn.guo@linaro.org Signed-off-by: Viresh Kumar viresh.kumar@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/qcom-cpufreq-hw.c | 40 ++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-)
--- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -32,6 +32,7 @@ struct qcom_cpufreq_soc_data {
struct qcom_cpufreq_data { void __iomem *base; + struct resource *res; const struct qcom_cpufreq_soc_data *soc_data; };
@@ -280,6 +281,7 @@ static int qcom_cpufreq_hw_cpu_init(stru struct of_phandle_args args; struct device_node *cpu_np; struct device *cpu_dev; + struct resource *res; void __iomem *base; struct qcom_cpufreq_data *data; int ret, index; @@ -303,18 +305,33 @@ static int qcom_cpufreq_hw_cpu_init(stru
index = args.args[0];
- base = devm_platform_ioremap_resource(pdev, index); - if (IS_ERR(base)) - return PTR_ERR(base); + res = platform_get_resource(pdev, IORESOURCE_MEM, index); + if (!res) { + dev_err(dev, "failed to get mem resource %d\n", index); + return -ENODEV; + } + + if (!request_mem_region(res->start, resource_size(res), res->name)) { + dev_err(dev, "failed to request resource %pR\n", res); + return -EBUSY; + }
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + base = ioremap(res->start, resource_size(res)); + if (IS_ERR(base)) { + dev_err(dev, "failed to map resource %pR\n", res); + ret = PTR_ERR(base); + goto release_region; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { ret = -ENOMEM; - goto error; + goto unmap_base; }
data->soc_data = of_device_get_match_data(&pdev->dev); data->base = base; + data->res = res;
/* HW should be in enabled state to proceed */ if (!(readl_relaxed(base + data->soc_data->reg_enable) & 0x1)) { @@ -349,7 +366,11 @@ static int qcom_cpufreq_hw_cpu_init(stru
return 0; error: - devm_iounmap(dev, base); + kfree(data); +unmap_base: + iounmap(data->base); +release_region: + release_mem_region(res->start, resource_size(res)); return ret; }
@@ -357,12 +378,15 @@ static int qcom_cpufreq_hw_cpu_exit(stru { struct device *cpu_dev = get_cpu_device(policy->cpu); struct qcom_cpufreq_data *data = policy->driver_data; - struct platform_device *pdev = cpufreq_get_driver_data(); + struct resource *res = data->res; + void __iomem *base = data->base;
dev_pm_opp_remove_all_dynamic(cpu_dev); dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); kfree(policy->freq_table); - devm_iounmap(&pdev->dev, data->base); + kfree(data); + iounmap(base); + release_mem_region(res->start, resource_size(res));
return 0; }
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit a45ee4d4e13b0e35a8ec7ea0bf9267243d57b302 upstream.
All of the callers of intel_pstate_get_hwp_max() access the struct cpudata object that corresponds to the given CPU already and the function itself needs to access that object (in order to update hwp_cap_cached), so modify the code to pass a struct cpudata pointer to it instead of the CPU number.
Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Tested-by: Chen Yu yu.c.chen@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/intel_pstate.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -819,13 +819,13 @@ static struct freq_attr *hwp_cpufreq_att NULL, };
-static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max, +static void intel_pstate_get_hwp_max(struct cpudata *cpu, int *phy_max, int *current_max) { u64 cap;
- rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); - WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap); + rdmsrl_on_cpu(cpu->cpu, MSR_HWP_CAPABILITIES, &cap); + WRITE_ONCE(cpu->hwp_cap_cached, cap); if (global.no_turbo || global.turbo_disabled) *current_max = HWP_GUARANTEED_PERF(cap); else @@ -1213,7 +1213,7 @@ static void update_qos_request(enum freq continue;
if (hwp_active) - intel_pstate_get_hwp_max(i, &turbo_max, &max_state); + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); else turbo_max = cpu->pstate.turbo_pstate;
@@ -1723,7 +1723,7 @@ static void intel_pstate_get_cpu_pstates if (hwp_active && !hwp_mode_bdw) { unsigned int phy_max, current_max;
- intel_pstate_get_hwp_max(cpu->cpu, &phy_max, ¤t_max); + intel_pstate_get_hwp_max(cpu, &phy_max, ¤t_max); cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling; cpu->pstate.turbo_pstate = phy_max; } else { @@ -2207,7 +2207,7 @@ static void intel_pstate_update_perf_lim * rather than pure ratios. */ if (hwp_active) { - intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state); + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); } else { max_state = global.no_turbo || global.turbo_disabled ? cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; @@ -2322,7 +2322,7 @@ static void intel_pstate_verify_cpu_poli if (hwp_active) { int max_state, turbo_max;
- intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state); + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); max_freq = max_state * cpu->pstate.scaling; } else { max_freq = intel_pstate_get_max_freq(cpu); @@ -2709,7 +2709,7 @@ static int intel_cpufreq_cpu_init(struct if (hwp_active) { u64 value;
- intel_pstate_get_hwp_max(policy->cpu, &turbo_max, &max_state); + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY_HWP; rdmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, &value); WRITE_ONCE(cpu->hwp_req_cached, value);
From: Chen Yu yu.c.chen@intel.com
commit 6f67e060083a84a4cc364eab6ae40c717165fb0c upstream.
Currently, when turbo is disabled (either by BIOS or by the user), the intel_pstate driver reads the max non-turbo frequency from the package-wide MSR_PLATFORM_INFO(0xce) register.
However, on asymmetric platforms it is possible in theory that small and big core with HWP enabled might have different max non-turbo CPU frequency, because MSR_HWP_CAPABILITIES is per-CPU scope according to Intel Software Developer Manual.
The turbo max freq is already per-CPU in current code, so make similar change to the max non-turbo frequency as well.
Reported-by: Wendy Wang wendy.wang@intel.com Signed-off-by: Chen Yu yu.c.chen@intel.com [ rjw: Subject and changelog edits ] Cc: 4.18+ stable@vger.kernel.org # 4.18+: a45ee4d4e13b: cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/intel_pstate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1714,11 +1714,9 @@ static void intel_pstate_max_within_limi static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { cpu->pstate.min_pstate = pstate_funcs.get_min(); - cpu->pstate.max_pstate = pstate_funcs.get_max(); cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(); cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); cpu->pstate.scaling = pstate_funcs.get_scaling(); - cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
if (hwp_active && !hwp_mode_bdw) { unsigned int phy_max, current_max; @@ -1726,9 +1724,12 @@ static void intel_pstate_get_cpu_pstates intel_pstate_get_hwp_max(cpu, &phy_max, ¤t_max); cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling; cpu->pstate.turbo_pstate = phy_max; + cpu->pstate.max_pstate = HWP_GUARANTEED_PERF(READ_ONCE(cpu->hwp_cap_cached)); } else { cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + cpu->pstate.max_pstate = pstate_funcs.get_max(); } + cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
if (pstate_funcs.get_aperf_mperf_shift) cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
From: Jens Axboe axboe@kernel.dk
commit 0d4370cfe36b7f1719123b621a4ec4d9c7a25f89 upstream.
If this is attempted by an io-wq 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.
Use PF_IO_WORKER for this to speciically target the io_uring workers. Modify the /proc/self/ check to use PF_IO_WORKER as well.
Cc: stable@vger.kernel.org Fixes: 8d4c3e76e3be ("proc: don't allow async path resolution of /proc/self components") Reported-by: Eric W. Biederman ebiederm@xmission.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/proc/self.c | 2 +- fs/proc/thread_self.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
--- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -20,7 +20,7 @@ static const char *proc_self_get_link(st * Not currently supported. Once we can inherit all of struct pid, * we can allow this. */ - if (current->flags & PF_KTHREAD) + if (current->flags & PF_IO_WORKER) return ERR_PTR(-EOPNOTSUPP);
if (!tgid) --- a/fs/proc/thread_self.c +++ b/fs/proc/thread_self.c @@ -17,6 +17,13 @@ static const char *proc_thread_self_get_ pid_t pid = task_pid_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_IO_WORKER) + return ERR_PTR(-EOPNOTSUPP); + if (!pid) return ERR_PTR(-ENOENT); name = kmalloc(10 + 6 + 10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);
From: Heiko Carstens hca@linux.ibm.com
commit b29c5093820d333eef22f58cd04ec0d089059c39 upstream.
The stck/stckf instruction used within the inline assembly within do_account_vtime() changes the condition code. This is not reflected with the clobber list, and therefore might result in incorrect code generation.
It seems unlikely that the compiler could generate incorrect code considering the surrounding C code, but it must still be fixed.
Cc: stable@vger.kernel.org Reviewed-by: Christian Borntraeger borntraeger@de.ibm.com Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/s390/kernel/vtime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -136,7 +136,8 @@ static int do_account_vtime(struct task_ " stck %1" /* Store current tod clock value */ #endif : "=Q" (S390_lowcore.last_update_timer), - "=Q" (S390_lowcore.last_update_clock)); + "=Q" (S390_lowcore.last_update_clock) + : : "cc"); clock = S390_lowcore.last_update_clock - clock; timer -= S390_lowcore.last_update_timer;
From: Cornelia Huck cohuck@redhat.com
commit 182f709c5cff683e6732d04c78e328de0532284f upstream.
CCW_CMD_READ_STATUS was introduced with revision 2 of virtio-ccw, and drivers should only rely on it being implemented when they negotiated at least that revision with the device.
However, virtio_ccw_get_status() issued READ_STATUS for any device operating at least at revision 1. If the device accepts READ_STATUS regardless of the negotiated revision (which some implementations like QEMU do, even though the spec currently does not allow it), everything works as intended. While a device rejecting the command should also be handled gracefully, we will not be able to see any changes the device makes to the status, such as setting NEEDS_RESET or setting the status to zero after a completed reset.
We negotiated the revision to at most 1, as we never bumped the maximum revision; let's do that now and properly send READ_STATUS only if we are operating at least at revision 2.
Cc: stable@vger.kernel.org Fixes: 7d3ce5ab9430 ("virtio/s390: support READ_STATUS command for virtio-ccw") Reviewed-by: Halil Pasic pasic@linux.ibm.com Signed-off-by: Cornelia Huck cohuck@redhat.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Link: https://lore.kernel.org/r/20210216110645.1087321-1-cohuck@redhat.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/s390/virtio/virtio_ccw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -117,7 +117,7 @@ struct virtio_rev_info { };
/* the highest virtio-ccw revision we support */ -#define VIRTIO_CCW_REV_MAX 1 +#define VIRTIO_CCW_REV_MAX 2
struct virtio_ccw_vq_info { struct virtqueue *vq; @@ -952,7 +952,7 @@ static u8 virtio_ccw_get_status(struct v u8 old_status = vcdev->dma_area->status; struct ccw1 *ccw;
- if (vcdev->revision < 1) + if (vcdev->revision < 2) return vcdev->dma_area->status;
ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
From: Johannes Berg johannes.berg@intel.com
commit 47da29763ec9a153b9b685bff9db659e4e09e494 upstream.
If userspace tries to change the stub, we need to kill it, because otherwise it can escape the virtual machine. In a few cases the stub checks weren't good, e.g. if userspace just tries to
mmap(0x100000 - 0x1000, 0x3000, ...)
it could succeed to get a new private/anonymous mapping replacing the stubs. Fix this by checking everywhere, and checking for _overlap_, not just direct changes.
Cc: stable@vger.kernel.org Fixes: 3963333fe676 ("uml: cover stubs with a VMA") Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/um/kernel/tlb.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -125,6 +125,9 @@ static int add_mmap(unsigned long virt, struct host_vm_op *last; int fd = -1, ret = 0;
+ if (virt + len > STUB_START && virt < STUB_END) + return -EINVAL; + if (hvc->userspace) fd = phys_mapping(phys, &offset); else @@ -162,7 +165,7 @@ static int add_munmap(unsigned long addr struct host_vm_op *last; int ret = 0;
- if ((addr >= STUB_START) && (addr < STUB_END)) + if (addr + len > STUB_START && addr < STUB_END) return -EINVAL;
if (hvc->index != 0) { @@ -192,6 +195,9 @@ static int add_mprotect(unsigned long ad struct host_vm_op *last; int ret = 0;
+ if (addr + len > STUB_START && addr < STUB_END) + return -EINVAL; + if (hvc->index != 0) { last = &hvc->ops[hvc->index - 1]; if ((last->type == MPROTECT) && @@ -472,6 +478,10 @@ void flush_tlb_page(struct vm_area_struc struct mm_id *mm_id;
address &= PAGE_MASK; + + if (address >= STUB_START && address < STUB_END) + goto kill; + pgd = pgd_offset(mm, address); if (!pgd_present(*pgd)) goto kill;
From: Johannes Berg johannes.berg@intel.com
commit a7d48886cacf8b426e0079bca9639d2657cf2d38 upstream.
In some cases we can get to fix_range_common() with mmap_sem held, and in others we get there without it being held. For example, we get there with it held from sys_mprotect(), and without it held from fork_handler().
Avoid any issues in this and simply defer killing the task until it runs the next time. Do it on the mm so that another task that shares the same mm can't continue running afterwards.
Cc: stable@vger.kernel.org Fixes: 468f65976a8d ("um: Fix hung task in fix_range_common()") Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Richard Weinberger richard@nod.at Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/um/include/shared/skas/mm_id.h | 1 + arch/um/kernel/tlb.c | 7 +++---- arch/um/os-Linux/skas/process.c | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-)
--- a/arch/um/include/shared/skas/mm_id.h +++ b/arch/um/include/shared/skas/mm_id.h @@ -12,6 +12,7 @@ struct mm_id { int pid; } u; unsigned long stack; + int kill; };
#endif --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -352,12 +352,11 @@ void fix_range_common(struct mm_struct *
/* This is not an else because ret is modified above */ if (ret) { + struct mm_id *mm_idp = ¤t->mm->context.id; + printk(KERN_ERR "fix_range_common: failed, killing current " "process: %d\n", task_tgid_vnr(current)); - /* We are under mmap_lock, release it such that current can terminate */ - mmap_write_unlock(current->mm); - force_sig(SIGKILL); - do_signal(¤t->thread.regs); + mm_idp->kill = 1; } }
--- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -249,6 +249,7 @@ static int userspace_tramp(void *stack) }
int userspace_pid[NR_CPUS]; +int kill_userspace_mm[NR_CPUS];
/** * start_userspace() - prepare a new userspace process @@ -342,6 +343,8 @@ void userspace(struct uml_pt_regs *regs, interrupt_end();
while (1) { + if (kill_userspace_mm[0]) + fatal_sigsegv();
/* * This can legitimately fail if the process loads a @@ -663,4 +666,5 @@ void reboot_skas(void) void __switch_mm(struct mm_id *mm_idp) { userspace_pid[0] = mm_idp->u.pid; + kill_userspace_mm[0] = mm_idp->kill; }
From: Huacai Chen chenhuacai@loongson.cn
commit c1f664d2400e73d5ca0fcd067fa5847d2c789c11 upstream.
Currently we use bitmap_alloc() to allocate msi bitmap which should be initialized with zero. This is obviously wrong but it works because msi can fallback to legacy interrupt mode. So use bitmap_zalloc() instead.
Fixes: 632dcc2c75ef6de3272aa ("irqchip: Add Loongson PCH MSI controller") Cc: stable@vger.kernel.org Signed-off-by: Huacai Chen chenhuacai@loongson.cn Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20210209071051.2078435-1-chenhuacai@loongson.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/irqchip/irq-loongson-pch-msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -225,7 +225,7 @@ static int pch_msi_init(struct device_no goto err_priv; }
- priv->msi_map = bitmap_alloc(priv->num_irqs, GFP_KERNEL); + priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL); if (!priv->msi_map) { ret = -ENOMEM; goto err_priv;
From: Chao Yu yuchao0@huawei.com
commit 2562515f0ad7342bde6456602c491b64c63fe950 upstream.
__setattr_copy() was copied from setattr_copy() in fs/attr.c, there is two missing patches doesn't cover this inner function, fix it.
Commit 7fa294c8991c ("userns: Allow chown and setgid preservation") Commit 23adbe12ef7d ("fs,userns: Change inode_capable to capable_wrt_inode_uidgid")
Fixes: fbfa2cc58d53 ("f2fs: add file operations") Cc: stable@vger.kernel.org Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/f2fs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -852,7 +852,8 @@ static void __setattr_copy(struct inode if (ia_valid & ATTR_MODE) { umode_t mode = attr->ia_mode;
- if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + if (!in_group_p(inode->i_gid) && + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) mode &= ~S_ISGID; set_acl_inode(inode, mode); }
From: Chao Yu yuchao0@huawei.com
commit e0fcd01510ad025c9bbce704c5c2579294056141 upstream.
This patch ports commit 02b016ca7f99 ("ext4: enforce the immutable flag on open files") to f2fs.
According to the chattr man page, "a file with the 'i' attribute cannot be modified..." Historically, this was only enforced when the file was opened, per the rest of the description, "... and the file can not be opened in write mode".
There is general agreement that we should standardize all file systems to prevent modifications even for files that were opened at the time the immutable flag is set. Eventually, a change to enforce this at the VFS layer should be landing in mainline.
Cc: stable@kernel.org Signed-off-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/f2fs/file.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
--- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -60,6 +60,9 @@ static vm_fault_t f2fs_vm_page_mkwrite(s bool need_alloc = true; int err = 0;
+ if (unlikely(IS_IMMUTABLE(inode))) + return VM_FAULT_SIGBUS; + if (unlikely(f2fs_cp_error(sbi))) { err = -EIO; goto err; @@ -870,6 +873,14 @@ int f2fs_setattr(struct dentry *dentry, if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) return -EIO;
+ if (unlikely(IS_IMMUTABLE(inode))) + return -EPERM; + + if (unlikely(IS_APPEND(inode) && + (attr->ia_valid & (ATTR_MODE | ATTR_UID | + ATTR_GID | ATTR_TIMES_SET)))) + return -EPERM; + if ((attr->ia_valid & ATTR_SIZE) && !f2fs_is_compress_backend_ready(inode)) return -EOPNOTSUPP; @@ -4356,6 +4367,11 @@ static ssize_t f2fs_file_write_iter(stru inode_lock(inode); }
+ if (unlikely(IS_IMMUTABLE(inode))) { + ret = -EPERM; + goto unlock; + } + ret = generic_write_checks(iocb, from); if (ret > 0) { bool preallocated = false; @@ -4420,6 +4436,7 @@ write: if (ret > 0) f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret); } +unlock: inode_unlock(inode); out: trace_f2fs_file_write_iter(inode, iocb->ki_pos,
From: Jaegeuk Kim jaegeuk@kernel.org
commit b0ff4fe746fd028eef920ddc8c7b0361c1ede6ec upstream.
During checkpoint=disable period, f2fs bypasses all the synchronous IOs such as sync and fsync. So, when enabling it back, we must flush all of them in order to keep the data persistent. Otherwise, suddern power-cut right after enabling checkpoint will cause data loss.
Fixes: 4354994f097d ("f2fs: checkpoint disabling") Cc: stable@vger.kernel.org Reviewed-by: Chao Yu yuchao0@huawei.com Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/f2fs/super.c | 3 +++ 1 file changed, 3 insertions(+)
--- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1796,6 +1796,9 @@ restore_flag:
static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) { + /* we should flush all the data to keep data consistency */ + sync_inodes_sb(sbi->sb); + down_write(&sbi->gc_lock); f2fs_dirty_to_prefree(sbi);
From: Paulo Alcantara pc@cjr.nz
commit 8513222b9ef2709ba40cbda07b55d5fbcfdd4bc7 upstream.
In do_dfs_failover(), the mount_get_conns() function requires the full fs context in order to get new connection to server, so clone the original context and change it accordingly when retrying the DFS targets in the referral.
If failover was successful, then update original context with the new UNC, prefix path and ip address.
Signed-off-by: Paulo Alcantara (SUSE) pc@cjr.nz Cc: stable@vger.kernel.org # 5.11 Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/connect.c | 123 +++++++++++++++++++++++++----------------------------- 1 file changed, 59 insertions(+), 64 deletions(-)
--- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3038,96 +3038,91 @@ static int update_vol_info(const struct return 0; }
-static int setup_dfs_tgt_conn(const char *path, const char *full_path, - const struct dfs_cache_tgt_iterator *tgt_it, - struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, - unsigned int *xid, struct TCP_Server_Info **server, - struct cifs_ses **ses, struct cifs_tcon **tcon) -{ - int rc; - struct dfs_info3_param ref = {0}; - char *mdata = NULL; - struct smb3_fs_context fake_ctx = {NULL}; - char *fake_devname = NULL; - - cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path); - - rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref); - if (rc) - return rc; - - mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, - full_path + 1, &ref, - &fake_devname); - free_dfs_info_param(&ref); - - if (IS_ERR(mdata)) { - rc = PTR_ERR(mdata); - mdata = NULL; - } else - rc = cifs_setup_volume_info(&fake_ctx, mdata, fake_devname); - - kfree(mdata); - kfree(fake_devname); - - if (!rc) { - /* - * We use a 'fake_ctx' here because we need pass it down to the - * mount_{get,put} functions to test connection against new DFS - * targets. - */ - mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); - rc = mount_get_conns(&fake_ctx, cifs_sb, xid, server, ses, - tcon); - if (!rc || (*server && *ses)) { - /* - * We were able to connect to new target server. - * Update current context with new target server. - */ - rc = update_vol_info(tgt_it, &fake_ctx, ctx); - } - } - smb3_cleanup_fs_context_contents(&fake_ctx); - return rc; -} - static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, struct cifs_ses *root_ses, unsigned int *xid, struct TCP_Server_Info **server, struct cifs_ses **ses, struct cifs_tcon **tcon) { int rc; - struct dfs_cache_tgt_list tgt_list; + struct dfs_cache_tgt_list tgt_list = {0}; struct dfs_cache_tgt_iterator *tgt_it = NULL; + struct smb3_fs_context tmp_ctx = {NULL};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) return -EOPNOTSUPP;
+ cifs_dbg(FYI, "%s: path=%s full_path=%s\n", __func__, path, full_path); + rc = dfs_cache_noreq_find(path, NULL, &tgt_list); if (rc) return rc; + /* + * We use a 'tmp_ctx' here because we need pass it down to the mount_{get,put} functions to + * test connection against new DFS targets. + */ + rc = smb3_fs_context_dup(&tmp_ctx, ctx); + if (rc) + goto out;
for (;;) { + struct dfs_info3_param ref = {0}; + char *fake_devname = NULL, *mdata = NULL; + /* Get next DFS target server - if any */ rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it); if (rc) break; - /* Connect to next DFS target */ - rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, ctx, xid, server, ses, - tcon); - if (!rc || (*server && *ses)) + + rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref); + if (rc) + break; + + cifs_dbg(FYI, "%s: old ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, + tmp_ctx.prepath); + + mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, &ref, + &fake_devname); + free_dfs_info_param(&ref); + + if (IS_ERR(mdata)) { + rc = PTR_ERR(mdata); + mdata = NULL; + } else + rc = cifs_setup_volume_info(&tmp_ctx, mdata, fake_devname); + + kfree(mdata); + kfree(fake_devname); + + if (rc) + break; + + cifs_dbg(FYI, "%s: new ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, + tmp_ctx.prepath); + + mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); + rc = mount_get_conns(&tmp_ctx, cifs_sb, xid, server, ses, tcon); + if (!rc || (*server && *ses)) { + /* + * We were able to connect to new target server. Update current context with + * new target server. + */ + rc = update_vol_info(tgt_it, &tmp_ctx, ctx); break; + } } if (!rc) { + cifs_dbg(FYI, "%s: final ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, + tmp_ctx.prepath); /* - * Update DFS target hint in DFS referral cache with the target - * server we successfully reconnected to. + * Update DFS target hint in DFS referral cache with the target server we + * successfully reconnected to. */ - rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, - cifs_sb->local_nls, - cifs_remap(cifs_sb), path, - tgt_it); + rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, cifs_sb->local_nls, + cifs_remap(cifs_sb), path, tgt_it); } + +out: + smb3_cleanup_fs_context_contents(&tmp_ctx); dfs_cache_free_tgts(&tgt_list); return rc; }
From: Paulo Alcantara pc@cjr.nz
commit ff2c54a04097dee0b8899c485360719844d923f8 upstream.
Handle the case where a resolved target share is like //server/users/dir, and the user "foo" has no read permission to access the parent folder "users" but has access to the final path component "dir".
is_path_remote() already implements that, so call it directly.
Signed-off-by: Paulo Alcantara (SUSE) pc@cjr.nz Cc: stable@vger.kernel.org # 5.11 Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/connect.c | 93 +++++++++++++++++++----------------------------------- 1 file changed, 33 insertions(+), 60 deletions(-)
--- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3280,73 +3280,46 @@ static void put_root_ses(struct cifs_ses cifs_put_smb_ses(ses); }
-/* Check if a path component is remote and then update @dfs_path accordingly */ -static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, - const unsigned int xid, struct TCP_Server_Info *server, - struct cifs_tcon *tcon, char **dfs_path) +/* Set up next dfs prefix path in @dfs_path */ +static int next_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, + const unsigned int xid, struct TCP_Server_Info *server, + struct cifs_tcon *tcon, char **dfs_path) { - char *path, *s; - char sep = CIFS_DIR_SEP(cifs_sb), tmp; - char *npath; - int rc = 0; - int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS; - int skip = added_treename; + char *path, *npath; + int added_treename = is_tcon_dfs(tcon); + int rc;
path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename); if (!path) return -ENOMEM;
- /* - * Walk through the path components in @path and check if they're accessible. In case any of - * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path - * (NOT including the remaining components). - */ - s = path; - do { - /* skip separators */ - while (*s && *s == sep) - s++; - if (!*s) - break; - /* next separator */ - while (*s && *s != sep) - s++; - /* - * if the treename is added, we then have to skip the first - * part within the separators - */ - if (skip) { - skip = 0; - continue; + rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); + if (rc == -EREMOTE) { + struct smb3_fs_context v = {NULL}; + /* if @path contains a tree name, skip it in the prefix path */ + if (added_treename) { + rc = smb3_parse_devname(path, &v); + if (rc) + goto out; + npath = build_unc_path_to_root(&v, cifs_sb, true); + smb3_cleanup_fs_context_contents(&v); + } else { + v.UNC = ctx->UNC; + v.prepath = path + 1; + npath = build_unc_path_to_root(&v, cifs_sb, true); } - tmp = *s; - *s = 0; - rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path); - if (rc && rc == -EREMOTE) { - struct smb3_fs_context v = {NULL}; - /* if @path contains a tree name, skip it in the prefix path */ - if (added_treename) { - rc = smb3_parse_devname(path, &v); - if (rc) - break; - rc = -EREMOTE; - npath = build_unc_path_to_root(&v, cifs_sb, true); - smb3_cleanup_fs_context_contents(&v); - } else { - v.UNC = ctx->UNC; - v.prepath = path + 1; - npath = build_unc_path_to_root(&v, cifs_sb, true); - } - if (IS_ERR(npath)) { - rc = PTR_ERR(npath); - break; - } - kfree(*dfs_path); - *dfs_path = npath; + + if (IS_ERR(npath)) { + rc = PTR_ERR(npath); + goto out; } - *s = tmp; - } while (rc == 0);
+ kfree(*dfs_path); + *dfs_path = npath; + rc = -EREMOTE; + } + +out: kfree(path); return rc; } @@ -3432,8 +3405,8 @@ int cifs_mount(struct cifs_sb_info *cifs put_root_ses(root_ses); set_root_ses(cifs_sb, ses, &root_ses); } - /* Check for remaining path components and then continue chasing them (-EREMOTE) */ - rc = check_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path); + /* Get next dfs path and then continue chasing them if -EREMOTE */ + rc = next_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path); /* Prevent recursion on broken link referrals */ if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) rc = -ELOOP;
From: Paulo Alcantara pc@cjr.nz
commit 5ff2836ed3a5c24420a7235be25a462594cdc4ea upstream.
Some servers seem to mistakenly report different values for capabilities and share flags, so we can't always rely on those values to decide whether the resolved target can handle any new DFS referrals.
Add a new helper is_referral_server() to check if all resolved targets can handle new DFS referrals by directly looking at the GET_DFS_REFERRAL.ReferralHeaderFlags value as specified in MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL in addition to is_tcon_dfs().
Signed-off-by: Paulo Alcantara (SUSE) pc@cjr.nz Cc: stable@vger.kernel.org # 5.11 Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/connect.c | 35 ++++++++++++++++++++++++++++++++++- fs/cifs/dfs_cache.c | 33 +++++++++++++++++---------------- 2 files changed, 51 insertions(+), 17 deletions(-)
--- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3324,6 +3324,33 @@ out: return rc; }
+/* Check if resolved targets can handle any DFS referrals */ +static int is_referral_server(const char *ref_path, struct cifs_tcon *tcon, bool *ref_server) +{ + int rc; + struct dfs_info3_param ref = {0}; + + if (is_tcon_dfs(tcon)) { + *ref_server = true; + } else { + cifs_dbg(FYI, "%s: ref_path=%s\n", __func__, ref_path); + + rc = dfs_cache_noreq_find(ref_path, &ref, NULL); + if (rc) { + cifs_dbg(VFS, "%s: dfs_cache_noreq_find: failed (rc=%d)\n", __func__, rc); + return rc; + } + cifs_dbg(FYI, "%s: ref.flags=0x%x\n", __func__, ref.flags); + /* + * Check if all targets are capable of handling DFS referrals as per + * MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL. + */ + *ref_server = !!(ref.flags & DFSREF_REFERRAL_SERVER); + free_dfs_info_param(&ref); + } + return 0; +} + int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) { int rc = 0; @@ -3335,6 +3362,7 @@ int cifs_mount(struct cifs_sb_info *cifs char *ref_path = NULL, *full_path = NULL; char *oldmnt = NULL; char *mntdata = NULL; + bool ref_server = false;
rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); /* @@ -3400,11 +3428,16 @@ int cifs_mount(struct cifs_sb_info *cifs break; if (!tcon) continue; + /* Make sure that requests go through new root servers */ - if (is_tcon_dfs(tcon)) { + rc = is_referral_server(ref_path + 1, tcon, &ref_server); + if (rc) + break; + if (ref_server) { put_root_ses(root_ses); set_root_ses(cifs_sb, ses, &root_ses); } + /* Get next dfs path and then continue chasing them if -EREMOTE */ rc = next_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path); /* Prevent recursion on broken link referrals */ --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -37,11 +37,12 @@ struct cache_dfs_tgt { struct cache_entry { struct hlist_node hlist; const char *path; - int ttl; - int srvtype; - int flags; + int hdr_flags; /* RESP_GET_DFS_REFERRAL.ReferralHeaderFlags */ + int ttl; /* DFS_REREFERRAL_V3.TimeToLive */ + int srvtype; /* DFS_REREFERRAL_V3.ServerType */ + int ref_flags; /* DFS_REREFERRAL_V3.ReferralEntryFlags */ struct timespec64 etime; - int path_consumed; + int path_consumed; /* RESP_GET_DFS_REFERRAL.PathConsumed */ int numtgts; struct list_head tlist; struct cache_dfs_tgt *tgthint; @@ -166,14 +167,11 @@ static int dfscache_proc_show(struct seq continue;
seq_printf(m, - "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," - "interlink=%s,path_consumed=%d,expired=%s\n", - ce->path, - ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", - ce->ttl, ce->etime.tv_nsec, - IS_INTERLINK_SET(ce->flags) ? "yes" : "no", - ce->path_consumed, - cache_entry_expired(ce) ? "yes" : "no"); + "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n", + ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", + ce->ttl, ce->etime.tv_nsec, ce->ref_flags, ce->hdr_flags, + IS_INTERLINK_SET(ce->hdr_flags) ? "yes" : "no", + ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no");
list_for_each_entry(t, &ce->tlist, list) { seq_printf(m, " %s%s\n", @@ -236,11 +234,12 @@ static inline void dump_tgts(const struc
static inline void dump_ce(const struct cache_entry *ce) { - cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,interlink=%s,path_consumed=%d,expired=%s\n", + cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n", ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ce->etime.tv_nsec, - IS_INTERLINK_SET(ce->flags) ? "yes" : "no", + ce->hdr_flags, ce->ref_flags, + IS_INTERLINK_SET(ce->hdr_flags) ? "yes" : "no", ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); dump_tgts(ce); @@ -381,7 +380,8 @@ static int copy_ref_data(const struct df ce->ttl = refs[0].ttl; ce->etime = get_expire_time(ce->ttl); ce->srvtype = refs[0].server_type; - ce->flags = refs[0].ref_flag; + ce->hdr_flags = refs[0].flags; + ce->ref_flags = refs[0].ref_flag; ce->path_consumed = refs[0].path_consumed;
for (i = 0; i < numrefs; i++) { @@ -799,7 +799,8 @@ static int setup_referral(const char *pa ref->path_consumed = ce->path_consumed; ref->ttl = ce->ttl; ref->server_type = ce->srvtype; - ref->ref_flag = ce->flags; + ref->ref_flag = ce->ref_flags; + ref->flags = ce->hdr_flags;
return 0;
From: Paulo Alcantara pc@cjr.nz
commit d01132ae50207bb6fd94e08e80c2d7b839408086 upstream.
Skip DFS resolving when mounting with 'nodfs' even if CONFIG_CIFS_DFS_UPCALL is enabled.
Signed-off-by: Paulo Alcantara (SUSE) pc@cjr.nz Cc: stable@vger.kernel.org # 5.11 Reviewed-by: Shyam Prasad N sprasad@microsoft.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/connect.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3366,15 +3366,15 @@ int cifs_mount(struct cifs_sb_info *cifs
rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); /* - * Unconditionally try to get an DFS referral (even cached) to determine whether it is an - * DFS mount. + * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally + * try to get an DFS referral (even cached) to determine whether it is an DFS mount. * * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem * to respond with PATH_NOT_COVERED to requests that include the prefix. */ - if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ctx->UNC + 1, NULL, + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) || + dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ctx->UNC + 1, NULL, NULL)) { - /* No DFS referral was returned. Looks like a regular share. */ if (rc) goto error; /* Check if it is fully accessible and then mount it */
From: Ronnie Sahlberg lsahlber@redhat.com
commit d08395a3f2f473c6ceeb316a1aeb7fad5b43014f upstream.
Passwords can contain ',' which are also used as the separator between mount options. Mount.cifs will escape all ',' characters as the string ",,". Update parsing of the mount options to detect ",," and treat it as a single 'c' character.
Fixes: 24e0a1eff9e2 ("cifs: switch to new mount api") Cc: stable@vger.kernel.org # 5.11 Reported-by: Simon Taylor simon@simon-taylor.me.uk Tested-by: Simon Taylor simon@simon-taylor.me.uk Signed-off-by: Ronnie Sahlberg lsahlber@redhat.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/cifs/fs_context.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-)
--- a/fs/cifs/fs_context.c +++ b/fs/cifs/fs_context.c @@ -542,20 +542,37 @@ static int smb3_fs_context_parse_monolit
/* BB Need to add support for sep= here TBD */ while ((key = strsep(&options, ",")) != NULL) { - if (*key) { - size_t v_len = 0; - char *value = strchr(key, '='); - - if (value) { - if (value == key) - continue; - *value++ = 0; - v_len = strlen(value); - } - ret = vfs_parse_fs_string(fc, key, value, v_len); - if (ret < 0) - break; + size_t len; + char *value; + + if (*key == 0) + break; + + /* Check if following character is the deliminator If yes, + * we have encountered a double deliminator reset the NULL + * character to the deliminator + */ + while (options && options[0] == ',') { + len = strlen(key); + strcpy(key + len, options); + options = strchr(options, ','); + if (options) + *options++ = 0; + } + + + len = 0; + value = strchr(key, '='); + if (value) { + if (value == key) + continue; + *value++ = 0; + len = strlen(value); } + + ret = vfs_parse_fs_string(fc, key, value, len); + if (ret < 0) + break; }
return ret;
From: Al Viro viro@zeniv.linux.org.uk
commit 7780918b36489f0b2f9a3749d7be00c2ceaec513 upstream.
Back in 2.1.29 the clear_user() guts (__bzero()) had been merged with memset(). Unfortunately, while all exception handlers had been copied, one of the exception table entries got lost. As the result, clear_user() starting at 128*n bytes before the end of page and spanning between 8 and 127 bytes into the next page would oops when the second page is unmapped. It's trivial to reproduce - all it takes is
main() { int fd = open("/dev/zero", O_RDONLY); char *p = mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); munmap(p + 8192, 8192); read(fd, p + 8192 - 128, 192); }
which had been oopsing since March 1997. Says something about the quality of test coverage... ;-/ And while today sparc32 port is nearly dead, back in '97 it had been very much alive; in fact, sparc64 had only been in mainline for 3 months by that point...
Cc: stable@kernel.org Fixes: v2.1.29 Signed-off-by: Al Viro viro@zeniv.linux.org.uk Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/sparc/lib/memset.S | 1 + 1 file changed, 1 insertion(+)
--- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S @@ -142,6 +142,7 @@ __bzero: ZERO_LAST_BLOCKS(%o0, 0x48, %g2) ZERO_LAST_BLOCKS(%o0, 0x08, %g2) 13: + EXT(12b, 13b, 21f) be 8f andcc %o1, 4, %g0
From: Paul Cercueil paul@crapouillou.net
commit a81fbb8771a3810a58d657763fde610bf2c33286 upstream.
ftw() has been obsolete for about 12 years now.
Committer notes:
Further notes provided by the patch author:
"NOTE: Not runtime-tested, I have no idea what I need to do in perf to test this. But at least it compiles now with my uClibc-based toolchain."
I looked at the nftw()/ftw() man page and for the use made with cgroups in 'perf stat' the end result is equivalent.
Fixes: bb1c15b60b98 ("perf stat: Support regex pattern in --for-each-cgroup") Signed-off-by: Paul Cercueil paul@crapouillou.net Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: od@zcrc.me Cc: stable@vger.kernel.org Link: http://lore.kernel.org/lkml/20210208181157.1324550-1-paul@crapouillou.net Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/perf/util/cgroup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -161,7 +161,7 @@ void evlist__set_default_cgroup(struct e
/* helper function for ftw() in match_cgroups and list_cgroups */ static int add_cgroup_name(const char *fpath, const struct stat *sb __maybe_unused, - int typeflag) + int typeflag, struct FTW *ftwbuf __maybe_unused) { struct cgroup_name *cn;
@@ -209,12 +209,12 @@ static int list_cgroups(const char *str) if (!s) return -1; /* pretend if it's added by ftw() */ - ret = add_cgroup_name(s, NULL, FTW_D); + ret = add_cgroup_name(s, NULL, FTW_D, NULL); free(s); if (ret) return -1; } else { - if (add_cgroup_name("", NULL, FTW_D) < 0) + if (add_cgroup_name("", NULL, FTW_D, NULL) < 0) return -1; }
@@ -247,7 +247,7 @@ static int match_cgroups(const char *str prefix_len = strlen(mnt);
/* collect all cgroups in the cgroup_list */ - if (ftw(mnt, add_cgroup_name, 20) < 0) + if (nftw(mnt, add_cgroup_name, 20, 0) < 0) return -1;
for (;;) {
From: Rasmus Villemoes rasmus.villemoes@prevas.dk
commit 9d2aa6dbf87af89c13cac2d1b4cccad83fb14a7e upstream.
Commit 7a2da5d7960a ("spi: fsl: Fix driver breakage when SPI_CS_HIGH is not set in spi->mode") broke our MPC8309 board by effectively inverting the boolean value passed to fsl_spi_cs_control. The SPISEL_BOOT signal is used as chipselect, but it's not a gpio, so we cannot rely on gpiolib handling the polarity.
Adapt to the new world order by inverting the logic here. This does assume that the slave sitting at the SPISEL_BOOT is active low, but should that ever turn out not to be the case, one can create a stub gpiochip driver controlling a single gpio (or rather, a single "spo", special-purpose output).
Fixes: 7a2da5d7960a ("spi: fsl: Fix driver breakage when SPI_CS_HIGH is not set in spi->mode") Cc: stable@vger.kernel.org Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk Link: https://lore.kernel.org/r/20210130143545.505613-1-rasmus.villemoes@prevas.dk Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/spi/spi-fsl-spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -695,7 +695,7 @@ static void fsl_spi_cs_control(struct sp
if (WARN_ON_ONCE(!pinfo->immr_spi_cs)) return; - iowrite32be(on ? SPI_BOOT_SEL_BIT : 0, pinfo->immr_spi_cs); + iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs); } }
From: Masahisa Kojima masahisa.kojima@linaro.org
commit 1c9f1750f0305bf605ff22686fc0ac89c06deb28 upstream.
When the slave chip select is deasserted, DMSTOP bit must be set.
Fixes: b0823ee35cf9 ("spi: Add spi driver for Socionext SynQuacer platform") Signed-off-by: Masahisa Kojima masahisa.kojima@linaro.org Signed-off-by: Jassi Brar jaswinder.singh@linaro.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210201073109.9036-1-jassisinghbrar@gmail.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/spi/spi-synquacer.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -490,6 +490,10 @@ static void synquacer_spi_set_cs(struct val &= ~(SYNQUACER_HSSPI_DMPSEL_CS_MASK << SYNQUACER_HSSPI_DMPSEL_CS_SHIFT); val |= spi->chip_select << SYNQUACER_HSSPI_DMPSEL_CS_SHIFT; + + if (!enable) + val |= SYNQUACER_HSSPI_DMSTOP_STOP; + writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); }
From: Bob Peterson rpeterso@redhat.com
commit f5f02fde9f52b2d769c1c2ddfd3d9c4a1fe739a7 upstream.
If go_free is defined, function signal_our_withdraw is supposed to synchronize on the GLF_FREEING flag of the inode glock, but it accidentally does that on the live glock. Fix that and disambiguate the glock variables.
Fixes: 601ef0d52e96 ("gfs2: Force withdraw to replay journals and wait for it to finish") Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Bob Peterson rpeterso@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/gfs2/util.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
--- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -93,9 +93,10 @@ out_unlock:
static void signal_our_withdraw(struct gfs2_sbd *sdp) { - struct gfs2_glock *gl = sdp->sd_live_gh.gh_gl; + struct gfs2_glock *live_gl = sdp->sd_live_gh.gh_gl; struct inode *inode = sdp->sd_jdesc->jd_inode; struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *i_gl = ip->i_gl; u64 no_formal_ino = ip->i_no_formal_ino; int ret = 0; int tries; @@ -141,7 +142,8 @@ static void signal_our_withdraw(struct g atomic_set(&sdp->sd_freeze_state, SFS_FROZEN); thaw_super(sdp->sd_vfs); } else { - wait_on_bit(&gl->gl_flags, GLF_DEMOTE, TASK_UNINTERRUPTIBLE); + wait_on_bit(&i_gl->gl_flags, GLF_DEMOTE, + TASK_UNINTERRUPTIBLE); }
/* @@ -161,15 +163,15 @@ static void signal_our_withdraw(struct g * on other nodes to be successful, otherwise we remain the owner of * the glock as far as dlm is concerned. */ - if (gl->gl_ops->go_free) { - set_bit(GLF_FREEING, &gl->gl_flags); - wait_on_bit(&gl->gl_flags, GLF_FREEING, TASK_UNINTERRUPTIBLE); + if (i_gl->gl_ops->go_free) { + set_bit(GLF_FREEING, &i_gl->gl_flags); + wait_on_bit(&i_gl->gl_flags, GLF_FREEING, TASK_UNINTERRUPTIBLE); }
/* * Dequeue the "live" glock, but keep a reference so it's never freed. */ - gfs2_glock_hold(gl); + gfs2_glock_hold(live_gl); gfs2_glock_dq_wait(&sdp->sd_live_gh); /* * We enqueue the "live" glock in EX so that all other nodes @@ -208,7 +210,7 @@ static void signal_our_withdraw(struct g gfs2_glock_nq(&sdp->sd_live_gh); }
- gfs2_glock_queue_put(gl); /* drop the extra reference we acquired */ + gfs2_glock_queue_put(live_gl); /* drop extra reference we acquired */ clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
/*
From: Bob Peterson rpeterso@redhat.com
commit 78178ca844f0eb88f21f31c7fde969384be4c901 upstream.
Patch fb6791d100d1 was designed to allow gfs2 to unmount quicker by skipping the step where it tells dlm to unlock glocks in EX with lvbs. This was done because when gfs2 unmounts a file system, it destroys the dlm lockspace shortly after it destroys the glocks so it doesn't need to unlock them all: the unlock is implied when the lockspace is destroyed by dlm.
However, that patch introduced a use-after-free in dlm: as part of its normal dlm_recoverd process, it can call ls_recovery to recover dead locks. In so doing, it can call recover_rsbs which calls recover_lvb for any mastered rsbs. Func recover_lvb runs through the list of lkbs queued to the given rsb (if the glock is cached but unlocked, it will still be queued to the lkb, but in NL--Unlocked--mode) and if it has an lvb, copies it to the rsb, thus trying to preserve the lkb. However, when gfs2 skips the dlm unlock step, it frees the glock and its lvb, which means dlm's function recover_lvb references the now freed lvb pointer, copying the freed lvb memory to the rsb.
This patch changes the check in gdlm_put_lock so that it calls dlm_unlock for all glocks that contain an lvb pointer.
Fixes: fb6791d100d1 ("GFS2: skip dlm_unlock calls in unmount") Cc: stable@vger.kernel.org # v3.8+ Signed-off-by: Bob Peterson rpeterso@redhat.com Signed-off-by: Andreas Gruenbacher agruenba@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/gfs2/lock_dlm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
--- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -284,7 +284,6 @@ static void gdlm_put_lock(struct gfs2_gl { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct lm_lockstruct *ls = &sdp->sd_lockstruct; - int lvb_needs_unlock = 0; int error;
if (gl->gl_lksb.sb_lkid == 0) { @@ -297,13 +296,10 @@ static void gdlm_put_lock(struct gfs2_gl gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_update_request_times(gl);
- /* don't want to skip dlm_unlock writing the lvb when lock is ex */ - - if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE)) - lvb_needs_unlock = 1; + /* don't want to skip dlm_unlock writing the lvb when lock has one */
if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && - !lvb_needs_unlock) { + !gl->gl_lksb.sb_lvbptr) { gfs2_glock_free(gl); return; }
From: Andreas Gruenbacher agruenba@redhat.com
commit 834ec3e1ee65029029225a86c12337a6cd385af7 upstream.
In gfs2_recover_one, fix a sd_log_flush_lock imbalance when a recovery pass fails.
Fixes: c9ebc4b73799 ("gfs2: allow journal replay to hold sd_log_flush_lock") Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Andreas Gruenbacher agruenba@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/gfs2/recovery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -514,8 +514,10 @@ void gfs2_recover_func(struct work_struc error = foreach_descriptor(jd, head.lh_tail, head.lh_blkno, pass); lops_after_scan(jd, error, pass); - if (error) + if (error) { + up_read(&sdp->sd_log_flush_lock); goto fail_gunlock_thaw; + } }
recover_local_statfs(jd, &head);
From: Andreas Gruenbacher agruenba@redhat.com
commit 7009fa9cd9a5262944b30eb7efb1f0561d074b68 upstream.
When starting an iomap write, gfs2_quota_lock_check -> gfs2_quota_lock -> gfs2_quota_hold is called from gfs2_iomap_begin. At the end of the write, before unlocking the quotas, punch_hole -> gfs2_quota_hold can be called again in gfs2_iomap_end, which is incorrect and leads to a failed assertion. Instead, move the call to gfs2_quota_unlock before the call to punch_hole to fix that.
Fixes: 64bc06bb32ee ("gfs2: iomap buffered write support") Cc: stable@vger.kernel.org # v4.19+ Signed-off-by: Andreas Gruenbacher agruenba@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/gfs2/bmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1230,6 +1230,9 @@ static int gfs2_iomap_end(struct inode *
gfs2_inplace_release(ip);
+ if (ip->i_qadata && ip->i_qadata->qa_qd_num) + gfs2_quota_unlock(ip); + if (length != written && (iomap->flags & IOMAP_F_NEW)) { /* Deallocate blocks that were just allocated. */ loff_t blockmask = i_blocksize(inode) - 1; @@ -1242,9 +1245,6 @@ static int gfs2_iomap_end(struct inode * } }
- if (ip->i_qadata && ip->i_qadata->qa_qd_num) - gfs2_quota_unlock(ip); - if (unlikely(!written)) goto out_unlock;
From: Mikulas Patocka mpatocka@redhat.com
commit a666e5c05e7c4aaabb2c5d58117b0946803d03d2 upstream.
The system would deadlock when swapping to a dm-crypt device. The reason is that for each incoming write bio, dm-crypt allocates memory that holds encrypted data. These excessive allocations exhaust all the memory and the result is either deadlock or OOM trigger.
This patch limits the number of in-flight swap bios, so that the memory consumed by dm-crypt is limited. The limit is enforced if the target set the "limit_swap_bios" variable and if the bio has REQ_SWAP set.
Non-swap bios are not affected becuase taking the semaphore would cause performance degradation.
This is similar to request-based drivers - they will also block when the number of requests is over the limit.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-core.h | 4 ++ drivers/md/dm-crypt.c | 1 drivers/md/dm.c | 60 ++++++++++++++++++++++++++++++++++++++++++ include/linux/device-mapper.h | 5 +++ 4 files changed, 70 insertions(+)
--- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -102,6 +102,10 @@ struct mapped_device { /* kobject and completion */ struct dm_kobject_holder kobj_holder;
+ int swap_bios; + struct semaphore swap_bios_semaphore; + struct mutex swap_bios_lock; + struct dm_stats stats;
/* for blk-mq request-based DM support */ --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -3324,6 +3324,7 @@ static int crypt_ctr(struct dm_target *t wake_up_process(cc->write_thread);
ti->num_flush_bios = 1; + ti->limit_swap_bios = true;
return 0;
--- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -148,6 +148,16 @@ EXPORT_SYMBOL_GPL(dm_bio_get_target_bio_ #define DM_NUMA_NODE NUMA_NO_NODE static int dm_numa_node = DM_NUMA_NODE;
+#define DEFAULT_SWAP_BIOS (8 * 1048576 / PAGE_SIZE) +static int swap_bios = DEFAULT_SWAP_BIOS; +static int get_swap_bios(void) +{ + int latch = READ_ONCE(swap_bios); + if (unlikely(latch <= 0)) + latch = DEFAULT_SWAP_BIOS; + return latch; +} + /* * For mempools pre-allocation at the table loading time. */ @@ -969,6 +979,11 @@ void disable_write_zeroes(struct mapped_ limits->max_write_zeroes_sectors = 0; }
+static bool swap_bios_limit(struct dm_target *ti, struct bio *bio) +{ + return unlikely((bio->bi_opf & REQ_SWAP) != 0) && unlikely(ti->limit_swap_bios); +} + static void clone_endio(struct bio *bio) { blk_status_t error = bio->bi_status; @@ -1019,6 +1034,11 @@ static void clone_endio(struct bio *bio) } }
+ if (unlikely(swap_bios_limit(tio->ti, bio))) { + struct mapped_device *md = io->md; + up(&md->swap_bios_semaphore); + } + free_tio(tio); dec_pending(io, error); } @@ -1252,6 +1272,22 @@ void dm_accept_partial_bio(struct bio *b } EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
+static noinline void __set_swap_bios_limit(struct mapped_device *md, int latch) +{ + mutex_lock(&md->swap_bios_lock); + while (latch < md->swap_bios) { + cond_resched(); + down(&md->swap_bios_semaphore); + md->swap_bios--; + } + while (latch > md->swap_bios) { + cond_resched(); + up(&md->swap_bios_semaphore); + md->swap_bios++; + } + mutex_unlock(&md->swap_bios_lock); +} + static blk_qc_t __map_bio(struct dm_target_io *tio) { int r; @@ -1271,6 +1307,14 @@ static blk_qc_t __map_bio(struct dm_targ atomic_inc(&io->io_count); sector = clone->bi_iter.bi_sector;
+ if (unlikely(swap_bios_limit(ti, clone))) { + struct mapped_device *md = io->md; + int latch = get_swap_bios(); + if (unlikely(latch != md->swap_bios)) + __set_swap_bios_limit(md, latch); + down(&md->swap_bios_semaphore); + } + r = ti->type->map(ti, clone); switch (r) { case DM_MAPIO_SUBMITTED: @@ -1281,10 +1325,18 @@ static blk_qc_t __map_bio(struct dm_targ ret = submit_bio_noacct(clone); break; case DM_MAPIO_KILL: + if (unlikely(swap_bios_limit(ti, clone))) { + struct mapped_device *md = io->md; + up(&md->swap_bios_semaphore); + } free_tio(tio); dec_pending(io, BLK_STS_IOERR); break; case DM_MAPIO_REQUEUE: + if (unlikely(swap_bios_limit(ti, clone))) { + struct mapped_device *md = io->md; + up(&md->swap_bios_semaphore); + } free_tio(tio); dec_pending(io, BLK_STS_DM_REQUEUE); break; @@ -1747,6 +1799,7 @@ static void cleanup_mapped_device(struct mutex_destroy(&md->suspend_lock); mutex_destroy(&md->type_lock); mutex_destroy(&md->table_devices_lock); + mutex_destroy(&md->swap_bios_lock);
dm_mq_cleanup_mapped_device(md); } @@ -1814,6 +1867,10 @@ static struct mapped_device *alloc_dev(i init_waitqueue_head(&md->eventq); init_completion(&md->kobj_holder.completion);
+ md->swap_bios = get_swap_bios(); + sema_init(&md->swap_bios_semaphore, md->swap_bios); + mutex_init(&md->swap_bios_lock); + md->disk->major = _major; md->disk->first_minor = minor; md->disk->fops = &dm_blk_dops; @@ -3097,6 +3154,9 @@ MODULE_PARM_DESC(reserved_bio_based_ios, module_param(dm_numa_node, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dm_numa_node, "NUMA node for DM device memory allocations");
+module_param(swap_bios, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(swap_bios, "Maximum allowed inflight swap IOs"); + MODULE_DESCRIPTION(DM_NAME " driver"); MODULE_AUTHOR("Joe Thornber dm-devel@redhat.com"); MODULE_LICENSE("GPL"); --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -325,6 +325,11 @@ struct dm_target { * whether or not its underlying devices have support. */ bool discards_supported:1; + + /* + * Set if we need to limit the number of in-flight bios when swapping. + */ + bool limit_swap_bios:1; };
void *dm_per_bio_data(struct bio *bio, size_t data_size);
From: Jeffle Xu jefflexu@linux.alibaba.com
commit a4c8dd9c2d0987cf542a2a0c42684c9c6d78a04e upstream.
According to the definition of dm_iterate_devices_fn: * This function must iterate through each section of device used by the * target until it encounters a non-zero return code, which it then returns. * Returns zero if no callout returned non-zero.
For some target type (e.g. dm-stripe), one call of iterate_devices() may iterate multiple underlying devices internally, in which case a non-zero return code returned by iterate_devices_callout_fn will stop the iteration in advance. No iterate_devices_callout_fn should return non-zero unless device iteration should stop.
Rename dm_table_requires_stable_pages() to dm_table_any_dev_attr() and elevate it for reuse to stop iterating (and return non-zero) on the first device that causes iterate_devices_callout_fn to return non-zero. Use dm_table_any_dev_attr() to properly iterate through devices.
Rename device_is_nonrot() to device_is_rotational() and invert logic accordingly to fix improper disposition.
Fixes: c3c4555edd10 ("dm table: clear add_random unless all devices have it set") Fixes: 4693c9668fdc ("dm table: propagate non rotational flag") Cc: stable@vger.kernel.org Signed-off-by: Jeffle Xu jefflexu@linux.alibaba.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-table.c | 97 ++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 46 deletions(-)
--- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1295,6 +1295,46 @@ struct dm_target *dm_table_find_target(s return &t->targets[(KEYS_PER_NODE * n) + k]; }
+/* + * type->iterate_devices() should be called when the sanity check needs to + * iterate and check all underlying data devices. iterate_devices() will + * iterate all underlying data devices until it encounters a non-zero return + * code, returned by whether the input iterate_devices_callout_fn, or + * iterate_devices() itself internally. + * + * For some target type (e.g. dm-stripe), one call of iterate_devices() may + * iterate multiple underlying devices internally, in which case a non-zero + * return code returned by iterate_devices_callout_fn will stop the iteration + * in advance. + * + * Cases requiring _any_ underlying device supporting some kind of attribute, + * should use the iteration structure like dm_table_any_dev_attr(), or call + * it directly. @func should handle semantics of positive examples, e.g. + * capable of something. + * + * Cases requiring _all_ underlying devices supporting some kind of attribute, + * should use the iteration structure like dm_table_supports_nowait() or + * dm_table_supports_discards(). Or introduce dm_table_all_devs_attr() that + * uses an @anti_func that handle semantics of counter examples, e.g. not + * capable of something. So: return !dm_table_any_dev_attr(t, anti_func); + */ +static bool dm_table_any_dev_attr(struct dm_table *t, + iterate_devices_callout_fn func) +{ + struct dm_target *ti; + unsigned int i; + + for (i = 0; i < dm_table_get_num_targets(t); i++) { + ti = dm_table_get_target(t, i); + + if (ti->type->iterate_devices && + ti->type->iterate_devices(ti, func, NULL)) + return true; + } + + return false; +} + static int count_device(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { @@ -1595,12 +1635,12 @@ static int dm_table_supports_dax_write_c return false; }
-static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_is_rotational(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev);
- return q && blk_queue_nonrot(q); + return q && !blk_queue_nonrot(q); }
static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, @@ -1611,23 +1651,6 @@ static int device_is_not_random(struct d return q && !blk_queue_add_random(q); }
-static bool dm_table_all_devices_attribute(struct dm_table *t, - iterate_devices_callout_fn func) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, func, NULL)) - return false; - } - - return true; -} - static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { @@ -1779,27 +1802,6 @@ static int device_requires_stable_pages( return q && blk_queue_stable_writes(q); }
-/* - * If any underlying device requires stable pages, a table must require - * them as well. Only targets that support iterate_devices are considered: - * don't want error, zero, etc to require stable pages. - */ -static bool dm_table_requires_stable_pages(struct dm_table *t) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, device_requires_stable_pages, NULL)) - return true; - } - - return false; -} - void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { @@ -1849,10 +1851,10 @@ void dm_table_set_restrictions(struct dm dax_write_cache(t->md->dax_dev, true);
/* Ensure that all underlying devices are non-rotational. */ - if (dm_table_all_devices_attribute(t, device_is_nonrot)) - blk_queue_flag_set(QUEUE_FLAG_NONROT, q); - else + if (dm_table_any_dev_attr(t, device_is_rotational)) blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); + else + blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
if (!dm_table_supports_write_same(t)) q->limits.max_write_same_sectors = 0; @@ -1864,8 +1866,11 @@ void dm_table_set_restrictions(struct dm /* * Some devices don't use blk_integrity but still want stable pages * because they do their own checksumming. + * If any underlying device requires stable pages, a table must require + * them as well. Only targets that support iterate_devices are considered: + * don't want error, zero, etc to require stable pages. */ - if (dm_table_requires_stable_pages(t)) + if (dm_table_any_dev_attr(t, device_requires_stable_pages)) blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, q); else blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, q); @@ -1876,7 +1881,7 @@ void dm_table_set_restrictions(struct dm * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not * have it set. */ - if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random)) + if (blk_queue_add_random(q) && dm_table_any_dev_attr(t, device_is_not_random)) blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
/*
From: Jeffle Xu jefflexu@linux.alibaba.com
commit 5b0fab508992c2e120971da658ce80027acbc405 upstream.
Fix dm_table_supports_dax() and invert logic of both iterate_devices_callout_fn so that all devices' DAX capabilities are properly checked.
Fixes: 545ed20e6df6 ("dm: add infrastructure for DAX support") Cc: stable@vger.kernel.org Signed-off-by: Jeffle Xu jefflexu@linux.alibaba.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-table.c | 37 ++++++++++--------------------------- drivers/md/dm.c | 2 +- drivers/md/dm.h | 2 +- 3 files changed, 12 insertions(+), 29 deletions(-)
--- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -820,24 +820,24 @@ void dm_table_set_type(struct dm_table * EXPORT_SYMBOL_GPL(dm_table_set_type);
/* validate the dax capability of the target device span */ -int device_supports_dax(struct dm_target *ti, struct dm_dev *dev, +int device_not_dax_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { int blocksize = *(int *) data, id; bool rc;
id = dax_read_lock(); - rc = dax_supported(dev->dax_dev, dev->bdev, blocksize, start, len); + rc = !dax_supported(dev->dax_dev, dev->bdev, blocksize, start, len); dax_read_unlock(id);
return rc; }
/* Check devices support synchronous DAX */ -static int device_dax_synchronous(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_not_dax_synchronous_capable(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { - return dev->dax_dev && dax_synchronous(dev->dax_dev); + return !dev->dax_dev || !dax_synchronous(dev->dax_dev); }
bool dm_table_supports_dax(struct dm_table *t, @@ -854,7 +854,7 @@ bool dm_table_supports_dax(struct dm_tab return false;
if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, iterate_fn, blocksize)) + ti->type->iterate_devices(ti, iterate_fn, blocksize)) return false; }
@@ -925,7 +925,7 @@ static int dm_table_determine_type(struc verify_bio_based: /* We must use this table as bio-based */ t->type = DM_TYPE_BIO_BASED; - if (dm_table_supports_dax(t, device_supports_dax, &page_size) || + if (dm_table_supports_dax(t, device_not_dax_capable, &page_size) || (list_empty(devices) && live_md_type == DM_TYPE_DAX_BIO_BASED)) { t->type = DM_TYPE_DAX_BIO_BASED; } @@ -1618,23 +1618,6 @@ static int device_dax_write_cache_enable return false; }
-static int dm_table_supports_dax_write_cache(struct dm_table *t) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, - device_dax_write_cache_enabled, NULL)) - return true; - } - - return false; -} - static int device_is_rotational(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { @@ -1839,15 +1822,15 @@ void dm_table_set_restrictions(struct dm } blk_queue_write_cache(q, wc, fua);
- if (dm_table_supports_dax(t, device_supports_dax, &page_size)) { + if (dm_table_supports_dax(t, device_not_dax_capable, &page_size)) { blk_queue_flag_set(QUEUE_FLAG_DAX, q); - if (dm_table_supports_dax(t, device_dax_synchronous, NULL)) + if (dm_table_supports_dax(t, device_not_dax_synchronous_capable, NULL)) set_dax_synchronous(t->md->dax_dev); } else blk_queue_flag_clear(QUEUE_FLAG_DAX, q);
- if (dm_table_supports_dax_write_cache(t)) + if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled)) dax_write_cache(t->md->dax_dev, true);
/* Ensure that all underlying devices are non-rotational. */ --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1148,7 +1148,7 @@ static bool dm_dax_supported(struct dax_ if (!map) goto out;
- ret = dm_table_supports_dax(map, device_supports_dax, &blocksize); + ret = dm_table_supports_dax(map, device_not_dax_capable, &blocksize);
out: dm_put_live_table(md, srcu_idx); --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -73,7 +73,7 @@ void dm_table_free_md_mempools(struct dm struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); bool dm_table_supports_dax(struct dm_table *t, iterate_devices_callout_fn fn, int *blocksize); -int device_supports_dax(struct dm_target *ti, struct dm_dev *dev, +int device_not_dax_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data);
void dm_lock_md_type(struct mapped_device *md);
From: Jeffle Xu jefflexu@linux.alibaba.com
commit 24f6b6036c9eec21191646930ad42808e6180510 upstream.
Fix dm_table_supports_zoned_model() and invert logic of both iterate_devices_callout_fn so that all devices' zoned capabilities are properly checked.
Add one more parameter to dm_table_any_dev_attr(), which is actually used as the @data parameter of iterate_devices_callout_fn, so that dm_table_matches_zone_sectors() can be replaced by dm_table_any_dev_attr().
Fixes: dd88d313bef02 ("dm table: add zoned block devices validation") Cc: stable@vger.kernel.org Signed-off-by: Jeffle Xu jefflexu@linux.alibaba.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-table.c | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-)
--- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1316,10 +1316,10 @@ struct dm_target *dm_table_find_target(s * should use the iteration structure like dm_table_supports_nowait() or * dm_table_supports_discards(). Or introduce dm_table_all_devs_attr() that * uses an @anti_func that handle semantics of counter examples, e.g. not - * capable of something. So: return !dm_table_any_dev_attr(t, anti_func); + * capable of something. So: return !dm_table_any_dev_attr(t, anti_func, data); */ static bool dm_table_any_dev_attr(struct dm_table *t, - iterate_devices_callout_fn func) + iterate_devices_callout_fn func, void *data) { struct dm_target *ti; unsigned int i; @@ -1328,7 +1328,7 @@ static bool dm_table_any_dev_attr(struct ti = dm_table_get_target(t, i);
if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, func, NULL)) + ti->type->iterate_devices(ti, func, data)) return true; }
@@ -1371,13 +1371,13 @@ bool dm_table_has_no_data_devices(struct return true; }
-static int device_is_zoned_model(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_not_zoned_model(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); enum blk_zoned_model *zoned_model = data;
- return q && blk_queue_zoned_model(q) == *zoned_model; + return !q || blk_queue_zoned_model(q) != *zoned_model; }
static bool dm_table_supports_zoned_model(struct dm_table *t, @@ -1394,37 +1394,20 @@ static bool dm_table_supports_zoned_mode return false;
if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_is_zoned_model, &zoned_model)) + ti->type->iterate_devices(ti, device_not_zoned_model, &zoned_model)) return false; }
return true; }
-static int device_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_not_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); unsigned int *zone_sectors = data;
- return q && blk_queue_zone_sectors(q) == *zone_sectors; -} - -static bool dm_table_matches_zone_sectors(struct dm_table *t, - unsigned int zone_sectors) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_matches_zone_sectors, &zone_sectors)) - return false; - } - - return true; + return !q || blk_queue_zone_sectors(q) != *zone_sectors; }
static int validate_hardware_zoned_model(struct dm_table *table, @@ -1444,7 +1427,7 @@ static int validate_hardware_zoned_model if (!zone_sectors || !is_power_of_2(zone_sectors)) return -EINVAL;
- if (!dm_table_matches_zone_sectors(table, zone_sectors)) { + if (dm_table_any_dev_attr(table, device_not_matches_zone_sectors, &zone_sectors)) { DMERR("%s: zone sectors is not consistent across all devices", dm_device_name(table->md)); return -EINVAL; @@ -1830,11 +1813,11 @@ void dm_table_set_restrictions(struct dm else blk_queue_flag_clear(QUEUE_FLAG_DAX, q);
- if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled)) + if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL)) dax_write_cache(t->md->dax_dev, true);
/* Ensure that all underlying devices are non-rotational. */ - if (dm_table_any_dev_attr(t, device_is_rotational)) + if (dm_table_any_dev_attr(t, device_is_rotational, NULL)) blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); else blk_queue_flag_set(QUEUE_FLAG_NONROT, q); @@ -1853,7 +1836,7 @@ void dm_table_set_restrictions(struct dm * them as well. Only targets that support iterate_devices are considered: * don't want error, zero, etc to require stable pages. */ - if (dm_table_any_dev_attr(t, device_requires_stable_pages)) + if (dm_table_any_dev_attr(t, device_requires_stable_pages, NULL)) blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, q); else blk_queue_flag_clear(QUEUE_FLAG_STABLE_WRITES, q); @@ -1864,7 +1847,8 @@ void dm_table_set_restrictions(struct dm * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not * have it set. */ - if (blk_queue_add_random(q) && dm_table_any_dev_attr(t, device_is_not_random)) + if (blk_queue_add_random(q) && + dm_table_any_dev_attr(t, device_is_not_random, NULL)) blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
/*
From: Mikulas Patocka mpatocka@redhat.com
commit cb728484a7710c202f02b96aa0962ce9b07aa5c2 upstream.
Fix a thinko in ssd_commit_superblock. region.count is in sectors, not bytes. This bug doesn't corrupt data, but it causes performance degradation.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Fixes: dc8a01ae1dbd ("dm writecache: optimize superblock write") Cc: stable@vger.kernel.org # v5.7+ Reported-by: J. Bruce Fields bfields@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-writecache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -523,7 +523,7 @@ static void ssd_commit_superblock(struct
region.bdev = wc->ssd_dev->bdev; region.sector = 0; - region.count = PAGE_SIZE; + region.count = PAGE_SIZE >> SECTOR_SHIFT;
if (unlikely(region.sector + region.count > wc->metadata_sectors)) region.count = wc->metadata_sectors - region.sector;
From: Mikulas Patocka mpatocka@redhat.com
commit 054bee16163df023e2589db09fd27d81f7ad9e72 upstream.
LVM doesn't like it when the target returns different values from what was set in the constructor. Fix dm-writecache so that the returned table values are exactly the same as requested values.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Cc: stable@vger.kernel.org # v4.18+ Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-writecache.c | 54 +++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 24 deletions(-)
--- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -159,14 +159,22 @@ struct dm_writecache { bool overwrote_committed:1; bool memory_vmapped:1;
+ bool start_sector_set:1; bool high_wm_percent_set:1; bool low_wm_percent_set:1; bool max_writeback_jobs_set:1; bool autocommit_blocks_set:1; bool autocommit_time_set:1; + bool max_age_set:1; bool writeback_fua_set:1; bool flush_on_suspend:1; bool cleaner:1; + bool cleaner_set:1; + + unsigned high_wm_percent_value; + unsigned low_wm_percent_value; + unsigned autocommit_time_value; + unsigned max_age_value;
unsigned writeback_all; struct workqueue_struct *writeback_wq; @@ -2205,6 +2213,7 @@ static int writecache_ctr(struct dm_targ if (sscanf(string, "%llu%c", &start_sector, &dummy) != 1) goto invalid_optional; wc->start_sector = start_sector; + wc->start_sector_set = true; if (wc->start_sector != start_sector || wc->start_sector >= wc->memory_map_size >> SECTOR_SHIFT) goto invalid_optional; @@ -2214,6 +2223,7 @@ static int writecache_ctr(struct dm_targ goto invalid_optional; if (high_wm_percent < 0 || high_wm_percent > 100) goto invalid_optional; + wc->high_wm_percent_value = high_wm_percent; wc->high_wm_percent_set = true; } else if (!strcasecmp(string, "low_watermark") && opt_params >= 1) { string = dm_shift_arg(&as), opt_params--; @@ -2221,6 +2231,7 @@ static int writecache_ctr(struct dm_targ goto invalid_optional; if (low_wm_percent < 0 || low_wm_percent > 100) goto invalid_optional; + wc->low_wm_percent_value = low_wm_percent; wc->low_wm_percent_set = true; } else if (!strcasecmp(string, "writeback_jobs") && opt_params >= 1) { string = dm_shift_arg(&as), opt_params--; @@ -2240,6 +2251,7 @@ static int writecache_ctr(struct dm_targ if (autocommit_msecs > 3600000) goto invalid_optional; wc->autocommit_jiffies = msecs_to_jiffies(autocommit_msecs); + wc->autocommit_time_value = autocommit_msecs; wc->autocommit_time_set = true; } else if (!strcasecmp(string, "max_age") && opt_params >= 1) { unsigned max_age_msecs; @@ -2249,7 +2261,10 @@ static int writecache_ctr(struct dm_targ if (max_age_msecs > 86400000) goto invalid_optional; wc->max_age = msecs_to_jiffies(max_age_msecs); + wc->max_age_set = true; + wc->max_age_value = max_age_msecs; } else if (!strcasecmp(string, "cleaner")) { + wc->cleaner_set = true; wc->cleaner = true; } else if (!strcasecmp(string, "fua")) { if (WC_MODE_PMEM(wc)) { @@ -2455,7 +2470,6 @@ static void writecache_status(struct dm_ struct dm_writecache *wc = ti->private; unsigned extra_args; unsigned sz = 0; - uint64_t x;
switch (type) { case STATUSTYPE_INFO: @@ -2467,11 +2481,11 @@ static void writecache_status(struct dm_ DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's', wc->dev->name, wc->ssd_dev->name, wc->block_size); extra_args = 0; - if (wc->start_sector) + if (wc->start_sector_set) extra_args += 2; - if (wc->high_wm_percent_set && !wc->cleaner) + if (wc->high_wm_percent_set) extra_args += 2; - if (wc->low_wm_percent_set && !wc->cleaner) + if (wc->low_wm_percent_set) extra_args += 2; if (wc->max_writeback_jobs_set) extra_args += 2; @@ -2479,37 +2493,29 @@ static void writecache_status(struct dm_ extra_args += 2; if (wc->autocommit_time_set) extra_args += 2; - if (wc->max_age != MAX_AGE_UNSPECIFIED) + if (wc->max_age_set) extra_args += 2; - if (wc->cleaner) + if (wc->cleaner_set) extra_args++; if (wc->writeback_fua_set) extra_args++;
DMEMIT("%u", extra_args); - if (wc->start_sector) + if (wc->start_sector_set) DMEMIT(" start_sector %llu", (unsigned long long)wc->start_sector); - if (wc->high_wm_percent_set && !wc->cleaner) { - x = (uint64_t)wc->freelist_high_watermark * 100; - x += wc->n_blocks / 2; - do_div(x, (size_t)wc->n_blocks); - DMEMIT(" high_watermark %u", 100 - (unsigned)x); - } - if (wc->low_wm_percent_set && !wc->cleaner) { - x = (uint64_t)wc->freelist_low_watermark * 100; - x += wc->n_blocks / 2; - do_div(x, (size_t)wc->n_blocks); - DMEMIT(" low_watermark %u", 100 - (unsigned)x); - } + if (wc->high_wm_percent_set) + DMEMIT(" high_watermark %u", wc->high_wm_percent_value); + if (wc->low_wm_percent_set) + DMEMIT(" low_watermark %u", wc->low_wm_percent_value); if (wc->max_writeback_jobs_set) DMEMIT(" writeback_jobs %u", wc->max_writeback_jobs); if (wc->autocommit_blocks_set) DMEMIT(" autocommit_blocks %u", wc->autocommit_blocks); if (wc->autocommit_time_set) - DMEMIT(" autocommit_time %u", jiffies_to_msecs(wc->autocommit_jiffies)); - if (wc->max_age != MAX_AGE_UNSPECIFIED) - DMEMIT(" max_age %u", jiffies_to_msecs(wc->max_age)); - if (wc->cleaner) + DMEMIT(" autocommit_time %u", wc->autocommit_time_value); + if (wc->max_age_set) + DMEMIT(" max_age %u", wc->max_age_value); + if (wc->cleaner_set) DMEMIT(" cleaner"); if (wc->writeback_fua_set) DMEMIT(" %sfua", wc->writeback_fua ? "" : "no"); @@ -2519,7 +2525,7 @@ static void writecache_status(struct dm_
static struct target_type writecache_target = { .name = "writecache", - .version = {1, 3, 0}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = writecache_ctr, .dtr = writecache_dtr,
From: Mikulas Patocka mpatocka@redhat.com
commit 4134455f2aafdfeab50cabb4cccb35e916034b93 upstream.
Do not attempt to write any data beyond the end of the underlying data device while shrinking it.
The DM writecache device must be suspended when the underlying data device is shrunk.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-writecache.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
--- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -148,6 +148,7 @@ struct dm_writecache { size_t metadata_sectors; size_t n_blocks; uint64_t seq_count; + sector_t data_device_sectors; void *block_start; struct wc_entry *entries; unsigned block_size; @@ -977,6 +978,8 @@ static void writecache_resume(struct dm_
wc_lock(wc);
+ wc->data_device_sectors = i_size_read(wc->dev->bdev->bd_inode) >> SECTOR_SHIFT; + if (WC_MODE_PMEM(wc)) { persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size); } else { @@ -1646,6 +1649,10 @@ static bool wc_add_block(struct writebac void *address = memory_data(wc, e);
persistent_memory_flush_cache(address, block_size); + + if (unlikely(bio_end_sector(&wb->bio) >= wc->data_device_sectors)) + return true; + return bio_add_page(&wb->bio, persistent_memory_page(address), block_size, persistent_memory_page_offset(address)) != 0; } @@ -1717,6 +1724,9 @@ static void __writecache_writeback_pmem( if (writecache_has_error(wc)) { bio->bi_status = BLK_STS_IOERR; bio_endio(bio); + } else if (unlikely(!bio_sectors(bio))) { + bio->bi_status = BLK_STS_OK; + bio_endio(bio); } else { submit_bio(bio); } @@ -1760,6 +1770,14 @@ static void __writecache_writeback_ssd(s e = f; }
+ if (unlikely(to.sector + to.count > wc->data_device_sectors)) { + if (to.sector >= wc->data_device_sectors) { + writecache_copy_endio(0, 0, c); + continue; + } + from.count = to.count = wc->data_device_sectors - to.sector; + } + dm_kcopyd_copy(wc->dm_kcopyd, &from, 1, &to, 0, writecache_copy_endio, c);
__writeback_throttle(wc, wbl);
From: Nikos Tsironis ntsironis@arrikto.com
commit de89afc1e40fdfa5f8b666e5d07c43d21a1d3be0 upstream.
Following a system crash, dm-era fails to recover the committed writeset for the current era, leading to lost writes. That is, we lose the information about what blocks were written during the affected era.
dm-era assumes that the writeset of the current era is archived when the device is suspended. So, when resuming the device, it just moves on to the next era, ignoring the committed writeset.
This assumption holds when the device is properly shut down. But, when the system crashes, the code that suspends the target never runs, so the writeset for the current era is not archived.
There are three issues that cause the committed writeset to get lost:
1. dm-era doesn't load the committed writeset when opening the metadata 2. The code that resizes the metadata wipes the information about the committed writeset (assuming it was loaded at step 1) 3. era_preresume() starts a new era, without taking into account that the current era might not have been archived, due to a system crash.
To fix this:
1. Load the committed writeset when opening the metadata 2. Fix the code that resizes the metadata to make sure it doesn't wipe the loaded writeset 3. Fix era_preresume() to check for a loaded writeset and archive it, before starting a new era.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -71,8 +71,6 @@ static size_t bitset_size(unsigned nr_bi */ static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks) { - ws->md.nr_bits = nr_blocks; - ws->md.root = INVALID_WRITESET_ROOT; ws->bits = vzalloc(bitset_size(nr_blocks)); if (!ws->bits) { DMERR("%s: couldn't allocate in memory bitset", __func__); @@ -85,12 +83,14 @@ static int writeset_alloc(struct writese /* * Wipes the in-core bitset, and creates a new on disk bitset. */ -static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws) +static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws, + dm_block_t nr_blocks) { int r;
- memset(ws->bits, 0, bitset_size(ws->md.nr_bits)); + memset(ws->bits, 0, bitset_size(nr_blocks));
+ ws->md.nr_bits = nr_blocks; r = setup_on_disk_bitset(info, ws->md.nr_bits, &ws->md.root); if (r) { DMERR("%s: setup_on_disk_bitset failed", __func__); @@ -579,6 +579,7 @@ static int open_metadata(struct era_meta md->nr_blocks = le32_to_cpu(disk->nr_blocks); md->current_era = le32_to_cpu(disk->current_era);
+ ws_unpack(&disk->current_writeset, &md->current_writeset->md); md->writeset_tree_root = le64_to_cpu(disk->writeset_tree_root); md->era_array_root = le64_to_cpu(disk->era_array_root); md->metadata_snap = le64_to_cpu(disk->metadata_snap); @@ -870,7 +871,6 @@ static int metadata_era_archive(struct e }
ws_pack(&md->current_writeset->md, &value); - md->current_writeset->md.root = INVALID_WRITESET_ROOT;
keys[0] = md->current_era; __dm_bless_for_disk(&value); @@ -882,6 +882,7 @@ static int metadata_era_archive(struct e return r; }
+ md->current_writeset->md.root = INVALID_WRITESET_ROOT; md->archived_writesets = true;
return 0; @@ -898,7 +899,7 @@ static int metadata_new_era(struct era_m int r; struct writeset *new_writeset = next_writeset(md);
- r = writeset_init(&md->bitset_info, new_writeset); + r = writeset_init(&md->bitset_info, new_writeset, md->nr_blocks); if (r) { DMERR("%s: writeset_init failed", __func__); return r; @@ -951,7 +952,7 @@ static int metadata_commit(struct era_me int r; struct dm_block *sblock;
- if (md->current_writeset->md.root != SUPERBLOCK_LOCATION) { + if (md->current_writeset->md.root != INVALID_WRITESET_ROOT) { r = dm_bitset_flush(&md->bitset_info, md->current_writeset->md.root, &md->current_writeset->md.root); if (r) { @@ -1565,7 +1566,7 @@ static int era_preresume(struct dm_targe
start_worker(era);
- r = in_worker0(era, metadata_new_era); + r = in_worker0(era, metadata_era_rollover); if (r) { DMERR("%s: metadata_era_rollover failed", __func__); return r;
From: Nikos Tsironis ntsironis@arrikto.com
commit 2099b145d77c1d53f5711f029c37cc537897cee6 upstream.
In case of a system crash, dm-era might fail to mark blocks as written in its metadata, although the corresponding writes to these blocks were passed down to the origin device and completed successfully.
Consider the following sequence of events:
1. We write to a block that has not been yet written in the current era 2. era_map() checks the in-core bitmap for the current era and sees that the block is not marked as written. 3. The write is deferred for submission after the metadata have been updated and committed. 4. The worker thread processes the deferred write (process_deferred_bios()) and marks the block as written in the in-core bitmap, **before** committing the metadata. 5. The worker thread starts committing the metadata. 6. We do more writes that map to the same block as the write of step (1) 7. era_map() checks the in-core bitmap and sees that the block is marked as written, **although the metadata have not been committed yet**. 8. These writes are passed down to the origin device immediately and the device reports them as completed. 9. The system crashes, e.g., power failure, before the commit from step (5) finishes.
When the system recovers and we query the dm-era target for the list of written blocks it doesn't report the aforementioned block as written, although the writes of step (6) completed successfully.
The issue is that era_map() decides whether to defer or not a write based on non committed information. The root cause of the bug is that we update the in-core bitmap, **before** committing the metadata.
Fix this by updating the in-core bitmap **after** successfully committing the metadata.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -134,7 +134,7 @@ static int writeset_test_and_set(struct { int r;
- if (!test_and_set_bit(block, ws->bits)) { + if (!test_bit(block, ws->bits)) { r = dm_bitset_set_bit(info, ws->md.root, block, &ws->md.root); if (r) { /* FIXME: fail mode */ @@ -1226,8 +1226,10 @@ static void process_deferred_bios(struct int r; struct bio_list deferred_bios, marked_bios; struct bio *bio; + struct blk_plug plug; bool commit_needed = false; bool failed = false; + struct writeset *ws = era->md->current_writeset;
bio_list_init(&deferred_bios); bio_list_init(&marked_bios); @@ -1237,9 +1239,11 @@ static void process_deferred_bios(struct bio_list_init(&era->deferred_bios); spin_unlock(&era->deferred_lock);
+ if (bio_list_empty(&deferred_bios)) + return; + while ((bio = bio_list_pop(&deferred_bios))) { - r = writeset_test_and_set(&era->md->bitset_info, - era->md->current_writeset, + r = writeset_test_and_set(&era->md->bitset_info, ws, get_block(era, bio)); if (r < 0) { /* @@ -1247,7 +1251,6 @@ static void process_deferred_bios(struct * FIXME: finish. */ failed = true; - } else if (r == 0) commit_needed = true;
@@ -1263,9 +1266,19 @@ static void process_deferred_bios(struct if (failed) while ((bio = bio_list_pop(&marked_bios))) bio_io_error(bio); - else - while ((bio = bio_list_pop(&marked_bios))) + else { + blk_start_plug(&plug); + while ((bio = bio_list_pop(&marked_bios))) { + /* + * Only update the in-core writeset if the on-disk one + * was updated too. + */ + if (commit_needed) + set_bit(get_block(era, bio), ws->bits); submit_bio_noacct(bio); + } + blk_finish_plug(&plug); + } }
static void process_rpc_calls(struct era *era)
From: Nikos Tsironis ntsironis@arrikto.com
commit c8e846ff93d5eaa5384f6f325a1687ac5921aade upstream.
dm-era doesn't support changing the data block size of existing devices, so check explicitly that the requested block size for a new target matches the one stored in the metadata.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Reviewed-by: Ming-Hung Tsai mtsai@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -564,6 +564,15 @@ static int open_metadata(struct era_meta }
disk = dm_block_data(sblock); + + /* Verify the data block size hasn't changed */ + if (le32_to_cpu(disk->data_block_size) != md->block_size) { + DMERR("changing the data block size (from %u to %llu) is not supported", + le32_to_cpu(disk->data_block_size), md->block_size); + r = -EINVAL; + goto bad; + } + r = dm_tm_open_with_sm(md->bm, SUPERBLOCK_LOCATION, disk->metadata_space_map_root, sizeof(disk->metadata_space_map_root), @@ -575,7 +584,6 @@ static int open_metadata(struct era_meta
setup_infos(md);
- md->block_size = le32_to_cpu(disk->data_block_size); md->nr_blocks = le32_to_cpu(disk->nr_blocks); md->current_era = le32_to_cpu(disk->current_era);
From: Nikos Tsironis ntsironis@arrikto.com
commit 904e6b266619c2da5c58b5dce14ae30629e39645 upstream.
Deallocate the memory allocated for the in-core bitsets when destroying the target and in error paths.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Reviewed-by: Ming-Hung Tsai mtsai@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -47,6 +47,7 @@ struct writeset { static void writeset_free(struct writeset *ws) { vfree(ws->bits); + ws->bits = NULL; }
static int setup_on_disk_bitset(struct dm_disk_bitset *info, @@ -811,6 +812,8 @@ static struct era_metadata *metadata_ope
static void metadata_close(struct era_metadata *md) { + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); destroy_persistent_data_objects(md); kfree(md); } @@ -848,6 +851,7 @@ static int metadata_resize(struct era_me r = writeset_alloc(&md->writesets[1], *new_size); if (r) { DMERR("%s: writeset_alloc failed for writeset 1", __func__); + writeset_free(&md->writesets[0]); return r; }
@@ -858,6 +862,8 @@ static int metadata_resize(struct era_me &value, &md->era_array_root); if (r) { DMERR("%s: dm_array_resize failed", __func__); + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); return r; }
From: Nikos Tsironis ntsironis@arrikto.com
commit 64f2d15afe7b336aafebdcd14cc835ecf856df4b upstream.
Fix the writeset tree equality test function to use the right value size when comparing two btree values.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Reviewed-by: Ming-Hung Tsai mtsai@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -389,7 +389,7 @@ static void ws_dec(void *context, const
static int ws_eq(void *context, const void *value1, const void *value2) { - return !memcmp(value1, value2, sizeof(struct writeset_metadata)); + return !memcmp(value1, value2, sizeof(struct writeset_disk)); }
/*----------------------------------------------------------------*/
From: Nikos Tsironis ntsironis@arrikto.com
commit 2524933307fd0036d5c32357c693c021ab09a0b0 upstream.
In case of devices with at most 64 blocks, the digestion of consecutive eras uses the writeset of the first era as the writeset of all eras to digest, leading to lost writes. That is, we lose the information about what blocks were written during the affected eras.
The digestion code uses a dm_disk_bitset object to access the archived writesets. This structure includes a one word (64-bit) cache to reduce the number of array lookups.
This structure is initialized only once, in metadata_digest_start(), when we kick off digestion.
But, when we insert a new writeset into the writeset tree, before the digestion of the previous writeset is done, or equivalently when there are multiple writesets in the writeset tree to digest, then all these writesets are digested using the same cache and the cache is not re-initialized when moving from one writeset to the next.
For devices with more than 64 blocks, i.e., the size of the cache, the cache is indirectly invalidated when we move to a next set of blocks, so we avoid the bug.
But for devices with at most 64 blocks we end up using the same cached data for digesting all archived writesets, i.e., the cache is loaded when digesting the first writeset and it never gets reloaded, until the digestion is done.
As a result, the writeset of the first era to digest is used as the writeset of all the following archived eras, leading to lost writes.
Fix this by reinitializing the dm_disk_bitset structure, and thus invalidating the cache, every time the digestion code starts digesting a new writeset.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -756,6 +756,12 @@ static int metadata_digest_lookup_writes ws_unpack(&disk, &d->writeset); d->value = cpu_to_le32(key);
+ /* + * We initialise another bitset info to avoid any caching side effects + * with the previous one. + */ + dm_disk_bitset_init(md->tm, &d->info); + d->nr_bits = min(d->writeset.nr_bits, md->nr_blocks); d->current_bit = 0; d->step = metadata_digest_transcribe_writeset; @@ -769,12 +775,6 @@ static int metadata_digest_start(struct return 0;
memset(d, 0, sizeof(*d)); - - /* - * We initialise another bitset info to avoid any caching side - * effects with the previous one. - */ - dm_disk_bitset_init(md->tm, &d->info); d->step = metadata_digest_lookup_writeset;
return 0;
From: Nikos Tsironis ntsironis@arrikto.com
commit cca2c6aebe86f68103a8615074b3578e854b5016 upstream.
Metadata resize shouldn't happen in the ctr. The ctr loads a temporary (inactive) table that will only become active upon resume. That is why resize should always be done in terms of resume. Otherwise a load (ctr) whose inactive table never becomes active will incorrectly resize the metadata.
Also, perform the resize directly in preresume, instead of using the worker to do it.
The worker might run other metadata operations, e.g., it could start digestion, before resizing the metadata. These operations will end up using the old size.
This could lead to errors, like:
device-mapper: era: metadata_digest_transcribe_writeset: dm_array_set_value failed device-mapper: era: process_old_eras: digest step failed, stopping digestion
The reason of the above error is that the worker started the digestion of the archived writeset using the old, larger size.
As a result, metadata_digest_transcribe_writeset tried to write beyond the end of the era array.
Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis ntsironis@arrikto.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/md/dm-era-target.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
--- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -1501,15 +1501,6 @@ static int era_ctr(struct dm_target *ti, } era->md = md;
- era->nr_blocks = calc_nr_blocks(era); - - r = metadata_resize(era->md, &era->nr_blocks); - if (r) { - ti->error = "couldn't resize metadata"; - era_destroy(era); - return -ENOMEM; - } - era->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM); if (!era->wq) { ti->error = "could not create workqueue for metadata object"; @@ -1584,9 +1575,17 @@ static int era_preresume(struct dm_targe dm_block_t new_size = calc_nr_blocks(era);
if (era->nr_blocks != new_size) { - r = in_worker1(era, metadata_resize, &new_size); - if (r) + r = metadata_resize(era->md, &new_size); + if (r) { + DMERR("%s: metadata_resize failed", __func__); + return r; + } + + r = metadata_commit(era->md); + if (r) { + DMERR("%s: metadata_commit failed", __func__); return r; + }
era->nr_blocks = new_size; }
From: Ville Syrjälä ville.syrjala@linux.intel.com
commit 7a6c6243b44a439bda4bf099032be35ebcf53406 upstream.
The BXT/GLK DPLL can't generate certain frequencies. We already reject the 233-240MHz range on both. But on GLK the DPLL max frequency was bumped from 300MHz to 594MHz, so now we get to also worry about the 446-480MHz range (double the original problem range). Reject any frequency within the higher problematic range as well.
Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3000 Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20210203093044.30532-1-ville.s... Reviewed-by: Mika Kahola mika.kahola@intel.com (cherry picked from commit 41751b3e5c1ac656a86f8d45a8891115281b729e) Signed-off-by: Rodrigo Vivi rodrigo.vivi@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2216,7 +2216,11 @@ hdmi_port_clock_valid(struct intel_hdmi has_hdmi_sink)) return MODE_CLOCK_HIGH;
- /* BXT DPLL can't generate 223-240 MHz */ + /* GLK DPLL can't generate 446-480 MHz */ + if (IS_GEMINILAKE(dev_priv) && clock > 446666 && clock < 480000) + return MODE_CLOCK_RANGE; + + /* BXT/GLK DPLL can't generate 223-240 MHz */ if (IS_GEN9_LP(dev_priv) && clock > 223333 && clock < 240000) return MODE_CLOCK_RANGE;
From: Sumit Garg sumit.garg@linaro.org
commit d54ce6158e354f5358a547b96299ecd7f3725393 upstream.
Currently breakpoints in kernel .init.text section are not handled correctly while allowing to remove them even after corresponding pages have been freed.
Fix it via killing .init.text section breakpoints just prior to initmem pages being freed.
Doug: "HW breakpoints aren't handled by this patch but it's probably not such a big deal".
Link: https://lkml.kernel.org/r/20210224081652.587785-1-sumit.garg@linaro.org Signed-off-by: Sumit Garg sumit.garg@linaro.org Suggested-by: Doug Anderson dianders@chromium.org Acked-by: Doug Anderson dianders@chromium.org Acked-by: Daniel Thompson daniel.thompson@linaro.org Tested-by: Daniel Thompson daniel.thompson@linaro.org Cc: Masami Hiramatsu mhiramat@kernel.org Cc: Steven Rostedt (VMware) rostedt@goodmis.org Cc: Jason Wessel jason.wessel@windriver.com Cc: Peter Zijlstra peterz@infradead.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/kgdb.h | 2 ++ init/main.c | 1 + kernel/debug/debug_core.c | 11 +++++++++++ 3 files changed, 14 insertions(+)
--- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -360,9 +360,11 @@ extern atomic_t kgdb_active; extern bool dbg_is_early; extern void __init dbg_late_init(void); extern void kgdb_panic(const char *msg); +extern void kgdb_free_init_mem(void); #else /* ! CONFIG_KGDB */ #define in_dbg_master() (0) #define dbg_late_init() static inline void kgdb_panic(const char *msg) {} +static inline void kgdb_free_init_mem(void) { } #endif /* ! CONFIG_KGDB */ #endif /* _KGDB_H_ */ --- a/init/main.c +++ b/init/main.c @@ -1423,6 +1423,7 @@ static int __ref kernel_init(void *unuse async_synchronize_full(); kprobe_free_init_mem(); ftrace_free_init_mem(); + kgdb_free_init_mem(); free_initmem(); mark_readonly();
--- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c @@ -456,6 +456,17 @@ setundefined: return 0; }
+void kgdb_free_init_mem(void) +{ + int i; + + /* Clear init memory breakpoints. */ + for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { + if (init_section_contains((void *)kgdb_break[i].bpt_addr, 0)) + kgdb_break[i].state = BP_UNDEFINED; + } +} + #ifdef CONFIG_KGDB_KDB void kdb_dump_stack_on_cpu(int cpu) {
From: Leon Romanovsky leonro@nvidia.com
commit 1faba27f11c8da244e793546a1b35a9b1da8208e upstream.
The W=1 compilation of allmodconfig generates the following warning:
net/ipv6/icmp.c:448:6: warning: no previous prototype for 'icmp6_send' [-Wmissing-prototypes] 448 | void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, | ^~~~~~~~~~
Fix it by providing function declaration for builds with ipv6 as a module.
Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/icmpv6.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -16,9 +16,9 @@ static inline struct icmp6hdr *icmp6_hdr
typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, const struct in6_addr *force_saddr); -#if IS_BUILTIN(CONFIG_IPV6) void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, const struct in6_addr *force_saddr); +#if IS_BUILTIN(CONFIG_IPV6) static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) { icmp6_send(skb, type, code, info, NULL);
From: Jason A. Donenfeld Jason@zx2c4.com
commit ee576c47db60432c37e54b1e2b43a8ca6d3a8dca upstream.
The icmp{,v6}_send functions make all sorts of use of skb->cb, casting it with IPCB or IP6CB, assuming the skb to have come directly from the inet layer. But when the packet comes from the ndo layer, especially when forwarded, there's no telling what might be in skb->cb at that point. As a result, the icmp sending code risks reading bogus memory contents, which can result in nasty stack overflows such as this one reported by a user:
panic+0x108/0x2ea __stack_chk_fail+0x14/0x20 __icmp_send+0x5bd/0x5c0 icmp_ndo_send+0x148/0x160
In icmp_send, skb->cb is cast with IPCB and an ip_options struct is read from it. The optlen parameter there is of particular note, as it can induce writes beyond bounds. There are quite a few ways that can happen in __ip_options_echo. For example:
// sptr/skb are attacker-controlled skb bytes sptr = skb_network_header(skb); // dptr/dopt points to stack memory allocated by __icmp_send dptr = dopt->__data; // sopt is the corrupt skb->cb in question if (sopt->rr) { optlen = sptr[sopt->rr+1]; // corrupt skb->cb + skb->data soffset = sptr[sopt->rr+2]; // corrupt skb->cb + skb->data // this now writes potentially attacker-controlled data, over // flowing the stack: memcpy(dptr, sptr+sopt->rr, optlen); }
In the icmpv6_send case, the story is similar, but not as dire, as only IP6CB(skb)->iif and IP6CB(skb)->dsthao are used. The dsthao case is worse than the iif case, but it is passed to ipv6_find_tlv, which does a bit of bounds checking on the value.
This is easy to simulate by doing a `memset(skb->cb, 0x41, sizeof(skb->cb));` before calling icmp{,v6}_ndo_send, and it's only by good fortune and the rarity of icmp sending from that context that we've avoided reports like this until now. For example, in KASAN:
BUG: KASAN: stack-out-of-bounds in __ip_options_echo+0xa0e/0x12b0 Write of size 38 at addr ffff888006f1f80e by task ping/89 CPU: 2 PID: 89 Comm: ping Not tainted 5.10.0-rc7-debug+ #5 Call Trace: dump_stack+0x9a/0xcc print_address_description.constprop.0+0x1a/0x160 __kasan_report.cold+0x20/0x38 kasan_report+0x32/0x40 check_memory_region+0x145/0x1a0 memcpy+0x39/0x60 __ip_options_echo+0xa0e/0x12b0 __icmp_send+0x744/0x1700
Actually, out of the 4 drivers that do this, only gtp zeroed the cb for the v4 case, while the rest did not. So this commit actually removes the gtp-specific zeroing, while putting the code where it belongs in the shared infrastructure of icmp{,v6}_ndo_send.
This commit fixes the issue by passing an empty IPCB or IP6CB along to the functions that actually do the work. For the icmp_send, this was already trivial, thanks to __icmp_send providing the plumbing function. For icmpv6_send, this required a tiny bit of refactoring to make it behave like the v4 case, after which it was straight forward.
Fixes: a2b78e9b2cac ("sunvnet: generate ICMP PTMUD messages for smaller port MTUs") Reported-by: SinYu liuxyon@gmail.com Reviewed-by: Willem de Bruijn willemb@google.com Link: https://lore.kernel.org/netdev/CAF=yD-LOF116aHub6RMe8vB8ZpnrrnoTdqhobEx+bvoA... Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Link: https://lore.kernel.org/r/20210223131858.72082-1-Jason@zx2c4.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/gtp.c | 1 - include/linux/icmpv6.h | 26 ++++++++++++++++++++------ include/linux/ipv6.h | 1 - include/net/icmp.h | 6 +++++- net/ipv4/icmp.c | 5 +++-- net/ipv6/icmp.c | 18 +++++++++--------- net/ipv6/ip6_icmp.c | 12 +++++++----- 7 files changed, 44 insertions(+), 25 deletions(-)
--- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -539,7 +539,6 @@ static int gtp_build_skb_ip4(struct sk_b if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) && mtu < ntohs(iph->tot_len)) { netdev_dbg(dev, "packet too big, fragmentation needed\n"); - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); goto err_rt; --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -3,6 +3,7 @@ #define _LINUX_ICMPV6_H
#include <linux/skbuff.h> +#include <linux/ipv6.h> #include <uapi/linux/icmpv6.h>
static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) @@ -15,13 +16,16 @@ static inline struct icmp6hdr *icmp6_hdr #if IS_ENABLED(CONFIG_IPV6)
typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr); + const struct in6_addr *force_saddr, + const struct inet6_skb_parm *parm); void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr); + const struct in6_addr *force_saddr, + const struct inet6_skb_parm *parm); #if IS_BUILTIN(CONFIG_IPV6) -static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +static inline void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct inet6_skb_parm *parm) { - icmp6_send(skb, type, code, info, NULL); + icmp6_send(skb, type, code, info, NULL, parm); } static inline int inet6_register_icmp_sender(ip6_icmp_send_t *fn) { @@ -34,18 +38,28 @@ static inline int inet6_unregister_icmp_ return 0; } #else -extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); +extern void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct inet6_skb_parm *parm); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); #endif
+static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +{ + __icmpv6_send(skb, type, code, info, IP6CB(skb)); +} + int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, unsigned int data_len);
#if IS_ENABLED(CONFIG_NF_NAT) void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); #else -#define icmpv6_ndo_send icmpv6_send +static inline void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info) +{ + struct inet6_skb_parm parm = { 0 }; + __icmpv6_send(skb_in, type, code, info, &parm); +} #endif
#else --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -84,7 +84,6 @@ struct ipv6_params { __s32 autoconf; }; extern struct ipv6_params ipv6_defaults; -#include <linux/icmpv6.h> #include <linux/tcp.h> #include <linux/udp.h>
--- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -46,7 +46,11 @@ static inline void icmp_send(struct sk_b #if IS_ENABLED(CONFIG_NF_NAT) void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info); #else -#define icmp_ndo_send icmp_send +static inline void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info) +{ + struct ip_options opts = { 0 }; + __icmp_send(skb_in, type, code, info, &opts); +} #endif
int icmp_rcv(struct sk_buff *skb); --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -775,13 +775,14 @@ EXPORT_SYMBOL(__icmp_send); void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info) { struct sk_buff *cloned_skb = NULL; + struct ip_options opts = { 0 }; enum ip_conntrack_info ctinfo; struct nf_conn *ct; __be32 orig_ip;
ct = nf_ct_get(skb_in, &ctinfo); if (!ct || !(ct->status & IPS_SRC_NAT)) { - icmp_send(skb_in, type, code, info); + __icmp_send(skb_in, type, code, info, &opts); return; }
@@ -796,7 +797,7 @@ void icmp_ndo_send(struct sk_buff *skb_i
orig_ip = ip_hdr(skb_in)->saddr; ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip; - icmp_send(skb_in, type, code, info); + __icmp_send(skb_in, type, code, info, &opts); ip_hdr(skb_in)->saddr = orig_ip; out: consume_skb(cloned_skb); --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -331,10 +331,9 @@ static int icmpv6_getfrag(void *from, ch }
#if IS_ENABLED(CONFIG_IPV6_MIP6) -static void mip6_addr_swap(struct sk_buff *skb) +static void mip6_addr_swap(struct sk_buff *skb, const struct inet6_skb_parm *opt) { struct ipv6hdr *iph = ipv6_hdr(skb); - struct inet6_skb_parm *opt = IP6CB(skb); struct ipv6_destopt_hao *hao; struct in6_addr tmp; int off; @@ -351,7 +350,7 @@ static void mip6_addr_swap(struct sk_buf } } #else -static inline void mip6_addr_swap(struct sk_buff *skb) {} +static inline void mip6_addr_swap(struct sk_buff *skb, const struct inet6_skb_parm *opt) {} #endif
static struct dst_entry *icmpv6_route_lookup(struct net *net, @@ -446,7 +445,8 @@ static int icmp6_iif(const struct sk_buf * Send an ICMP message in response to a packet in error */ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr) + const struct in6_addr *force_saddr, + const struct inet6_skb_parm *parm) { struct inet6_dev *idev = NULL; struct ipv6hdr *hdr = ipv6_hdr(skb); @@ -542,7 +542,7 @@ void icmp6_send(struct sk_buff *skb, u8 if (!(skb->dev->flags & IFF_LOOPBACK) && !icmpv6_global_allow(net, type)) goto out_bh_enable;
- mip6_addr_swap(skb); + mip6_addr_swap(skb, parm);
sk = icmpv6_xmit_lock(net); if (!sk) @@ -559,7 +559,7 @@ void icmp6_send(struct sk_buff *skb, u8 /* select a more meaningful saddr from input if */ struct net_device *in_netdev;
- in_netdev = dev_get_by_index(net, IP6CB(skb)->iif); + in_netdev = dev_get_by_index(net, parm->iif); if (in_netdev) { ipv6_dev_get_saddr(net, in_netdev, &fl6.daddr, inet6_sk(sk)->srcprefs, @@ -640,7 +640,7 @@ EXPORT_SYMBOL(icmp6_send); */ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) { - icmp6_send(skb, ICMPV6_PARAMPROB, code, pos, NULL); + icmp6_send(skb, ICMPV6_PARAMPROB, code, pos, NULL, IP6CB(skb)); kfree_skb(skb); }
@@ -697,10 +697,10 @@ int ip6_err_gen_icmpv6_unreach(struct sk } if (type == ICMP_TIME_EXCEEDED) icmp6_send(skb2, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, - info, &temp_saddr); + info, &temp_saddr, IP6CB(skb2)); else icmp6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, - info, &temp_saddr); + info, &temp_saddr, IP6CB(skb2)); if (rt) ip6_rt_put(rt);
--- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -33,23 +33,25 @@ int inet6_unregister_icmp_sender(ip6_icm } EXPORT_SYMBOL(inet6_unregister_icmp_sender);
-void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct inet6_skb_parm *parm) { ip6_icmp_send_t *send;
rcu_read_lock(); send = rcu_dereference(ip6_icmp_send); if (send) - send(skb, type, code, info, NULL); + send(skb, type, code, info, NULL, parm); rcu_read_unlock(); } -EXPORT_SYMBOL(icmpv6_send); +EXPORT_SYMBOL(__icmpv6_send); #endif
#if IS_ENABLED(CONFIG_NF_NAT) #include <net/netfilter/nf_conntrack.h> void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info) { + struct inet6_skb_parm parm = { 0 }; struct sk_buff *cloned_skb = NULL; enum ip_conntrack_info ctinfo; struct in6_addr orig_ip; @@ -57,7 +59,7 @@ void icmpv6_ndo_send(struct sk_buff *skb
ct = nf_ct_get(skb_in, &ctinfo); if (!ct || !(ct->status & IPS_SRC_NAT)) { - icmpv6_send(skb_in, type, code, info); + __icmpv6_send(skb_in, type, code, info, &parm); return; }
@@ -72,7 +74,7 @@ void icmpv6_ndo_send(struct sk_buff *skb
orig_ip = ipv6_hdr(skb_in)->saddr; ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6; - icmpv6_send(skb_in, type, code, info); + __icmpv6_send(skb_in, type, code, info, &parm); ipv6_hdr(skb_in)->saddr = orig_ip; out: consume_skb(cloned_skb);
From: Jason A. Donenfeld Jason@zx2c4.com
commit d5a49aa6c3e264a93a7d08485d66e346be0969dd upstream.
In order to test ndo_start_xmit being called in parallel, explicitly add separate tests, which should all run on different cores. This should help tease out bugs associated with queueing up packets from different cores in parallel. Currently, it hasn't found those types of bugs, but given future planned work, this is a useful regression to avoid.
Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/testing/selftests/wireguard/netns.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
--- a/tools/testing/selftests/wireguard/netns.sh +++ b/tools/testing/selftests/wireguard/netns.sh @@ -39,7 +39,7 @@ ip0() { pretty 0 "ip $*"; ip -n $netns0 ip1() { pretty 1 "ip $*"; ip -n $netns1 "$@"; } ip2() { pretty 2 "ip $*"; ip -n $netns2 "$@"; } sleep() { read -t "$1" -N 1 || true; } -waitiperf() { pretty "${1//*-}" "wait for iperf:5201 pid $2"; while [[ $(ss -N "$1" -tlpH 'sport = 5201') != *"iperf3",pid=$2,fd=* ]]; do sleep 0.1; done; } +waitiperf() { pretty "${1//*-}" "wait for iperf:${3:-5201} pid $2"; while [[ $(ss -N "$1" -tlpH "sport = ${3:-5201}") != *"iperf3",pid=$2,fd=* ]]; do sleep 0.1; done; } waitncatudp() { pretty "${1//*-}" "wait for udp:1111 pid $2"; while [[ $(ss -N "$1" -ulpH 'sport = 1111') != *"ncat",pid=$2,fd=* ]]; do sleep 0.1; done; } waitiface() { pretty "${1//*-}" "wait for $2 to come up"; ip netns exec "$1" bash -c "while [[ $(< "/sys/class/net/$2/operstate") != up ]]; do read -t .1 -N 0 || true; done;"; }
@@ -141,6 +141,19 @@ tests() { n2 iperf3 -s -1 -B fd00::2 & waitiperf $netns2 $! n1 iperf3 -Z -t 3 -b 0 -u -c fd00::2 + + # TCP over IPv4, in parallel + for max in 4 5 50; do + local pids=( ) + for ((i=0; i < max; ++i)) do + n2 iperf3 -p $(( 5200 + i )) -s -1 -B 192.168.241.2 & + pids+=( $! ); waitiperf $netns2 $! $(( 5200 + i )) + done + for ((i=0; i < max; ++i)) do + n1 iperf3 -Z -t 3 -p $(( 5200 + i )) -c 192.168.241.2 & + done + wait "${pids[@]}" + done }
[[ $(ip1 link show dev wg0) =~ mtu\ ([0-9]+) ]] && orig_mtu="${BASH_REMATCH[1]}"
From: Jason A. Donenfeld Jason@zx2c4.com
commit 8b5553ace83cced775eefd0f3f18b5c6214ccf7a upstream.
Having two ring buffers per-peer means that every peer results in two massive ring allocations. On an 8-core x86_64 machine, this commit reduces the per-peer allocation from 18,688 bytes to 1,856 bytes, which is an 90% reduction. Ninety percent! With some single-machine deployments approaching 500,000 peers, we're talking about a reduction from 7 gigs of memory down to 700 megs of memory.
In order to get rid of these per-peer allocations, this commit switches to using a list-based queueing approach. Currently GSO fragments are chained together using the skb->next pointer (the skb_list_* singly linked list approach), so we form the per-peer queue around the unused skb->prev pointer (which sort of makes sense because the links are pointing backwards). Use of skb_queue_* is not possible here, because that is based on doubly linked lists and spinlocks. Multiple cores can write into the queue at any given time, because its writes occur in the start_xmit path or in the udp_recv path. But reads happen in a single workqueue item per-peer, amounting to a multi-producer, single-consumer paradigm.
The MPSC queue is implemented locklessly and never blocks. However, it is not linearizable (though it is serializable), with a very tight and unlikely race on writes, which, when hit (some tiny fraction of the 0.15% of partial adds on a fully loaded 16-core x86_64 system), causes the queue reader to terminate early. However, because every packet sent queues up the same workqueue item after it is fully added, the worker resumes again, and stopping early isn't actually a problem, since at that point the packet wouldn't have yet been added to the encryption queue. These properties allow us to avoid disabling interrupts or spinning. The design is based on Dmitry Vyukov's algorithm [1].
Performance-wise, ordinarily list-based queues aren't preferable to ringbuffers, because of cache misses when following pointers around. However, we *already* have to follow the adjacent pointers when working through fragments, so there shouldn't actually be any change there. A potential downside is that dequeueing is a bit more complicated, but the ptr_ring structure used prior had a spinlock when dequeueing, so all and all the difference appears to be a wash.
Actually, from profiling, the biggest performance hit, by far, of this commit winds up being atomic_add_unless(count, 1, max) and atomic_ dec(count), which account for the majority of CPU time, according to perf. In that sense, the previous ring buffer was superior in that it could check if it was full by head==tail, which the list-based approach cannot do.
But all and all, this enables us to get massive memory savings, allowing WireGuard to scale for real world deployments, without taking much of a performance hit.
[1] http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-nod...
Reviewed-by: Dmitry Vyukov dvyukov@google.com Reviewed-by: Toke Høiland-Jørgensen toke@redhat.com Fixes: e7096c131e51 ("net: WireGuard secure network tunnel") Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/wireguard/device.c | 12 ++--- drivers/net/wireguard/device.h | 15 +++--- drivers/net/wireguard/peer.c | 28 ++++-------- drivers/net/wireguard/peer.h | 4 - drivers/net/wireguard/queueing.c | 86 +++++++++++++++++++++++++++++++-------- drivers/net/wireguard/queueing.h | 45 ++++++++++++++------ drivers/net/wireguard/receive.c | 16 ++----- drivers/net/wireguard/send.c | 31 ++++---------- 8 files changed, 144 insertions(+), 93 deletions(-)
--- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -235,8 +235,8 @@ static void wg_destruct(struct net_devic destroy_workqueue(wg->handshake_receive_wq); destroy_workqueue(wg->handshake_send_wq); destroy_workqueue(wg->packet_crypt_wq); - wg_packet_queue_free(&wg->decrypt_queue, true); - wg_packet_queue_free(&wg->encrypt_queue, true); + wg_packet_queue_free(&wg->decrypt_queue); + wg_packet_queue_free(&wg->encrypt_queue); rcu_barrier(); /* Wait for all the peers to be actually freed. */ wg_ratelimiter_uninit(); memzero_explicit(&wg->static_identity, sizeof(wg->static_identity)); @@ -338,12 +338,12 @@ static int wg_newlink(struct net *src_ne goto err_destroy_handshake_send;
ret = wg_packet_queue_init(&wg->encrypt_queue, wg_packet_encrypt_worker, - true, MAX_QUEUED_PACKETS); + MAX_QUEUED_PACKETS); if (ret < 0) goto err_destroy_packet_crypt;
ret = wg_packet_queue_init(&wg->decrypt_queue, wg_packet_decrypt_worker, - true, MAX_QUEUED_PACKETS); + MAX_QUEUED_PACKETS); if (ret < 0) goto err_free_encrypt_queue;
@@ -368,9 +368,9 @@ static int wg_newlink(struct net *src_ne err_uninit_ratelimiter: wg_ratelimiter_uninit(); err_free_decrypt_queue: - wg_packet_queue_free(&wg->decrypt_queue, true); + wg_packet_queue_free(&wg->decrypt_queue); err_free_encrypt_queue: - wg_packet_queue_free(&wg->encrypt_queue, true); + wg_packet_queue_free(&wg->encrypt_queue); err_destroy_packet_crypt: destroy_workqueue(wg->packet_crypt_wq); err_destroy_handshake_send: --- a/drivers/net/wireguard/device.h +++ b/drivers/net/wireguard/device.h @@ -27,13 +27,14 @@ struct multicore_worker {
struct crypt_queue { struct ptr_ring ring; - union { - struct { - struct multicore_worker __percpu *worker; - int last_cpu; - }; - struct work_struct work; - }; + struct multicore_worker __percpu *worker; + int last_cpu; +}; + +struct prev_queue { + struct sk_buff *head, *tail, *peeked; + struct { struct sk_buff *next, *prev; } empty; // Match first 2 members of struct sk_buff. + atomic_t count; };
struct wg_device { --- a/drivers/net/wireguard/peer.c +++ b/drivers/net/wireguard/peer.c @@ -32,27 +32,22 @@ struct wg_peer *wg_peer_create(struct wg peer = kzalloc(sizeof(*peer), GFP_KERNEL); if (unlikely(!peer)) return ERR_PTR(ret); - peer->device = wg; + if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)) + goto err;
+ peer->device = wg; wg_noise_handshake_init(&peer->handshake, &wg->static_identity, public_key, preshared_key, peer); - if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)) - goto err_1; - if (wg_packet_queue_init(&peer->tx_queue, wg_packet_tx_worker, false, - MAX_QUEUED_PACKETS)) - goto err_2; - if (wg_packet_queue_init(&peer->rx_queue, NULL, false, - MAX_QUEUED_PACKETS)) - goto err_3; - peer->internal_id = atomic64_inc_return(&peer_counter); peer->serial_work_cpu = nr_cpumask_bits; wg_cookie_init(&peer->latest_cookie); wg_timers_init(peer); wg_cookie_checker_precompute_peer_keys(peer); spin_lock_init(&peer->keypairs.keypair_update_lock); - INIT_WORK(&peer->transmit_handshake_work, - wg_packet_handshake_send_worker); + INIT_WORK(&peer->transmit_handshake_work, wg_packet_handshake_send_worker); + INIT_WORK(&peer->transmit_packet_work, wg_packet_tx_worker); + wg_prev_queue_init(&peer->tx_queue); + wg_prev_queue_init(&peer->rx_queue); rwlock_init(&peer->endpoint_lock); kref_init(&peer->refcount); skb_queue_head_init(&peer->staged_packet_queue); @@ -68,11 +63,7 @@ struct wg_peer *wg_peer_create(struct wg pr_debug("%s: Peer %llu created\n", wg->dev->name, peer->internal_id); return peer;
-err_3: - wg_packet_queue_free(&peer->tx_queue, false); -err_2: - dst_cache_destroy(&peer->endpoint_cache); -err_1: +err: kfree(peer); return ERR_PTR(ret); } @@ -197,8 +188,7 @@ static void rcu_release(struct rcu_head struct wg_peer *peer = container_of(rcu, struct wg_peer, rcu);
dst_cache_destroy(&peer->endpoint_cache); - wg_packet_queue_free(&peer->rx_queue, false); - wg_packet_queue_free(&peer->tx_queue, false); + WARN_ON(wg_prev_queue_peek(&peer->tx_queue) || wg_prev_queue_peek(&peer->rx_queue));
/* The final zeroing takes care of clearing any remaining handshake key * material and other potentially sensitive information. --- a/drivers/net/wireguard/peer.h +++ b/drivers/net/wireguard/peer.h @@ -36,7 +36,7 @@ struct endpoint {
struct wg_peer { struct wg_device *device; - struct crypt_queue tx_queue, rx_queue; + struct prev_queue tx_queue, rx_queue; struct sk_buff_head staged_packet_queue; int serial_work_cpu; struct noise_keypairs keypairs; @@ -45,7 +45,7 @@ struct wg_peer { rwlock_t endpoint_lock; struct noise_handshake handshake; atomic64_t last_sent_handshake; - struct work_struct transmit_handshake_work, clear_peer_work; + struct work_struct transmit_handshake_work, clear_peer_work, transmit_packet_work; struct cookie latest_cookie; struct hlist_node pubkey_hash; u64 rx_bytes, tx_bytes; --- a/drivers/net/wireguard/queueing.c +++ b/drivers/net/wireguard/queueing.c @@ -9,8 +9,7 @@ struct multicore_worker __percpu * wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr) { int cpu; - struct multicore_worker __percpu *worker = - alloc_percpu(struct multicore_worker); + struct multicore_worker __percpu *worker = alloc_percpu(struct multicore_worker);
if (!worker) return NULL; @@ -23,7 +22,7 @@ wg_packet_percpu_multicore_worker_alloc( }
int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, - bool multicore, unsigned int len) + unsigned int len) { int ret;
@@ -31,25 +30,78 @@ int wg_packet_queue_init(struct crypt_qu ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL); if (ret) return ret; - if (function) { - if (multicore) { - queue->worker = wg_packet_percpu_multicore_worker_alloc( - function, queue); - if (!queue->worker) { - ptr_ring_cleanup(&queue->ring, NULL); - return -ENOMEM; - } - } else { - INIT_WORK(&queue->work, function); - } + queue->worker = wg_packet_percpu_multicore_worker_alloc(function, queue); + if (!queue->worker) { + ptr_ring_cleanup(&queue->ring, NULL); + return -ENOMEM; } return 0; }
-void wg_packet_queue_free(struct crypt_queue *queue, bool multicore) +void wg_packet_queue_free(struct crypt_queue *queue) { - if (multicore) - free_percpu(queue->worker); + free_percpu(queue->worker); WARN_ON(!__ptr_ring_empty(&queue->ring)); ptr_ring_cleanup(&queue->ring, NULL); } + +#define NEXT(skb) ((skb)->prev) +#define STUB(queue) ((struct sk_buff *)&queue->empty) + +void wg_prev_queue_init(struct prev_queue *queue) +{ + NEXT(STUB(queue)) = NULL; + queue->head = queue->tail = STUB(queue); + queue->peeked = NULL; + atomic_set(&queue->count, 0); + BUILD_BUG_ON( + offsetof(struct sk_buff, next) != offsetof(struct prev_queue, empty.next) - + offsetof(struct prev_queue, empty) || + offsetof(struct sk_buff, prev) != offsetof(struct prev_queue, empty.prev) - + offsetof(struct prev_queue, empty)); +} + +static void __wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb) +{ + WRITE_ONCE(NEXT(skb), NULL); + WRITE_ONCE(NEXT(xchg_release(&queue->head, skb)), skb); +} + +bool wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb) +{ + if (!atomic_add_unless(&queue->count, 1, MAX_QUEUED_PACKETS)) + return false; + __wg_prev_queue_enqueue(queue, skb); + return true; +} + +struct sk_buff *wg_prev_queue_dequeue(struct prev_queue *queue) +{ + struct sk_buff *tail = queue->tail, *next = smp_load_acquire(&NEXT(tail)); + + if (tail == STUB(queue)) { + if (!next) + return NULL; + queue->tail = next; + tail = next; + next = smp_load_acquire(&NEXT(next)); + } + if (next) { + queue->tail = next; + atomic_dec(&queue->count); + return tail; + } + if (tail != READ_ONCE(queue->head)) + return NULL; + __wg_prev_queue_enqueue(queue, STUB(queue)); + next = smp_load_acquire(&NEXT(tail)); + if (next) { + queue->tail = next; + atomic_dec(&queue->count); + return tail; + } + return NULL; +} + +#undef NEXT +#undef STUB --- a/drivers/net/wireguard/queueing.h +++ b/drivers/net/wireguard/queueing.h @@ -17,12 +17,13 @@ struct wg_device; struct wg_peer; struct multicore_worker; struct crypt_queue; +struct prev_queue; struct sk_buff;
/* queueing.c APIs: */ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, - bool multicore, unsigned int len); -void wg_packet_queue_free(struct crypt_queue *queue, bool multicore); + unsigned int len); +void wg_packet_queue_free(struct crypt_queue *queue); struct multicore_worker __percpu * wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr);
@@ -135,8 +136,31 @@ static inline int wg_cpumask_next_online return cpu; }
+void wg_prev_queue_init(struct prev_queue *queue); + +/* Multi producer */ +bool wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb); + +/* Single consumer */ +struct sk_buff *wg_prev_queue_dequeue(struct prev_queue *queue); + +/* Single consumer */ +static inline struct sk_buff *wg_prev_queue_peek(struct prev_queue *queue) +{ + if (queue->peeked) + return queue->peeked; + queue->peeked = wg_prev_queue_dequeue(queue); + return queue->peeked; +} + +/* Single consumer */ +static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue) +{ + queue->peeked = NULL; +} + static inline int wg_queue_enqueue_per_device_and_peer( - struct crypt_queue *device_queue, struct crypt_queue *peer_queue, + struct crypt_queue *device_queue, struct prev_queue *peer_queue, struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu) { int cpu; @@ -145,8 +169,9 @@ static inline int wg_queue_enqueue_per_d /* We first queue this up for the peer ingestion, but the consumer * will wait for the state to change to CRYPTED or DEAD before. */ - if (unlikely(ptr_ring_produce_bh(&peer_queue->ring, skb))) + if (unlikely(!wg_prev_queue_enqueue(peer_queue, skb))) return -ENOSPC; + /* Then we queue it up in the device queue, which consumes the * packet as soon as it can. */ @@ -157,9 +182,7 @@ static inline int wg_queue_enqueue_per_d return 0; }
-static inline void wg_queue_enqueue_per_peer(struct crypt_queue *queue, - struct sk_buff *skb, - enum packet_state state) +static inline void wg_queue_enqueue_per_peer_tx(struct sk_buff *skb, enum packet_state state) { /* We take a reference, because as soon as we call atomic_set, the * peer can be freed from below us. @@ -167,14 +190,12 @@ static inline void wg_queue_enqueue_per_ struct wg_peer *peer = wg_peer_get(PACKET_PEER(skb));
atomic_set_release(&PACKET_CB(skb)->state, state); - queue_work_on(wg_cpumask_choose_online(&peer->serial_work_cpu, - peer->internal_id), - peer->device->packet_crypt_wq, &queue->work); + queue_work_on(wg_cpumask_choose_online(&peer->serial_work_cpu, peer->internal_id), + peer->device->packet_crypt_wq, &peer->transmit_packet_work); wg_peer_put(peer); }
-static inline void wg_queue_enqueue_per_peer_napi(struct sk_buff *skb, - enum packet_state state) +static inline void wg_queue_enqueue_per_peer_rx(struct sk_buff *skb, enum packet_state state) { /* We take a reference, because as soon as we call atomic_set, the * peer can be freed from below us. --- a/drivers/net/wireguard/receive.c +++ b/drivers/net/wireguard/receive.c @@ -444,7 +444,6 @@ packet_processed: int wg_packet_rx_poll(struct napi_struct *napi, int budget) { struct wg_peer *peer = container_of(napi, struct wg_peer, napi); - struct crypt_queue *queue = &peer->rx_queue; struct noise_keypair *keypair; struct endpoint endpoint; enum packet_state state; @@ -455,11 +454,10 @@ int wg_packet_rx_poll(struct napi_struct if (unlikely(budget <= 0)) return 0;
- while ((skb = __ptr_ring_peek(&queue->ring)) != NULL && + while ((skb = wg_prev_queue_peek(&peer->rx_queue)) != NULL && (state = atomic_read_acquire(&PACKET_CB(skb)->state)) != PACKET_STATE_UNCRYPTED) { - __ptr_ring_discard_one(&queue->ring); - peer = PACKET_PEER(skb); + wg_prev_queue_drop_peeked(&peer->rx_queue); keypair = PACKET_CB(skb)->keypair; free = true;
@@ -508,7 +506,7 @@ void wg_packet_decrypt_worker(struct wor enum packet_state state = likely(decrypt_packet(skb, PACKET_CB(skb)->keypair)) ? PACKET_STATE_CRYPTED : PACKET_STATE_DEAD; - wg_queue_enqueue_per_peer_napi(skb, state); + wg_queue_enqueue_per_peer_rx(skb, state); if (need_resched()) cond_resched(); } @@ -531,12 +529,10 @@ static void wg_packet_consume_data(struc if (unlikely(READ_ONCE(peer->is_dead))) goto err;
- ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, - &peer->rx_queue, skb, - wg->packet_crypt_wq, - &wg->decrypt_queue.last_cpu); + ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb, + wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu); if (unlikely(ret == -EPIPE)) - wg_queue_enqueue_per_peer_napi(skb, PACKET_STATE_DEAD); + wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD); if (likely(!ret || ret == -EPIPE)) { rcu_read_unlock_bh(); return; --- a/drivers/net/wireguard/send.c +++ b/drivers/net/wireguard/send.c @@ -239,8 +239,7 @@ void wg_packet_send_keepalive(struct wg_ wg_packet_send_staged_packets(peer); }
-static void wg_packet_create_data_done(struct sk_buff *first, - struct wg_peer *peer) +static void wg_packet_create_data_done(struct wg_peer *peer, struct sk_buff *first) { struct sk_buff *skb, *next; bool is_keepalive, data_sent = false; @@ -262,22 +261,19 @@ static void wg_packet_create_data_done(s
void wg_packet_tx_worker(struct work_struct *work) { - struct crypt_queue *queue = container_of(work, struct crypt_queue, - work); + struct wg_peer *peer = container_of(work, struct wg_peer, transmit_packet_work); struct noise_keypair *keypair; enum packet_state state; struct sk_buff *first; - struct wg_peer *peer;
- while ((first = __ptr_ring_peek(&queue->ring)) != NULL && + while ((first = wg_prev_queue_peek(&peer->tx_queue)) != NULL && (state = atomic_read_acquire(&PACKET_CB(first)->state)) != PACKET_STATE_UNCRYPTED) { - __ptr_ring_discard_one(&queue->ring); - peer = PACKET_PEER(first); + wg_prev_queue_drop_peeked(&peer->tx_queue); keypair = PACKET_CB(first)->keypair;
if (likely(state == PACKET_STATE_CRYPTED)) - wg_packet_create_data_done(first, peer); + wg_packet_create_data_done(peer, first); else kfree_skb_list(first);
@@ -306,16 +302,14 @@ void wg_packet_encrypt_worker(struct wor break; } } - wg_queue_enqueue_per_peer(&PACKET_PEER(first)->tx_queue, first, - state); + wg_queue_enqueue_per_peer_tx(first, state); if (need_resched()) cond_resched(); } }
-static void wg_packet_create_data(struct sk_buff *first) +static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first) { - struct wg_peer *peer = PACKET_PEER(first); struct wg_device *wg = peer->device; int ret = -EINVAL;
@@ -323,13 +317,10 @@ static void wg_packet_create_data(struct if (unlikely(READ_ONCE(peer->is_dead))) goto err;
- ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, - &peer->tx_queue, first, - wg->packet_crypt_wq, - &wg->encrypt_queue.last_cpu); + ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first, + wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu); if (unlikely(ret == -EPIPE)) - wg_queue_enqueue_per_peer(&peer->tx_queue, first, - PACKET_STATE_DEAD); + wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD); err: rcu_read_unlock_bh(); if (likely(!ret || ret == -EPIPE)) @@ -393,7 +384,7 @@ void wg_packet_send_staged_packets(struc packets.prev->next = NULL; wg_peer_get(keypair->entry.peer); PACKET_CB(packets.next)->keypair = keypair; - wg_packet_create_data(packets.next); + wg_packet_create_data(peer, packets.next); return;
out_invalid:
From: Vlad Buslov vladbu@nvidia.com
commit 396d7f23adf9e8c436dd81a69488b5b6a865acf8 upstream.
When police action is created by cls API tcf_exts_validate() first conditional that calls tcf_action_init_1() directly, the action idr is not updated according to latest changes in action API that require caller to commit newly created action to idr with tcf_idr_insert_many(). This results such action not being accessible through act API and causes crash reported by syzbot:
================================================================== BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:71 [inline] BUG: KASAN: null-ptr-deref in atomic_read include/asm-generic/atomic-instrumented.h:27 [inline] BUG: KASAN: null-ptr-deref in __tcf_idr_release net/sched/act_api.c:178 [inline] BUG: KASAN: null-ptr-deref in tcf_idrinfo_destroy+0x129/0x1d0 net/sched/act_api.c:598 Read of size 4 at addr 0000000000000010 by task kworker/u4:5/204
CPU: 0 PID: 204 Comm: kworker/u4:5 Not tainted 5.11.0-rc7-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: netns cleanup_net Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x107/0x163 lib/dump_stack.c:120 __kasan_report mm/kasan/report.c:400 [inline] kasan_report.cold+0x5f/0xd5 mm/kasan/report.c:413 check_memory_region_inline mm/kasan/generic.c:179 [inline] check_memory_region+0x13d/0x180 mm/kasan/generic.c:185 instrument_atomic_read include/linux/instrumented.h:71 [inline] atomic_read include/asm-generic/atomic-instrumented.h:27 [inline] __tcf_idr_release net/sched/act_api.c:178 [inline] tcf_idrinfo_destroy+0x129/0x1d0 net/sched/act_api.c:598 tc_action_net_exit include/net/act_api.h:151 [inline] police_exit_net+0x168/0x360 net/sched/act_police.c:390 ops_exit_list+0x10d/0x160 net/core/net_namespace.c:190 cleanup_net+0x4ea/0xb10 net/core/net_namespace.c:604 process_one_work+0x98d/0x15f0 kernel/workqueue.c:2275 worker_thread+0x64c/0x1120 kernel/workqueue.c:2421 kthread+0x3b1/0x4a0 kernel/kthread.c:292 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296 ================================================================== Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 204 Comm: kworker/u4:5 Tainted: G B 5.11.0-rc7-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: netns cleanup_net Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x107/0x163 lib/dump_stack.c:120 panic+0x306/0x73d kernel/panic.c:231 end_report+0x58/0x5e mm/kasan/report.c:100 __kasan_report mm/kasan/report.c:403 [inline] kasan_report.cold+0x67/0xd5 mm/kasan/report.c:413 check_memory_region_inline mm/kasan/generic.c:179 [inline] check_memory_region+0x13d/0x180 mm/kasan/generic.c:185 instrument_atomic_read include/linux/instrumented.h:71 [inline] atomic_read include/asm-generic/atomic-instrumented.h:27 [inline] __tcf_idr_release net/sched/act_api.c:178 [inline] tcf_idrinfo_destroy+0x129/0x1d0 net/sched/act_api.c:598 tc_action_net_exit include/net/act_api.h:151 [inline] police_exit_net+0x168/0x360 net/sched/act_police.c:390 ops_exit_list+0x10d/0x160 net/core/net_namespace.c:190 cleanup_net+0x4ea/0xb10 net/core/net_namespace.c:604 process_one_work+0x98d/0x15f0 kernel/workqueue.c:2275 worker_thread+0x64c/0x1120 kernel/workqueue.c:2421 kthread+0x3b1/0x4a0 kernel/kthread.c:292 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296 Kernel Offset: disabled
Fix the issue by calling tcf_idr_insert_many() after successful action initialization.
Fixes: 0fedc63fadf0 ("net_sched: commit action insertions together") Reported-by: syzbot+151e3e714d34ae4ce7e8@syzkaller.appspotmail.com Signed-off-by: Vlad Buslov vladbu@nvidia.com Reviewed-by: Cong Wang xiyou.wangcong@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/net/act_api.h | 1 + net/sched/act_api.c | 2 +- net/sched/cls_api.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-)
--- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -166,6 +166,7 @@ int tcf_idr_create_from_flags(struct tc_ struct nlattr *est, struct tc_action **a, const struct tc_action_ops *ops, int bind, u32 flags); +void tcf_idr_insert_many(struct tc_action *actions[]); void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, struct tc_action **a, int bind); --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -908,7 +908,7 @@ static const struct nla_policy tcf_actio [TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY), };
-static void tcf_idr_insert_many(struct tc_action *actions[]) +void tcf_idr_insert_many(struct tc_action *actions[]) { int i;
--- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3053,6 +3053,7 @@ int tcf_exts_validate(struct net *net, s act->type = exts->type = TCA_OLD_COMPAT; exts->actions[0] = act; exts->nr_actions = 1; + tcf_idr_insert_many(exts->actions); } else if (exts->action && tb[exts->action]) { int err;
From: Takeshi Misawa jeliantsurux@gmail.com
commit fc0494ead6398609c49afa37bc949b61c5c16b91 upstream.
If qrtr_endpoint_register() failed, tun is leaked. Fix this, by freeing tun in error path.
syzbot report: BUG: memory leak unreferenced object 0xffff88811848d680 (size 64): comm "syz-executor684", pid 10171, jiffies 4294951561 (age 26.070s) hex dump (first 32 bytes): 80 dd 0a 84 ff ff ff ff 00 00 00 00 00 00 00 00 ................ 90 d6 48 18 81 88 ff ff 90 d6 48 18 81 88 ff ff ..H.......H..... backtrace: [<0000000018992a50>] kmalloc include/linux/slab.h:552 [inline] [<0000000018992a50>] kzalloc include/linux/slab.h:682 [inline] [<0000000018992a50>] qrtr_tun_open+0x22/0x90 net/qrtr/tun.c:35 [<0000000003a453ef>] misc_open+0x19c/0x1e0 drivers/char/misc.c:141 [<00000000dec38ac8>] chrdev_open+0x10d/0x340 fs/char_dev.c:414 [<0000000079094996>] do_dentry_open+0x1e6/0x620 fs/open.c:817 [<000000004096d290>] do_open fs/namei.c:3252 [inline] [<000000004096d290>] path_openat+0x74a/0x1b00 fs/namei.c:3369 [<00000000b8e64241>] do_filp_open+0xa0/0x190 fs/namei.c:3396 [<00000000a3299422>] do_sys_openat2+0xed/0x230 fs/open.c:1172 [<000000002c1bdcef>] do_sys_open fs/open.c:1188 [inline] [<000000002c1bdcef>] __do_sys_openat fs/open.c:1204 [inline] [<000000002c1bdcef>] __se_sys_openat fs/open.c:1199 [inline] [<000000002c1bdcef>] __x64_sys_openat+0x7f/0xe0 fs/open.c:1199 [<00000000f3a5728f>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 [<000000004b38b7ec>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
Fixes: 28fb4e59a47d ("net: qrtr: Expose tunneling endpoint to user space") Reported-by: syzbot+5d6e4af21385f5cfc56a@syzkaller.appspotmail.com Signed-off-by: Takeshi Misawa jeliantsurux@gmail.com Link: https://lore.kernel.org/r/20210221234427.GA2140@DESKTOP Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/qrtr/tun.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
--- a/net/qrtr/tun.c +++ b/net/qrtr/tun.c @@ -31,6 +31,7 @@ static int qrtr_tun_send(struct qrtr_end static int qrtr_tun_open(struct inode *inode, struct file *filp) { struct qrtr_tun *tun; + int ret;
tun = kzalloc(sizeof(*tun), GFP_KERNEL); if (!tun) @@ -43,7 +44,16 @@ static int qrtr_tun_open(struct inode *i
filp->private_data = tun;
- return qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); + ret = qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); + if (ret) + goto out; + + return 0; + +out: + filp->private_data = NULL; + kfree(tun); + return ret; }
static ssize_t qrtr_tun_read_iter(struct kiocb *iocb, struct iov_iter *to)
From: Cong Wang cong.wang@bytedance.com
commit d349f997686887906b1183b5be96933c5452362a upstream.
tcf_action_init_1() loads tc action modules automatically with request_module() after parsing the tc action names, and it drops RTNL lock and re-holds it before and after request_module(). This causes a lot of troubles, as discovered by syzbot, because we can be in the middle of batch initializations when we create an array of tc actions.
One of the problem is deadlock:
CPU 0 CPU 1 rtnl_lock(); for (...) { tcf_action_init_1(); -> rtnl_unlock(); -> request_module(); rtnl_lock(); for (...) { tcf_action_init_1(); -> tcf_idr_check_alloc(); // Insert one action into idr, // but it is not committed until // tcf_idr_insert_many(), then drop // the RTNL lock in the _next_ // iteration -> rtnl_unlock(); -> rtnl_lock(); -> a_o->init(); -> tcf_idr_check_alloc(); // Now waiting for the same index // to be committed -> request_module(); -> rtnl_lock() // Now waiting for RTNL lock } rtnl_unlock(); } rtnl_unlock();
This is not easy to solve, we can move the request_module() before this loop and pre-load all the modules we need for this netlink message and then do the rest initializations. So the loop breaks down to two now:
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { struct tc_action_ops *a_o;
a_o = tc_action_load_ops(name, tb[i]...); ops[i - 1] = a_o; }
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { act = tcf_action_init_1(ops[i - 1]...); }
Although this looks serious, it only has been reported by syzbot, so it seems hard to trigger this by humans. And given the size of this patch, I'd suggest to make it to net-next and not to backport to stable.
This patch has been tested by syzbot and tested with tdc.py by me.
Fixes: 0fedc63fadf0 ("net_sched: commit action insertions together") Reported-and-tested-by: syzbot+82752bc5331601cf4899@syzkaller.appspotmail.com Reported-and-tested-by: syzbot+b3b63b6bff456bd95294@syzkaller.appspotmail.com Reported-by: syzbot+ba67b12b1ca729912834@syzkaller.appspotmail.com Cc: Jiri Pirko jiri@resnulli.us Signed-off-by: Cong Wang cong.wang@bytedance.com Tested-by: Jamal Hadi Salim jhs@mojatatu.com Acked-by: Jamal Hadi Salim jhs@mojatatu.com Link: https://lore.kernel.org/r/20210117005657.14810-1-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/net/act_api.h | 5 +- net/sched/act_api.c | 104 +++++++++++++++++++++++++++++++------------------- net/sched/cls_api.c | 11 ++++- 3 files changed, 79 insertions(+), 41 deletions(-)
--- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -187,10 +187,13 @@ int tcf_action_init(struct net *net, str struct nlattr *est, char *name, int ovr, int bind, struct tc_action *actions[], size_t *attr_size, bool rtnl_held, struct netlink_ext_ack *extack); +struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, + bool rtnl_held, + struct netlink_ext_ack *extack); struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct nlattr *nla, struct nlattr *est, char *name, int ovr, int bind, - bool rtnl_held, + struct tc_action_ops *ops, bool rtnl_held, struct netlink_ext_ack *extack); int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, int ref, bool terse); --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -928,19 +928,13 @@ void tcf_idr_insert_many(struct tc_actio } }
-struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, - struct nlattr *nla, struct nlattr *est, - char *name, int ovr, int bind, - bool rtnl_held, - struct netlink_ext_ack *extack) +struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, + bool rtnl_held, + struct netlink_ext_ack *extack) { - struct nla_bitfield32 flags = { 0, 0 }; - u8 hw_stats = TCA_ACT_HW_STATS_ANY; - struct tc_action *a; + struct nlattr *tb[TCA_ACT_MAX + 1]; struct tc_action_ops *a_o; - struct tc_cookie *cookie = NULL; char act_name[IFNAMSIZ]; - struct nlattr *tb[TCA_ACT_MAX + 1]; struct nlattr *kind; int err;
@@ -948,33 +942,21 @@ struct tc_action *tcf_action_init_1(stru err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, tcf_action_policy, extack); if (err < 0) - goto err_out; + return ERR_PTR(err); err = -EINVAL; kind = tb[TCA_ACT_KIND]; if (!kind) { NL_SET_ERR_MSG(extack, "TC action kind must be specified"); - goto err_out; + return ERR_PTR(err); } if (nla_strscpy(act_name, kind, IFNAMSIZ) < 0) { NL_SET_ERR_MSG(extack, "TC action name too long"); - goto err_out; + return ERR_PTR(err); } - if (tb[TCA_ACT_COOKIE]) { - cookie = nla_memdup_cookie(tb); - if (!cookie) { - NL_SET_ERR_MSG(extack, "No memory to generate TC cookie"); - err = -ENOMEM; - goto err_out; - } - } - hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]); - if (tb[TCA_ACT_FLAGS]) - flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]); } else { if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) { NL_SET_ERR_MSG(extack, "TC action name too long"); - err = -EINVAL; - goto err_out; + return ERR_PTR(-EINVAL); } }
@@ -996,24 +978,56 @@ struct tc_action *tcf_action_init_1(stru * indicate this using -EAGAIN. */ if (a_o != NULL) { - err = -EAGAIN; - goto err_mod; + module_put(a_o->owner); + return ERR_PTR(-EAGAIN); } #endif NL_SET_ERR_MSG(extack, "Failed to load TC action module"); - err = -ENOENT; - goto err_free; + return ERR_PTR(-ENOENT); }
+ return a_o; +} + +struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, + struct nlattr *nla, struct nlattr *est, + char *name, int ovr, int bind, + struct tc_action_ops *a_o, bool rtnl_held, + struct netlink_ext_ack *extack) +{ + struct nla_bitfield32 flags = { 0, 0 }; + u8 hw_stats = TCA_ACT_HW_STATS_ANY; + struct nlattr *tb[TCA_ACT_MAX + 1]; + struct tc_cookie *cookie = NULL; + struct tc_action *a; + int err; + /* backward compatibility for policer */ - if (name == NULL) + if (name == NULL) { + err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, + tcf_action_policy, extack); + if (err < 0) + return ERR_PTR(err); + if (tb[TCA_ACT_COOKIE]) { + cookie = nla_memdup_cookie(tb); + if (!cookie) { + NL_SET_ERR_MSG(extack, "No memory to generate TC cookie"); + err = -ENOMEM; + goto err_out; + } + } + hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]); + if (tb[TCA_ACT_FLAGS]) + flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]); + err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, rtnl_held, tp, flags.value, extack); - else + } else { err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, tp, flags.value, extack); + } if (err < 0) - goto err_mod; + goto err_out;
if (!name && tb[TCA_ACT_COOKIE]) tcf_set_action_cookie(&a->act_cookie, cookie); @@ -1030,14 +1044,11 @@ struct tc_action *tcf_action_init_1(stru
return a;
-err_mod: - module_put(a_o->owner); -err_free: +err_out: if (cookie) { kfree(cookie->data); kfree(cookie); } -err_out: return ERR_PTR(err); }
@@ -1048,6 +1059,7 @@ int tcf_action_init(struct net *net, str struct tc_action *actions[], size_t *attr_size, bool rtnl_held, struct netlink_ext_ack *extack) { + struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct tc_action *act; size_t sz = 0; @@ -1060,8 +1072,19 @@ int tcf_action_init(struct net *net, str return err;
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { + struct tc_action_ops *a_o; + + a_o = tc_action_load_ops(name, tb[i], rtnl_held, extack); + if (IS_ERR(a_o)) { + err = PTR_ERR(a_o); + goto err_mod; + } + ops[i - 1] = a_o; + } + + for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind, - rtnl_held, extack); + ops[i - 1], rtnl_held, extack); if (IS_ERR(act)) { err = PTR_ERR(act); goto err; @@ -1081,6 +1104,11 @@ int tcf_action_init(struct net *net, str
err: tcf_action_destroy(actions, bind); +err_mod: + for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { + if (ops[i]) + module_put(ops[i]->owner); + } return err; }
--- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3043,12 +3043,19 @@ int tcf_exts_validate(struct net *net, s size_t attr_size = 0;
if (exts->police && tb[exts->police]) { + struct tc_action_ops *a_o; + + a_o = tc_action_load_ops("police", tb[exts->police], rtnl_held, extack); + if (IS_ERR(a_o)) + return PTR_ERR(a_o); act = tcf_action_init_1(net, tp, tb[exts->police], rate_tlv, "police", ovr, - TCA_ACT_BIND, rtnl_held, + TCA_ACT_BIND, a_o, rtnl_held, extack); - if (IS_ERR(act)) + if (IS_ERR(act)) { + module_put(a_o->owner); return PTR_ERR(act); + }
act->type = exts->type = TCA_OLD_COMPAT; exts->actions[0] = act;
linux-stable-mirror@lists.linaro.org