This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.4.102-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.4.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.4.102-rc1
Takeshi Misawa jeliantsurux@gmail.com net: qrtr: Fix memory leak in qrtr_tun_open
Nikos Tsironis ntsironis@arrikto.com dm era: Update in-core bitset after committing the metadata
Vlad Buslov vladbu@nvidia.com net: sched: fix police ext initialization
Jason A. Donenfeld Jason@zx2c4.com net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky leonro@nvidia.com ipv6: silence compilation warning for non-IPV6 builds
Eric Dumazet edumazet@google.com ipv6: icmp6: avoid indirect call for icmpv6_send()
Jason A. Donenfeld Jason@zx2c4.com xfrm: interface: use icmp_ndo_send helper
Jason A. Donenfeld Jason@zx2c4.com sunvnet: use icmp_ndo_send helper
Jason A. Donenfeld Jason@zx2c4.com gtp: use icmp_ndo_send helper
Jason A. Donenfeld Jason@zx2c4.com icmp: introduce helper for nat'd source address in network device context
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: 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: fix deadlock when swapping to encrypted device
Andreas Gruenbacher agruenba@redhat.com gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Bob Peterson rpeterso@redhat.com gfs2: Don't skip dlm unlock if glock has an lvb
Masahisa Kojima masahisa.kojima@linaro.org spi: spi-synquacer: fix set_cs handling
Al Viro viro@zeniv.linux.org.uk sparc32: fix a user-triggerable oops in clear_user()
Chao Yu chao@kernel.org f2fs: fix out-of-repair __setattr_copy()
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
Chen Yu yu.c.chen@intel.com cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Muchun Song songmuchun@bytedance.com printk: fix deadlock when kernel panic
Maxim Kiselev bigunclemax@gmail.com gpio: pcf857x: Fix missing first interrupt
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
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
Sean Young sean@mess.org media: smipcie: fix interrupt handling and IR timeout
Suzuki K Poulose suzuki.poulose@arm.com arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
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
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
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
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
Jiri Kosina jkosina@suse.cz floppy: reintroduce O_NDELAY fix
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
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
Pavel Machek pavel@denx.de media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
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
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
Paul Cercueil paul@crapouillou.net seccomp: Add missing return in non-void function
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: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel ardb@kernel.org crypto: arm64/sha - add missing module aliases
Filipe Manana fdmanana@suse.com btrfs: fix extent buffer leak on failure to copy root
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
Jarkko Sakkinen jarkko@kernel.org KEYS: trusted: Fix migratable=1 failing
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
Andrey Grodzovsky andrey.grodzovsky@amd.com drm/sched: Cancel and flush all outstanding jobs before finish.
Karol Herbst kherbst@redhat.com drm/nouveau/kms: handle mDP connectors
Alex Deucher alexander.deucher@amd.com drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Rodrigo Siqueira Rodrigo.Siqueira@amd.com drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
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"
PeiSen Hou pshou@realtek.com ALSA: hda/realtek: modify EAPD in the ALC886
Kai Vehmanen kai.vehmanen@linux.intel.com ALSA: hda: Add another CometLake-H PCI ID
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: 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
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
Mikulas Patocka mpatocka@redhat.com blk-settings: align max_sectors on "logical_block_size" boundary
Randy Dunlap rdunlap@infradead.org scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Miaohe Lin linmiaohe@huawei.com mm/rmap: fix potential pte_unmap on an not mapped pte
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
Heiner Kallweit hkallweit1@gmail.com r8169: fix jumbo packet handling on RTL8168e
Wonhyuk Yang vvghjk1234@gmail.com mm/compaction: fix misbehaviors of fast_find_migrateblock()
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
Dan Carpenter dan.carpenter@oracle.com ocfs2: fix a use after free on error
Taehee Yoo ap420073@gmail.com vxlan: move debug check after netdev unregister
Chuhong Yuan hslester96@gmail.com net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Alex Williamson alex.williamson@redhat.com vfio/type1: Use follow_pte()
Mateusz Palczewski mateusz.palczewski@intel.com i40e: Fix add TC filter for IPv6
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)
Bard Liao yung-chuan.liao@linux.intel.com regmap: sdw: use _no_pm functions in regmap_read/write
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()
Theodore Ts'o tytso@mit.edu ext4: fix potential htree index checksum corruption
Keqian Zhu zhukeqian1@huawei.com vfio/iommu_type1: Fix some sanity checks in detach group
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)
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
Simon South simon@simonsouth.net pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com soundwire: cadence: fix ACK/NAK handling
Aswath Govindraju a-govindraju@ti.com misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
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
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 premature IPC
Adrian Hunter adrian.hunter@intel.com perf intel-pt: Fix missing CYC processing in PSB
Dan Carpenter dan.carpenter@oracle.com Input: sur40 - fix an error code in sur40_probe()
Lang Cheng chenglang@huawei.com RDMA/hns: Fixes missing error code of CMDQ
J. Bruce Fields bfields@redhat.com nfsd: register pernet ops last, unregister first
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
Andy Shevchenko andriy.shevchenko@linux.intel.com spi: pxa2xx: Fix the controller numbering for Wildcat Point
Weihang Li liweihang@huawei.com RDMA/hns: Fix type of sq_signal_bits
Kamal Heib kamalheib1@gmail.com RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang liangwenpeng@huawei.com RDMA/hns: Fixed wrong judgments in the goto branch
AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
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()
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
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
Uwe Kleine-König u.kleine-koenig@pengutronix.de amba: Fix resource leak for drivers without .remove
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
Ananth N Mavinakayanahalli ananth@linux.ibm.com powerpc/sstep: Fix incorrect return from analyze_instr()
Christophe Leroy christophe.leroy@csgroup.eu powerpc/47x: Disable 256k page size
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
Josh Poimboeuf jpoimboe@redhat.com objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf jpoimboe@redhat.com objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven geert@linux-m68k.org auxdisplay: ht16k33: Fix refresh rate handling
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
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
Pan Bian bianpan2016@163.com regulator: axp20x: Fix reference cout leak
Andre Przywara andre.przywara@arm.com clk: sunxi-ng: h6: Fix clock divider range on some clocks
Yishai Hadas yishaih@nvidia.com RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
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
Bartosz Golaszewski bgolaszewski@baylibre.com rtc: s5m: select REGMAP_I2C
Claudiu Beznea claudiu.beznea@microchip.com power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
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
Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth ftoth@exalondelft.nl dmaengine: hsu: disable spurious interrupt
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()
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
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
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
Wang ShaoBo bobo.shaobowang@huawei.com ubifs: Fix error return code in alloc_wbufs()
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
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
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
Andrea Parri (Microsoft) parri.andrea@gmail.com Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
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
Manivannan Sadhasivam manivannan.sadhasivam@linaro.org mtd: parsers: afs: Fix freeing the part name memory in failure
Sebastian Reichel sre@kernel.org ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli f.fainelli@gmail.com ata: ahci_brcm: Add back regulators management
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 - 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()
Qais Yousef qais.yousef@arm.com sched/eas: Don't update misfit status if the task is pinned
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
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()
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.
Pan Bian bianpan2016@163.com bsg: free the request before return error code
Alexander Lobakin alobakin@pm.me MIPS: properly stop .eh_frame generation
Giulio Benetti giulio.benetti@micronovasrl.com drm/sun4i: tcon: fix inverted DCLK polarity
Jiri Olsa jolsa@kernel.org crypto: bcm - Rename struct device_private to bcm_device_private
Dinghao Liu dinghao.liu@zju.edu.cn evm: Fix memleak in init_desc
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()
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
Nathan Chancellor natechancellor@gmail.com MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor natechancellor@gmail.com 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
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
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
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
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
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
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
Jesper Dangaard Brouer brouer@redhat.com bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Colin Ian King colin.king@canonical.com mac80211: fix potential overflow when multiplying to u32 integers
Juergen Gross jgross@suse.com xen/netback: fix spurious event detection for common event case
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
Linus Lüssing ll@simonwunderlich.de ath9k: fix data bus crash when setting nf_override via debugfs
Marco Elver elver@google.com bpf_lru_list: Read double-checked variable once without lock
Jae Hyun Yoo jae.hyun.yoo@intel.com soc: aspeed: snoop: Add clock control logic
Arnd Bergmann arnd@arndb.de ARM: s3c: fix fiq for clang IAS
Vincent Knecht vincent.knecht@mailoo.org arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Jupeng Zhong zhongjupeng@yulong.com Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
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
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
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
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
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
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
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
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
Eric Biggers ebiggers@google.com random: fix the RNDRESEEDCRNG ioctl
Alexander Lobakin alobakin@pm.me MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
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
Sumit Garg sumit.garg@linaro.org kdb: Make memory allocations more robust
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()
Maxim Levitsky mlevitsk@redhat.com kvm: x86: replace kvm_spec_ctrl_test_value with runtime test on the host
Nick Desaulniers ndesaulniers@google.com vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/filesystems/seq_file.txt | 6 + 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/mach-ixp4xx/Kconfig | 1 - 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/exynos/exynos5433-tm2-common.dtsi | 2 +- arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +- .../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +- arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 + arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +- 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/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/mips/include/asm/asm.h | 18 ++ arch/mips/kernel/vmlinux.lds.S | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/mm/c-r4k.c | 2 +- arch/nios2/kernel/sys_nios2.c | 11 +- arch/powerpc/Kconfig | 2 +- arch/powerpc/kernel/entry_32.S | 3 + arch/powerpc/kernel/head_8xx.S | 2 +- arch/powerpc/kernel/prom_init.c | 12 +- arch/powerpc/kvm/powerpc.c | 8 +- arch/powerpc/lib/sstep.c | 7 +- arch/powerpc/platforms/pseries/dlpar.c | 7 +- arch/s390/kernel/vtime.c | 3 +- arch/sparc/Kconfig | 2 +- arch/sparc/lib/memset.S | 1 + arch/um/kernel/tlb.c | 12 +- arch/x86/crypto/aesni-intel_glue.c | 28 ++- arch/x86/include/asm/virtext.h | 17 +- arch/x86/kernel/reboot.c | 29 +-- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/x86.c | 38 +-- arch/x86/kvm/x86.h | 2 +- arch/x86/mm/pat.c | 3 +- block/bfq-iosched.c | 1 + block/blk-settings.c | 12 + block/bsg.c | 4 +- certs/blacklist.c | 2 +- crypto/ecdh_helper.c | 3 + drivers/acpi/acpi_configfs.c | 7 +- drivers/acpi/property.c | 44 +++- drivers/amba/bus.c | 20 +- drivers/ata/ahci_brcm.c | 14 +- drivers/auxdisplay/ht16k33.c | 3 +- drivers/base/regmap/regmap-sdw.c | 4 +- drivers/base/swnode.c | 8 +- drivers/block/floppy.c | 27 +- drivers/bluetooth/btqcomsmd.c | 27 +- drivers/bluetooth/btusb.c | 20 +- drivers/bluetooth/hci_ldisc.c | 7 +- drivers/bluetooth/hci_serdev.c | 4 +- drivers/char/hw_random/timeriomem-rng.c | 2 +- drivers/char/random.c | 2 +- drivers/char/tpm/tpm_tis_core.c | 50 +--- drivers/clk/clk-ast2600.c | 37 ++- drivers/clk/meson/clk-pll.c | 10 +- drivers/clk/qcom/gcc-msm8998.c | 100 ++++---- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +- drivers/clocksource/Kconfig | 1 + drivers/clocksource/mxs_timer.c | 5 +- drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +- drivers/cpufreq/intel_pstate.c | 5 +- drivers/crypto/bcm/cipher.c | 2 +- drivers/crypto/bcm/cipher.h | 4 +- drivers/crypto/bcm/util.c | 2 +- drivers/crypto/chelsio/chtls/chtls_cm.h | 3 - drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 173 ++++++++----- drivers/crypto/sunxi-ss/sun4i-ss.h | 2 + drivers/crypto/talitos.c | 28 ++- drivers/crypto/talitos.h | 1 + drivers/dma/fsldma.c | 6 + drivers/dma/hsu/pci.c | 21 +- drivers/dma/owl-dma.c | 1 + drivers/gpio/gpio-pcf857x.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +- drivers/gpu/drm/amd/amdgpu/soc15.c | 2 + .../gpu/drm/amd/display/dc/bios/command_table.c | 61 +++++ .../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 +- .../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 ++ drivers/gpu/drm/drm_fb_helper.c | 15 +- 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/msm/disp/mdp5/mdp5_crtc.c | 2 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +- .../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/scheduler/sched_main.c | 3 + drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +- drivers/gpu/drm/sun4i/sun4i_tcon.h | 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/i2c/busses/i2c-bcm-iproc.c | 231 ++++++++++++++---- drivers/i2c/busses/i2c-brcmstb.c | 2 +- drivers/i2c/busses/i2c-qcom-geni.c | 93 +++++-- drivers/infiniband/core/cm.c | 8 +- drivers/infiniband/core/user_mad.c | 17 +- drivers/infiniband/hw/hns/hns_roce_device.h | 2 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 7 +- drivers/infiniband/hw/hns/hns_roce_main.c | 3 +- drivers/infiniband/hw/mlx5/devx.c | 4 +- drivers/infiniband/hw/mlx5/main.c | 3 +- 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/input/joydev.c | 7 +- drivers/input/joystick/xpad.c | 1 + drivers/input/serio/i8042-x86ia64io.h | 4 + drivers/input/touchscreen/elo.c | 4 +- drivers/input/touchscreen/raydium_i2c_ts.c | 3 +- drivers/input/touchscreen/sur40.c | 1 + 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-writecache.c | 18 ++ drivers/md/dm.c | 60 +++++ drivers/media/i2c/ov5670.c | 3 +- drivers/media/pci/cx25821/cx25821-core.c | 4 +- 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/pxa_camera.c | 3 + drivers/media/platform/qcom/camss/camss-video.c | 1 + drivers/media/platform/vsp1/vsp1_drv.c | 4 +- drivers/media/rc/mceusb.c | 2 +- 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/memory/mtk-smi.c | 4 +- drivers/memory/ti-aemif.c | 8 +- drivers/mfd/bd9571mwv.c | 6 +- drivers/mfd/wm831x-auxadc.c | 3 +- drivers/misc/cardreader/rts5227.c | 5 + drivers/misc/eeprom/eeprom_93xx46.c | 1 + drivers/misc/mei/hbm.c | 2 +- drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +- drivers/mmc/host/sdhci-esdhc-imx.c | 3 +- drivers/mmc/host/sdhci-sprd.c | 6 +- drivers/mmc/host/usdhi6rol0.c | 4 +- drivers/mtd/parsers/afs.c | 4 +- drivers/mtd/parsers/parser_imagetag.c | 4 + drivers/mtd/spi-nor/cadence-quadspi.c | 2 +- drivers/mtd/spi-nor/hisi-sfc.c | 4 +- drivers/mtd/spi-nor/spi-nor.c | 15 +- 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/chelsio/cxgb4/cxgb4_uld.h | 3 + drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +- drivers/net/ethernet/ibm/ibmvnic.c | 16 +- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 50 ++-- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +- drivers/net/ethernet/marvell/mvneta.c | 9 +- .../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 + drivers/net/ethernet/realtek/r8169_main.c | 4 +- drivers/net/ethernet/sun/sunvnet_common.c | 23 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +- drivers/net/gtp.c | 5 +- drivers/net/vxlan.c | 11 +- drivers/net/wireless/ath/ath10k/snoc.c | 5 +- drivers/net/wireless/ath/ath9k/debug.c | 5 +- drivers/net/wireless/broadcom/b43/phy_n.c | 2 +- drivers/net/xen-netback/interface.c | 8 +- drivers/nvmem/core.c | 5 +- drivers/of/fdt.c | 12 +- drivers/pci/controller/dwc/pcie-qcom.c | 4 +- drivers/pci/setup-res.c | 6 + drivers/pci/syscall.c | 10 +- drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +- drivers/power/reset/at91-sama5d2_shdwc.c | 2 +- drivers/pwm/pwm-rockchip.c | 1 - drivers/regulator/axp20x-regulator.c | 7 +- drivers/regulator/core.c | 6 +- drivers/regulator/qcom-rpmh-regulator.c | 2 +- drivers/regulator/s5m8767.c | 15 +- drivers/rtc/Kconfig | 1 + drivers/s390/virtio/virtio_ccw.c | 4 +- drivers/scsi/bnx2fc/Kconfig | 1 + drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 ++- drivers/soundwire/cadence_master.c | 8 +- drivers/spi/spi-atmel.c | 2 +- drivers/spi/spi-pxa2xx-pci.c | 27 +- drivers/spi/spi-s3c24xx-fiq.S | 9 +- drivers/spi/spi-stm32.c | 4 + drivers/spi/spi-synquacer.c | 4 + drivers/spmi/spmi-pmic-arb.c | 5 +- drivers/staging/gdm724x/gdm_usb.c | 10 +- drivers/staging/media/imx/imx-media-csc-scaler.c | 4 - drivers/staging/media/imx/imx-media-dev.c | 7 +- 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 +- drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +- 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/vfio/vfio_iommu_type1.c | 46 ++-- drivers/video/fbdev/Kconfig | 2 +- drivers/virt/vboxguest/vboxguest_utils.c | 18 +- drivers/watchdog/mei_wdt.c | 1 + drivers/watchdog/qcom-wdt.c | 13 +- fs/affs/namei.c | 4 +- fs/btrfs/block-group.c | 19 +- fs/btrfs/ctree.c | 7 +- fs/btrfs/free-space-cache.c | 6 +- fs/btrfs/relocation.c | 4 +- fs/debugfs/inode.c | 5 +- fs/erofs/xattr.c | 10 +- fs/erofs/zmap.c | 10 +- fs/ext4/namei.c | 7 +- fs/f2fs/data.c | 2 +- fs/f2fs/file.c | 7 +- fs/f2fs/inline.c | 4 + fs/gfs2/bmap.c | 6 +- fs/gfs2/lock_dlm.c | 8 +- fs/isofs/dir.c | 1 + fs/isofs/namei.c | 1 + fs/jffs2/summary.c | 3 + fs/jfs/jfs_dmap.c | 2 +- fs/nfsd/nfsctl.c | 14 +- fs/ocfs2/cluster/heartbeat.c | 8 +- fs/pstore/platform.c | 4 +- fs/quota/quota_v2.c | 11 +- fs/ubifs/auth.c | 2 +- fs/ubifs/super.c | 4 +- include/acpi/acexcep.h | 10 +- include/asm-generic/vmlinux.lds.h | 7 +- include/linux/bpf.h | 3 + include/linux/device-mapper.h | 5 + include/linux/filter.h | 2 +- include/linux/icmpv6.h | 44 +++- include/linux/ipv6.h | 1 - include/linux/kexec.h | 5 + include/linux/key.h | 1 + include/linux/rcupdate.h | 2 + include/linux/rmap.h | 3 +- include/net/act_api.h | 1 + include/net/icmp.h | 10 + include/net/tcp.h | 9 +- kernel/bpf/bpf_lru_list.c | 7 +- kernel/debug/kdb/kdb_private.h | 2 +- kernel/kexec_file.c | 5 + kernel/module.c | 21 +- kernel/printk/printk_safe.c | 16 +- kernel/rcu/tree.c | 27 +- kernel/rcu/tree.h | 2 +- kernel/rcu/tree_plugin.h | 30 ++- kernel/sched/fair.c | 2 +- kernel/sched/idle.c | 1 + kernel/seccomp.c | 2 + kernel/tracepoint.c | 80 ++++-- mm/compaction.c | 27 +- mm/hugetlb.c | 10 +- mm/memory.c | 16 +- net/bluetooth/a2mp.c | 3 +- net/bluetooth/hci_core.c | 6 +- net/core/filter.c | 13 +- net/ipv4/icmp.c | 34 +++ net/ipv6/icmp.c | 19 +- net/ipv6/ip6_icmp.c | 46 +++- net/mac80211/mesh_hwmp.c | 2 +- net/qrtr/tun.c | 12 +- net/sched/act_api.c | 2 +- net/sched/cls_api.c | 1 + net/xfrm/xfrm_interface.c | 6 +- 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/key.c | 2 + security/keys/trusted.c | 2 +- sound/pci/hda/hda_intel.c | 2 + sound/pci/hda/patch_realtek.c | 11 + sound/soc/codecs/cpcap.c | 12 +- sound/soc/codecs/cs42l56.c | 3 +- sound/soc/generic/simple-card-utils.c | 13 +- sound/soc/sof/debug.c | 2 +- sound/usb/pcm.c | 2 +- tools/objtool/check.c | 12 +- .../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +- tools/perf/tests/sample-parsing.c | 2 +- tools/perf/util/event.c | 2 + .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 14 +- .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + tools/perf/util/intel-pt.c | 16 +- tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +- 337 files changed, 2573 insertions(+), 1253 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 @@ -756,8 +756,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: Maxim Levitsky mlevitsk@redhat.com
commit 841c2be09fe4f495fe5224952a419bd8c7e5b455 upstream.
To avoid complex and in some cases incorrect logic in kvm_spec_ctrl_test_value, just try the guest's given value on the host processor instead, and if it doesn't #GP, allow the guest to set it.
One such case is when host CPU supports STIBP mitigation but doesn't support IBRS (as is the case with some Zen2 AMD cpus), and in this case we were giving guest #GP when it tried to use STIBP
The reason why can can do the host test is that IA32_SPEC_CTRL msr is passed to the guest, after the guest sets it to a non zero value for the first time (due to performance reasons), and as as result of this, it is pointless to emulate #GP condition on this first access, in a different way than what the host CPU does.
This is based on a patch from Sean Christopherson, who suggested this idea.
Fixes: 6441fa6178f5 ("KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL") Cc: stable@vger.kernel.org Suggested-by: Sean Christopherson sean.j.christopherson@intel.com Signed-off-by: Maxim Levitsky mlevitsk@redhat.com Message-Id: 20200708115731.180097-1-mlevitsk@redhat.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Thomas Lamprecht t.lamprecht@proxmox.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/x86.c | 40 ++++++++++++++++++++++------------------ arch/x86/kvm/x86.h | 2 +- 4 files changed, 25 insertions(+), 21 deletions(-)
--- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -4327,7 +4327,7 @@ static int svm_set_msr(struct kvm_vcpu * !guest_has_spec_ctrl_msr(vcpu)) return 1;
- if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1;
svm->spec_ctrl = data; --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1974,7 +1974,7 @@ static int vmx_set_msr(struct kvm_vcpu * !guest_has_spec_ctrl_msr(vcpu)) return 1;
- if (data & ~kvm_spec_ctrl_valid_bits(vcpu)) + if (kvm_spec_ctrl_test_value(data)) return 1;
vmx->spec_ctrl = data; --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10374,28 +10374,32 @@ bool kvm_arch_no_poll(struct kvm_vcpu *v } EXPORT_SYMBOL_GPL(kvm_arch_no_poll);
-u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu) + +int kvm_spec_ctrl_test_value(u64 value) { - uint64_t bits = SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD; + /* + * test that setting IA32_SPEC_CTRL to given value + * is allowed by the host processor + */ + + u64 saved_value; + unsigned long flags; + int ret = 0; + + local_irq_save(flags); + + if (rdmsrl_safe(MSR_IA32_SPEC_CTRL, &saved_value)) + ret = 1; + else if (wrmsrl_safe(MSR_IA32_SPEC_CTRL, value)) + ret = 1; + else + wrmsrl(MSR_IA32_SPEC_CTRL, saved_value);
- /* The STIBP bit doesn't fault even if it's not advertised */ - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL) && - !boot_cpu_has(X86_FEATURE_AMD_IBRS)) - bits &= ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP); - - if (!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL_SSBD) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; - if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) && - !boot_cpu_has(X86_FEATURE_AMD_SSBD)) - bits &= ~SPEC_CTRL_SSBD; + local_irq_restore(flags);
- return bits; + return ret; } -EXPORT_SYMBOL_GPL(kvm_spec_ctrl_valid_bits); +EXPORT_SYMBOL_GPL(kvm_spec_ctrl_test_value);
EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio); --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -368,6 +368,6 @@ static inline bool kvm_pat_valid(u64 dat
void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu); void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu); -u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu); +int kvm_spec_ctrl_test_value(u64 value);
#endif
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 @@ -293,7 +293,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 @@ -315,6 +315,9 @@ static struct dentry *start_creating(con struct dentry *dentry; int error;
+ if (!debugfs_initialized()) + return ERR_PTR(-ENOENT); + pr_debug("creating file '%s'\n", name);
if (IS_ERR(parent))
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 @@ -233,7 +233,7 @@ extern struct task_struct *kdb_curr_task #define kdb_do_each_thread(g, p) do_each_thread(g, p) #define kdb_while_each_thread(g, p) while_each_thread(g, 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: 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 @@ -402,7 +402,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 @@ -409,10 +409,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 @@ -466,7 +466,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; @@ -493,10 +493,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) @@ -629,7 +634,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 @@ -1885,7 +1885,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_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG,
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 @@ -93,6 +93,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: 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 @@ -2149,7 +2149,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: 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 63607c3b8e818..d4589b2ab3b6d 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1039,12 +1039,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 5b9aa73ff2b7f..1b4ad231e6ed3 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -85,9 +85,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: 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 dee35e3a5c4ba..69d134db6e94e 100644 --- a/arch/arm/boot/dts/exynos3250-artik5.dtsi +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -75,7 +75,7 @@ s2mps14_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 248bd372fe705..a23a8749c94e4 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -195,7 +195,7 @@ s2mps14_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 86c26a4edfd72..468932f452895 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -260,7 +260,7 @@ s2mps14_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 3d501926c2278..2355c53164840 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -108,7 +108,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 592d7b45ecc87..53bf988855e0d 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 829147e320e08..9e64a4ab94940 100644 --- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi @@ -141,7 +141,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 6f90b0e62cba6..148bdca8d9c96 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi @@ -389,7 +389,7 @@ s2mps13-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 61ee7b6a31594..09aead2be000c 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -90,7 +90,7 @@ s2mps15_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 a113e811faabe..da1ce7fd4cf5c 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -127,7 +127,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; } @@ -336,7 +336,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: 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 7aa0d8b5aaf0c..007147f643908 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -711,7 +711,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
/* Map specifics */ struct xdp_buff;
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 79830bc9e45cf..c53e2fe3c8f7f 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -846,7 +846,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: 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 78c82a665c84a..b0f81802d334b 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -103,8 +103,6 @@ };
&ehci0 { - phys = <&usbphy 0>; - phy-names = "usb"; status = "okay"; };
@@ -150,8 +148,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 367699c8c9028..4c85dfc811c80 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -530,6 +530,8 @@ <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>, <&ccu RST_BUS_EHCI0>; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; };
@@ -540,6 +542,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 ab081efd59718..8b77bd5a3c017 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -533,6 +533,8 @@ <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>, <&ccu RST_BUS_EHCI0>; + phys = <&usb2phy 0>; + phy-names = "usb"; status = "disabled"; };
@@ -543,6 +545,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 9d20e13f0c02b..d935e3028fcb6 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi @@ -55,7 +55,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 8b77bd5a3c017..1583cd5915214 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -332,6 +332,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>; @@ -348,6 +349,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>; @@ -364,6 +366,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 b0f81802d334b..bb1de8217b86d 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -140,6 +140,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 4c85dfc811c80..cf9e3234afaf8 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -476,7 +476,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: 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 77b0e5d0fb134..1514c9846c5d5 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -566,6 +566,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; @@ -701,21 +711,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 1514c9846c5d5..a3c82f530d608 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -723,8 +723,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: 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 233a72f169bb7..e1de0fe281644 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 56906d15fb551..223029fa84459 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;
/* @@ -351,8 +356,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: 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 9e19d5a3aac87..83b324419ad3d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1317,8 +1317,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 db526dbf71eed..94219d2a2773d 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 86b9caf461dfa..6e320efd9fc1d 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 81afe553aa666..a91f2aa24118a 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 578b9f734231e..65592bf84f380 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: 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 705adfa8c680f..e0fa1391948c1 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>; @@ -291,9 +297,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 e0fa1391948c1..a94758090fb0d 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 { @@ -307,9 +311,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 aa52927e2e9c2..fad70c2df7bc0 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts @@ -202,7 +202,7 @@ };
partition@20000 { - label = "u-boot"; + label = "a53-firmware"; reg = <0x20000 0x160000>; };
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 b92bd97b1c399..b467fd05c5e82 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2568,7 +2568,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; @@ -2586,13 +2586,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)) { @@ -2601,11 +2606,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: 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 d95273af9f1e4..449843f2184d8 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -53,7 +53,7 @@ no-map; };
- reserved@8668000 { + reserved@86680000 { reg = <0x0 0x86680000 0x0 0x80000>; no-map; }; @@ -66,7 +66,7 @@ qcom,client-id = <1>; };
- rfsa@867e00000 { + rfsa@867e0000 { reg = <0x0 0x867e0000 0x0 0x20000>; no-map; };
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 --- drivers/spi/spi-s3c24xx-fiq.S | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/spi/spi-s3c24xx-fiq.S b/drivers/spi/spi-s3c24xx-fiq.S index e95d6282109e7..68ea12bead227 100644 --- a/drivers/spi/spi-s3c24xx-fiq.S +++ b/drivers/spi/spi-s3c24xx-fiq.S @@ -33,7 +33,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: @@ -47,7 +46,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 @@ -59,7 +58,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: @@ -74,7 +72,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 ] @@ -86,7 +84,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: @@ -99,7 +96,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: 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 f3d8d53ab84de..dbe5325a324d5 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: 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: 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 26ea51a721564..859a865c59950 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: 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 0f35eec967ae8..5b5d488c2f374 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1254,10 +1254,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 7c8187d386756..4ae49d92c1eed 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -8347,9 +8347,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: 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 e889488b84a03..8090895873011 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: 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 aa5150929996d..b5b728a71ab53 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: 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 2fa10fdcf6b1d..524f3364f8a05 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4880,6 +4880,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; @@ -4887,22 +4888,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: 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 37b51456784f8..b914959cd2c67 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1409,8 +1409,13 @@ static inline int tcp_full_space(const struct sock *sk) */ 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 bb6e52f3bdf9b..f98318d93ce72 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1689,6 +1689,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); @@ -1836,20 +1848,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/crypto/chelsio/chtls/chtls_cm.h | 3 --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 ++++++++--- drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-- 4 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.h b/drivers/crypto/chelsio/chtls/chtls_cm.h index 3fac0c74a41fa..df4451b306495 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.h +++ b/drivers/crypto/chelsio/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/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index cee582e361341..6b71ec33bf14d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -44,6 +44,9 @@
#define MAX_ULD_QSETS 16
+/* 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 049f1bbe27ab3..57bf10b4d80c8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2158,17 +2158,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/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index fcdc4211e3c27..45a1bfa2f7351 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 d3c001fa8eb46..32ce1b42ce08b 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -5308,7 +5308,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: 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 5b5d488c2f374..901883a44a320 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1518,6 +1518,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;
@@ -2340,6 +2343,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 901883a44a320..309cdc5ebc1ff 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -202,8 +202,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: 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 128cd648ba99c..f024db6d90158 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1948,6 +1948,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) { @@ -1955,9 +1976,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); @@ -1979,6 +2002,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 3bd20f7651207..da8c2c4aca7ef 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1443,6 +1443,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 8a3a60bb26888..4d5506d928973 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 4d5506d928973..156a0bc8ab01d 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 f024db6d90158..387d3aeebf237 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2601,6 +2601,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 387d3aeebf237..d6f6afb67bcc6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -921,6 +921,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 94e3f8b869be4..7b0543056b101 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3027,7 +3027,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp, }
/* 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(); @@ -3764,6 +3766,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: 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 1e70e838530ee..a7e5f12687b70 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 7005f8f69c683..d414525eccf6d 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -313,6 +313,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: 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 6b8502bcf0fd3..02ffde5fd7226 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -965,11 +965,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; @@ -982,8 +986,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: 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/sunxi-ss/sun4i-ss-cipher.c | 12 ++++-------- drivers/crypto/sunxi-ss/sun4i-ss.h | 2 ++ 2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 7e5e092a23b3c..4145a046274e5 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -235,8 +235,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 @@ -258,12 +256,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; } @@ -297,13 +295,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 { @@ -315,7 +311,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/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h index 35a27a7145f84..9a2adc130d9aa 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss.h +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h @@ -138,6 +138,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 --- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 109 +++++++++++++--------- 1 file changed, 65 insertions(+), 44 deletions(-)
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 4145a046274e5..f17551d4fa7e4 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-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; @@ -164,6 +177,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*/ @@ -217,17 +232,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; @@ -235,6 +239,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 @@ -267,31 +281,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 { @@ -316,12 +337,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++) { @@ -331,8 +354,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 aa57dc639f77f..aa13344a3a5e8 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)"); @@ -668,7 +668,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: 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 91899d28fa722..e8132210c244c 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 504fd61592405..3375bbe63284e 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1560,7 +1560,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 115b417dfb8e3..9fcc118312cb9 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: 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 041fcbb4eebdf..79e608dba4b6d 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2081,7 +2081,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 2c3c2adca6832..e16408af92d9c 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 2b635ebf62d6a..a15d970adb983 100644 --- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -866,11 +866,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: 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 1d50dfbbb762e..4c2675b437181 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -901,6 +901,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 cb65d345fd3e9..e2666d1c68964 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 4eaaf39b9223c..e0299a7899231 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -1529,12 +1529,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 ac569ab3d30f4..51d7a87ab4c3b 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1248,6 +1248,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; @@ -1305,7 +1306,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: 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 ee6bd945f3d6a..25dac691491b1 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -75,7 +75,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) { @@ -120,13 +120,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: 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 ec4b5033013eb..98b8483577ce2 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -41,7 +41,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 766452b24d0ab..01feed268a0d4 100644 --- a/drivers/crypto/bcm/cipher.h +++ b/drivers/crypto/bcm/cipher.h @@ -418,7 +418,7 @@ struct spu_hw { u32 num_chan; };
-struct device_private { +struct bcm_device_private { struct platform_device *pdev;
struct spu_hw spu; @@ -465,6 +465,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 cd7504101acde..7227dbf8f46c7 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: 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 6bf1425e8b0ca..eb3b2350687fb 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -545,30 +545,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 5bdbaf0847824..ce500c8dd4c72 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: 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 c23527ba65d09..64bffc1f75e0c 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 09770a4d97846..faf98f209b3f4 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -226,6 +226,5 @@ SECTIONS *(.options) *(.pdr) *(.reginfo) - *(.eh_frame) } }
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 833c44b3d458e..0d012efef5274 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: 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 ab63d0d0304cb..6fd57cfb112f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -429,12 +429,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 5815983caaf80..0d2e13627c647 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 f787a6b947812..eca67d5d5b10d 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 6ed922a3c1cd5..c25840a774f94 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 @@ -563,6 +563,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 77cc138d138cd..7d5236eafe845 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -534,14 +534,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 62d3566bf7eeb..5ac1a6af87826 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: 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 83ca5dc047ea2..baa9950783b66 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 41be22ce66f3e..44839a6461e88 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 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 8d47ea0c33f84..6e04e3ec61bac 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -1447,6 +1447,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 5e6f3153b5ff8..7d60dd3b0bd85 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: 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 3dd7c10d6a582..611adca1e6d0c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3814,7 +3814,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: 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 b7c66fc0ae0c2..8ef6e93e43f3c 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1097,11 +1097,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); @@ -1125,7 +1126,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; @@ -1148,10 +1149,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); @@ -1159,22 +1161,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; @@ -1186,7 +1188,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); }
/* @@ -1255,7 +1257,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; @@ -1275,7 +1277,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) { @@ -1583,6 +1585,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 */
@@ -1603,8 +1607,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: 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 282fd90b65e13..9ce7b0d4b8764 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -497,6 +497,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: 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 66a570d0da837..067b55cc157ef 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -361,6 +361,10 @@ static int 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); @@ -390,6 +394,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; } @@ -463,6 +469,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. */ @@ -472,7 +482,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() */ @@ -497,6 +507,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 d7f05b384f1fb..1902689c5ea2c 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1263,12 +1263,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: 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 752b6cf005f71..8fd61767af831 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: 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 5d94abe467a4f..6273a8768081e 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -686,6 +686,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 183388393c6a8..cbd17e4ff920c 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -189,6 +189,10 @@ int f2fs_convert_inline_inode(struct inode *inode) if (!f2fs_has_inline_data(inode)) 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/amdgpu/amdgpu_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 3f744e72912f1..bcb7ab5c602d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -870,7 +870,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]; @@ -886,8 +886,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 68be334afc286..64ee2a064e339 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -318,7 +318,7 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi, if (test_opt(sbi, LFS) && 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: 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 452307c79e4b9..0b55bc146b292 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -1101,8 +1101,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: 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 5529e8eeca462..08726034ff090 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -135,7 +135,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 6e6be922b937d..23f59d463e24e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -744,8 +744,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) { @@ -754,6 +756,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; } @@ -774,6 +777,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: 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: 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 9e94eca48b898..37b1244e3a166 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -120,6 +120,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 1776eb2e43a44..a1cffce3de8cd 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -293,6 +293,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 79f252af7dee3..4e74db89bd23f 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -165,6 +165,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 37b1244e3a166..955e4b4d09e21 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -130,6 +130,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 9b794775df537..edad6721251f4 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 caade185e568d..6fe82ce8663ef 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 b10418b5fb719..8be17a7731961 100644 --- a/fs/ubifs/auth.c +++ b/fs/ubifs/auth.c @@ -342,7 +342,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: 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 e49bd69dfc1c8..701f15ba61352 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -820,8 +820,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: 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 28a6939bcc4e5..ed89a6dd4f83d 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -500,7 +500,8 @@ int cap_convert_nscap(struct dentry *dentry, 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, 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 2be9c01e175ca..f36036be7f032 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: 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 3a5853ca98c6c..fb0bc8c0ad4d4 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -369,7 +369,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 fb0bc8c0ad4d4..a92f44fa5a24e 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -363,8 +363,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 a92f44fa5a24e..e8df254f8085b 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -392,7 +392,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); /* @@ -404,7 +405,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 cf001a2c69420..7c2cb04569dab 100755 --- a/tools/testing/selftests/powerpc/eeh/eeh-basic.sh +++ b/tools/testing/selftests/powerpc/eeh/eeh-basic.sh @@ -81,5 +81,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: 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 36dce17b01016..56aedf4ba8864 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -166,19 +166,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 dd9661c11782a..2983cd9f855b4 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -503,12 +503,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 2983cd9f855b4..38a28bf6cfee4 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -213,7 +213,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 38a28bf6cfee4..70cd9fc7fb869 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -157,6 +157,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, @@ -203,8 +208,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 */ @@ -258,6 +273,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); @@ -294,8 +310,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); }
@@ -320,76 +339,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; }
@@ -1031,6 +1150,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; } @@ -1051,6 +1174,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/mtd/spi-nor/cadence-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 7bef63947b29f..97a5e1eaeefdf 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -475,7 +475,7 @@ static int cqspi_read_setup(struct spi_nor *nor) /* Setup dummy clock cycles */ dummy_clk = nor->read_dummy; if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) - dummy_clk = CQSPI_DUMMY_CLKS_MAX; + return -EOPNOTSUPP;
if (dummy_clk / 8) { reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
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 d89353a3cdec7..183dd350cce95 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -673,7 +673,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: 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 263eca119ff0f..8d202011b2db5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1300,6 +1300,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 dba4535494abd..4d8bc995b4503 100644 --- a/drivers/infiniband/sw/siw/siw.h +++ b/drivers/infiniband/sw/siw/siw.h @@ -667,7 +667,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 b4317480cee74..5927ac5923dd8 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 0520e70084f97..c7c38f7fd29d6 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 e7cd04eda04ac..424918eb1cd4a 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 1b1a40db529c6..2c3704f0f10fa 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.c +++ b/drivers/infiniband/sw/siw/siw_verbs.c @@ -387,13 +387,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 (qp->kernel_verbs) qp->sendq = vzalloc(num_sqe * sizeof(struct siw_sqe)); @@ -401,7 +411,6 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, qp->sendq = vmalloc_user(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; } @@ -434,7 +443,6 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, vmalloc_user(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; } @@ -982,9 +990,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 (!qp->kernel_verbs) { siw_dbg_qp(qp, "no kernel post_recv for user mapped sq\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 ad72b3f42ffa0..996f1d7623d69 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 996f1d7623d69..eae385a312b88 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 af20e9a790a2a..bb9c361e224bc 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -1201,6 +1201,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: 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: 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 223d617ecfe17..036af904e0cfa 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1154,7 +1154,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 036af904e0cfa..fc24102e25ce7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1153,8 +1153,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: 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 e341cc5c0ea6f..c84df27cd5482 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 c5b9804140860..9ae7ce3f50696 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -683,6 +683,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: 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 f35a53ce8988a..3bb5625504e2f 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 f6ddae30933f7..dae8c0c2e606f 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -138,10 +138,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: 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 fd75a9043bf15..4d6f25fdcc0ef 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -1118,7 +1118,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: 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 183dd350cce95..2f00f1b7b9c00 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -228,7 +228,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); @@ -237,19 +237,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: 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 aefc351bfed59..86a3c2dd05848 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -1072,7 +1072,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); @@ -1087,13 +1087,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: 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 ec00bf337eb67..025a41de28fda 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -153,7 +153,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 6cf8e71cf8b7c..9c26cc9b802a0 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -269,6 +269,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 e9845d0d8d349..623fcb4094dd4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -302,6 +302,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 6ca27e9d5ef7d..ee0ed538e244f 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -574,10 +574,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, 0, 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 abbc1582f457e..d9711ea5b01d3 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1569,7 +1569,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 ee0ed538e244f..5276f8442f3c6 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: 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 5b9d570df85cc..a31b6ae92a84e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1576,7 +1576,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]; @@ -1622,8 +1622,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 cac468f04820e..558e7c51ce0d4 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: 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 a2fcde582e2a1..33b887b389061 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: 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 1b7e748170e54..1cff21aef0730 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2192,15 +2192,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 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 1cff21aef0730..06aaf04e629c2 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -626,8 +626,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: 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 da229eab59032..dec5175803fe2 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 dec5175803fe2..ad3a092b8b5c3 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 3a77bb6434521..e03c064716789 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -1513,7 +1513,7 @@ int kvmppc_handle_vmx_load(struct kvm_run *run, 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; @@ -1531,7 +1531,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; @@ -1549,7 +1549,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; @@ -1567,7 +1567,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 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 cb285e474c880..c4cbb65e742f4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -723,7 +723,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 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 c077acb983a19..bf3432b10d0af 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1304,6 +1304,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)) return -1;
@@ -1331,7 +1336,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: 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 d07b9793380f0..10705e5fa90ee 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -665,14 +665,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 b11ac2314328d..6eba2441c7efd 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1860,10 +1860,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 cb89f0578d425..f54d0427e9c00 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 93dffed0ac6e0..cbe126297f549 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -1142,9 +1142,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 r12, lr
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 17abf60c94aeb..b56a427fb928f 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -87,6 +87,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 { @@ -350,14 +353,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 = NULL; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur;
if (!of_machine_is_compatible("lenovo,yoga-c630")) dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); @@ -374,19 +402,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; } @@ -394,11 +421,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 = NULL; struct geni_se *se = &gi2c->se; size_t len = msg->len; + struct i2c_msg *cur;
if (!of_machine_is_compatible("lenovo,yoga-c630")) dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); @@ -415,22 +443,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 b56a427fb928f..2262bf295286c 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -377,6 +377,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) { @@ -641,6 +667,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; @@ -701,6 +734,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: 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 fe1523664816a..af58768a03937 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: 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 c9e583c05ef27..e2656b68ec222 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -6213,8 +6213,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_stage_flow_db_init(struct mlx5_ib_dev *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 fd7c84721b0de..c933c1c7ddd8e 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -4336,7 +4336,7 @@ static void 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); @@ -4348,7 +4348,7 @@ static void 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;
@@ -4427,7 +4427,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;
if (!cm_dev) return; @@ -4440,7 +4440,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 73956eaff8a9c..be51df4508cbe 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -53,6 +53,12 @@ struct tp_probes { struct tracepoint_func probes[0]; };
+/* 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; @@ -271,10 +317,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: 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 fc1e5a991008d..bfaa9afdb8b4c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -597,6 +597,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 df9201434cb6a..b0a10a219b50d 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 9bfb98056fc2a..2dc808988d949 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -36,21 +36,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; } @@ -58,7 +63,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 2dc808988d949..369ba76f1605e 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -305,7 +305,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); @@ -317,12 +316,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; @@ -337,9 +342,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 312c2fc961c00..d411356828911 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -453,6 +453,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 77ddf23b65d65..8622cf9d3f640 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -1668,6 +1668,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: 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 f6428b90a6c77..6f3e417f55a35 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -191,7 +191,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)
/* Called from DataStoreTLBMiss when perf TLB misses events are activated */ #ifdef CONFIG_PERF_EVENTS
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 091acd59c1d64..752f267b2881a 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: 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 b5d196c119eec..f23a341400c06 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -848,8 +848,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: 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 fb66d67572787..dbbf8c6c16d38 100644 --- a/drivers/infiniband/sw/siw/siw_main.c +++ b/drivers/infiniband/sw/siw/siw_main.c @@ -134,7 +134,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 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 e36d315690819..3e68ba9dab45d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -657,7 +657,7 @@ struct hns_roce_qp { u8 rdb_en; u8 sdb_en; u32 doorbell_qpn; - u32 sq_signal_bits; + enum ib_sig_type sq_signal_bits; struct hns_roce_wq sq;
struct ib_umem *umem;
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: 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 a47f87b8373df..68d22acdb037a 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -874,7 +874,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 7015974f24b43..84ca38450d021 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -17,7 +17,8 @@
#define ASPEED_G6_NUM_CLKS 67
-#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 @@ -189,18 +190,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: 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 be418fccc9d86..7f39d6091dfa0 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1523,12 +1523,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; @@ -1546,9 +1543,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: @@ -1562,13 +1564,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); @@ -1579,7 +1580,6 @@ static void __exit exit_nfsd(void) nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); unregister_cld_notifier(); - unregister_pernet_subsys(&nfsd_net_ops); }
MODULE_AUTHOR("Olaf Kirch okir@monad.swb.de");
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 e8933daab4995..d01e3222c00cf 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -1009,7 +1009,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); @@ -1054,15 +1054,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: 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 2e2ea5719c90e..902522df03592 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -774,6 +774,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: 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 7ffcbd6fcd1ae..a3fdea49ad663 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1745,6 +1745,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 a3fdea49ad663..7f53b63088b2c 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -2637,9 +2637,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 e289e463d635e..7396da0fa3a7c 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 8aeaeba48a41f..d0e0ce11faf58 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1304,7 +1304,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; @@ -1366,7 +1367,8 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) sample.stream_id = ptq->pt->instructions_id; 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; @@ -1901,14 +1903,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: 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 3a02426db9a63..2f76d4a9de860 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -180,7 +180,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) .data = {1, 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}; struct perf_sample sample = { .ip = 101,
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 d6772a2c2d096..e396857cb4c1b 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 18e9fb6fcf1bf..349e27771ceaf 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -524,7 +524,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: 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 94cfb675fe4ed..6adf979299667 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -510,4 +510,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 2dc19ddd120f5..a005fc58bbf02 100644 --- a/drivers/phy/rockchip/phy-rockchip-emmc.c +++ b/drivers/phy/rockchip/phy-rockchip-emmc.c @@ -240,15 +240,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: 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 6adf979299667..414dcbd3c3c25 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -510,4 +510,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: 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 e3d06330d1258..f7d0f63921dc2 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -368,10 +368,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 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 73352e6fbccbf..6ad6aad215cf1 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -361,7 +361,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: 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 a44094cdbc36c..d20b2b99c6f24 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -1300,7 +1300,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: 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 03c6d6157e4d0..395146884a222 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -1099,7 +1099,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: 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 bc6ba41686fa3..9cbe058a530f0 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -866,6 +866,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); @@ -1974,23 +1975,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 @@ -2088,10 +2072,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; @@ -2124,10 +2108,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); @@ -2201,7 +2187,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: 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 f05ec9bfbf4fd..7f22487d502b5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2405,11 +2405,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: 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 84f4078216a36..acd82ff41951f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -345,6 +345,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 acd82ff41951f..3ba68baeed1db 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -314,7 +314,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: 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 50a66382d87d0..e75168b941d0c 100644 --- a/drivers/base/regmap/regmap-sdw.c +++ b/drivers/base/regmap/regmap-sdw.c @@ -12,7 +12,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) @@ -21,7 +21,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: 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 f47841f3a69d5..218aada8949d9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3093,13 +3093,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 c19b45a90fcd2..e41f7acc0e1fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7612,6 +7612,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);
@@ -7679,6 +7681,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);
@@ -11770,6 +11774,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 e41f7acc0e1fa..c63de06c98df2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9959,7 +9959,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; @@ -10085,13 +10084,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. @@ -14774,7 +14766,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) @@ -15096,24 +15087,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 b577e6adf3bff..82c62e4678705 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -4874,7 +4874,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;
@@ -4919,9 +4919,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. @@ -5038,7 +5040,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, @@ -5067,8 +5069,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 c63de06c98df2..4f584a9dcf44e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8485,11 +8485,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 * @@ -8497,6 +8492,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 4f584a9dcf44e..96d818cb2b5b7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2603,7 +2603,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; } @@ -2621,7 +2621,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: 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 96d818cb2b5b7..0604b5aaad86f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7676,7 +7676,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;
@@ -7705,7 +7706,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: Alex Williamson alex.williamson@redhat.com
[ Upstream commit 07956b6269d3ed05d854233d5bb776dca91751dd ]
follow_pfn() doesn't make sure that we're using the correct page protections, get the pte with follow_pte() so that we can test protections and get the pfn from the pte.
Fixes: 5cbf3264bc71 ("vfio/type1: Fix VA->PA translation for PFNMAP VMAs in vaddr_get_pfn()") Reviewed-by: Jason Gunthorpe jgg@nvidia.com Reviewed-by: Cornelia Huck cohuck@redhat.com Reviewed-by: Peter Xu peterx@redhat.com Signed-off-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/vfio/vfio_iommu_type1.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 9cbe058a530f0..6b1e8cba17984 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -24,6 +24,7 @@ #include <linux/compat.h> #include <linux/device.h> #include <linux/fs.h> +#include <linux/highmem.h> #include <linux/iommu.h> #include <linux/module.h> #include <linux/mm.h> @@ -339,9 +340,11 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, unsigned long vaddr, unsigned long *pfn, bool write_fault) { + pte_t *ptep; + spinlock_t *ptl; int ret;
- ret = follow_pfn(vma, vaddr, pfn); + ret = follow_pte(vma->vm_mm, vaddr, &ptep, &ptl); if (ret) { bool unlocked = false;
@@ -355,9 +358,17 @@ static int follow_fault_pfn(struct vm_area_struct *vma, struct mm_struct *mm, if (ret) return ret;
- ret = follow_pfn(vma, vaddr, pfn); + ret = follow_pte(vma->vm_mm, vaddr, &ptep, &ptl); + if (ret) + return ret; }
+ if (write_fault && !pte_write(*ptep)) + ret = -EFAULT; + else + *pfn = pte_pfn(*ptep); + + pte_unmap_unlock(ptep, ptl); return ret; }
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 1187ef1375e29..cb341372d5a35 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: 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 5502e145aa17b..8443df79fabc7 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -4424,7 +4424,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) @@ -4438,14 +4437,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) @@ -4453,6 +4451,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: 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 a368350d4c279..c843bc318382b 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -2052,7 +2052,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), @@ -2067,6 +2067,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: 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 b23831132933a..9710e94ff4f21 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1804,11 +1804,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(); @@ -1822,7 +1822,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 d5b03b9262d4f..2e2527c9f9a21 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2812,8 +2812,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: 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 88c3f6bad1aba..d686887856fee 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -1630,6 +1630,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) @@ -1672,7 +1673,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; @@ -1687,7 +1688,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) { /* @@ -1696,12 +1701,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); @@ -1709,15 +1710,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); } @@ -1728,9 +1724,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: 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 1e8244ec5b332..131be1fa770cb 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4077,7 +4077,7 @@ 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); rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_512B); @@ -4085,7 +4085,7 @@ static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
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); rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
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 bdb5ec3419006..438de2301cfe3 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -970,6 +970,7 @@ __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 506991596b68d..5e89cd6b690ce 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: 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 988d176472df7..d7d6d4eb17949 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -214,7 +214,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: 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 e0ccb48ec9617..40e9c9dc04bd8 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: 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 @@ -473,6 +473,14 @@ void blk_queue_stack_limits(struct reque } EXPORT_SYMBOL(blk_queue_stack_limits);
+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) @@ -586,6 +594,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: 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 @@ -794,9 +794,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) @@ -806,28 +803,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 { @@ -841,7 +853,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); @@ -935,10 +947,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 @@ -267,7 +267,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: 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 @@ -410,6 +410,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) { @@ -418,7 +419,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 @@ -2102,32 +2102,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 @@ -593,7 +593,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 @@ -603,8 +603,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: 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 @@ -1330,8 +1330,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 @@ -1250,8 +1250,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: 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 @@ -2447,6 +2447,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: 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 @@ -1895,6 +1895,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, @@ -2228,6 +2229,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[]) { @@ -2500,6 +2510,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: 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 @@ -1027,5 +1027,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)
/* @@ -366,7 +368,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); } @@ -539,7 +541,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);
@@ -2659,3 +2661,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 @@ -2652,6 +2652,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"); @@ -2707,6 +2708,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 @@ -2670,7 +2670,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 @@ -986,6 +986,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 @@ -958,8 +958,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 @@ -48,6 +48,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;
@@ -2652,6 +2653,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) @@ -2715,6 +2718,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: 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: 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 @@ -276,6 +276,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: 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 @@ -1240,6 +1240,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: 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 @@ -851,6 +851,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: 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 fill_inode_lazy(struct inode 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 fill_inode_lazy(struct inode
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 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.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -805,7 +805,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: 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 @@ -260,9 +260,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 @@ -1336,9 +1336,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); }
spin_lock(&fs_info->trans_lock);
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 @@ -2391,8 +2391,10 @@ again:
if (!path) { path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out; + } }
/* @@ -2487,16 +2489,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); @@ -2520,7 +2520,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: 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 @@ -261,6 +261,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: 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 @@ -707,7 +707,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; @@ -760,8 +761,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); @@ -771,10 +771,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; @@ -792,10 +792,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; @@ -804,7 +804,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) @@ -853,7 +853,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);
@@ -880,7 +881,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)) @@ -1010,7 +1012,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); @@ -1026,7 +1029,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: 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/sunxi-ss/sun4i-ss-cipher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -203,12 +203,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/sunxi-ss/sun4i-ss-cipher.c | 34 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-)
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-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); } }
@@ -176,6 +187,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; @@ -219,6 +231,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) @@ -347,9 +366,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/sunxi-ss/sun4i-ss-cipher.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-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); @@ -240,13 +240,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/sunxi-ss/sun4i-ss-cipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -196,7 +196,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: 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 @@ -921,6 +921,8 @@ static int __seccomp_filter(int this_sys const bool recheck_after_trace) { BUG(); + + return -1; } #endif
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 @@ -338,6 +338,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 @@ -275,7 +275,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); @@ -664,7 +664,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: 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 | 762 ++++++++++++++++++++++++++++++ drivers/staging/mt7621-dma/mtk-hsdma.c | 762 ------------------------------ 3 files changed, 763 insertions(+), 763 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,762 @@ +// 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(unsigned long arg) +{ + struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg; + + 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; + struct resource *res; + 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; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + hsdma->base = base + HSDMA_BASE_OFFSET; + tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); + + 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,762 +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(unsigned long arg) -{ - struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg; - - 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; - struct resource *res; - 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; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - hsdma->base = base + HSDMA_BASE_OFFSET; - tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); - - 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");
Sorry, I should have been more clear in my original email, but we don't strictly need this in 5.4 as the check only became fatal in 5.10 (actually, before 5.10, but 5.10 is the first stable release with it). Feel free to take or omit this from 5.4.
On Mon, Mar 1, 2021 at 9:00 AM Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
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 | 762 ++++++++++++++++++++++++++++++ drivers/staging/mt7621-dma/mtk-hsdma.c | 762 ------------------------------ 3 files changed, 763 insertions(+), 763 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,762 @@ +// 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(unsigned long arg) +{
struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg;
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;
struct resource *res;
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;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
hsdma->base = base + HSDMA_BASE_OFFSET;
tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma);
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,762 +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(unsigned long arg) -{
struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg;
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;
struct resource *res;
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;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
hsdma->base = base + HSDMA_BASE_OFFSET;
tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma);
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: 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 @@ -1288,7 +1288,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: 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 | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-)
--- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -538,29 +538,20 @@ 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 ignore 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: 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 @@ -1305,14 +1305,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 @@ -579,7 +579,6 @@ static void rcu_eqs_enter(bool user) 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); WRITE_ONCE(rdp->dynticks_nesting, 0); /* Avoid irq-access tearing. */ @@ -600,7 +599,10 @@ static void rcu_eqs_enter(bool user) */ 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); }
@@ -618,7 +620,14 @@ void rcu_idle_enter(void) */ 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 @@ -96,8 +96,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 @@ -599,10 +599,7 @@ static void rcu_eqs_enter(bool user) */ 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); }
--- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -2190,6 +2190,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 @@ -249,6 +249,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 @@ -604,6 +604,18 @@ void rcu_idle_enter(void) }
#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. * @@ -621,12 +633,19 @@ 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 @@ -438,7 +438,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 @@ -1639,8 +1639,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; @@ -1651,7 +1651,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); @@ -1664,6 +1664,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; }
/* @@ -2155,20 +2157,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. */ @@ -2184,10 +2189,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) @@ -2527,8 +2533,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: 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 | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
--- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4063,21 +4063,22 @@ static int floppy_open(struct block_devi if (UFDCS->rawcmd == 1) UFDCS->rawcmd = 2;
- if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - UDRS->last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - check_disk_change(bdev); - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + if (mode & (FMODE_READ|FMODE_WRITE)) { + UDRS->last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) goto out; } + + res = -EROFS; + + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + goto out; + mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); return 0;
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 @@ -150,8 +150,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: 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, @@ -58,16 +57,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; @@ -86,7 +75,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: 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/spi-nor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -3770,6 +3770,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, @@ -3793,8 +3794,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/spi-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -3700,7 +3700,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/spi-nor.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1011,14 +1011,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/spi-nor.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1153,6 +1153,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/hisi-sfc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/mtd/spi-nor/hisi-sfc.c +++ b/drivers/mtd/spi-nor/hisi-sfc.c @@ -396,8 +396,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.txt | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/Documentation/filesystems/seq_file.txt +++ b/Documentation/filesystems/seq_file.txt @@ -192,6 +192,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.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -1132,12 +1132,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) @@ -1146,7 +1148,6 @@ static int memtype_seq_show(struct seq_f
seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type), print_entry->start, print_entry->end); - kfree(print_entry);
return 0; }
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 @@ -1192,14 +1192,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 @@ -4718,17 +4718,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: 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 @@ -489,7 +489,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 @@ -1092,7 +1092,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), #endif {}, };
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,39 +60,45 @@ 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 = US_TO_NS(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); }
@@ -151,7 +157,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_NS(100); + rc_dev->timeout = US_TO_NS(SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN); rc_dev->rx_resolution = US_TO_NS(SMI_SAMPLE_PERIOD);
ir->rc_dev = rc_dev; @@ -174,7 +180,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: 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 @@ -2310,6 +2310,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) { @@ -2355,8 +2370,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 @@ -1589,9 +1589,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: 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 @@ -336,6 +336,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: 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);
status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio); if (status < 0)
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 @@ -43,6 +43,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 @@ -178,8 +180,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; @@ -193,7 +193,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: @@ -230,7 +230,7 @@ more:
out: report_message_lost(s); - raw_spin_unlock_irqrestore(&read_lock, flags); + raw_spin_unlock_irqrestore(&safe_read_lock, flags); }
/** @@ -276,6 +276,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: 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 @@ -1566,11 +1566,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; @@ -1578,9 +1576,12 @@ static void intel_pstate_get_cpu_pstates intel_pstate_get_hwp_max(cpu->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: 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 @@ -126,6 +126,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 @@ -163,7 +166,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) { @@ -193,6 +196,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) && @@ -433,6 +439,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: 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 @@ -765,7 +765,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: 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: 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 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 @@ -280,7 +280,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) { @@ -293,13 +292,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 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 @@ -1228,6 +1228,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; @@ -1240,9 +1243,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 @@ -106,6 +106,10 @@ struct mapped_device {
struct block_device *bdev;
+ 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 @@ -2737,6 +2737,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 @@ -146,6 +146,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. */ @@ -972,6 +982,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; @@ -1009,6 +1024,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); } @@ -1263,6 +1283,22 @@ void dm_remap_zone_report(struct dm_targ } EXPORT_SYMBOL_GPL(dm_remap_zone_report);
+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; @@ -1283,6 +1319,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: @@ -1297,10 +1341,18 @@ static blk_qc_t __map_bio(struct dm_targ ret = generic_make_request(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; @@ -1894,6 +1946,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); } @@ -1963,6 +2016,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; @@ -3245,6 +3302,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 @@ -316,6 +316,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; };
/* Each target can link one of these into the table */
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 @@ -142,6 +142,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; @@ -918,6 +919,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 { @@ -1488,6 +1491,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; } @@ -1559,6 +1566,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); } @@ -1602,6 +1612,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) { @@ -1580,7 +1581,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 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"; @@ -1586,9 +1577,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 @@ -2129,7 +2129,11 @@ hdmi_port_clock_valid(struct intel_hdmi if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits, force_dvi)) 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: Jason A. Donenfeld Jason@zx2c4.com
commit 0b41713b606694257b90d61ba7e2712d8457648b upstream.
This introduces a helper function to be called only by network drivers that wraps calls to icmp[v6]_send in a conntrack transformation, in case NAT has been used. We don't want to pollute the non-driver path, though, so we introduce this as a helper to be called by places that actually make use of this, as suggested by Florian.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: Florian Westphal fw@strlen.de Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/icmpv6.h | 6 ++++++ include/net/icmp.h | 6 ++++++ net/ipv4/icmp.c | 33 +++++++++++++++++++++++++++++++++ net/ipv6/ip6_icmp.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+)
--- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -31,6 +31,12 @@ static inline void icmpv6_send(struct sk } #endif
+#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 +#endif + extern int icmpv6_init(void); extern int icmpv6_err_convert(u8 type, u8 code, int *err); --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -43,6 +43,12 @@ static inline void icmp_send(struct sk_b __icmp_send(skb_in, type, code, info, &IPCB(skb_in)->opt); }
+#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 +#endif + int icmp_rcv(struct sk_buff *skb); int icmp_err(struct sk_buff *skb, u32 info); int icmp_init(void); --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -750,6 +750,39 @@ out:; } EXPORT_SYMBOL(__icmp_send);
+#if IS_ENABLED(CONFIG_NF_NAT) +#include <net/netfilter/nf_conntrack.h> +void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info) +{ + struct sk_buff *cloned_skb = NULL; + 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); + return; + } + + if (skb_shared(skb_in)) + skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC); + + if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head || + (skb_network_header(skb_in) + sizeof(struct iphdr)) > + skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in, + skb_network_offset(skb_in) + sizeof(struct iphdr)))) + goto out; + + 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); + ip_hdr(skb_in)->saddr = orig_ip; +out: + consume_skb(cloned_skb); +} +EXPORT_SYMBOL(icmp_ndo_send); +#endif
static void icmp_socket_deliver(struct sk_buff *skb, u32 info) { --- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -45,4 +45,38 @@ out: rcu_read_unlock(); } EXPORT_SYMBOL(icmpv6_send); + +#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 sk_buff *cloned_skb = NULL; + enum ip_conntrack_info ctinfo; + struct in6_addr orig_ip; + struct nf_conn *ct; + + ct = nf_ct_get(skb_in, &ctinfo); + if (!ct || !(ct->status & IPS_SRC_NAT)) { + icmpv6_send(skb_in, type, code, info); + return; + } + + if (skb_shared(skb_in)) + skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC); + + if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head || + (skb_network_header(skb_in) + sizeof(struct ipv6hdr)) > + skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in, + skb_network_offset(skb_in) + sizeof(struct ipv6hdr)))) + goto out; + + 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); + ipv6_hdr(skb_in)->saddr = orig_ip; +out: + consume_skb(cloned_skb); +} +EXPORT_SYMBOL(icmpv6_ndo_send); +#endif #endif
From: Jason A. Donenfeld Jason@zx2c4.com
commit e0fce6f945a26d4e953a147fe7ca11410322c9fe upstream.
Because gtp is calling icmp from network device context, it should use the ndo helper so that the rate limiting applies correctly.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: Harald Welte laforge@gnumonks.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/gtp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -546,8 +546,8 @@ static int gtp_build_skb_ip4(struct sk_b mtu < ntohs(iph->tot_len)) { netdev_dbg(dev, "packet too big, fragmentation needed\n"); memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); goto err_rt; }
From: Jason A. Donenfeld Jason@zx2c4.com
commit 67c9a7e1e3ac491b5df018803639addc36f154ba upstream.
Because sunvnet is calling icmp from network device context, it should use the ndo helper so that the rate limiting applies correctly. While we're at it, doing the additional route lookup before calling icmp_ndo_send is superfluous, since this is the job of the icmp code in the first place.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: Shannon Nelson shannon.nelson@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/ethernet/sun/sunvnet_common.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-)
--- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1353,27 +1353,12 @@ sunvnet_start_xmit_common(struct sk_buff if (vio_version_after_eq(&port->vio, 1, 3)) localmtu -= VLAN_HLEN;
- if (skb->protocol == htons(ETH_P_IP)) { - struct flowi4 fl4; - struct rtable *rt = NULL; - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = dev->ifindex; - fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); - fl4.daddr = ip_hdr(skb)->daddr; - fl4.saddr = ip_hdr(skb)->saddr; - - rt = ip_route_output_key(dev_net(dev), &fl4); - if (!IS_ERR(rt)) { - skb_dst_set(skb, &rt->dst); - icmp_send(skb, ICMP_DEST_UNREACH, - ICMP_FRAG_NEEDED, - htonl(localmtu)); - } - } + if (skb->protocol == htons(ETH_P_IP)) + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(localmtu)); #if IS_ENABLED(CONFIG_IPV6) else if (skb->protocol == htons(ETH_P_IPV6)) - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); #endif goto out_dropped; }
From: Jason A. Donenfeld Jason@zx2c4.com
commit 45942ba890e6f35232727a5fa33d732681f4eb9f upstream.
Because xfrmi is calling icmp from network device context, it should use the ndo helper so that the rate limiting applies correctly.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: Nicolas Dichtel nicolas.dichtel@6wind.com Cc: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/xfrm/xfrm_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/net/xfrm/xfrm_interface.c +++ b/net/xfrm/xfrm_interface.c @@ -300,10 +300,10 @@ xfrmi_xmit2(struct sk_buff *skb, struct if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); } else { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); }
dst_release(dst);
From: Eric Dumazet edumazet@google.com
commit cc7a21b6fbd945f8d8f61422ccd27203c1fafeb7 upstream.
If IPv6 is builtin, we do not need an expensive indirect call to reach icmp6_send().
v2: put inline keyword before the type to avoid sparse warnings.
Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- include/linux/icmpv6.h | 22 +++++++++++++++++++++- net/ipv6/icmp.c | 5 +++-- net/ipv6/ip6_icmp.c | 10 +++++----- 3 files changed, 29 insertions(+), 8 deletions(-)
--- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -13,12 +13,32 @@ static inline struct icmp6hdr *icmp6_hdr #include <linux/netdevice.h>
#if IS_ENABLED(CONFIG_IPV6) -extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info);
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); +static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +{ + icmp6_send(skb, type, code, info, NULL); +} +static inline int inet6_register_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +static inline int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +#else +extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); +#endif + int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, unsigned int data_len);
--- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -426,8 +426,8 @@ static int icmp6_iif(const struct sk_buf /* * Send an ICMP message in response to a packet in error */ -static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr) +void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr) { struct inet6_dev *idev = NULL; struct ipv6hdr *hdr = ipv6_hdr(skb); @@ -600,6 +600,7 @@ out: out_bh_enable: local_bh_enable(); } +EXPORT_SYMBOL(icmp6_send);
/* Slightly more convenient version of icmp6_send. */ --- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -9,6 +9,8 @@
#if IS_ENABLED(CONFIG_IPV6)
+#if !IS_BUILTIN(CONFIG_IPV6) + static ip6_icmp_send_t __rcu *ip6_icmp_send;
int inet6_register_icmp_sender(ip6_icmp_send_t *fn) @@ -37,14 +39,12 @@ void icmpv6_send(struct sk_buff *skb, u8
rcu_read_lock(); send = rcu_dereference(ip6_icmp_send); - - if (!send) - goto out; - send(skb, type, code, info, NULL); -out: + if (send) + send(skb, type, code, info, NULL); rcu_read_unlock(); } EXPORT_SYMBOL(icmpv6_send); +#endif
#if IS_ENABLED(CONFIG_NF_NAT) #include <net/netfilter/nf_conntrack.h>
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 | 16 ++++++++-------- net/ipv6/ip6_icmp.c | 12 +++++++----- 7 files changed, 43 insertions(+), 24 deletions(-)
--- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -545,7 +545,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,11 +38,17 @@ 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);
@@ -54,7 +64,11 @@ static inline void icmpv6_send(struct sk #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
extern int icmpv6_init(void); --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -83,7 +83,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 @@ -755,13 +755,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; }
@@ -776,7 +777,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 @@ -312,10 +312,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; @@ -332,7 +331,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, @@ -427,7 +426,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); @@ -520,7 +520,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);
memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_proto = IPPROTO_ICMPV6; @@ -606,7 +606,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); }
@@ -663,10 +663,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: 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 @@ -156,6 +156,7 @@ int tcf_idr_search(struct tc_action_net int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tc_action **a, const struct tc_action_ops *ops, int bind, bool cpustats); +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 @@ -823,7 +823,7 @@ static const struct nla_policy tcf_actio [TCA_ACT_OPTIONS] = { .type = NLA_NESTED }, };
-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 @@ -3026,6 +3026,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: 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 @@ -135,7 +135,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 */ @@ -1241,8 +1241,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); @@ -1252,9 +1254,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) { /* @@ -1262,7 +1266,6 @@ static void process_deferred_bios(struct * FIXME: finish. */ failed = true; - } else if (r == 0) commit_needed = true;
@@ -1278,9 +1281,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); generic_make_request(bio); + } + blk_finish_plug(&plug); + } }
static void process_rpc_calls(struct era *era)
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)
Hi Greg,
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Our test CI monitored the 5.4.102-rc2, and compile failure:
kernel/rcu/tree.c:617:2: error: implicit declaration of function ‘IRQ_WORK_INIT’; did you mean ‘IRQ_WORK_BUSY’? [-Werror=implicit-function-declaration] IRQ_WORK_INIT(late_wakeup_func); ^~~~~~~~~~~~~ IRQ_WORK_BUSY kernel/rcu/tree.c:617:2: error: invalid initializer
Should be commit e1e41aa31ed1 (rcu/nocb: Trigger self-IPI on late deferred wake up before user resume) fails the build.
By the way, do you expect us test the 5.4.102-rc1 or the 5.4.102-rc2 in your tree?
Thanks Hanjun
On Tue, Mar 02, 2021 at 02:42:15PM +0800, Hanjun Guo wrote:
Hi Greg,
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Our test CI monitored the 5.4.102-rc2, and compile failure:
kernel/rcu/tree.c:617:2: error: implicit declaration of function ‘IRQ_WORK_INIT’; did you mean ‘IRQ_WORK_BUSY’? [-Werror=implicit-function-declaration] IRQ_WORK_INIT(late_wakeup_func); ^~~~~~~~~~~~~ IRQ_WORK_BUSY kernel/rcu/tree.c:617:2: error: invalid initializer
Should be commit e1e41aa31ed1 (rcu/nocb: Trigger self-IPI on late deferred wake up before user resume) fails the build.
Odd, what arch/configuration causes this?
By the way, do you expect us test the 5.4.102-rc1 or the 5.4.102-rc2 in your tree?
-rc2 would be great, given that it fixes a number of reported issues with -rc1.
thanks,
greg k-h
On Tue, Mar 02, 2021 at 02:42:15PM +0800, Hanjun Guo wrote:
Hi Greg,
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Our test CI monitored the 5.4.102-rc2, and compile failure:
kernel/rcu/tree.c:617:2: error: implicit declaration of function ‘IRQ_WORK_INIT’; did you mean ‘IRQ_WORK_BUSY’? [-Werror=implicit-function-declaration] IRQ_WORK_INIT(late_wakeup_func); ^~~~~~~~~~~~~ IRQ_WORK_BUSY kernel/rcu/tree.c:617:2: error: invalid initializer
Should be commit e1e41aa31ed1 (rcu/nocb: Trigger self-IPI on late deferred wake up before user resume) fails the build.
Ah, thank you, I'll go fix that up. Looks like 5.10.y also fails with that issue...
thanks,
greg k-h
On 2021/3/2 20:31, Greg Kroah-Hartman wrote:
On Tue, Mar 02, 2021 at 02:42:15PM +0800, Hanjun Guo wrote:
Hi Greg,
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Our test CI monitored the 5.4.102-rc2, and compile failure:
kernel/rcu/tree.c:617:2: error: implicit declaration of function ‘IRQ_WORK_INIT’; did you mean ‘IRQ_WORK_BUSY’? [-Werror=implicit-function-declaration] IRQ_WORK_INIT(late_wakeup_func); ^~~~~~~~~~~~~ IRQ_WORK_BUSY kernel/rcu/tree.c:617:2: error: invalid initializer
Should be commit e1e41aa31ed1 (rcu/nocb: Trigger self-IPI on late deferred wake up before user resume) fails the build.
Ah, thank you, I'll go fix that up. Looks like 5.10.y also fails with that issue...
It is, same compile error for 5.10. I just confirmed both arm64 and x86 have the same compile error.
Thanks Hanjun
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Tested on arm64 and x86 for 5.4.102-rc4+,
arm64: -------------------------------------------------------------------- Testcase Result Summary: total_num: 4716 succeed_num: 4716 failed_num: 0 timeout_num: 0
x86 (No kernel failures) -------------------------------------------------------------------- Testcase Result Summary: total_num: 4716 succeed_num: 4715 failed_num: 1 timeout_num: 0
Tested-by: Hulk Robot hulkci@huawei.com
On Wed, Mar 03, 2021 at 04:11:09PM +0800, Hanjun Guo wrote:
On 2021/3/2 0:09, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.4.102 release. There are 340 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.
Tested on arm64 and x86 for 5.4.102-rc4+,
arm64:
Testcase Result Summary: total_num: 4716 succeed_num: 4716 failed_num: 0 timeout_num: 0
x86 (No kernel failures)
Testcase Result Summary: total_num: 4716 succeed_num: 4715 failed_num: 1 timeout_num: 0
Tested-by: Hulk Robot hulkci@huawei.com
Thanks for testing some of these releases and letting me know.
greg k-h
linux-stable-mirror@lists.linaro.org