5.10.157-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 5.10.157-rc1 review
This is the start of the stable review cycle for the 5.10.157 release. There are 162 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 Fri, 02 Dec 2022 18:05:05 +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.10.157-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.10.157-rc1
Andrzej Hajda <[email protected]>
drm/i915: fix TLB invalidation for Gen12 video and compute engines
Christian König <[email protected]>
drm/amdgpu: always register an MMU notifier for userptr
Lyude Paul <[email protected]>
drm/amd/dc/dce120: Fix audio register mapping, stop triggering KASAN
Zhen Lei <[email protected]>
btrfs: sysfs: normalize the error handling branch in btrfs_init_sysfs()
Anand Jain <[email protected]>
btrfs: free btrfs_path before copying subvol info to userspace
Anand Jain <[email protected]>
btrfs: free btrfs_path before copying fspath to userspace
Josef Bacik <[email protected]>
btrfs: free btrfs_path before copying root refs to userspace
Luiz Capitulino <[email protected]>
genirq: Take the proposed affinity at face value if force==true
Luiz Capitulino <[email protected]>
irqchip/gic-v3: Always trust the managed affinity provided by the core code
Luiz Capitulino <[email protected]>
genirq: Always limit the affinity to online CPUs
Luiz Capitulino <[email protected]>
genirq/msi: Shutdown managed interrupts with unsatifiable affinities
Phil Turnbull <[email protected]>
wifi: wilc1000: validate number of channels
Phil Turnbull <[email protected]>
wifi: wilc1000: validate length of IEEE80211_P2P_ATTR_CHANNEL_LIST attribute
Phil Turnbull <[email protected]>
wifi: wilc1000: validate length of IEEE80211_P2P_ATTR_OPER_CHANNEL attribute
Phil Turnbull <[email protected]>
wifi: wilc1000: validate pairwise and authentication suite offsets
Mikulas Patocka <[email protected]>
dm integrity: clear the journal on suspend
Mikulas Patocka <[email protected]>
dm integrity: flush the journal on suspend
Robin Murphy <[email protected]>
gpu: host1x: Avoid trying to use GART on Tegra20
Enrico Sau <[email protected]>
net: usb: qmi_wwan: add Telit 0x103a composition
Gleb Mazovetskiy <[email protected]>
tcp: configurable source port perturb table size
Kai-Heng Feng <[email protected]>
platform/x86: hp-wmi: Ignore Smart Experience App event
Damien Le Moal <[email protected]>
zonefs: fix zone report size in __zonefs_io_error()
Hans de Goede <[email protected]>
platform/x86: acer-wmi: Enable SW_TABLET_MODE on Switch V 10 (SW5-017)
Xiongfeng Wang <[email protected]>
platform/x86: asus-wmi: add missing pci_dev_put() in asus_wmi_set_xusb2pr()
ruanjinjie <[email protected]>
xen/platform-pci: add missing free_irq() in error path
Marek Marczykowski-Górecki <[email protected]>
xen-pciback: Allow setting PCI_MSIX_FLAGS_MASKALL too
Hans de Goede <[email protected]>
Input: soc_button_array - add Acer Switch V 10 to dmi_use_low_level_irq[]
Hans de Goede <[email protected]>
Input: soc_button_array - add use_low_level_irq module parameter
Hans de Goede <[email protected]>
Input: goodix - try resetting the controller when no config is set
Lukas Wunner <[email protected]>
serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios()
Hans de Goede <[email protected]>
ASoC: Intel: bytcht_es8316: Add quirk for the Nanote UMPC-01
Aman Dhoot <[email protected]>
Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode
Alessandro Astone <[email protected]>
binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
Alessandro Astone <[email protected]>
binder: Address corner cases in deferred copy and fixup
Arnd Bergmann <[email protected]>
binder: fix pointer cast warning
Todd Kjos <[email protected]>
binder: defer copies of pre-patched txn data
Todd Kjos <[email protected]>
binder: read pre-translated fds from sender buffer
Todd Kjos <[email protected]>
binder: avoid potential data leakage when copying txn
Michael Kelley <[email protected]>
x86/ioremap: Fix page aligned size calculation in __ioremap_caller()
Maxim Levitsky <[email protected]>
KVM: x86: remove exit_int_info warning in svm_handle_exit
Maxim Levitsky <[email protected]>
KVM: x86: nSVM: leave nested mode on vCPU free
Johannes Weiner <[email protected]>
mm: vmscan: fix extreme overreclaim and swap floods
Mukesh Ojha <[email protected]>
gcov: clang: fix the buffer overflow issue
Chen Zhongjin <[email protected]>
nilfs2: fix nilfs_sufile_mark_dirty() not set segment usage as dirty
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Clear ep descriptor last
Thinh Nguyen <[email protected]>
usb: dwc3: gadget: Return -ESHUTDOWN on ep disable
Michael Grzeschik <[email protected]>
usb: dwc3: gadget: conditionally remove requests
Xiubo Li <[email protected]>
ceph: fix NULL pointer dereference for req->r_session
Kenneth Lee <[email protected]>
ceph: Use kcalloc for allocating multiple elements
Xiubo Li <[email protected]>
ceph: fix possible NULL pointer dereference for req->r_session
Xiubo Li <[email protected]>
ceph: put the requests/sessions when it fails to alloc memory
Dan Carpenter <[email protected]>
ceph: fix off by one bugs in unsafe_request_wait()
Xiubo Li <[email protected]>
ceph: flush the mdlog before waiting on unsafe reqs
Xiubo Li <[email protected]>
ceph: flush mdlog before umounting
Xiubo Li <[email protected]>
ceph: make iterate_sessions a global symbol
Xiubo Li <[email protected]>
ceph: make ceph_create_session_msg a global symbol
Pawel Laszczak <[email protected]>
usb: cdnsp: Device side header file for CDNSP driver
Pawel Laszczak <[email protected]>
usb: cdns3: Add support for DRD CDNSP
Brian Norris <[email protected]>
mmc: sdhci-brcmstb: Fix SDHCI_RESET_ALL for CQHCI
Al Cooper <[email protected]>
mmc: sdhci-brcmstb: Enable Clock Gating to save power
Al Cooper <[email protected]>
mmc: sdhci-brcmstb: Re-organize flags
Maxim Levitsky <[email protected]>
KVM: x86: emulator: update the emulation mode after rsm
Randy Dunlap <[email protected]>
nios2: add FORCE for vmlinuz.gz
Alexandre Belloni <[email protected]>
init/Kconfig: fix CC_HAS_ASM_GOTO_TIED_OUTPUT test with dash
Chen Zhongjin <[email protected]>
iio: core: Fix entry not deleted when iio_register_sw_trigger_type() fails
Alejandro Concepción Rodríguez <[email protected]>
iio: light: apds9960: fix wrong register for gesture gain
Sam James <[email protected]>
kbuild: fix -Wimplicit-function-declaration in license_is_gpl_compatible
Jakob Unterwurzacher <[email protected]>
arm64: dts: rockchip: lower rk3399-puma-haikou SD controller clock frequency
Baokun Li <[email protected]>
ext4: fix use-after-free in ext4_ext_shift_extents
Marek Szyprowski <[email protected]>
usb: dwc3: exynos: Fix remove() function
Greg Kroah-Hartman <[email protected]>
lib/vdso: use "grep -E" instead of "egrep"
Vladimir Oltean <[email protected]>
net: enetc: preserve TX ring priority across reconfiguration
Vladimir Oltean <[email protected]>
net: enetc: cache accesses to &priv->si->hw
Vladimir Oltean <[email protected]>
net: enetc: manage ENETC_F_QBV in priv->active_offloads only when enabled
Heiko Carstens <[email protected]>
s390/crashdump: fix TOD programmable field size
Yu Liao <[email protected]>
net: thunderx: Fix the ACPI memory leak
Martin Faltesek <[email protected]>
nfc: st-nci: fix memory leaks in EVT_TRANSACTION
Martin Faltesek <[email protected]>
nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION
Wang Hai <[email protected]>
arcnet: fix potential memory leak in com20020_probe()
Ahmed S. Darwish <[email protected]>
net: arcnet: Fix RESET flag handling
Stefan Haberland <[email protected]>
s390/dasd: fix no record found for raw_track_access
Ziyang Xuan <[email protected]>
ipv4: Fix error return code in fib_table_insert()
Kuniyuki Iwashima <[email protected]>
dccp/tcp: Reset saddr on failure after inet6?_hash_connect().
Felix Fietkau <[email protected]>
netfilter: flowtable_offload: add missing locking
Dawei Li <[email protected]>
dma-buf: fix racing conflict of dma_heap_add()
Yang Yingliang <[email protected]>
bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending()
Andreas Kemnade <[email protected]>
regulator: twl6030: re-add TWL6032_SUBCLASS
Liu Shixin <[email protected]>
NFC: nci: fix memory leak in nci_rx_data_packet()
Xin Long <[email protected]>
net: sched: allow act_ct to be built without NF_NAT
Zhang Changzhong <[email protected]>
sfc: fix potential memleak in __ef100_hard_start_xmit()
Chen Zhongjin <[email protected]>
xfrm: Fix ignored return value in xfrm6_init()
YueHaibing <[email protected]>
tipc: check skb_linearize() return value in tipc_disc_rcv()
Xin Long <[email protected]>
tipc: add an extra conn_get in tipc_conn_alloc
Xin Long <[email protected]>
tipc: set con sock in tipc_conn_alloc
Moshe Shemesh <[email protected]>
net/mlx5: Fix handling of entry refcount when command is not issued to FW
Moshe Shemesh <[email protected]>
net/mlx5: Fix FW tracer timestamp calculation
Vishwanath Pai <[email protected]>
netfilter: ipset: regression in ip_set_hash_ip.c
Jozsef Kadlecsik <[email protected]>
netfilter: ipset: Limit the maximal range of consecutive elements to add/delete
Yang Yingliang <[email protected]>
Drivers: hv: vmbus: fix possible memory leak in vmbus_device_register()
Yang Yingliang <[email protected]>
Drivers: hv: vmbus: fix double free in the error path of vmbus_add_channel_work()
YueHaibing <[email protected]>
macsec: Fix invalid error code set
Jaco Coetzee <[email protected]>
nfp: add port from netdev validation for EEPROM access
Diana Wang <[email protected]>
nfp: fill splittable of devlink_port_attrs correctly
Yang Yingliang <[email protected]>
net: pch_gbe: fix pci device refcount leak while module exiting
Zhang Changzhong <[email protected]>
net/qla3xxx: fix potential memleak in ql3xxx_send()
Peter Kosyh <[email protected]>
net/mlx4: Check retval of mlx4_bitmap_init
Liu Jian <[email protected]>
net: ethernet: mtk_eth_soc: fix error handling in mtk_open()
Fabio Estevam <[email protected]>
ARM: dts: imx6q-prti6q: Fix ref/tcxo-clock-frequency properties
Zheng Yongjun <[email protected]>
ARM: mxs: fix memory leak in mxs_machine_init()
Daniel Xu <[email protected]>
netfilter: conntrack: Fix data-races around ct mark
Zhengchao Shao <[email protected]>
9p/fd: fix issue of list_del corruption in p9_fd_cancel()
Wang Hai <[email protected]>
net: pch_gbe: fix potential memleak in pch_gbe_tx_queue()
Lin Ma <[email protected]>
nfc/nci: fix race with opening and closing
David Howells <[email protected]>
rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]
David Howells <[email protected]>
rxrpc: Use refcount_t rather than atomic_t
David Howells <[email protected]>
rxrpc: Allow list of in-use local UDP endpoints to be viewed in /proc
Leon Romanovsky <[email protected]>
net: liquidio: simplify if expression
Michael Grzeschik <[email protected]>
ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl
Yang Yingliang <[email protected]>
tee: optee: fix possible memory leak in optee_register_device()
Samuel Holland <[email protected]>
bus: sunxi-rsb: Support atomic transfers
Yang Yingliang <[email protected]>
regulator: core: fix UAF in destroy_regulator()
Xiongfeng Wang <[email protected]>
spi: dw-dma: decrease reference count in dw_spi_dma_init_mfld()
Zeng Heng <[email protected]>
regulator: core: fix kobject release warning and memory leak in regulator_register()
Michael Kelley <[email protected]>
scsi: storvsc: Fix handling of srb_status and capacity change events
Richard Fitzgerald <[email protected]>
ASoC: soc-pcm: Don't zero TDM masks in __soc_pcm_open()
Detlev Casanova <[email protected]>
ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove
Junxiao Chang <[email protected]>
ASoC: hdac_hda: fix hda pcm buffer overflow issue
Dominik Haller <[email protected]>
ARM: dts: am335x-pcm-953: Define fixed regulators in root node
Herbert Xu <[email protected]>
af_key: Fix send_acquire race with pfkey_register
Christian Langrock <[email protected]>
xfrm: replay: Fix ESN wrap around for GSO
Eyal Birger <[email protected]>
xfrm: fix "disable_policy" on ipv4 early demux
Jason A. Donenfeld <[email protected]>
MIPS: pic32: treat port as signed integer
Nathan Chancellor <[email protected]>
RISC-V: vdso: Do not add missing symbols to version section in linker script
Kuniyuki Iwashima <[email protected]>
arm64/syscall: Include asm/ptrace.h in syscall_wrapper header.
Yu Kuai <[email protected]>
block, bfq: fix null pointer dereference in bfq_bio_bfqg()
Hans de Goede <[email protected]>
drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)
Bart Van Assche <[email protected]>
scsi: scsi_debug: Make the READ CAPACITY response compliant with ZBC
Brian King <[email protected]>
scsi: ibmvfc: Avoid path failures during live migration
Hans de Goede <[email protected]>
platform/x86: touchscreen_dmi: Add info for the RCA Cambio W101 v2 2-in-1
Sabrina Dubroca <[email protected]>
Revert "net: macsec: report real_dev features when HW offloading is enabled"
Youlin Li <[email protected]>
selftests/bpf: Add verifier test for release_reference()
Sean Nyekjaer <[email protected]>
spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run
Nicolas Cavallari <[email protected]>
wifi: mac80211: Fix ack frame idr leak when mesh has no route
Jason A. Donenfeld <[email protected]>
wifi: airo: do not assign -1 to unsigned char
Gaosheng Cui <[email protected]>
audit: fix undefined behavior in bit shift for AUDIT_BIT
Emil Renner Berthing <[email protected]>
riscv: dts: sifive unleashed: Add PWM controlled LEDs
Jonas Jelonek <[email protected]>
wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support
taozhang <[email protected]>
wifi: mac80211: fix memory free error when registering wiphy fail
Xiubo Li <[email protected]>
ceph: avoid putting the realm twice when decoding snaps fails
Xiubo Li <[email protected]>
ceph: do not update snapshot context when there is no new snapshot
Mitja Spes <[email protected]>
iio: pressure: ms5611: fixed value compensation bug
Lars-Peter Clausen <[email protected]>
iio: ms5611: Simplify IO callback parameters
Đoàn Trần Công Danh <[email protected]>
speakup: replace utils' u_char with unsigned char
Samuel Thibault <[email protected]>
speakup: Generate speakupmap.h automatically
Bean Huo <[email protected]>
nvme-pci: add NVME_QUIRK_BOGUS_NID for Micron Nitro
Leo Savernik <[email protected]>
nvme: add a bogus subsystem NQN quirk for Micron MTFDKBA2T0TFH
Simon Rettberg <[email protected]>
drm/display: Don't assume dual mode adaptors support i2c sub-addressing
Ido Schimmel <[email protected]>
bridge: switchdev: Fix memory leaks when changing VLAN protocol
Danielle Ratson <[email protected]>
bridge: switchdev: Notify about VLAN protocol changes
Niklas Cassel <[email protected]>
ata: libata-core: do not issue non-internal commands once EH is pending
Wenchao Hao <[email protected]>
ata: libata-scsi: simplify __ata_scsi_queuecmd()
Yang Yingliang <[email protected]>
scsi: scsi_transport_sas: Fix error handling in sas_phy_add()
-------------
Diffstat:
Makefile | 4 +- arch/arm/boot/dts/am335x-pcm-953.dtsi | 28 +- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 9 + arch/arm/boot/dts/imx6q-prti6q.dts | 4 +- arch/arm/mach-mxs/mach-mxs.c | 4 +- .../arm64/boot/dts/rockchip/rk3399-puma-haikou.dts | 2 +- arch/arm64/include/asm/syscall_wrapper.h | 2 +- arch/mips/include/asm/fw/fw.h | 2 +- arch/mips/pic32/pic32mzda/early_console.c | 13 +- arch/mips/pic32/pic32mzda/init.c | 2 +- arch/nios2/boot/Makefile | 2 +- .../riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 38 + arch/riscv/kernel/vdso/Makefile | 3 + arch/riscv/kernel/vdso/vdso.lds.S | 2 + arch/s390/kernel/crash_dump.c | 2 +- arch/x86/kvm/emulate.c | 9 + arch/x86/kvm/svm/svm.c | 16 +- arch/x86/mm/ioremap.c | 8 +- block/bfq-cgroup.c | 4 + drivers/accessibility/speakup/.gitignore | 4 + drivers/accessibility/speakup/Makefile | 28 + drivers/accessibility/speakup/genmap.c | 162 +++ drivers/accessibility/speakup/makemapdata.c | 125 ++ drivers/accessibility/speakup/speakupmap.h | 66 - drivers/accessibility/speakup/utils.h | 102 ++ drivers/android/binder.c | 437 +++++- drivers/ata/libata-scsi.c | 55 +- drivers/bus/sunxi-rsb.c | 29 +- drivers/dma-buf/dma-heap.c | 28 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 8 +- .../drm/amd/display/dc/dce120/dce120_resource.c | 3 +- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 51 +- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 + drivers/gpu/drm/i915/gt/intel_gt.c | 4 + drivers/gpu/drm/tegra/drm.c | 4 + drivers/gpu/host1x/dev.c | 4 + drivers/hv/channel_mgmt.c | 6 +- drivers/hv/vmbus_drv.c | 1 + drivers/iio/industrialio-sw-trigger.c | 6 +- drivers/iio/light/apds9960.c | 12 +- drivers/iio/pressure/ms5611.h | 18 +- drivers/iio/pressure/ms5611_core.c | 56 +- drivers/iio/pressure/ms5611_i2c.c | 11 +- drivers/iio/pressure/ms5611_spi.c | 17 +- drivers/input/misc/soc_button_array.c | 14 +- drivers/input/mouse/synaptics.c | 1 + drivers/input/touchscreen/goodix.c | 11 + drivers/irqchip/irq-gic-v3-its.c | 2 +- drivers/md/dm-integrity.c | 20 +- drivers/mmc/host/sdhci-brcmstb.c | 68 +- drivers/net/arcnet/arc-rimi.c | 4 +- drivers/net/arcnet/arcdevice.h | 6 + drivers/net/arcnet/arcnet.c | 66 +- drivers/net/arcnet/com20020-isa.c | 4 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020_cs.c | 13 +- drivers/net/arcnet/com90io.c | 4 +- drivers/net/arcnet/com90xx.c | 4 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 12 +- drivers/net/ethernet/cavium/liquidio/lio_main.c | 4 +- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +- drivers/net/ethernet/freescale/enetc/enetc.c | 32 +- drivers/net/ethernet/freescale/enetc/enetc.h | 10 +- drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 +- drivers/net/ethernet/freescale/enetc/enetc_qos.c | 83 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 + drivers/net/ethernet/mellanox/mlx4/qp.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 6 +- .../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 2 +- .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 3 + .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 6 +- drivers/net/ethernet/qlogic/qla3xxx.c | 1 + drivers/net/ethernet/sfc/ef100_netdev.c | 1 + drivers/net/macsec.c | 28 +- drivers/net/usb/qmi_wwan.c | 1 + drivers/net/wireless/cisco/airo.c | 18 +- drivers/net/wireless/mac80211_hwsim.c | 5 + drivers/net/wireless/microchip/wilc1000/cfg80211.c | 40 +- drivers/net/wireless/microchip/wilc1000/hif.c | 21 +- drivers/nfc/st-nci/se.c | 6 +- drivers/nvme/host/pci.c | 4 + drivers/platform/x86/acer-wmi.c | 9 + drivers/platform/x86/asus-wmi.c | 2 + drivers/platform/x86/hp-wmi.c | 3 + drivers/platform/x86/touchscreen_dmi.c | 25 + drivers/regulator/core.c | 8 +- drivers/regulator/twl6030-regulator.c | 2 + drivers/s390/block/dasd_eckd.c | 6 +- drivers/scsi/ibmvscsi/ibmvfc.c | 14 +- drivers/scsi/scsi_debug.c | 7 + drivers/scsi/scsi_transport_sas.c | 13 +- drivers/scsi/storvsc_drv.c | 69 +- drivers/spi/spi-dw-dma.c | 3 + drivers/spi/spi-stm32.c | 2 +- drivers/tee/optee/device.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 7 +- drivers/usb/cdns3/cdnsp-gadget.h | 1463 ++++++++++++++++++++ drivers/usb/cdns3/core.c | 24 +- drivers/usb/cdns3/core.h | 5 + drivers/usb/cdns3/drd.c | 101 +- drivers/usb/cdns3/drd.h | 67 +- drivers/usb/dwc3/dwc3-exynos.c | 11 +- drivers/usb/dwc3/gadget.c | 22 +- drivers/xen/platform-pci.c | 7 +- drivers/xen/xen-pciback/conf_space_capability.c | 9 +- fs/btrfs/ioctl.c | 7 +- fs/btrfs/sysfs.c | 7 +- fs/ceph/caps.c | 105 +- fs/ceph/mds_client.c | 90 +- fs/ceph/mds_client.h | 5 + fs/ceph/snap.c | 31 +- fs/ceph/strings.c | 1 + fs/ext4/extents.c | 18 +- fs/nilfs2/sufile.c | 8 + fs/zonefs/super.c | 37 +- include/linux/ceph/ceph_fs.h | 1 + include/linux/license.h | 2 + include/linux/netfilter/ipset/ip_set.h | 3 + include/net/switchdev.h | 2 + include/trace/events/rxrpc.h | 2 +- include/uapi/linux/audit.h | 2 +- init/Kconfig | 2 +- kernel/gcov/clang.c | 2 + kernel/irq/manage.c | 31 +- kernel/irq/msi.c | 7 + lib/vdso/Makefile | 2 +- mm/vmscan.c | 10 +- net/9p/trans_fd.c | 2 + net/bridge/br_vlan.c | 33 +- net/core/flow_dissector.c | 2 +- net/dccp/ipv4.c | 2 + net/dccp/ipv6.c | 2 + net/ipv4/Kconfig | 10 + net/ipv4/esp4_offload.c | 3 + net/ipv4/fib_trie.c | 4 +- net/ipv4/inet_hashtables.c | 10 +- net/ipv4/ip_input.c | 5 + net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 +- net/ipv4/tcp_ipv4.c | 2 + net/ipv6/esp6_offload.c | 3 + net/ipv6/tcp_ipv6.c | 2 + net/ipv6/xfrm6_policy.c | 6 +- net/key/af_key.c | 32 +- net/mac80211/main.c | 8 +- net/mac80211/mesh_pathtbl.c | 2 +- net/netfilter/ipset/ip_set_hash_ip.c | 17 +- net/netfilter/ipset/ip_set_hash_ipmark.c | 10 +- net/netfilter/ipset/ip_set_hash_ipport.c | 3 + net/netfilter/ipset/ip_set_hash_ipportip.c | 3 + net/netfilter/ipset/ip_set_hash_ipportnet.c | 3 + net/netfilter/ipset/ip_set_hash_net.c | 11 +- net/netfilter/ipset/ip_set_hash_netiface.c | 10 +- net/netfilter/ipset/ip_set_hash_netnet.c | 16 +- net/netfilter/ipset/ip_set_hash_netport.c | 11 +- net/netfilter/ipset/ip_set_hash_netportnet.c | 16 +- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 24 +- net/netfilter/nf_conntrack_standalone.c | 2 +- net/netfilter/nf_flow_table_offload.c | 4 + net/netfilter/nft_ct.c | 6 +- net/netfilter/xt_connmark.c | 18 +- net/nfc/nci/core.c | 2 +- net/nfc/nci/data.c | 4 +- net/openvswitch/conntrack.c | 8 +- net/rxrpc/af_rxrpc.c | 2 +- net/rxrpc/ar-internal.h | 24 +- net/rxrpc/call_accept.c | 4 +- net/rxrpc/call_object.c | 44 +- net/rxrpc/conn_client.c | 66 +- net/rxrpc/conn_object.c | 49 +- net/rxrpc/conn_service.c | 8 +- net/rxrpc/input.c | 4 +- net/rxrpc/local_object.c | 68 +- net/rxrpc/net_ns.c | 5 +- net/rxrpc/peer_object.c | 40 +- net/rxrpc/proc.c | 75 +- net/rxrpc/skbuff.c | 1 - net/sched/Kconfig | 2 +- net/sched/act_connmark.c | 4 +- net/sched/act_ct.c | 8 +- net/sched/act_ctinfo.c | 6 +- net/tipc/discover.c | 5 +- net/tipc/topsrv.c | 20 +- net/xfrm/xfrm_device.c | 15 +- net/xfrm/xfrm_replay.c | 2 +- sound/soc/codecs/hdac_hda.h | 4 +- sound/soc/codecs/sgtl5000.c | 1 + sound/soc/intel/boards/bytcht_es8316.c | 7 + sound/soc/soc-pcm.c | 5 - .../testing/selftests/bpf/verifier/ref_tracking.c | 36 + 191 files changed, 4038 insertions(+), 942 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/162 scsi: scsi_transport_sas: Fix error handling in sas_phy_add()
From: Yang Yingliang <[email protected]>
[ Upstream commit 5d7bebf2dfb0dc97aac1fbace0910e557ecdb16f ]
If transport_add_device() fails in sas_phy_add(), the kernel will crash trying to delete the device in transport_remove_device() called from sas_remove_host().
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000108 CPU: 61 PID: 42829 Comm: rmmod Kdump: loaded Tainted: G W 6.1.0-rc1+ #173 pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : device_del+0x54/0x3d0 lr : device_del+0x37c/0x3d0 Call trace: device_del+0x54/0x3d0 attribute_container_class_device_del+0x28/0x38 transport_remove_classdev+0x6c/0x80 attribute_container_device_trigger+0x108/0x110 transport_remove_device+0x28/0x38 sas_phy_delete+0x30/0x60 [scsi_transport_sas] do_sas_phy_delete+0x6c/0x80 [scsi_transport_sas] device_for_each_child+0x68/0xb0 sas_remove_children+0x40/0x50 [scsi_transport_sas] sas_remove_host+0x20/0x38 [scsi_transport_sas] hisi_sas_remove+0x40/0x68 [hisi_sas_main] hisi_sas_v2_remove+0x20/0x30 [hisi_sas_v2_hw] platform_remove+0x2c/0x60
Fix this by checking and handling return value of transport_add_device() in sas_phy_add().
--- drivers/scsi/scsi_transport_sas.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/scsi/scsi_transport_sas.c +9 -4
@@ -716,12 +716,17 @@ int sas_phy_add(struct sas_phy *phy)int error; error =device_add (&phy->dev); -if (!error) { -transport_add_device (&phy->dev); -transport_configure_device (&phy->dev); +if (error) +return error; + + error =transport_add_device (&phy->dev); +if (error) { +device_del (&phy->dev); +return error; } +transport_configure_device (&phy->dev); -return error; +return 0 ; }EXPORT_SYMBOL (sas_phy_add);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 2/162 ata: libata-scsi: simplify __ata_scsi_queuecmd()
In reply to Greg Kroah-HartmanFrom: Wenchao Hao <[email protected]>
[ Upstream commit 84eac327af543f03172085d5ef9f98ea25a51191 ]
This patch cleans up the code of __ata_scsi_queuecmd(). Since each branch of the "if" condition check that scmd->cmd_len is not zero, move this check out of the "if" to simplify the conditions being checked in the "else" branch.
While at it, avoid the if-else-if-else structure using if-else if structure and remove the redundant rc local variable.
This patch does not change the function logic.
Stable-dep-of: e20e81a24a4d ("ata: libata-core: do not issue non-internal commands once EH is pending")
--- drivers/ata/libata-scsi.c | 45 ++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 24 deletions(-)
drivers/ata/libata-scsi.c +21 -24
@@ -4034,42 +4034,39 @@ int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev) {u8 scsi_op = scmd->cmnd[0 ];ata_xlat_func_t xlat_func; -int rc =0 ; + +if (unlikely (!scmd->cmd_len)) + goto bad_cdb_len;if (dev->class ==ATA_DEV_ATA || dev->class ==ATA_DEV_ZAC ) { -if (unlikely (!scmd->cmd_len || scmd->cmd_len > dev->cdb_len)) +if (unlikely (scmd->cmd_len > dev->cdb_len)) goto bad_cdb_len; xlat_func =ata_get_xlat_func (dev, scsi_op); - }else { -if (unlikely (!scmd->cmd_len)) - goto bad_cdb_len; + }else if (likely ((scsi_op !=ATA_16 ) || !atapi_passthru16)) { +/* relay SCSI command to ATAPI device */ +int len =COMMAND_SIZE (scsi_op); - xlat_func =NULL ; -if (likely ((scsi_op !=ATA_16 ) || !atapi_passthru16)) { -/* relay SCSI command to ATAPI device */ -int len =COMMAND_SIZE (scsi_op); -if (unlikely (len > scmd->cmd_len || - len > dev->cdb_len || - scmd->cmd_len >ATAPI_CDB_LEN )) - goto bad_cdb_len; +if (unlikely (len > scmd->cmd_len || + len > dev->cdb_len || + scmd->cmd_len >ATAPI_CDB_LEN )) + goto bad_cdb_len; - xlat_func = atapi_xlat; - }else { -/* ATA_16 passthru, treat as an ATA command */ -if (unlikely (scmd->cmd_len >16 )) - goto bad_cdb_len; + xlat_func = atapi_xlat; + }else { +/* ATA_16 passthru, treat as an ATA command */ +if (unlikely (scmd->cmd_len >16 )) + goto bad_cdb_len; - xlat_func =ata_get_xlat_func (dev, scsi_op); - } + xlat_func =ata_get_xlat_func (dev, scsi_op); }if (xlat_func) - rc =ata_scsi_translate (dev, scmd, xlat_func); -else -ata_scsi_simulate (dev, scmd); +return ata_scsi_translate (dev, scmd, xlat_func); -return rc; +ata_scsi_simulate (dev, scmd); + +return 0 ; bad_cdb_len: DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 3/162 ata: libata-core: do not issue non-internal commands once EH is pending
In reply to Greg Kroah-HartmanFrom: Niklas Cassel <[email protected]>
[ Upstream commit e20e81a24a4d58744a29715aac2f795cd1651955 ]
While the ATA specification states that a device should return command aborted for all commands queued after the device has entered error state, since ATA only keeps the sense data for the latest command (in non-NCQ case), we really don't want to send block layer commands to the device after it has entered error state. (Only ATA EH commands should be sent, to read the sense data etc.)
Currently, scsi_queue_rq() will check if scsi_host_in_recovery() (state is SHOST_RECOVERY), and if so, it will _not_ issue a command via:scsi_dispatch_cmd() -> host->hostt->queuecommand() (ata_scsi_queuecmd()) -> __ata_scsi_queuecmd() -> ata_scsi_translate() -> ata_qc_issue()
Before commit e494f6a72839 ("[SCSI] improved eh timeout handler"), when receiving a TFES error IRQ, the call chain looked like this:ahci_error_intr() -> ata_port_abort() -> ata_do_link_abort() -> ata_qc_complete() -> ata_qc_schedule_eh() -> blk_abort_request() -> blk_rq_timed_out() -> q->rq_timed_out_fn() (scsi_times_out()) -> scsi_eh_scmd_add() -> scsi_host_set_state(shost, SHOST_RECOVERY)
Which meant that as soon as an error IRQ was serviced, SHOST_RECOVERY would be set.
However, after commit e494f6a72839 ("[SCSI] improved eh timeout handler"), scsi_times_out() will instead call scsi_abort_command() which will queue delayed work, and the worker function scmd_eh_abort_handler() will call scsi_eh_scmd_add(), which calls scsi_host_set_state(shost, SHOST_RECOVERY).
So now, after the TFES error IRQ has been serviced, we need to wait for the SCSI workqueue to run its work before SHOST_RECOVERY gets set.
It is worth noting that, even before commit e494f6a72839 ("[SCSI] improved eh timeout handler"), we could receive an error IRQ from the time when scsi_queue_rq() checks scsi_host_in_recovery(), to the time when ata_scsi_queuecmd() is actually called.
In order to handle both the delayed setting of SHOST_RECOVERY and the window where we can receive an error IRQ, add a check against ATA_PFLAG_EH_PENDING (which gets set when servicing the error IRQ), inside ata_scsi_queuecmd() itself, while holding the ap->lock. (Since the ap->lock is held while servicing IRQs.)
--- drivers/ata/libata-scsi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/ata/libata-scsi.c +10 -0
@@ -4032,9 +4032,19 @@ void ata_scsi_dump_cdb(struct ata_port *ap, struct scsi_cmnd *cmd)int __ata_scsi_queuecmd (struct scsi_cmnd *scmd,struct ata_device *dev) { +struct ata_port *ap = dev->link->ap;u8 scsi_op = scmd->cmnd[0 ];ata_xlat_func_t xlat_func; +/* +* scsi_queue_rq() will defer commands if scsi_host_in_recovery(). +* However, this check is done without holding the ap->lock (a libata +* specific lock), so we can have received an error irq since then, +* therefore we must check if EH is pending, while holding ap->lock. +*/ +if (ap->pflags & (ATA_PFLAG_EH_PENDING |ATA_PFLAG_EH_IN_PROGRESS )) +return SCSI_MLQUEUE_DEVICE_BUSY ; +if (unlikely (!scmd->cmd_len)) goto bad_cdb_len;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 4/162 bridge: switchdev: Notify about VLAN protocol changes
In reply to Greg Kroah-HartmanFrom: Danielle Ratson <[email protected]>
[ Upstream commit 22ec19f3aee327806c37c9fa1188741574bc6445 ]
Drivers that support bridge offload need to be notified about changes to the bridge's VLAN protocol so that they could react accordingly and potentially veto the change.
Add a new switchdev attribute to communicate the change to drivers.
Stable-dep-of: 9d45921ee4cb ("bridge: switchdev: Fix memory leaks when changing VLAN protocol")
--- include/net/switchdev.h | 2 ++ net/bridge/br_vlan.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
include/net/switchdev.h +2 -0
@@ -38,6 +38,7 @@ enum switchdev_attr_id {SWITCHDEV_ATTR_ID_PORT_MROUTER ,SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME ,SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING , +SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL ,SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED ,SWITCHDEV_ATTR_ID_BRIDGE_MROUTER , #if IS_ENABLED(CONFIG_BRIDGE_MRP)
@@ -57,6 +58,7 @@ struct switchdev_attr {bool mrouter;/* PORT_MROUTER */ clock_t ageing_time;/* BRIDGE_AGEING_TIME */ bool vlan_filtering;/* BRIDGE_VLAN_FILTERING */ +u16 vlan_protocol;/* BRIDGE_VLAN_PROTOCOL */ bool mc_disabled;/* MC_DISABLED */ #if IS_ENABLED (CONFIG_BRIDGE_MRP )u8 mrp_port_role;/* MRP_PORT_ROLE */
net/bridge/br_vlan.c +14 -2
@@ -855,15 +855,25 @@ EXPORT_SYMBOL_GPL(br_vlan_get_proto);int __br_vlan_set_proto (struct net_bridge *br,__be16 proto) { +struct switchdev_attr attr = { + .orig_dev = br->dev, + .id =SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL , + .flags =SWITCHDEV_F_SKIP_EOPNOTSUPP , + .u.vlan_protocol =ntohs (proto), + };int err =0 ;struct net_bridge_port *p;struct net_bridge_vlan *vlan;struct net_bridge_vlan_group *vg; -__be16 oldproto; +__be16 oldproto = br->vlan_proto;if (br->vlan_proto == proto)return 0 ; + err =switchdev_port_attr_set (br->dev, &attr); +if (err && err != -EOPNOTSUPP ) +return err; +/* Add VLANs for the new proto to the device filter. */ list_for_each_entry (p, &br->port_list, list) { vg =nbp_vlan_group (p);
@@ -874,7 +884,6 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) } } - oldproto = br->vlan_proto; br->vlan_proto = proto;recalculate_group_addr (br);
@@ -890,6 +899,9 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)return 0 ; err_filt: + attr.u.vlan_protocol =ntohs (oldproto); +switchdev_port_attr_set (br->dev, &attr); +list_for_each_entry_continue_reverse (vlan, &vg->vlan_list, vlist)vlan_vid_del (p->dev, proto, vlan->vid);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 5/162 bridge: switchdev: Fix memory leaks when changing VLAN protocol
In reply to Greg Kroah-HartmanFrom: Ido Schimmel <[email protected]>
[ Upstream commit 9d45921ee4cb364910097e7d1b7558559c2f9fd2 ]
The bridge driver can offload VLANs to the underlying hardware either via switchdev or the 8021q driver. When the former is used, the VLAN is marked in the bridge driver with the 'BR_VLFLAG_ADDED_BY_SWITCHDEV' private flag.
To avoid the memory leaks mentioned in the cited commit, the bridge driver will try to delete a VLAN via the 8021q driver if the VLAN is not marked with the previously mentioned flag.
When the VLAN protocol of the bridge changes, switchdev drivers are notified via the 'SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL' attribute, but the 8021q driver is also called to add the existing VLANs with the new protocol and delete them with the old protocol.
In case the VLANs were offloaded via switchdev, the above behavior is both redundant and buggy. Redundant because the VLANs are already programmed in hardware and drivers that support VLAN protocol change (currently only mlx5) change the protocol upon the switchdev attribute notification. Buggy because the 8021q driver is called despite these VLANs being marked with 'BR_VLFLAG_ADDED_BY_SWITCHDEV'. This leads to memory leaks [1] when the VLANs are deleted.
Fix by not calling the 8021q driver for VLANs that were already programmed via switchdev.
[1]
unreferenced object 0xffff8881f6771200 (size 256):
comm "ip", pid 446855, jiffies 4298238841 (age 55.240s) hex dump (first 32 bytes):
00 00 7f 0e 83 88 ff ff 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000012819ac>] vlan_vid_add+0x437/0x750
[<00000000f2281fad>] __br_vlan_set_proto+0x289/0x920
[<000000000632b56f>] br_changelink+0x3d6/0x13f0
[<0000000089d25f04>] __rtnl_newlink+0x8ae/0x14c0
[<00000000f6276baf>] rtnl_newlink+0x5f/0x90
[<00000000746dc902>] rtnetlink_rcv_msg+0x336/0xa00
[<000000001c2241c0>] netlink_rcv_skb+0x11d/0x340
[<0000000010588814>] netlink_unicast+0x438/0x710
[<00000000e1a4cd5c>] netlink_sendmsg+0x788/0xc40
[<00000000e8992d4e>] sock_sendmsg+0xb0/0xe0
[<00000000621b8f91>] ____sys_sendmsg+0x4ff/0x6d0
[<000000000ea26996>] ___sys_sendmsg+0x12e/0x1b0
[<00000000684f7e25>] __sys_sendmsg+0xab/0x130
[<000000004538b104>] do_syscall_64+0x3d/0x90
[<0000000091ed9678>] entry_SYSCALL_64_after_hwframe+0x46/0xb0--- net/bridge/br_vlan.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
net/bridge/br_vlan.c +14 -3
@@ -878,6 +878,8 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)list_for_each_entry (p, &br->port_list, list) { vg =nbp_vlan_group (p);list_for_each_entry (vlan, &vg->vlan_list, vlist) { +if (vlan->priv_flags &BR_VLFLAG_ADDED_BY_SWITCHDEV ) +continue ; err =vlan_vid_add (p->dev, proto, vlan->vid);if (err) goto err_filt;
@@ -892,8 +894,11 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)/* Delete VLANs for the old proto from the device filter. */ list_for_each_entry (p, &br->port_list, list) { vg =nbp_vlan_group (p); -list_for_each_entry (vlan, &vg->vlan_list, vlist) +list_for_each_entry (vlan, &vg->vlan_list, vlist) { +if (vlan->priv_flags &BR_VLFLAG_ADDED_BY_SWITCHDEV ) +continue ;vlan_vid_del (p->dev, oldproto, vlan->vid); + } }return 0 ;
@@ -902,13 +907,19 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) attr.u.vlan_protocol =ntohs (oldproto);switchdev_port_attr_set (br->dev, &attr); -list_for_each_entry_continue_reverse (vlan, &vg->vlan_list, vlist) +list_for_each_entry_continue_reverse (vlan, &vg->vlan_list, vlist) { +if (vlan->priv_flags &BR_VLFLAG_ADDED_BY_SWITCHDEV ) +continue ;vlan_vid_del (p->dev, proto, vlan->vid); + }list_for_each_entry_continue_reverse (p, &br->port_list, list) { vg =nbp_vlan_group (p); -list_for_each_entry (vlan, &vg->vlan_list, vlist) +list_for_each_entry (vlan, &vg->vlan_list, vlist) { +if (vlan->priv_flags &BR_VLFLAG_ADDED_BY_SWITCHDEV ) +continue ;vlan_vid_del (p->dev, proto, vlan->vid); + } }return err;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 6/162 drm/display: Dont assume dual mode adaptors support i2c sub-addressing
In reply to Greg Kroah-HartmanFrom: Simon Rettberg <[email protected]>
[ Upstream commit 5954acbacbd1946b96ce8ee799d309cb0cd3cb9d ]
Current dual mode adaptor ("DP++") detection code assumes that all adaptors support i2c sub-addressing for read operations from the DP-HDMI adaptor ID buffer. It has been observed that multiple adaptors do not in fact support this, and always return data starting at register 0. On affected adaptors, the code fails to read the proper registers that would identify the device as a type 2 adaptor, and handles those as type 1, limiting the TMDS clock to 165MHz, even if the according register would announce a higher TMDS clock. Fix this by always reading the ID buffer starting from offset 0, and discarding any bytes before the actual offset of interest.
We tried finding authoritative documentation on whether or not this is allowed behaviour, but since all the official VESA docs are paywalled, the best we could come up with was the spec sheet for Texas Instruments' SNx5DP149 chip family.[1] It explicitly mentions that sub-addressing is supported for register writes, but *not* for reads (See NOTE in section 8.5.3). Unless TI openly decided to violate the VESA spec, one could take that as a hint that sub-addressing is in fact not mandated by VESA.
The other two adaptors affected used the PS8409(A) and the LT8611, according to the data returned from their ID buffers.
[1] https://www.ti.com/lit/ds/symlink/sn75dp149.pdf
--- drivers/gpu/drm/drm_dp_dual_mode_helper.c | 51 +++++++++++++---------- 1 file changed, 29 insertions(+), 22 deletions(-)
drivers/gpu/drm/drm_dp_dual_mode_helper.c +29 -22
@@ -62,23 +62,45 @@ssize_t drm_dp_dual_mode_read (struct i2c_adapter *adapter,u8 offset,void *buffer,size_t size) { +u8 zero =0 ; +char *tmpbuf =NULL ; +/* +* As sub-addressing is not supported by all adaptors, +* always explicitly read from the start and discard +* any bytes that come before the requested offset. +* This way, no matter whether the adaptor supports it +* or not, we'll end up reading the proper data. +*/ struct i2c_msg msgs[] = { { .addr =DP_DUAL_MODE_SLAVE_ADDRESS , .flags =0 , .len =1 , - .buf = &offset, + .buf = &zero, }, { .addr =DP_DUAL_MODE_SLAVE_ADDRESS , .flags =I2C_M_RD , - .len = size, + .len = size + offset, .buf = buffer, }, };int ret; +if (offset) { + tmpbuf =kmalloc (size + offset,GFP_KERNEL ); +if (!tmpbuf) +return -ENOMEM ; + + msgs[1 ].buf = tmpbuf; + } + ret =i2c_transfer (adapter, msgs,ARRAY_SIZE (msgs)); +if (tmpbuf) +memcpy (buffer, tmpbuf + offset, size); + +kfree (tmpbuf); +if (ret <0 )return ret;if (ret !=ARRAY_SIZE (msgs))
@@ -205,18 +227,6 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter)if (ret)return DRM_DP_DUAL_MODE_UNKNOWN ; -/* -* Sigh. Some (maybe all?) type 1 adaptors are broken and ack -* the offset but ignore it, and instead they just always return -* data from the start of the HDMI ID buffer. So for a broken -* type 1 HDMI adaptor a single byte read will always give us -* 0x44, and for a type 1 DVI adaptor it should give 0x00 -* (assuming it implements any registers). Fortunately neither -* of those values will match the type 2 signature of the -* DP_DUAL_MODE_ADAPTOR_ID register so we can proceed with -* the type 2 adaptor detection safely even in the presence -* of broken type 1 adaptors. -*/ ret =drm_dp_dual_mode_read (adapter,DP_DUAL_MODE_ADAPTOR_ID , &adaptor_id,sizeof (adaptor_id)); DRM_DEBUG_KMS("DP dual mode adaptor ID: %02x (err %zd)\n",
@@ -231,11 +241,10 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter)return DRM_DP_DUAL_MODE_TYPE2_DVI ; }/* -* If neither a proper type 1 ID nor a broken type 1 adaptor -* as described above, assume type 1, but let the user know -* that we may have misdetected the type. +* If not a proper type 1 ID, still assume type 1, but let +* the user know that we may have misdetected the type. */ -if (!is_type1_adaptor (adaptor_id) && adaptor_id != hdmi_id[0 ]) +if (!is_type1_adaptor (adaptor_id))DRM_ERROR ("Unexpected DP dual mode adaptor ID %02x\n" , adaptor_id);
@@ -339,10 +348,8 @@ EXPORT_SYMBOL(drm_dp_dual_mode_get_tmds_output);* @enable: enable (as opposed to disable) the TMDS output buffers * * Set the state of the TMDS output buffers in the adaptor. For -* type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As -* some type 1 adaptors have problems with registers (see comments -* in drm_dp_dual_mode_detect()) we avoid touching the register, -* making this function a no-op on type 1 adaptors. +* type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. +* Type1 adaptors do not support any register writes. * * Returns: * 0 on success, negative error code on failure
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 7/162 nvme: add a bogus subsystem NQN quirk for Micron MTFDKBA2T0TFH
In reply to Greg Kroah-HartmanFrom: Leo Savernik <[email protected]>
[ Upstream commit 41f38043f884c66af4114a7109cf540d6222f450 ]
The Micron MTFDKBA2T0TFH device reports the same subsysem NQN for all devices. Add a quick to ignore it.
Stable-dep-of: d5ceb4d1c507 ("nvme-pci: add NVME_QUIRK_BOGUS_NID for Micron Nitro")
--- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/nvme/host/pci.c +2 -0
@@ -3252,6 +3252,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_DEVICE(0x1cc1, 0x8201), /* ADATA SX8200PNP 512GB */ .driver_data =NVME_QUIRK_NO_DEEPEST_PS | NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x1344, 0x5407), /* Micron Technology Inc NVMe SSD */ + .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN }, { PCI_DEVICE(0x1c5c, 0x1504), /* SK Hynix PC400 */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x15b7, 0x2001), /* Sandisk Skyhawk */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 8/162 nvme-pci: add NVME_QUIRK_BOGUS_NID for Micron Nitro
In reply to Greg Kroah-HartmanFrom: Bean Huo <[email protected]>
[ Upstream commit d5ceb4d1c50786d21de3d4b06c3f43109ec56dd8 ]
Added a quirk to fix Micron Nitro NVMe reporting duplicate NGUIDs.
--- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/nvme/host/pci.c +2 -0
@@ -3254,6 +3254,8 @@ static const struct pci_device_id nvme_id_table[] = { NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE(0x1344, 0x5407), /* Micron Technology Inc NVMe SSD */ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN }, + { PCI_DEVICE(0x1344, 0x6001), /* Micron Nitro NVMe */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1c5c, 0x1504), /* SK Hynix PC400 */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x15b7, 0x2001), /* Sandisk Skyhawk */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 9/162 speakup: Generate speakupmap.h automatically
In reply to Greg Kroah-HartmanFrom: Samuel Thibault <[email protected]>
[ Upstream commit 6646b95aab5f62c049f1416a3801dec5432c348b ]
speakupmap.h was not actually intended to be source code, speakupmap.map is.
This resurrects the makemapdata.c and genmap.c tools to generate speakupmap.h automatically from the input and speakup headers, and the speakupmap.map keyboard mapping source file.
Stable-dep-of: 92ca969ff881 ("speakup: replace utils' u_char with unsigned char")
--- drivers/accessibility/speakup/.gitignore | 4 + drivers/accessibility/speakup/Makefile | 28 ++++ drivers/accessibility/speakup/genmap.c | 162 ++++++++++++++++++++ drivers/accessibility/speakup/makemapdata.c | 125 +++++++++++++++ drivers/accessibility/speakup/speakupmap.h | 66 -------- drivers/accessibility/speakup/utils.h | 102 ++++++++++++ 6 files changed, 421 insertions(+), 66 deletions(-) create mode 100644 drivers/accessibility/speakup/.gitignore create mode 100644 drivers/accessibility/speakup/genmap.c create mode 100644 drivers/accessibility/speakup/makemapdata.c delete mode 100644 drivers/accessibility/speakup/speakupmap.h create mode 100644 drivers/accessibility/speakup/utils.h
drivers/accessibility/speakup/.gitignore new file +4 -0
@@ -0,0 +1,4 @@ +/makemapdata +/mapdata.h +/genmap +/speakupmap.h
drivers/accessibility/speakup/Makefile +28 -0
@@ -30,3 +30,31 @@ speakup-y := \ thread.o \ varhandlers.o speakup-$(CONFIG_SPEAKUP_SERIALIO) += serialio.o + + +clean-files := mapdata.h speakupmap.h + + +# Generate mapdata.h from headers +hostprogs += makemapdata +makemapdata-objs := makemapdata.o + +quiet_cmd_mkmap = MKMAP $@ + cmd_mkmap = TOPDIR=$(srctree) $(obj)/makemapdata > $@ + +$(obj)/mapdata.h: $(obj)/makemapdata + $(call cmd,mkmap) + + +# Generate speakupmap.h from mapdata.h +hostprogs += genmap +genmap-objs := genmap.o +$(obj)/genmap.o: $(obj)/mapdata.h + +quiet_cmd_genmap = GENMAP $@ + cmd_genmap = $(obj)/genmap $< > $@ + +$(obj)/speakupmap.h: $(src)/speakupmap.map $(obj)/genmap + $(call cmd,genmap) + +$(obj)/main.o: $(obj)/speakupmap.h
drivers/accessibility/speakup/genmap.c new file +162 -0
162 lines not on this page · raw message
drivers/accessibility/speakup/makemapdata.c new file +125 -0
125 lines not on this page · raw message
drivers/accessibility/speakup/speakupmap.h deleted +0 -66
66 lines not on this page · raw message
drivers/accessibility/speakup/utils.h new file +102 -0
102 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 10/162 speakup: replace utils u_char with unsigned char
In reply to Greg Kroah-HartmanFrom: Đoàn Trần Công Danh <[email protected]>
[ Upstream commit 92ca969ff8815f3feef2645199bd39bf594e5eeb ]
drivers/accessibility/speakup/utils.h will be used to compile host tool to generate metadata.
"u_char" is a non-standard type, which is defined to "unsigned char" on glibc but not defined by some libc, e.g. musl.
Let's replace "u_char" with "unsigned char"
--- drivers/accessibility/speakup/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accessibility/speakup/utils.h +1 -1
@@ -54,7 +54,7 @@ static inline int oops(const char *msg, const char *info)static inline struct st_key *hash_name (char *name) { -u_char *pn = (u_char *)name; +unsigned char *pn = (unsigned char *)name;int hash =0 ;while (*pn) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 11/162 iio: ms5611: Simplify IO callback parameters
In reply to Greg Kroah-HartmanFrom: Lars-Peter Clausen <[email protected]>
[ Upstream commit dc19fa63ad80a636fdbc1a02153d1ab140cb901f ]
The ms5611 passes &indio_dev->dev as a parameter to all its IO callbacks only to directly cast the struct device back to struct iio_dev. And the struct iio_dev is then only used to get the drivers state struct.
Simplify this a bit by passing the state struct directly. This makes it a bit easier to follow what the code is doing.
Stable-dep-of: 17f442e7e475 ("iio: pressure: ms5611: fixed value compensation bug")
--- drivers/iio/pressure/ms5611.h | 6 +++--- drivers/iio/pressure/ms5611_core.c | 7 +++---- drivers/iio/pressure/ms5611_i2c.c | 11 ++++------- drivers/iio/pressure/ms5611_spi.c | 17 +++++++---------- 4 files changed, 17 insertions(+), 24 deletions(-)
drivers/iio/pressure/ms5611.h +3 -3
@@ -50,9 +50,9 @@ struct ms5611_state {const struct ms5611_osr *pressure_osr;const struct ms5611_osr *temp_osr; -int (*reset)(struct device *dev); -int (*read_prom_word)(struct device *dev,int index,u16 *word); -int (*read_adc_temp_and_pressure)(struct device *dev, +int (*reset)(struct ms5611_state *st); +int (*read_prom_word)(struct ms5611_state *st,int index,u16 *word); +int (*read_adc_temp_and_pressure)(struct ms5611_state *st,s32 *temp,s32 *pressure);struct ms5611_chip_info *chip_info;
drivers/iio/pressure/ms5611_core.c +3 -4
@@ -85,8 +85,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)struct ms5611_state *st =iio_priv (indio_dev);for (i =0 ; i <MS5611_PROM_WORDS_NB ; i++) { - ret = st->read_prom_word (&indio_dev->dev, - i, &st->chip_info->prom[i]); + ret = st->read_prom_word (st, i, &st->chip_info->prom[i]);if (ret <0 ) {dev_err (&indio_dev->dev,"failed to read prom at %d\n" , i);
@@ -108,7 +107,7 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,int ret;struct ms5611_state *st =iio_priv (indio_dev); - ret = st->read_adc_temp_and_pressure (&indio_dev->dev, temp, pressure); + ret = st->read_adc_temp_and_pressure (st, temp, pressure);if (ret <0 ) {dev_err (&indio_dev->dev,"failed to read temperature and pressure\n" );
@@ -196,7 +195,7 @@ static int ms5611_reset(struct iio_dev *indio_dev)int ret;struct ms5611_state *st =iio_priv (indio_dev); - ret = st->reset (&indio_dev->dev); + ret = st->reset (st);if (ret <0 ) {dev_err (&indio_dev->dev,"failed to reset device\n" );return ret;
drivers/iio/pressure/ms5611_i2c.c +4 -7
@@ -20,17 +20,15 @@#include "ms5611.h" -static int ms5611_i2c_reset (struct device *dev) +static int ms5611_i2c_reset (struct ms5611_state *st) { -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev)); -return i2c_smbus_write_byte (st->client,MS5611_RESET ); } -static int ms5611_i2c_read_prom_word (struct device *dev,int index,u16 *word) +static int ms5611_i2c_read_prom_word (struct ms5611_state *st,int index, +u16 *word) {int ret; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev)); ret =i2c_smbus_read_word_swapped (st->client,MS5611_READ_PROM_WORD + (index <<1 ));
@@ -57,11 +55,10 @@ static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val)return 0 ; } -static int ms5611_i2c_read_adc_temp_and_pressure (struct device *dev, +static int ms5611_i2c_read_adc_temp_and_pressure (struct ms5611_state *st,s32 *temp,s32 *pressure) {int ret; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev));const struct ms5611_osr *osr = st->temp_osr; ret =i2c_smbus_write_byte (st->client, osr->cmd);
drivers/iio/pressure/ms5611_spi.c +7 -10
@@ -15,18 +15,17 @@#include "ms5611.h" -static int ms5611_spi_reset (struct device *dev) +static int ms5611_spi_reset (struct ms5611_state *st) {u8 cmd =MS5611_RESET ; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev));return spi_write_then_read (st->client, &cmd,1 ,NULL ,0 ); } -static int ms5611_spi_read_prom_word (struct device *dev,int index,u16 *word) +static int ms5611_spi_read_prom_word (struct ms5611_state *st,int index, +u16 *word) {int ret; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev)); ret =spi_w8r16be (st->client,MS5611_READ_PROM_WORD + (index <<1 ));if (ret <0 )
@@ -37,11 +36,10 @@ static int ms5611_spi_read_prom_word(struct device *dev, int index, u16 *word)return 0 ; } -static int ms5611_spi_read_adc (struct device *dev,s32 *val) +static int ms5611_spi_read_adc (struct ms5611_state *st,s32 *val) {int ret;u8 buf[3 ] = {MS5611_READ_ADC }; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev)); ret =spi_write_then_read (st->client, buf,1 , buf,3 );if (ret <0 )
@@ -52,11 +50,10 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val)return 0 ; } -static int ms5611_spi_read_adc_temp_and_pressure (struct device *dev, +static int ms5611_spi_read_adc_temp_and_pressure (struct ms5611_state *st,s32 *temp,s32 *pressure) {int ret; -struct ms5611_state *st =iio_priv (dev_to_iio_dev (dev));const struct ms5611_osr *osr = st->temp_osr;/*
@@ -68,7 +65,7 @@ static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,return ret;usleep_range (osr->conv_usec, osr->conv_usec + (osr->conv_usec /10UL )); - ret =ms5611_spi_read_adc (dev, temp); + ret =ms5611_spi_read_adc (st, temp);if (ret <0 )return ret;
@@ -78,7 +75,7 @@ static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,return ret;usleep_range (osr->conv_usec, osr->conv_usec + (osr->conv_usec /10UL )); -return ms5611_spi_read_adc (dev, pressure); +return ms5611_spi_read_adc (st, pressure); }static int ms5611_spi_probe (struct spi_device *spi)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 12/162 iio: pressure: ms5611: fixed value compensation bug
In reply to Greg Kroah-HartmanFrom: Mitja Spes <[email protected]>
[ Upstream commit 17f442e7e47579d3881fc4d47354eaef09302e6f ]
When using multiple instances of this driver the compensation PROM was overwritten by the last initialized sensor. Now each sensor has own PROM storage.
--- drivers/iio/pressure/ms5611.h | 12 +++---- drivers/iio/pressure/ms5611_core.c | 51 ++++++++++++++++-------------- 2 files changed, 31 insertions(+), 32 deletions(-)
drivers/iio/pressure/ms5611.h +4 -8
@@ -25,13 +25,6 @@ enum { MS5607, }; -struct ms5611_chip_info { -u16 prom[MS5611_PROM_WORDS_NB ]; - -int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info, -s32 *temp,s32 *pressure); -}; -/* * OverSampling Rate descriptor. * Warning: cmd MUST be kept aligned on a word boundary (see
@@ -50,12 +43,15 @@ struct ms5611_state {const struct ms5611_osr *pressure_osr;const struct ms5611_osr *temp_osr; +u16 prom[MS5611_PROM_WORDS_NB ]; +int (*reset)(struct ms5611_state *st);int (*read_prom_word)(struct ms5611_state *st,int index,u16 *word);int (*read_adc_temp_and_pressure)(struct ms5611_state *st,s32 *temp,s32 *pressure); -struct ms5611_chip_info *chip_info; +int (*compensate_temp_and_pressure)(struct ms5611_state *st,s32 *temp, +s32 *pressure);struct regulator *vdd; };
drivers/iio/pressure/ms5611_core.c +27 -24
101 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 13/162 ceph: do not update snapshot context when there is no new snapshot
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 2e586641c950e7f3e7e008404bd783a466b9b590 ]
We will only track the uppest parent snapshot realm from which we need to rebuild the snapshot contexts _downward_ in hierarchy. For all the others having no new snapshot we will do nothing.
This fix will avoid calling ceph_queue_cap_snap() on some inodes inappropriately. For example, with the code in mainline, suppose there are 2 directory hierarchies (with 6 directories total), like this:
/dir_X1/dir_X2/dir_X3/
/dir_Y1/dir_Y2/dir_Y3/
Firstly, make a snapshot under /dir_X1/dir_X2/.snap/snap_X2, then make a root snapshot under /.snap/root_snap. Every time we make snapshots under /dir_Y1/..., the kclient will always try to rebuild the snap context for snap_X2 realm and finally will always try to queue cap snaps for dir_Y2 and dir_Y3, which makes no sense.
That's because the snap_X2's seq is 2 and root_snap's seq is 3. So when creating a new snapshot under /dir_Y1/... the new seq will be 4, and the mds will send the kclient a snapshot backtrace in _downward_
order: seqs 4, 3.
When ceph_update_snap_trace() is called, it will always rebuild the from the last realm, that's the root_snap. So later when rebuilding the snap context, the current logic will always cause it to rebuild the snap_X2 realm and then try to queue cap snaps for all the inodes related in that realm, even though it's not necessary.
This is accompanied by a lot of these sorts of dout messages:
"ceph: queue_cap_snap 00000000a42b796b nothing dirty|writing"
Fix the logic to avoid this situation.
Also, the 'invalidate' word is not precise here. In actuality, it will cause a rebuild of the existing snapshot contexts or just build non-existent ones. Rename it to 'rebuild_snapcs'.
URL: https://tracker.ceph.com/issues/44100
Stable-dep-of: 51884d153f7e ("ceph: avoid putting the realm twice when decoding snaps fails")
--- fs/ceph/snap.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
fs/ceph/snap.c +19 -9
@@ -699,7 +699,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,__le64 *prior_parent_snaps;/* encoded */ struct ceph_snap_realm *realm =NULL ;struct ceph_snap_realm *first_realm =NULL ; -int invalidate =0 ; +struct ceph_snap_realm *realm_to_rebuild =NULL ; +int rebuild_snapcs;int err = -ENOMEM ;LIST_HEAD (dirty_realms);
@@ -707,6 +708,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,dout ("update_snap_trace deletion=%d\n" , deletion); more: + rebuild_snapcs =0 ;ceph_decode_need (&p, e,sizeof (*ri), bad); ri = p; p +=sizeof (*ri);
@@ -730,7 +732,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc, err =adjust_snap_realm_parent (mdsc, realm,le64_to_cpu (ri->parent));if (err <0 ) goto fail; - invalidate += err; + rebuild_snapcs += err;if (le64_to_cpu (ri->seq) > realm->seq) { dout("update_snap_trace updating %llx %p %lld -> %lld\n",
@@ -755,22 +757,30 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,if (realm->seq > mdsc->last_snap_seq) mdsc->last_snap_seq = realm->seq; - invalidate =1 ; + rebuild_snapcs =1 ; }else if (!realm->cached_context) {dout ("update_snap_trace %llx %p seq %lld new\n" , realm->ino, realm, realm->seq); - invalidate =1 ; + rebuild_snapcs =1 ; }else {dout ("update_snap_trace %llx %p seq %lld unchanged\n" , realm->ino, realm, realm->seq); } -dout ("done with %llx %p, invalidated=%d, %p %p\n" , realm->ino, - realm, invalidate, p, e); +dout ("done with %llx %p, rebuild_snapcs=%d, %p %p\n" , realm->ino, + realm, rebuild_snapcs, p, e); -/* invalidate when we reach the _end_ (root) of the trace */ -if (invalidate && p >= e) -rebuild_snap_realms (realm, &dirty_realms); +/* +* this will always track the uppest parent realm from which +* we need to rebuild the snapshot contexts _downward_ in +* hierarchy. +*/ +if (rebuild_snapcs) + realm_to_rebuild = realm; + +/* rebuild_snapcs when we reach the _end_ (root) of the trace */ +if (realm_to_rebuild && p >= e) +rebuild_snap_realms (realm_to_rebuild, &dirty_realms);if (!first_realm) first_realm = realm;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 14/162 ceph: avoid putting the realm twice when decoding snaps fails
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 51884d153f7ec85e18d607b2467820a90e0f4359 ]
When decoding the snaps fails it maybe leaving the 'first_realm' and 'realm' pointing to the same snaprealm memory. And then it'll put it twice and could cause random use-after-free, BUG_ON, etc issues.
--- fs/ceph/snap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ceph/snap.c +2 -1
@@ -697,7 +697,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,struct ceph_mds_snap_realm *ri;/* encoded */ __le64 *snaps;/* encoded */ __le64 *prior_parent_snaps;/* encoded */ -struct ceph_snap_realm *realm =NULL ; +struct ceph_snap_realm *realm;struct ceph_snap_realm *first_realm =NULL ;struct ceph_snap_realm *realm_to_rebuild =NULL ;int rebuild_snapcs;
@@ -708,6 +708,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,dout ("update_snap_trace deletion=%d\n" , deletion); more: + realm =NULL ; rebuild_snapcs =0 ;ceph_decode_need (&p, e,sizeof (*ri), bad); ri = p;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 15/162 wifi: mac80211: fix memory free error when registering wiphy fail
In reply to Greg Kroah-HartmanFrom: taozhang <[email protected]>
[ Upstream commit 50b2e8711462409cd368c41067405aa446dfa2af ]
ieee80211_register_hw free the allocated cipher suites when registering wiphy fail, and ieee80211_free_hw will re-free it.
set wiphy_ciphers_allocated to false after freeing allocated cipher suites.
--- net/mac80211/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/mac80211/main.c +6 -2
@@ -1349,8 +1349,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)ieee80211_led_exit (local);destroy_workqueue (local->workqueue); fail_workqueue: -if (local->wiphy_ciphers_allocated) +if (local->wiphy_ciphers_allocated) {kfree (local->hw.wiphy->cipher_suites); + local->wiphy_ciphers_allocated = false; + }kfree (local->int_scan_req);return result; }
@@ -1420,8 +1422,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)mutex_destroy (&local->iflist_mtx);mutex_destroy (&local->mtx); -if (local->wiphy_ciphers_allocated) +if (local->wiphy_ciphers_allocated) {kfree (local->hw.wiphy->cipher_suites); + local->wiphy_ciphers_allocated = false; + }idr_for_each (&local->ack_status_frames, ieee80211_free_ack_frame,NULL );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 16/162 wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support
In reply to Greg Kroah-HartmanFrom: Jonas Jelonek <[email protected]>
[ Upstream commit 69188df5f6e4cecc6b76b958979ba363cd5240e8 ]
Fixes a warning that occurs when rc table support is enabled (IEEE80211_HW_SUPPORTS_RC_TABLE) in mac80211_hwsim and the PS mode is changed via the exported debugfs attribute.
When the PS mode is changed, a packet is broadcasted via hwsim_send_nullfunc by creating and transmitting a plain skb with only header initialized. The ieee80211 rate array in the control buffer is zero-initialized. When ratetbl support is enabled, ieee80211_get_tx_rates is called for the skb with sta parameter set to NULL and thus no ratetbl can be used. The final rate array then looks like [-1,0; 0,0; 0,0; 0,0] which causes the warning in ieee80211_get_tx_rate.
The issue is fixed by setting the count of the first rate with idx '0' to 1 and hence ieee80211_get_tx_rates won't overwrite it with idx '-1'.
--- drivers/net/wireless/mac80211_hwsim.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/wireless/mac80211_hwsim.c +5 -0
@@ -775,6 +775,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,struct hwsim_vif_priv *vp = (void *)vif->drv_priv;struct sk_buff *skb;struct ieee80211_hdr *hdr; +struct ieee80211_tx_info *cb;if (!vp->assoc)return ;
@@ -796,6 +797,10 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,memcpy (hdr->addr2, mac,ETH_ALEN );memcpy (hdr->addr3, vp->bssid,ETH_ALEN ); + cb =IEEE80211_SKB_CB (skb); + cb->control.rates[0 ].count =1 ; + cb->control.rates[1 ].idx =-1 ; +rcu_read_lock ();mac80211_hwsim_tx_frame (data->hw, skb,rcu_dereference (vif->chanctx_conf)->def.chan);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 17/162 riscv: dts: sifive unleashed: Add PWM controlled LEDs
In reply to Greg Kroah-HartmanFrom: Emil Renner Berthing <[email protected]>
[ Upstream commit 8bc8824d30193eb7755043d5bb65fa7f0d11a595 ]
This adds the 4 PWM controlled green LEDs to the HiFive Unleashed device tree. The schematic doesn't specify any special function for the LEDs, so they're added here without any default triggers and named d1, d2, d3 and d4 just like in the schematic.
--- .../boot/dts/sifive/hifive-unleashed-a00.dts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+)
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts +38 -0
@@ -3,6 +3,8 @@ #include "fu540-c000.dtsi" #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/leds/common.h> +#include <dt-bindings/pwm/pwm.h> /* Clock frequency (in Hz) of the PCB crystal for rtcclk */ #define RTCCLK_FREQ 1000000
@@ -46,6 +48,42 @@ compatible = "gpio-restart"; gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; + + led-controller { + compatible = "pwm-leds"; + + led-d1 { + pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>; + active-low; + color = <LED_COLOR_ID_GREEN>; + max-brightness = <255>; + label = "d1"; + }; + + led-d2 { + pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>; + active-low; + color = <LED_COLOR_ID_GREEN>; + max-brightness = <255>; + label = "d2"; + }; + + led-d3 { + pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>; + active-low; + color = <LED_COLOR_ID_GREEN>; + max-brightness = <255>; + label = "d3"; + }; + + led-d4 { + pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>; + active-low; + color = <LED_COLOR_ID_GREEN>; + max-brightness = <255>; + label = "d4"; + }; + }; }; &uart0 {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 18/162 audit: fix undefined behavior in bit shift for AUDIT_BIT
In reply to Greg Kroah-HartmanFrom: Gaosheng Cui <[email protected]>
[ Upstream commit 986d93f55bdeab1cac858d1e47b41fac10b2d7f6 ]
Shifting signed 32-bit value by 31 bits is undefined, so changing significant bit to unsigned. The UBSAN warning calltrace like below:
UBSAN: shift-out-of-bounds in kernel/auditfilter.c:179:23 left shift of 1 by 31 places cannot be represented in type 'int' Call Trace: <TASK> dump_stack_lvl+0x7d/0xa5 dump_stack+0x15/0x1b ubsan_epilogue+0xe/0x4e __ubsan_handle_shift_out_of_bounds+0x1e7/0x20c audit_register_class+0x9d/0x137 audit_classes_init+0x4d/0xb8 do_one_initcall+0x76/0x430 kernel_init_freeable+0x3b3/0x422 kernel_init+0x24/0x1e0 ret_from_fork+0x1f/0x30 </TASK>
--- include/uapi/linux/audit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/audit.h +1 -1
@@ -182,7 +182,7 @@#define AUDIT_MAX_KEY_LEN 256#define AUDIT_BITMASK_SIZE 64#define AUDIT_WORD (nr) ((__u32)((nr)/32)) -#define AUDIT_BIT (nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) +#define AUDIT_BIT (nr) (1U << ((nr) - AUDIT_WORD(nr)*32))#define AUDIT_SYSCALL_CLASSES 16#define AUDIT_CLASS_DIR_WRITE 0
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 19/162 wifi: airo: do not assign -1 to unsigned char
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
[ Upstream commit e6cb8769452e8236b52134e5cb4a18b8f5986932 ]
With char becoming unsigned by default, and with char alone being ambiguous and based on architecture, we get a warning when assigning the unchecked output of hex_to_bin() to that unsigned char. Mark key as a u8, which matches the struct's type, and then check each call to hex_to_bin() before casting.
--- drivers/net/wireless/cisco/airo.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/net/wireless/cisco/airo.c +14 -4
@@ -5236,7 +5236,7 @@ static int get_wep_tx_idx(struct airo_info *ai)return -1 ; } -static int set_wep_key (struct airo_info *ai,u16 index,const char *key, +static int set_wep_key (struct airo_info *ai,u16 index,const u8 *key,u16 keylen,int perm,int lock) {static const unsigned char macaddr[ETH_ALEN ] = {0x01 ,0 ,0 ,0 ,0 ,0 };
@@ -5287,7 +5287,7 @@ static void proc_wepkey_on_close(struct inode *inode, struct file *file)struct net_device *dev =PDE_DATA (inode);struct airo_info *ai = dev->ml_priv;int i, rc; -char key[16 ]; +u8 key[16 ];u16 index =0 ;int j =0 ;
@@ -5315,12 +5315,22 @@ static void proc_wepkey_on_close(struct inode *inode, struct file *file) }for (i =0 ; i <16 *3 && data->wbuffer[i+j]; i++) { +int val; + +if (i %3 ==2 ) +continue ; + + val =hex_to_bin (data->wbuffer[i+j]); +if (val <0 ) { +airo_print_err (ai->dev->name,"WebKey passed invalid key hex" ); +return ; + }switch (i%3 ) {case 0 : - key[i/3 ] =hex_to_bin (data->wbuffer[i+j])<<4 ; + key[i/3 ] = (u8 )val <<4 ;break ;case 1 : - key[i/3 ] |=hex_to_bin (data->wbuffer[i+j]); + key[i/3 ] |= (u8 )val;break ; } }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 20/162 wifi: mac80211: Fix ack frame idr leak when mesh has no route
In reply to Greg Kroah-HartmanFrom: Nicolas Cavallari <[email protected]>
[ Upstream commit 39e7b5de9853bd92ddbfa4b14165babacd7da0ba ]
When trying to transmit an data frame with tx_status to a destination that have no route in the mesh, then it is dropped without recrediting the ack_status_frames idr.
Once it is exhausted, wpa_supplicant starts failing to do SAE with NL80211_CMD_FRAME and logs "nl80211: Frame command failed".
Use ieee80211_free_txskb() instead of kfree_skb() to fix it.
--- net/mac80211/mesh_pathtbl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/mesh_pathtbl.c +1 -1
@@ -718,7 +718,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath)void mesh_path_discard_frame (struct ieee80211_sub_if_data *sdata,struct sk_buff *skb) { -kfree_skb (skb); +ieee80211_free_txskb (&sdata->local->hw, skb); sdata->u.mesh.mshstats.dropped_frames_no_route++; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 21/162 spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run
In reply to Greg Kroah-HartmanFrom: Sean Nyekjaer <[email protected]>
[ Upstream commit 62aa1a344b0904549f6de7af958e8a1136fd5228 ]
When this driver is used with a driver that uses preallocated spi_transfer structs. The speed_hz is halved by every run. This results in:
spi_stm32 44004000.spi: SPI transfer setup failed
ads7846 spi0.0: SPI transfer failed: -22
Example when running with DIV_ROUND_UP():
- First run; speed_hz = 1000000, spi->clk_rate 125000000
div 125 -> mbrdiv = 7, cur_speed = 976562
- Second run; speed_hz = 976562
div 128,00007 (roundup to 129) -> mbrdiv = 8, cur_speed = 488281
- Third run; speed_hz = 488281
div 256,000131072067109 (roundup to 257) and then -EINVAL is returned.
Use DIV_ROUND_CLOSEST to allow to round down and allow us to keep the set speed.
--- drivers/spi/spi-stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-stm32.c +1 -1
@@ -443,7 +443,7 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,u32 div, mbrdiv;/* Ensure spi->clk_rate is even */ - div =DIV_ROUND_UP (spi->clk_rate & ~0x1 , speed_hz); + div =DIV_ROUND_CLOSEST (spi->clk_rate & ~0x1 , speed_hz);/* * SPI framework set xfer->speed_hz to master->max_speed_hz if
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 22/162 selftests/bpf: Add verifier test for release_reference()
In reply to Greg Kroah-HartmanFrom: Youlin Li <[email protected]>
[ Upstream commit 475244f5e06beeda7b557d9dde46a5f439bf3379 ]
Add a test case to ensure that released pointer registers will not be leaked into the map.
Before fix:
./test_verifier 984
984/u reference tracking: try to leak released ptr reg FAIL Unexpected success to load!
verification time 67 usec
stack depth 4
processed 23 insns (limit 1000000) max_states_per_insn 0 total_states 2 peak_states 2 mark_read 1
984/p reference tracking: try to leak released ptr reg OK
Summary: 1 PASSED, 0 SKIPPED, 1 FAILED
After fix:
./test_verifier 984
984/u reference tracking: try to leak released ptr reg OK 984/p reference tracking: try to leak released ptr reg OK
Summary: 2 PASSED, 0 SKIPPED, 0 FAILED
--- .../selftests/bpf/verifier/ref_tracking.c | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+)
tools/testing/selftests/bpf/verifier/ref_tracking.c +36 -0
@@ -901,3 +901,39 @@ .result_unpriv = REJECT, .errstr_unpriv = "unknown func", }, +{ + "reference tracking: try to leak released ptr reg", + .insns = { +BPF_MOV64_IMM (BPF_REG_0 ,0 ), +BPF_STX_MEM (BPF_W ,BPF_REG_10 ,BPF_REG_0 ,-4 ), +BPF_MOV64_REG (BPF_REG_2 ,BPF_REG_10 ), +BPF_ALU64_IMM (BPF_ADD ,BPF_REG_2 ,-4 ), +BPF_LD_MAP_FD (BPF_REG_1 ,0 ), +BPF_EMIT_CALL (BPF_FUNC_map_lookup_elem), +BPF_JMP_IMM (BPF_JNE ,BPF_REG_0 ,0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_REG (BPF_REG_9 ,BPF_REG_0 ), + +BPF_MOV64_IMM (BPF_REG_0 ,0 ), +BPF_LD_MAP_FD (BPF_REG_1 ,0 ), +BPF_MOV64_IMM (BPF_REG_2 ,8 ), +BPF_MOV64_IMM (BPF_REG_3 ,0 ), +BPF_EMIT_CALL (BPF_FUNC_ringbuf_reserve), +BPF_JMP_IMM (BPF_JNE ,BPF_REG_0 ,0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_REG (BPF_REG_8 ,BPF_REG_0 ), + +BPF_MOV64_REG (BPF_REG_1 ,BPF_REG_8 ), +BPF_MOV64_IMM (BPF_REG_2 ,0 ), +BPF_EMIT_CALL (BPF_FUNC_ringbuf_discard), +BPF_MOV64_IMM (BPF_REG_0 ,0 ), + +BPF_STX_MEM (BPF_DW ,BPF_REG_9 ,BPF_REG_8 ,0 ), +BPF_EXIT_INSN () + }, + .fixup_map_array_48b = { 4 }, + .fixup_map_ringbuf = { 11 }, + .result = ACCEPT, + .result_unpriv = REJECT, + .errstr_unpriv = "R8 !read_ok" +},
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 23/162 Revert "net: macsec: report real_dev features when HW offloading is enabled"
In reply to Greg Kroah-HartmanFrom: Sabrina Dubroca <[email protected]>
[ Upstream commit 8bcd560ae8784da57c610d857118c5d6576b1a8f ]
This reverts commit c850240b6c4132574a00f2da439277ab94265b66.
That commit tried to improve the performance of macsec offload by taking advantage of some of the NIC's features, but in doing so, broke macsec offload when the lower device supports both macsec and ipsec offload, as the ipsec offload feature flags (mainly NETIF_F_HW_ESP) were copied from the real device. Since the macsec device doesn't provide xdo_* ops, the XFRM core rejects the registration of the new macsec device in xfrm_api_check.
Example perf trace when running
ip link add link eni1np1 type macsec port 4 offload mac
ip 737 [003] 795.477676: probe:xfrm_dev_event__REGISTER name="macsec0" features=0x1c000080014869
xfrm_dev_event+0x3a
notifier_call_chain+0x47
register_netdevice+0x846
macsec_newlink+0x25a
ip 737 [003] 795.477687: probe:xfrm_dev_event__return ret=0x8002 (NOTIFY_BAD)
notifier_call_chain+0x47
register_netdevice+0x846
macsec_newlink+0x25adev->features includes NETIF_F_HW_ESP (0x04000000000000), so xfrm_api_check returns NOTIFY_BAD because we don't have dev->xfrmdev_ops on the macsec device.
We could probably propagate GSO and a few other features from the lower device, similar to macvlan. This will be done in a future patch.
--- drivers/net/macsec.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-)
drivers/net/macsec.c +4 -23
@@ -2648,11 +2648,6 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)if (ret) goto rollback; -/* Force features update, since they are different for SW MACSec and -* HW offloading cases. -*/ -netdev_update_features (dev); -rtnl_unlock ();return 0 ;
@@ -3420,16 +3415,9 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,return ret; } -#define SW_MACSEC_FEATURES \ +#define MACSEC_FEATURES \ (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) -/* If h/w offloading is enabled, use real device features save for -* VLAN_FEATURES - they require additional ops -* HW_MACSEC - no reason to report it -*/ -#define REAL_DEV_FEATURES (dev) \ - ((dev)->features & ~(NETIF_F_VLAN_FEATURES | NETIF_F_HW_MACSEC)) -static int macsec_dev_init (struct net_device *dev) {struct macsec_dev *macsec =macsec_priv (dev);
@@ -3446,12 +3434,8 @@ static int macsec_dev_init(struct net_device *dev)return err; } -if (macsec_is_offloaded (macsec)) { - dev->features =REAL_DEV_FEATURES (real_dev); - }else { - dev->features = real_dev->features &SW_MACSEC_FEATURES ; - dev->features |=NETIF_F_LLTX |NETIF_F_GSO_SOFTWARE ; - } + dev->features = real_dev->features &MACSEC_FEATURES ; + dev->features |=NETIF_F_LLTX |NETIF_F_GSO_SOFTWARE ; dev->needed_headroom = real_dev->needed_headroom +MACSEC_NEEDED_HEADROOM ;
@@ -3480,10 +3464,7 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,struct macsec_dev *macsec =macsec_priv (dev);struct net_device *real_dev = macsec->real_dev; -if (macsec_is_offloaded (macsec)) -return REAL_DEV_FEATURES (real_dev); - - features &= (real_dev->features &SW_MACSEC_FEATURES ) | + features &= (real_dev->features &MACSEC_FEATURES ) |NETIF_F_GSO_SOFTWARE |NETIF_F_SOFT_FEATURES ; features |=NETIF_F_LLTX ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 24/162 platform/x86: touchscreen_dmi: Add info for the RCA Cambio W101 v2 2-in-1
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
[ Upstream commit 0df044b34bf33e7e35c32b3bf6747fde6279c162 ]
Add touchscreen info for the RCA Cambio W101 v2 2-in-1.
--- drivers/platform/x86/touchscreen_dmi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
drivers/platform/x86/touchscreen_dmi.c +25 -0
@@ -756,6 +756,22 @@ static const struct ts_dmi_data predia_basic_data = { .properties = predia_basic_props, }; +static const struct property_entry rca_cambio_w101_v2_props[] = { +PROPERTY_ENTRY_U32 ("touchscreen-min-x" ,4 ), +PROPERTY_ENTRY_U32 ("touchscreen-min-y" ,20 ), +PROPERTY_ENTRY_U32 ("touchscreen-size-x" ,1644 ), +PROPERTY_ENTRY_U32 ("touchscreen-size-y" ,874 ), +PROPERTY_ENTRY_BOOL ("touchscreen-swapped-x-y" ), +PROPERTY_ENTRY_STRING ("firmware-name" ,"gsl1680-rca-cambio-w101-v2.fw" ), +PROPERTY_ENTRY_U32 ("silead,max-fingers" ,10 ), + { } +}; + +static const struct ts_dmi_data rca_cambio_w101_v2_data = { + .acpi_name ="MSSL1680:00" , + .properties = rca_cambio_w101_v2_props, +}; +static const struct property_entry rwc_nanote_p8_props[] = {PROPERTY_ENTRY_U32 ("touchscreen-min-y" ,46 ),PROPERTY_ENTRY_U32 ("touchscreen-size-x" ,1728 ),
@@ -1341,6 +1357,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), }, }, + { +/* RCA Cambio W101 v2 */ +/* https://github.com/onitake/gsl-firmware/discussions/193 */ + .driver_data = (void *)&rca_cambio_w101_v2_data, + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"RCA" ), + DMI_MATCH(DMI_PRODUCT_NAME, "W101SA23T1"), + }, + }, {/* RWC NANOTE P8 */ .driver_data = (void *)&rwc_nanote_p8_data,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 25/162 scsi: ibmvfc: Avoid path failures during live migration
In reply to Greg Kroah-HartmanFrom: Brian King <[email protected]>
[ Upstream commit 62fa3ce05d5d73c5eccc40b2db493f55fecfc446 ]
Fix an issue reported when performing a live migration when multipath is configured with a short fast fail timeout of 5 seconds and also to have no_path_retry set to fail. In this scenario, all paths would go into the devloss state while the ibmvfc driver went through discovery to log back in. On a loaded system, the discovery might take longer than 5 seconds, which was resulting in all paths being marked failed, which then resulted in a read only filesystem.
This patch changes the migration code in ibmvfc to avoid deleting rports at all in this scenario, so we avoid losing all paths.
--- drivers/scsi/ibmvscsi/ibmvfc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/scsi/ibmvscsi/ibmvfc.c +11 -3
@@ -635,8 +635,13 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost)memset (vhost->async_crq.msgs,0 ,PAGE_SIZE ); vhost->async_crq.cur =0 ; -list_for_each_entry (tgt, &vhost->targets, queue) -ibmvfc_del_tgt (tgt); +list_for_each_entry (tgt, &vhost->targets, queue) { +if (vhost->client_migrated) + tgt->need_login =1 ; +else +ibmvfc_del_tgt (tgt); + } +scsi_block_requests (vhost->host);ibmvfc_set_host_action (vhost,IBMVFC_HOST_ACTION_INIT ); vhost->job_step = ibmvfc_npiv_login;
@@ -2822,9 +2827,12 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)/* We need to re-setup the interpartition connection */ dev_info (vhost->dev,"Partition migrated, Re-enabling adapter\n" ); vhost->client_migrated =1 ; + +scsi_block_requests (vhost->host);ibmvfc_purge_requests (vhost,DID_REQUEUE ); -ibmvfc_link_down (vhost,IBMVFC_LINK_DOWN ); +ibmvfc_set_host_state (vhost,IBMVFC_LINK_DOWN );ibmvfc_set_host_action (vhost,IBMVFC_HOST_ACTION_REENABLE ); +wake_up (&vhost->work_wait_q); }else if (crq->format ==IBMVFC_PARTNER_FAILED || crq->format ==IBMVFC_PARTNER_DEREGISTER ) {dev_err (vhost->dev,"Host partner adapter deregistered or failed (rc=%d)\n" , crq->format);ibmvfc_purge_requests (vhost,DID_ERROR );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 26/162 scsi: scsi_debug: Make the READ CAPACITY response compliant with ZBC
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
[ Upstream commit ecb8c2580d37dbb641451049376d80c8afaa387f ]
Quoted 1 line
From ZBC-1:
- RC BASIS = 0: The RETURNED LOGICAL BLOCK ADDRESS field indicates the highest LBA of a contiguous range of zones that are not sequential write required zones starting with the first zone.
- RC BASIS = 1: The RETURNED LOGICAL BLOCK ADDRESS field indicates the LBA of the last logical block on the logical unit.
The current scsi_debug READ CAPACITY response does not comply with the above if there are one or more sequential write required zones. SCSI initiators need a way to retrieve the largest valid LBA from SCSI devices. Reporting the largest valid LBA if there are one or more sequential zones requires to set the RC BASIS field in the READ CAPACITY response to one. Hence this patch.
--- drivers/scsi/scsi_debug.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/scsi/scsi_debug.c +7 -0
@@ -1878,6 +1878,13 @@ static int resp_readcap16(struct scsi_cmnd *scp, arr[14 ] |=0x40 ; } +/* +* Since the scsi_debug READ CAPACITY implementation always reports the +* total disk capacity, set RC BASIS = 1 for host-managed ZBC devices. +*/ +if (devip->zmodel ==BLK_ZONED_HM ) + arr[12 ] |=1 <<4 ; + arr[15 ] = sdebug_lowest_aligned &0xff ;if (have_dif_prot) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 27/162 drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
[ Upstream commit 653f2d94fcda200b02bd79cea2e0307b26c1b747 ]
Like the Acer Switch One 10 S1003, for which there already is a quirk, the Acer Switch V 10 (SW5-017) has a 800x1280 portrait screen mounted in the tablet part of a landscape oriented 2-in-1. Add a quirk for this.
--- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/drm_panel_orientation_quirks.c +6 -0
@@ -128,6 +128,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* Acer Switch V 10 (SW5-017) */ + .matches = { +DMI_EXACT_MATCH (DMI_SYS_VENDOR ,"Acer" ), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, }, { /* Anbernic Win600 */ .matches = { DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"),
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 28/162 block, bfq: fix null pointer dereference in bfq_bio_bfqg()
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
[ Upstream commit f02be9002c480cd3ec0fcf184ad27cf531bd6ece ]
Out test found a following problem in kernel 5.10, and the same problem should exist in mainline:
BUG: kernel NULL pointer dereference, address: 0000000000000094 PGD 0 P4D 0 Oops: 0000 [#1] SMP CPU: 7 PID: 155 Comm: kworker/7:1 Not tainted 5.10.0-01932-g19e0ace2ca1d-dirty 4 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-b4 Workqueue: kthrotld blk_throtl_dispatch_work_fn RIP: 0010:bfq_bio_bfqg+0x52/0xc0 Code: 94 00 00 00 00 75 2e 48 8b 40 30 48 83 05 35 06 c8 0b 01 48 85 c0 74 3d 4b RSP: 0018:ffffc90001a1fba0 EFLAGS: 00010002 RAX: ffff888100d60400 RBX: ffff8881132e7000 RCX: 0000000000000000 RDX: 0000000000000017 RSI: ffff888103580a18 RDI: ffff888103580a18 RBP: ffff8881132e7000 R08: 0000000000000000 R09: ffffc90001a1fe10 R10: 0000000000000a20 R11: 0000000000034320 R12: 0000000000000000 R13: ffff888103580a18 R14: ffff888114447000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88881fdc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000094 CR3: 0000000100cdb000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: bfq_bic_update_cgroup+0x3c/0x350 ? ioc_create_icq+0x42/0x270 bfq_init_rq+0xfd/0x1060 bfq_insert_requests+0x20f/0x1cc0 ? ioc_create_icq+0x122/0x270 blk_mq_sched_insert_requests+0x86/0x1d0 blk_mq_flush_plug_list+0x193/0x2a0 blk_flush_plug_list+0x127/0x170 blk_finish_plug+0x31/0x50 blk_throtl_dispatch_work_fn+0x151/0x190 process_one_work+0x27c/0x5f0 worker_thread+0x28b/0x6b0 ? rescuer_thread+0x590/0x590 kthread+0x153/0x1b0 ? kthread_flush_work+0x170/0x170 ret_from_fork+0x1f/0x30 Modules linked in: CR2: 0000000000000094 ---[ end trace e2e59ac014314547 ]--- RIP: 0010:bfq_bio_bfqg+0x52/0xc0 Code: 94 00 00 00 00 75 2e 48 8b 40 30 48 83 05 35 06 c8 0b 01 48 85 c0 74 3d 4b RSP: 0018:ffffc90001a1fba0 EFLAGS: 00010002 RAX: ffff888100d60400 RBX: ffff8881132e7000 RCX: 0000000000000000 RDX: 0000000000000017 RSI: ffff888103580a18 RDI: ffff888103580a18 RBP: ffff8881132e7000 R08: 0000000000000000 R09: ffffc90001a1fe10 R10: 0000000000000a20 R11: 0000000000034320 R12: 0000000000000000 R13: ffff888103580a18 R14: ffff888114447000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88881fdc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000094 CR3: 0000000100cdb000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Root cause is quite complex:
1) use bfq elevator for the test device.
2) create a cgroup CG
3) config blk throtl in CG
blkg_conf_prep
blkg_create
4) create a thread T1 and issue async io in CG:
bio_init
bio_associate_blkg
...
submit_bio
submit_bio_noacct
blk_throtl_bio -> io is throttled
// io submit is done5) switch elevator:
bfq_exit_queue
blkcg_deactivate_policy
list_for_each_entry(blkg, &q->blkg_list, q_node)
blkg->pd[] = NULL
// bfq policy is removed5) thread t1 exist, then remove the cgroup CG:
blkcg_unpin_online
blkcg_destroy_blkgs
blkg_destroy
list_del_init(&blkg->q_node)
// blkg is removed from queue list6) switch elevator back to bfq
bfq_init_queue
bfq_create_group_hierarchy
blkcg_activate_policy
list_for_each_entry_reverse(blkg, &q->blkg_list)
// blkg is removed from list, hence bfq policy is still NULL7) throttled io is dispatched to bfq:
bfq_insert_requests
bfq_init_rq
bfq_bic_update_cgroup
bfq_bio_bfqg
bfqg = blkg_to_bfqg(blkg)
// bfqg is NULL because bfq policy is NULL
The problem is only possible in bfq because only bfq can be deactivated and activated while queue is online, while others can only be deactivated while the device is removed.
Fix the problem in bfq by checking if blkg is online before calling blkg_to_bfqg().
--- block/bfq-cgroup.c | 4 ++++ 1 file changed, 4 insertions(+)
block/bfq-cgroup.c +4 -0
@@ -611,6 +611,10 @@ struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)struct bfq_group *bfqg;while (blkg) { +if (!blkg->online) { + blkg = blkg->parent; +continue ; + } bfqg =blkg_to_bfqg (blkg);if (bfqg->online) {bio_associate_blkg_from_css (bio, &blkg->blkcg->css);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 29/162 arm64/syscall: Include asm/ptrace.h in syscall_wrapper header.
In reply to Greg Kroah-HartmanFrom: Kuniyuki Iwashima <[email protected]>
[ Upstream commit acfc35cfcee5df419391671ef1a631f43feee4e3 ]
Add the same change for ARM64 as done in the commit 9440c4294160 ("x86/syscall: Include asm/ptrace.h in syscall_wrapper header") to make sure all syscalls see 'struct pt_regs' definition and resulted BTF for '__arm64_sys_*(struct pt_regs *regs)' functions point to actual struct.
Without this patch, the BPF verifier refuses to load a tracing prog which accesses pt_regs.
bpf(BPF_PROG_LOAD, {prog_type=0x1a, ...}, 128) = -1 EACCES
With this patch, we can see the correct error, which saves us time in debugging the prog.
bpf(BPF_PROG_LOAD, {prog_type=0x1a, ...}, 128) = 4 bpf(BPF_RAW_TRACEPOINT_OPEN, {raw_tracepoint={name=NULL, prog_fd=4}}, 128) = -1 ENOTSUPP
--- arch/arm64/include/asm/syscall_wrapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/syscall_wrapper.h +1 -1
@@ -8,7 +8,7 @@#ifndef __ASM_SYSCALL_WRAPPER_H#define __ASM_SYSCALL_WRAPPER_H -struct pt_regs ; +#include <asm/ptrace.h> #define SC_ARM64_REGS_TO_ARGS (x, ...) \ __MAP(x,__SC_ARGS \
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 30/162 RISC-V: vdso: Do not add missing symbols to version section in linker script
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit fcae44fd36d052e956e69a64642fc03820968d78 ]
Recently, ld.lld moved from '--undefined-version' to '--no-undefined-version' as the default, which breaks the compat vDSO build:
ld.lld: error: version script assignment of 'LINUX_4.15' to symbol '__vdso_gettimeofday' failed: symbol not defined ld.lld: error: version script assignment of 'LINUX_4.15' to symbol '__vdso_clock_gettime' failed: symbol not defined ld.lld: error: version script assignment of 'LINUX_4.15' to symbol '__vdso_clock_getres' failed: symbol not defined
These symbols are not present in the compat vDSO or the regular vDSO for 32-bit but they are unconditionally included in the version section of the linker script, which is prohibited with '--no-undefined-version'.
Fix this issue by only including the symbols that are actually exported in the version section of the linker script.
--- arch/riscv/kernel/vdso/Makefile | 3 +++ arch/riscv/kernel/vdso/vdso.lds.S | 2 ++ 2 files changed, 5 insertions(+)
arch/riscv/kernel/vdso/Makefile +3 -0
@@ -28,6 +28,9 @@ obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) obj-y += vdso.o vdso-syms.o CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +ifneq ($(filter vgettimeofday, $(vdso-syms)),) +CPPFLAGS_vdso.lds += -DHAS_VGETTIMEOFDAY +endif # Disable -pg to prevent insert call site CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE)
arch/riscv/kernel/vdso/vdso.lds.S +2 -0
@@ -64,9 +64,11 @@ VERSION LINUX_4.15 { global: __vdso_rt_sigreturn; +#ifdef HAS_VGETTIMEOFDAY __vdso_gettimeofday; __vdso_clock_gettime; __vdso_clock_getres; +#endif __vdso_getcpu; __vdso_flush_icache; local: *;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 31/162 MIPS: pic32: treat port as signed integer
In reply to Greg Kroah-HartmanFrom: Jason A. Donenfeld <[email protected]>
[ Upstream commit 648060902aa302331b5d6e4f26d8ee0761d239ab ]
get_port_from_cmdline() returns an int, yet is assigned to a char, which is wrong in its own right, but also, with char becoming unsigned, this poses problems, because -1 is used as an error value. Further complicating things, fw_init_early_console() is only ever called with a -1 argument. Fix this up by removing the unused argument from fw_init_early_console() and treating port as a proper signed integer.
--- arch/mips/include/asm/fw/fw.h | 2 +- arch/mips/pic32/pic32mzda/early_console.c | 13 ++++++------- arch/mips/pic32/pic32mzda/init.c | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-)
arch/mips/include/asm/fw/fw.h +1 -1
@@ -26,6 +26,6 @@ extern char *fw_getcmdline(void);extern void fw_meminit (void );extern char *fw_getenv (char *name);extern unsigned long fw_getenvl (char *name); -extern void fw_init_early_console (char port); +extern void fw_init_early_console (void );#endif /* __ASM_FW_H_ */
arch/mips/pic32/pic32mzda/early_console.c +6 -7
@@ -27,7 +27,7 @@#define U_BRG (x) (UART_BASE(x) + 0x40)static void __iomem *uart_base; -static char console_port =-1 ; +static int console_port =-1 ;static int __init configure_uart_pins (int port) {
@@ -47,7 +47,7 @@ static int __init configure_uart_pins(int port)return 0 ; } -static void __init configure_uart (char port,int baud) +static void __init configure_uart (int port,int baud) {u32 pbclk;
@@ -60,7 +60,7 @@ static void __init configure_uart(char port, int baud) uart_base + PIC32_SET(U_STA(port))); } -static void __init setup_early_console (char port,int baud) +static void __init setup_early_console (int port,int baud) {if (configure_uart_pins (port))return ;
@@ -130,16 +130,15 @@ static int __init get_baud_from_cmdline(char *arch_cmdline)return baud; } -void __init fw_init_early_console (char port) +void __init fw_init_early_console (void ) {char *arch_cmdline =pic32_getcmdline (); -int baud =-1 ; +int baud, port; uart_base =ioremap (PIC32_BASE_UART ,0xc00 ); baud =get_baud_from_cmdline (arch_cmdline); -if (port ==-1 ) - port =get_port_from_cmdline (arch_cmdline); + port =get_port_from_cmdline (arch_cmdline);if (port ==-1 ) port =EARLY_CONSOLE_PORT ;
arch/mips/pic32/pic32mzda/init.c +1 -1
@@ -60,7 +60,7 @@ void __init plat_mem_setup(void)strlcpy (arcs_cmdline, boot_command_line,COMMAND_LINE_SIZE );#ifdef CONFIG_EARLY_PRINTK -fw_init_early_console (-1 ); +fw_init_early_console ();#endif pic32_config_init (); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 32/162 xfrm: fix "disable_policy" on ipv4 early demux
In reply to Greg Kroah-HartmanFrom: Eyal Birger <[email protected]>
[ Upstream commit 3a5913183aa1b14148c723bda030e6102ad73008 ]
The commit in the "Fixes" tag tried to avoid a case where policy check is ignored due to dst caching in next hops.
However, when the traffic is locally consumed, the dst may be cached in a local TCP or UDP socket as part of early demux. In this case the "disable_policy" flag is not checked as ip_route_input_noref() was only called before caching, and thus, packets after the initial packet in a flow will be dropped if not matching policies.
Fix by checking the "disable_policy" flag also when a valid dst is already available.
----
v2: use dev instead of skb->dev
--- net/ipv4/ip_input.c | 5 +++++ 1 file changed, 5 insertions(+)
net/ipv4/ip_input.c +5 -0
@@ -361,6 +361,11 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk, iph->tos, dev);if (unlikely (err)) goto drop_error; + }else { +struct in_device *in_dev =__in_dev_get_rcu (dev); + +if (in_dev &&IN_DEV_ORCONF (in_dev,NOPOLICY )) +IPCB (skb)->flags |=IPSKB_NOPOLICY ; }#ifdef CONFIG_IP_ROUTE_CLASSID
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 33/162 xfrm: replay: Fix ESN wrap around for GSO
In reply to Greg Kroah-HartmanFrom: Christian Langrock <[email protected]>
[ Upstream commit 4b549ccce941798703f159b227aa28c716aa78fa ]
When using GSO it can happen that the wrong seq_hi is used for the last packets before the wrap around. This can lead to double usage of a sequence number. To avoid this, we should serialize this last GSO packet.
--- net/ipv4/esp4_offload.c | 3 +++ net/ipv6/esp6_offload.c | 3 +++ net/xfrm/xfrm_device.c | 15 ++++++++++++++- net/xfrm/xfrm_replay.c | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-)
net/ipv4/esp4_offload.c +3 -0
@@ -312,6 +312,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_ xo->seq.low +=skb_shinfo (skb)->gso_segs; } +if (xo->seq.low < seq) + xo->seq.hi++; + esp.seqno =cpu_to_be64 (seq + ((u64 )xo->seq.hi <<32 ));ip_hdr (skb)->tot_len =htons (skb->len);
net/ipv6/esp6_offload.c +3 -0
@@ -343,6 +343,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features xo->seq.low +=skb_shinfo (skb)->gso_segs; } +if (xo->seq.low < seq) + xo->seq.hi++; + esp.seqno =cpu_to_be64 (xo->seq.low + ((u64 )xo->seq.hi <<32 )); len = skb->len -sizeof (struct ipv6hdr );
net/xfrm/xfrm_device.c +14 -1
@@ -97,6 +97,18 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb) } } +static inline bool xmit_xfrm_check_overflow (struct sk_buff *skb) +{ +struct xfrm_offload *xo =xfrm_offload (skb); +__u32 seq = xo->seq.low; + + seq +=skb_shinfo (skb)->gso_segs; +if (unlikely (seq < xo->seq.low)) +return true; + +return false; +} +struct sk_buff *validate_xmit_xfrm (struct sk_buff *skb,netdev_features_t features,bool *again) {int err;
@@ -134,7 +146,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featurreturn skb; } -if (skb_is_gso (skb) &&unlikely (x->xso.dev != dev)) { +if (skb_is_gso (skb) && (unlikely (x->xso.dev != dev) || +unlikely (xmit_xfrm_check_overflow (skb)))) {struct sk_buff *segs;/* Packet got rerouted, fixup features and segment it. */
net/xfrm/xfrm_replay.c +1 -1
@@ -657,7 +657,7 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff oseq +=skb_shinfo (skb)->gso_segs; } -if (unlikely (oseq < replay_esn->oseq)) { +if (unlikely (xo->seq.low < replay_esn->oseq)) {XFRM_SKB_CB (skb)->seq.output.hi = ++oseq_hi; xo->seq.hi = oseq_hi; replay_esn->oseq_hi = oseq_hi;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 34/162 af_key: Fix send_acquire race with pfkey_register
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
[ Upstream commit 7f57f8165cb6d2c206e2b9ada53b9e2d6d8af42f ]
The function pfkey_send_acquire may race with pfkey_register (which could even be in a different name space). This may result in a buffer overrun.
Allocating the maximum amount of memory that could be used prevents this.
--- net/key/af_key.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-)
net/key/af_key.c +22 -10
@@ -2909,7 +2909,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t)break ;if (!aalg->pfkey_supported)continue ; -if (aalg_tmpl_set (t, aalg) && aalg->available) +if (aalg_tmpl_set (t, aalg)) sz +=sizeof (struct sadb_comb ); }return sz +sizeof (struct sadb_prop );
@@ -2927,7 +2927,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)if (!ealg->pfkey_supported)continue ; -if (!(ealg_tmpl_set (t, ealg) && ealg->available)) +if (!(ealg_tmpl_set (t, ealg)))continue ;for (k =1 ; ; k++) {
@@ -2938,16 +2938,17 @@ static int count_esp_combs(const struct xfrm_tmpl *t)if (!aalg->pfkey_supported)continue ; -if (aalg_tmpl_set (t, aalg) && aalg->available) +if (aalg_tmpl_set (t, aalg)) sz +=sizeof (struct sadb_comb ); } }return sz +sizeof (struct sadb_prop ); } -static void dump_ah_combs (struct sk_buff *skb,const struct xfrm_tmpl *t) +static int dump_ah_combs (struct sk_buff *skb,const struct xfrm_tmpl *t) {struct sadb_prop *p; +int sz =0 ;int i; p =skb_put (skb,sizeof (struct sadb_prop ));
@@ -2975,13 +2976,17 @@ static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) c->sadb_comb_soft_addtime =20 *60 *60 ; c->sadb_comb_hard_usetime =8 *60 *60 ; c->sadb_comb_soft_usetime =7 *60 *60 ; + sz +=sizeof (*c); } } + +return sz +sizeof (*p); } -static void dump_esp_combs (struct sk_buff *skb,const struct xfrm_tmpl *t) +static int dump_esp_combs (struct sk_buff *skb,const struct xfrm_tmpl *t) {struct sadb_prop *p; +int sz =0 ;int i, k; p =skb_put (skb,sizeof (struct sadb_prop ));
@@ -3023,8 +3028,11 @@ static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) c->sadb_comb_soft_addtime =20 *60 *60 ; c->sadb_comb_hard_usetime =8 *60 *60 ; c->sadb_comb_soft_usetime =7 *60 *60 ; + sz +=sizeof (*c); } } + +return sz +sizeof (*p); }static int key_notify_policy_expire (struct xfrm_policy *xp,const struct km_event *c)
@@ -3154,6 +3162,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, structstruct sadb_x_sec_ctx *sec_ctx;struct xfrm_sec_ctx *xfrm_ctx;int ctx_size =0 ; +int alg_size =0 ; sockaddr_size =pfkey_sockaddr_size (x->props.family);if (!sockaddr_size)
@@ -3165,16 +3174,16 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, structsizeof (struct sadb_x_policy );if (x->id.proto ==IPPROTO_AH ) - size +=count_ah_combs (t); + alg_size =count_ah_combs (t);else if (x->id.proto ==IPPROTO_ESP ) - size +=count_esp_combs (t); + alg_size =count_esp_combs (t);if ((xfrm_ctx = x->security)) { ctx_size =PFKEY_ALIGN8 (xfrm_ctx->ctx_len); size +=sizeof (struct sadb_x_sec_ctx ) + ctx_size; } - skb =alloc_skb (size +16 ,GFP_ATOMIC ); + skb =alloc_skb (size + alg_size +16 ,GFP_ATOMIC );if (skb ==NULL )return -ENOMEM ;
@@ -3228,10 +3237,13 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct pol->sadb_x_policy_priority = xp->priority;/* Set sadb_comb's. */ + alg_size =0 ;if (x->id.proto ==IPPROTO_AH ) -dump_ah_combs (skb, t); + alg_size =dump_ah_combs (skb, t);else if (x->id.proto ==IPPROTO_ESP ) -dump_esp_combs (skb, t); + alg_size =dump_esp_combs (skb, t); + + hdr->sadb_msg_len += alg_size /8 ;/* security context */ if (xfrm_ctx) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 35/162 ARM: dts: am335x-pcm-953: Define fixed regulators in root node
In reply to Greg Kroah-HartmanFrom: Dominik Haller <[email protected]>
[ Upstream commit 8950f345a67d8046d2472dd6ea81fa18ef5b4844 ]
Remove the regulators node and define fixed regulators in the root node. Prevents the sdhci-omap driver from waiting in probe deferral forever because of the missing vmmc-supply and keeps am335x-pcm-953 consistent with the other Phytec AM335 boards.
Message-Id: <[email protected]>
--- arch/arm/boot/dts/am335x-pcm-953.dtsi | 28 +++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-)
arch/arm/boot/dts/am335x-pcm-953.dtsi +13 -15
@@ -12,22 +12,20 @@ / { compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx"; /* Power */ - regulators { - vcc3v3: fixedregulator@1 { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - }; + vcc3v3: fixedregulator1 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; - vcc1v8: fixedregulator@2 { - compatible = "regulator-fixed"; - regulator-name = "vcc1v8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - }; + vcc1v8: fixedregulator2 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; }; /* User IO */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 36/162 ASoC: hdac_hda: fix hda pcm buffer overflow issue
In reply to Greg Kroah-HartmanFrom: Junxiao Chang <[email protected]>
[ Upstream commit 37882100cd0629d830db430a8cee0b724fe1fea3 ]
When KASAN is enabled, below log might be dumped with Intel EHL hardware:
[ 48.583597] ================================================================== [ 48.585921] BUG: KASAN: slab-out-of-bounds in hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] [ 48.587995] Write of size 4 at addr ffff888103489708 by task pulseaudio/759
[ 48.589237] CPU: 2 PID: 759 Comm: pulseaudio Tainted: G U E 5.15.71-intel-ese-standard-lts #9 [ 48.591272] Hardware name: Intel Corporation Elkhart Lake Embedded Platform/ElkhartLake LPDDR4x T3 CRB, BIOS EHLSFWI1.R00.4251.A01.2206130432 06/13/2022 [ 48.593010] Call Trace: [ 48.593648] <TASK> [ 48.593852] dump_stack_lvl+0x34/0x48 [ 48.594404] print_address_description.constprop.0+0x1f/0x140 [ 48.595174] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] [ 48.595868] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] [ 48.596519] kasan_report.cold+0x7f/0x11b [ 48.597003] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] [ 48.597885] hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda]
HDAC_LAST_DAI_ID is last index id, pcm buffer array size should be +1 to avoid out of bound access.
--- sound/soc/codecs/hdac_hda.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/codecs/hdac_hda.h +2 -2
@@ -14,7 +14,7 @@ enum {HDAC_HDMI_1_DAI_ID ,HDAC_HDMI_2_DAI_ID ,HDAC_HDMI_3_DAI_ID , - HDAC_LAST_DAI_ID = HDAC_HDMI_3_DAI_ID, +HDAC_DAI_ID_NUM }; struct hdac_hda_pcm {
@@ -24,7 +24,7 @@ struct hdac_hda_pcm {struct hdac_hda_priv {struct hda_codec codec; -struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID ]; +struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM ];bool need_display_power; };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 37/162 ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove
In reply to Greg Kroah-HartmanFrom: Detlev Casanova <[email protected]>
[ Upstream commit 0bb8e9b36b5b7f2e77892981ff6c27ee831d8026 ]
Since commit bf2aebccddef ("ASoC: sgtl5000: Fix noise on shutdown/remove"), the device power control registers are reset when the driver is removed/shutdown.
This is an issue when the device is configured to use the PLL clock. The device will stop responding if it is still configured to use the PLL clock but the PLL clock is powered down.
When rebooting linux, the probe function will show:
sgtl5000 0-000a: Error reading chip id -11
Make sure that the CHIP_CLK_CTRL is reset to its default value before powering down the device.
--- sound/soc/codecs/sgtl5000.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/codecs/sgtl5000.c +1 -0
@@ -1797,6 +1797,7 @@ static int sgtl5000_i2c_remove(struct i2c_client *client) {struct sgtl5000_priv *sgtl5000 =i2c_get_clientdata (client); +regmap_write (sgtl5000->regmap,SGTL5000_CHIP_CLK_CTRL ,SGTL5000_CHIP_CLK_CTRL_DEFAULT );regmap_write (sgtl5000->regmap,SGTL5000_CHIP_DIG_POWER ,SGTL5000_DIG_POWER_DEFAULT );regmap_write (sgtl5000->regmap,SGTL5000_CHIP_ANA_POWER ,SGTL5000_ANA_POWER_DEFAULT );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 38/162 ASoC: soc-pcm: Dont zero TDM masks in __soc_pcm_open()
In reply to Greg Kroah-HartmanFrom: Richard Fitzgerald <[email protected]>
[ Upstream commit 39bd801d6908900e9ab0cdc2655150f95ddd4f1a ]
The DAI tx_mask and rx_mask are set by snd_soc_dai_set_tdm_slot() and used by later code that depends on the TDM settings. So __soc_pcm_open() should not be obliterating those mask values.
The code in __soc_pcm_hw_params() uses these masks to calculate the active channels so that only the AIF_IN/AIF_OUT widgets for the active TDM slots are enabled. The zeroing of the masks in __soc_pcm_open() disables this functionality so all AIF widgets were enabled even for channels that are not assigned to a TDM slot.
--- sound/soc/soc-pcm.c | 5 ----- 1 file changed, 5 deletions(-)
sound/soc/soc-pcm.c +0 -5
@@ -723,11 +723,6 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ret =snd_soc_dai_startup (dai, substream);if (ret <0 ) goto err; - -if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) - dai->tx_mask =0 ; -else - dai->rx_mask =0 ; }/* Dynamic PCM DAI links compat checks use dynamic capabilities */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 39/162 scsi: storvsc: Fix handling of srb_status and capacity change events
In reply to Greg Kroah-HartmanFrom: Michael Kelley <[email protected]>
[ Upstream commit b8a5376c321b4669f7ffabc708fd30c3970f3084 ]
Current handling of the srb_status is incorrect. Commit 52e1b3b3daa9 ("scsi: storvsc: Correctly handle multiple flags in srb_status") is based on srb_status being a set of flags, when in fact only the 2 high order bits are flags and the remaining 6 bits are an integer status. Because the integer values of interest mostly look like flags, the code actually works when treated that way.
But in the interest of correctness going forward, fix this by treating the low 6 bits of srb_status as an integer status code. Add handling for SRB_STATUS_INVALID_REQUEST, which was the original intent of commit 52e1b3b3daa9. Furthermore, treat the ERROR, ABORTED, and INVALID_REQUEST srb status codes as essentially equivalent for the cases we care about. There's no harm in doing so, and it isn't always clear which status code current or older versions of Hyper-V report for particular conditions.
Treating the srb status codes as equivalent has the additional benefit of ensuring that capacity change events result in an immediate rescan so that the new size is known to Linux. Existing code checks SCSI sense data for capacity change events when the srb status is ABORTED. But capacity change events are also being observed when Hyper-V reports the srb status as ERROR. Without the immediate rescan, the new size isn't known until something else causes a rescan (such as running fdisk to expand a partition), and in the meantime, tools such as "lsblk" continue to report the old size.
--- drivers/scsi/storvsc_drv.c | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-)
drivers/scsi/storvsc_drv.c +34 -35
@@ -356,16 +356,21 @@ enum storvsc_request_type { };/* -* SRB status codes and masks; a subset of the codes used here. +* SRB status codes and masks. In the 8-bit field, the two high order bits +* are flags, while the remaining 6 bits are an integer status code. The +* definitions here include only the subset of the integer status codes that +* are tested for in this driver. */ -#define SRB_STATUS_AUTOSENSE_VALID 0x80#define SRB_STATUS_QUEUE_FROZEN 0x40 -#define SRB_STATUS_INVALID_LUN 0x20 -#define SRB_STATUS_SUCCESS 0x01 -#define SRB_STATUS_ABORTED 0x02 -#define SRB_STATUS_ERROR 0x04 -#define SRB_STATUS_DATA_OVERRUN 0x12 + +/* SRB status integer codes */ +#define SRB_STATUS_SUCCESS 0x01 +#define SRB_STATUS_ABORTED 0x02 +#define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS_INVALID_REQUEST 0x06 +#define SRB_STATUS_DATA_OVERRUN 0x12 +#define SRB_STATUS_INVALID_LUN 0x20#define SRB_STATUS (status) \ (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -995,38 +1000,25 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,void (*process_err_fn)(struct work_struct *work);struct hv_host_device *host_dev =shost_priv (host); -/* -* In some situations, Hyper-V sets multiple bits in the -* srb_status, such as ABORTED and ERROR. So process them -* individually, with the most specific bits first. -*/ - -if (vm_srb->srb_status &SRB_STATUS_INVALID_LUN ) { -set_host_byte (scmnd,DID_NO_CONNECT ); - process_err_fn = storvsc_remove_lun; - goto do_work; - } +switch (SRB_STATUS (vm_srb->srb_status)) { +case SRB_STATUS_ERROR : +case SRB_STATUS_ABORTED : +case SRB_STATUS_INVALID_REQUEST : +if (vm_srb->srb_status &SRB_STATUS_AUTOSENSE_VALID ) { +/* Check for capacity change */ +if ((asc ==0x2a ) && (ascq ==0x9 )) { + process_err_fn = storvsc_device_scan; +/* Retry the I/O that triggered this. */ +set_host_byte (scmnd,DID_REQUEUE ); + goto do_work; + } -if (vm_srb->srb_status &SRB_STATUS_ABORTED ) { -if (vm_srb->srb_status &SRB_STATUS_AUTOSENSE_VALID && -/* Capacity data has changed */ - (asc ==0x2a ) && (ascq ==0x9 )) { - process_err_fn = storvsc_device_scan;/* -* Retry the I/O that triggered this. +* Otherwise, let upper layer deal with the +* error when sense message is present */ -set_host_byte (scmnd,DID_REQUEUE ); - goto do_work; - } - } - -if (vm_srb->srb_status &SRB_STATUS_ERROR ) { -/* -* Let upper layer deal with error when -* sense message is present. -*/ -if (vm_srb->srb_status &SRB_STATUS_AUTOSENSE_VALID )return ; + }/* * If there is an error; offline the device since all
@@ -1049,6 +1041,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,default :set_host_byte (scmnd,DID_ERROR ); } +return ; + +case SRB_STATUS_INVALID_LUN : +set_host_byte (scmnd,DID_NO_CONNECT ); + process_err_fn = storvsc_remove_lun; + goto do_work; + }return ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 40/162 regulator: core: fix kobject release warning and memory leak in regulator_register()
In reply to Greg Kroah-HartmanFrom: Zeng Heng <[email protected]>
[ Upstream commit 5f4b204b6b8153923d5be8002c5f7082985d153f ]
Here is a warning report about lack of registered release() from kobject lib:
Device '(null)' does not have a release() function, it is broken and must be fixed.
WARNING: CPU: 0 PID: 48430 at drivers/base/core.c:2332 device_release+0x104/0x120 Call Trace: kobject_put+0xdc/0x180 put_device+0x1b/0x30 regulator_register+0x651/0x1170 devm_regulator_register+0x4f/0xb0
When regulator_register() returns fail and directly goto clean symbol, rdev->dev has not registered release() function yet (which is registered by regulator_class in the following), so rdev needs to be freed manually. If rdev->dev.of_node is not NULL, which means the of_node has gotten by regulator_of_get_init_data(), it needs to call of_node_put() to avoid refcount leak.
Otherwise, only calling put_device() would lead memory leak of rdev in further:
unreferenced object 0xffff88810d0b1000 (size 2048):
comm "107-i2c-rtq6752", pid 48430, jiffies 4342258431 (age 1341.780s) backtrace:
kmalloc_trace+0x22/0x110
regulator_register+0x184/0x1170
devm_regulator_register+0x4f/0xb0When regulator_register() returns fail and goto wash symbol, rdev->dev has registered release() function, so directly call put_device() to cleanup everything.
--- drivers/regulator/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/regulator/core.c +5 -1
@@ -5401,11 +5401,15 @@ regulator_register(const struct regulator_desc *regulator_desc,mutex_lock (®ulator_list_mutex);regulator_ena_gpio_free (rdev);mutex_unlock (®ulator_list_mutex); +put_device (&rdev->dev); + rdev =NULL ; clean:if (dangling_of_gpiod)gpiod_put (config->ena_gpiod); +if (rdev && rdev->dev.of_node) +of_node_put (rdev->dev.of_node); +kfree (rdev);kfree (config); -put_device (&rdev->dev); rinse:if (dangling_cfg_gpiod)gpiod_put (cfg->ena_gpiod);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 41/162 spi: dw-dma: decrease reference count in dw_spi_dma_init_mfld()
In reply to Greg Kroah-HartmanFrom: Xiongfeng Wang <[email protected]>
[ Upstream commit 804313b64e412a81b0b3389a10e7622452004aa6 ]
pci_get_device() will increase the reference count for the returned pci_dev. Since 'dma_dev' is only used to filter the channel in dw_spi_dma_chan_filer() after using it we need to call pci_dev_put() to decrease the reference count. Also add pci_dev_put() for the error case.
--- drivers/spi/spi-dw-dma.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/spi/spi-dw-dma.c +3 -0
@@ -127,12 +127,15 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)dw_spi_dma_sg_burst_init (dws); +pci_dev_put (dma_dev); +return 0 ; free_rxchan:dma_release_channel (dws->rxchan); dws->rxchan =NULL ; err_exit: +pci_dev_put (dma_dev);return -EBUSY ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 42/162 regulator: core: fix UAF in destroy_regulator()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit 1f386d6894d0f1b7de8ef640c41622ddd698e7ab ]
I got a UAF report as following:
==================================================================
BUG: KASAN: use-after-free in __lock_acquire+0x935/0x2060 Read of size 8 at addr ffff88810e838220 by task python3/268 Call Trace: <TASK> dump_stack_lvl+0x67/0x83 print_report+0x178/0x4b0 kasan_report+0x90/0x190 __lock_acquire+0x935/0x2060 lock_acquire+0x156/0x400 _raw_spin_lock+0x2a/0x40 lockref_get+0x11/0x30 simple_recursive_removal+0x41/0x440 debugfs_remove.part.12+0x32/0x50 debugfs_remove+0x29/0x30 _regulator_put.cold.54+0x3e/0x27f regulator_put+0x1f/0x30 release_nodes+0x6a/0xa0 devres_release_all+0xf8/0x150 Allocated by task 37: kasan_save_stack+0x1c/0x40 kasan_set_track+0x21/0x30 __kasan_slab_alloc+0x5d/0x70 slab_post_alloc_hook+0x62/0x510 kmem_cache_alloc_lru+0x222/0x5a0 __d_alloc+0x31/0x440 d_alloc+0x30/0xf0 d_alloc_parallel+0xc4/0xd20 __lookup_slow+0x15e/0x2f0 lookup_one_len+0x13a/0x150 start_creating+0xea/0x190 debugfs_create_dir+0x1e/0x210 create_regulator+0x254/0x4e0 _regulator_get+0x2a1/0x467 _devm_regulator_get+0x5a/0xb0 regulator_virtual_probe+0xb9/0x1a0 Freed by task 30: kasan_save_stack+0x1c/0x40 kasan_set_track+0x21/0x30 kasan_save_free_info+0x2a/0x50 __kasan_slab_free+0x102/0x190 kmem_cache_free+0xf6/0x600 rcu_core+0x54c/0x12b0 __do_softirq+0xf2/0x5e3 Last potentially related work creation: kasan_save_stack+0x1c/0x40 __kasan_record_aux_stack+0x98/0xb0 call_rcu+0x42/0x700 dentry_free+0x6c/0xd0 __dentry_kill+0x23b/0x2d0 dput.part.31+0x431/0x780 simple_recursive_removal+0xa9/0x440 debugfs_remove.part.12+0x32/0x50 debugfs_remove+0x29/0x30 regulator_unregister+0xe3/0x230 release_nodes+0x6a/0xa0
==================================================================
Here is how happened:
processor A processor Bregulator_register()
rdev_init_debugfs()
rdev->debugfs = debugfs_create_dir() devm_regulator_get() rdev = regulator_dev_lookup() create_regulator(rdev) // using rdev->debugfs as parent debugfs_create_dir(rdev->debugfs)
mfd_remove_devices_fn()
release_nodes()
regulator_unregister()
// free rdev->debugfs
debugfs_remove_recursive(rdev->debugfs)
release_nodes()
destroy_regulator()
debugfs_remove_recursive() <- causes UAFIn devm_regulator_get(), after getting rdev, the refcount is get, so fix this by moving debugfs_remove_recursive() to regulator_dev_release(), then it can be proctected by the refcount, the 'rdev->debugfs' can not be freed until the refcount is 0.
--- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/regulator/core.c +1 -1
@@ -4928,6 +4928,7 @@ static void regulator_dev_release(struct device *dev) {struct regulator_dev *rdev =dev_get_drvdata (dev); +debugfs_remove_recursive (rdev->debugfs);kfree (rdev->constraints);of_node_put (rdev->dev.of_node);kfree (rdev);
@@ -5438,7 +5439,6 @@ void regulator_unregister(struct regulator_dev *rdev)mutex_lock (®ulator_list_mutex); -debugfs_remove_recursive (rdev->debugfs);WARN_ON (rdev->open_count);regulator_remove_coupling (rdev);unset_regulator_supplies (rdev);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 43/162 bus: sunxi-rsb: Support atomic transfers
In reply to Greg Kroah-HartmanFrom: Samuel Holland <[email protected]>
[ Upstream commit 077686da0e2162c4ea5ae0df205849c2a7a84479 ]
When communicating with a PMIC during system poweroff (pm_power_off()), IRQs are disabled and we are in a RCU read-side critical section, so we cannot use wait_for_completion_io_timeout(). Instead, poll the status register for transfer completion.
--- drivers/bus/sunxi-rsb.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
drivers/bus/sunxi-rsb.c +21 -8
@@ -268,6 +268,9 @@ EXPORT_SYMBOL_GPL(sunxi_rsb_driver_register);/* common code that starts a transfer */ static int _sunxi_rsb_run_xfer (struct sunxi_rsb *rsb) { +u32 int_mask, status; +bool timeout; +if (readl (rsb->regs +RSB_CTRL ) &RSB_CTRL_START_TRANS ) {dev_dbg (rsb->dev,"RSB transfer still in progress\n" );return -EBUSY ;
@@ -275,13 +278,23 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)reinit_completion (&rsb->complete); -writel (RSB_INTS_LOAD_BSY |RSB_INTS_TRANS_ERR |RSB_INTS_TRANS_OVER , - rsb->regs +RSB_INTE ); + int_mask =RSB_INTS_LOAD_BSY |RSB_INTS_TRANS_ERR |RSB_INTS_TRANS_OVER ; +writel (int_mask, rsb->regs +RSB_INTE );writel (RSB_CTRL_START_TRANS |RSB_CTRL_GLOBAL_INT_ENB , rsb->regs +RSB_CTRL ); -if (!wait_for_completion_io_timeout (&rsb->complete, -msecs_to_jiffies (100 ))) { +if (irqs_disabled ()) { + timeout =readl_poll_timeout_atomic (rsb->regs +RSB_INTS , + status, (status & int_mask), +10 ,100000 ); +writel (status, rsb->regs +RSB_INTS ); + }else { + timeout = !wait_for_completion_io_timeout (&rsb->complete, +msecs_to_jiffies (100 )); + status = rsb->status; + } + +if (timeout) {dev_dbg (rsb->dev,"RSB timeout\n" );/* abort the transfer */
@@ -293,18 +306,18 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)return -ETIMEDOUT ; } -if (rsb->status &RSB_INTS_LOAD_BSY ) { +if (status &RSB_INTS_LOAD_BSY ) {dev_dbg (rsb->dev,"RSB busy\n" );return -EBUSY ; } -if (rsb->status &RSB_INTS_TRANS_ERR ) { -if (rsb->status &RSB_INTS_TRANS_ERR_ACK ) { +if (status &RSB_INTS_TRANS_ERR ) { +if (status &RSB_INTS_TRANS_ERR_ACK ) {dev_dbg (rsb->dev,"RSB slave nack\n" );return -EINVAL ; } -if (rsb->status &RSB_INTS_TRANS_ERR_DATA ) { +if (status &RSB_INTS_TRANS_ERR_DATA ) {dev_dbg (rsb->dev,"RSB transfer data error\n" );return -EIO ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 44/162 tee: optee: fix possible memory leak in optee_register_device()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit cce616e012c215d65c15e5d1afa73182dea49389 ]
If device_register() returns error in optee_register_device(), the name allocated by dev_set_name() need be freed. As comment of device_register() says, it should use put_device() to give up the reference in the error path. So fix this by calling put_device(), then the name can be freed in kobject_cleanup(), and optee_device is freed in optee_release_device().
--- drivers/tee/optee/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tee/optee/device.c +1 -1
@@ -80,7 +80,7 @@ static int optee_register_device(const uuid_t *device_uuid) rc =device_register (&optee_device->dev);if (rc) {pr_err ("device registration failed, err: %d\n" , rc); -kfree (optee_device); +put_device (&optee_device->dev); }return rc;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 45/162 ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl
In reply to Greg Kroah-HartmanFrom: Michael Grzeschik <[email protected]>
[ Upstream commit 40a2226e8bfacb79dd154dea68febeead9d847e9 ]
We set the PIOC to GPIO mode. This way the pin becomes an input signal will be usable by the controller. Without this change the udc on the 9g20ek does not work.
--- arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm/boot/dts/at91sam9g20ek_common.dtsi +9 -0
@@ -39,6 +39,13 @@ pinctrl_pck0_as_mck: pck0_as_mck { }; + usb1 { + pinctrl_usb1_vbus_gpio: usb1_vbus_gpio { + atmel,pins = + <AT91_PIOC 5 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>; /* PC5 GPIO */ + }; + }; + mmc0_slot1 { pinctrl_board_mmc0_slot1: mmc0_slot1-board { atmel,pins =
@@ -84,6 +91,8 @@ macb0: ethernet@fffc4000 { }; usb1: gadget@fffa4000 { + pinctrl-0 = <&pinctrl_usb1_vbus_gpio>; + pinctrl-names = "default"; atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>; status = "okay"; };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 46/162 net: liquidio: simplify if expression
In reply to Greg Kroah-HartmanFrom: Leon Romanovsky <[email protected]>
[ Upstream commit 733d4bbf9514890eb53ebe75827bf1fb4fd25ebe ]
Fix the warning reported by kbuild:
cocci warnings: (new ones prefixed by >>)
Quoted 1 line
Quoted 1 line
drivers/net/ethernet/cavium/liquidio/lio_main.c:1797:54-56: WARNING !A || A && B is equivalent to !A || B
drivers/net/ethernet/cavium/liquidio/lio_main.c:1827:54-56: WARNING !A || A && B is equivalent to !A || B
--- drivers/net/ethernet/cavium/liquidio/lio_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/cavium/liquidio/lio_main.c +2 -2
@@ -1798,7 +1798,7 @@ static int liquidio_open(struct net_device *netdev)ifstate_set (lio,LIO_IFSTATE_RUNNING ); -if (!OCTEON_CN23XX_PF (oct) || (OCTEON_CN23XX_PF (oct) && !oct->msix_on)) { +if (!OCTEON_CN23XX_PF (oct) || !oct->msix_on) { ret =setup_tx_poll_fn (netdev);if (ret) goto err_poll;
@@ -1828,7 +1828,7 @@ static int liquidio_open(struct net_device *netdev)return 0 ; err_rx_ctrl: -if (!OCTEON_CN23XX_PF (oct) || (OCTEON_CN23XX_PF (oct) && !oct->msix_on)) +if (!OCTEON_CN23XX_PF (oct) || !oct->msix_on)cleanup_tx_poll_fn (netdev); err_poll:if (lio->ptp_clock) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 47/162 rxrpc: Allow list of in-use local UDP endpoints to be viewed in /proc
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 33912c2639ad76660988c8ca97e4d18fca89b668 ]
Allow the list of in-use local UDP endpoints in the current network namespace to be viewed in /proc.
To aid with this, the endpoint list is converted to an hlist and RCU-safe manipulation is used so that the list can be read with only the RCU read lock held.
Stable-dep-of: 3bcd6c7eaa53 ("rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]")
--- net/rxrpc/ar-internal.h | 5 +-- net/rxrpc/local_object.c | 37 +++++++++++---------- net/rxrpc/net_ns.c | 5 ++- net/rxrpc/proc.c | 69 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 22 deletions(-)
net/rxrpc/ar-internal.h +3 -2
@@ -86,7 +86,7 @@ struct rxrpc_net {struct work_struct client_conn_reaper;struct timer_list client_conn_reap_timer; -struct list_head local_endpoints; +struct hlist_head local_endpoints;struct mutex local_mutex;/* Lock for ->local_endpoints */ DECLARE_HASHTABLE (peer_hash,10 );
@@ -266,7 +266,7 @@ struct rxrpc_local {atomic_t active_users;/* Number of users of the local endpoint */ atomic_t usage;/* Number of references to the structure */ struct rxrpc_net *rxnet;/* The network ns in which this resides */ -struct list_head link; +struct hlist_node link;struct socket *socket;/* my UDP socket */ struct work_struct processor;struct rxrpc_sock __rcu *service;/* Service(s) listening on this endpoint */
@@ -1001,6 +1001,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *);extern const struct seq_operations rxrpc_call_seq_ops;extern const struct seq_operations rxrpc_connection_seq_ops;extern const struct seq_operations rxrpc_peer_seq_ops; +extern const struct seq_operations rxrpc_local_seq_ops;/* * recvmsg.c
net/rxrpc/local_object.c +18 -19
@@ -81,7 +81,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,atomic_set (&local->usage,1 );atomic_set (&local->active_users,1 ); local->rxnet = rxnet; -INIT_LIST_HEAD (&local->link); +INIT_HLIST_NODE (&local->link);INIT_WORK (&local->processor, rxrpc_local_processor);init_rwsem (&local->defrag_sem);skb_queue_head_init (&local->reject_queue);
@@ -199,7 +199,7 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, {struct rxrpc_local *local;struct rxrpc_net *rxnet =rxrpc_net (net); -struct list_head *cursor; +struct hlist_node *cursor;const char *age;long diff;int ret;
@@ -209,16 +209,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,mutex_lock (&rxnet->local_mutex); -for (cursor = rxnet->local_endpoints.next; - cursor != &rxnet->local_endpoints; - cursor = cursor->next) { - local = list_entry(cursor, struct rxrpc_local, link); +hlist_for_each (cursor, &rxnet->local_endpoints) { + local = hlist_entry(cursor, struct rxrpc_local, link); diff =rxrpc_local_cmp_key (local, srx); -if (diff <0 ) +if (diff !=0 )continue ; -if (diff >0 ) -break ;/* Services aren't allowed to share transport sockets, so * reject that here. It is possible that the object is dying -
@@ -230,9 +226,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, goto addr_in_use; } -/* Found a match. We replace a dying object. Attempting to -* bind the transport socket may still fail if we're attempting -* to use a local address that the dying object is still using. +/* Found a match. We want to replace a dying object. +* Attempting to bind the transport socket may still fail if +* we're attempting to use a local address that the dying +* object is still using. */ if (!rxrpc_use_local (local))break ;
@@ -249,10 +246,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,if (ret <0 ) goto sock_error; -if (cursor != &rxnet->local_endpoints) -list_replace_init (cursor, &local->link); -else -list_add_tail (&local->link, cursor); +if (cursor) { +hlist_replace_rcu (cursor, &local->link); + cursor->pprev =NULL ; + }else { +hlist_add_head_rcu (&local->link, &rxnet->local_endpoints); + } age ="new" ; found:
@@ -393,7 +392,7 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local) local->dead = true;mutex_lock (&rxnet->local_mutex); -list_del_init (&local->link); +hlist_del_init_rcu (&local->link);mutex_unlock (&rxnet->local_mutex);rxrpc_clean_up_local_conns (local);
@@ -480,9 +479,9 @@ void rxrpc_destroy_all_locals(struct rxrpc_net *rxnet)flush_workqueue (rxrpc_workqueue); -if (!list_empty (&rxnet->local_endpoints)) { +if (!hlist_empty (&rxnet->local_endpoints)) {mutex_lock (&rxnet->local_mutex); -list_for_each_entry (local, &rxnet->local_endpoints, link) { +hlist_for_each_entry (local, &rxnet->local_endpoints, link) {pr_err ("AF_RXRPC: Leaked local %p {%d}\n" , local,atomic_read (&local->usage)); }
net/rxrpc/net_ns.c +4 -1
@@ -72,7 +72,7 @@ static __net_init int rxrpc_init_net(struct net *net)timer_setup (&rxnet->client_conn_reap_timer, rxrpc_client_conn_reap_timeout,0 ); -INIT_LIST_HEAD (&rxnet->local_endpoints); +INIT_HLIST_HEAD (&rxnet->local_endpoints);mutex_init (&rxnet->local_mutex);hash_init (rxnet->peer_hash);
@@ -98,6 +98,9 @@ static __net_init int rxrpc_init_net(struct net *net)proc_create_net ("peers" ,0444 , rxnet->proc_net, &rxrpc_peer_seq_ops,sizeof (struct seq_net_private )); +proc_create_net ("locals" ,0444 , rxnet->proc_net, + &rxrpc_local_seq_ops, +sizeof (struct seq_net_private ));return 0 ; err_proc:
net/rxrpc/proc.c +69 -0
72 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 48/162 rxrpc: Use refcount_t rather than atomic_t
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit a05754295e01f006a651eec759c5dbe682ef6cef ]
Move to using refcount_t rather than atomic_t for refcounts in rxrpc.
Stable-dep-of: 3bcd6c7eaa53 ("rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]")
--- include/trace/events/rxrpc.h | 2 +- net/rxrpc/af_rxrpc.c | 2 +- net/rxrpc/ar-internal.h | 18 ++++--------- net/rxrpc/call_accept.c | 4 +-- net/rxrpc/call_object.c | 44 ++++++++++++++++---------------- net/rxrpc/conn_client.c | 30 +++++++++++----------- net/rxrpc/conn_object.c | 49 ++++++++++++++++++------------------ net/rxrpc/conn_service.c | 8 +++--- net/rxrpc/input.c | 4 +-- net/rxrpc/local_object.c | 31 ++++++++++++----------- net/rxrpc/peer_object.c | 40 +++++++++++++++-------------- net/rxrpc/proc.c | 8 +++--- net/rxrpc/skbuff.c | 1 - 13 files changed, 119 insertions(+), 122 deletions(-)
include/trace/events/rxrpc.h +1 -1
@@ -583,7 +583,7 @@ TRACE_EVENT(rxrpc_client,TP_fast_assign ( __entry->conn = conn ? conn->debug_id : 0; __entry->channel = channel; - __entry->usage = conn ?atomic_read (&conn->usage) :-2 ; + __entry->usage = conn ?refcount_read (&conn->ref) :-2 ; __entry->op = op; __entry->cid = conn ? conn->proto.cid :0 ; ),
net/rxrpc/af_rxrpc.c +1 -1
@@ -351,7 +351,7 @@ static void rxrpc_dummy_notify_rx(struct sock *sk, struct rxrpc_call *rxcall,*/ void rxrpc_kernel_end_call (struct socket *sock,struct rxrpc_call *call) { -_enter ("%d{%d}" , call->debug_id,atomic_read (&call->usage)); +_enter ("%d{%d}" , call->debug_id,refcount_read (&call->ref));mutex_lock (&call->user_mutex);rxrpc_release_call (rxrpc_sk (sock->sk), call);
net/rxrpc/ar-internal.h +5 -13
@@ -14,14 +14,6 @@#include <net/af_rxrpc.h> #include "protocol.h" -#if 0 -#define CHECK_SLAB_OKAY (X ) \ - BUG_ON(atomic_read((X)) >> (sizeof(atomic_t) - 2) == \ - (POISON_FREE << 8 | POISON_FREE)) -#else -#define CHECK_SLAB_OKAY (X ) do {} while (0) -#endif -#define FCRYPT_BSIZE 8 struct rxrpc_crypt { union {
@@ -264,7 +256,7 @@ struct rxrpc_security {struct rxrpc_local {struct rcu_head rcu;atomic_t active_users;/* Number of users of the local endpoint */ -atomic_t usage;/* Number of references to the structure */ +refcount_t ref;/* Number of references to the structure */ struct rxrpc_net *rxnet;/* The network ns in which this resides */ struct hlist_node link;struct socket *socket;/* my UDP socket */
@@ -289,7 +281,7 @@ struct rxrpc_local {*/ struct rxrpc_peer {struct rcu_head rcu;/* This must be first */ -atomic_t usage; +refcount_t ref;unsigned long hash_key;struct hlist_node hash_link;struct rxrpc_local *local;
@@ -391,7 +383,7 @@ enum rxrpc_conn_proto_state {*/ struct rxrpc_bundle {struct rxrpc_conn_parameters params; -atomic_t usage; +refcount_t ref;unsigned int debug_id;bool try_upgrade;/* True if the bundle is attempting upgrade */ bool alloc_conn;/* True if someone's getting a conn */
@@ -412,7 +404,7 @@ struct rxrpc_connection {struct rxrpc_conn_proto proto;struct rxrpc_conn_parameters params; -atomic_t usage; +refcount_t ref;struct rcu_head rcu;struct list_head cache_link;
@@ -592,7 +584,7 @@ struct rxrpc_call {int error;/* Local error incurred */ enum rxrpc_call_state state;/* current state of call */ enum rxrpc_call_completion completion;/* Call completion condition */ -atomic_t usage; +refcount_t ref;u16 service_id;/* service ID */ u8 security_ix;/* Security type */ enum rxrpc_interruptibility interruptibility;/* At what point call may be interrupted */
net/rxrpc/call_accept.c +2 -2
@@ -91,7 +91,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, (head + 1) & (size - 1));trace_rxrpc_conn (conn->debug_id, rxrpc_conn_new_service, -atomic_read (&conn->usage), here); +refcount_read (&conn->ref), here); }/* Now it gets complicated, because calls get registered with the
@@ -104,7 +104,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, call->state =RXRPC_CALL_SERVER_PREALLOC ;trace_rxrpc_call (call->debug_id, rxrpc_call_new_service, -atomic_read (&call->usage), +refcount_read (&call->ref), here, (const void *)user_call_ID);write_lock (&rx->call_lock);
net/rxrpc/call_object.c +23 -21
138 lines not on this page · raw message
net/rxrpc/conn_client.c +16 -14
@@ -102,7 +102,7 @@ void rxrpc_destroy_client_conn_ids(void)if (!idr_is_empty (&rxrpc_client_conn_ids)) {idr_for_each_entry (&rxrpc_client_conn_ids, conn, id) {pr_err ("AF_RXRPC: Leaked client conn %p {%d}\n" , - conn,atomic_read (&conn->usage)); + conn,refcount_read (&conn->ref)); }BUG (); }
@@ -122,7 +122,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp,if (bundle) { bundle->params = *cp;rxrpc_get_peer (bundle->params.peer); -atomic_set (&bundle->usage,1 ); +refcount_set (&bundle->ref,1 );spin_lock_init (&bundle->channel_lock);INIT_LIST_HEAD (&bundle->waiting_calls); }
@@ -131,7 +131,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp,struct rxrpc_bundle *rxrpc_get_bundle (struct rxrpc_bundle *bundle) { -atomic_inc (&bundle->usage); +refcount_inc (&bundle->ref);return bundle; }
@@ -144,10 +144,13 @@ static void rxrpc_free_bundle(struct rxrpc_bundle *bundle)void rxrpc_put_bundle (struct rxrpc_bundle *bundle) {unsigned int d = bundle->debug_id; -unsigned int u =atomic_dec_return (&bundle->usage); +bool dead; +int r; -_debug ("PUT B=%x %u" , d, u); -if (u ==0 ) + dead =__refcount_dec_and_test (&bundle->ref, &r); + +_debug ("PUT B=%x %d" , d, r); +if (dead)rxrpc_free_bundle (bundle); }
@@ -169,7 +172,7 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)return ERR_PTR (-ENOMEM ); } -atomic_set (&conn->usage,1 ); +refcount_set (&conn->ref,1 ); conn->bundle = bundle; conn->params = bundle->params; conn->out_clientflag =RXRPC_CLIENT_INITIATED ;
@@ -199,7 +202,7 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)key_get (conn->params.key);trace_rxrpc_conn (conn->debug_id, rxrpc_conn_new_client, -atomic_read (&conn->usage), +refcount_read (&conn->ref),__builtin_return_address (0 ));atomic_inc (&rxnet->nr_client_conns);
@@ -972,14 +975,13 @@ void rxrpc_put_client_conn(struct rxrpc_connection *conn) {const void *here =__builtin_return_address (0 );unsigned int debug_id = conn->debug_id; -int n; +bool dead; +int r; - n =atomic_dec_return (&conn->usage); -trace_rxrpc_conn (debug_id, rxrpc_conn_put_client, n, here); -if (n <=0 ) { - ASSERTCMP(n, >=, 0); + dead =__refcount_dec_and_test (&conn->ref, &r); +trace_rxrpc_conn (debug_id, rxrpc_conn_put_client, r -1 , here); +if (dead)rxrpc_kill_client_conn (conn); - } }/*
net/rxrpc/conn_object.c +25 -24
134 lines not on this page · raw message
net/rxrpc/conn_service.c +4 -4
@@ -9,7 +9,7 @@#include "ar-internal.h" static struct rxrpc_bundle rxrpc_service_dummy_bundle = { - .usage =ATOMIC_INIT (1 ), + .ref =REFCOUNT_INIT (1 ), .debug_id =UINT_MAX , .channel_lock =__SPIN_LOCK_UNLOCKED (&rxrpc_service_dummy_bundle.channel_lock), };
@@ -99,7 +99,7 @@ static void rxrpc_publish_service_conn(struct rxrpc_peer *peer,return ; found_extant_conn: -if (atomic_read (&cursor->usage) ==0 ) +if (refcount_read (&cursor->ref) ==0 ) goto replace_old_connection;write_sequnlock_bh (&peer->service_conn_lock);/* We should not be able to get here. rxrpc_incoming_connection() is
@@ -132,7 +132,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn* the rxrpc_connections list. */ conn->state =RXRPC_CONN_SERVICE_PREALLOC ; -atomic_set (&conn->usage,2 ); +refcount_set (&conn->ref,2 ); conn->bundle =rxrpc_get_bundle (&rxrpc_service_dummy_bundle);atomic_inc (&rxnet->nr_conns);
@@ -142,7 +142,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxnwrite_unlock (&rxnet->conn_lock);trace_rxrpc_conn (conn->debug_id, rxrpc_conn_new_service, -atomic_read (&conn->usage), +refcount_read (&conn->ref),__builtin_return_address (0 )); }
net/rxrpc/input.c +1 -3
@@ -1163,8 +1163,6 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,*/ static void rxrpc_reject_packet (struct rxrpc_local *local,struct sk_buff *skb) { -CHECK_SLAB_OKAY (&local->usage); -if (rxrpc_get_local_maybe (local)) {skb_queue_tail (&local->reject_queue, skb);rxrpc_queue_local (local);
@@ -1422,7 +1420,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) } } -if (!call ||atomic_read (&call->usage) ==0 ) { +if (!call ||refcount_read (&call->ref) ==0 ) {if (rxrpc_to_client (sp) || sp->hdr.type !=RXRPC_PACKET_TYPE_DATA ) goto bad_message;
net/rxrpc/local_object.c +16 -15
@@ -78,7 +78,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, local =kzalloc (sizeof (struct rxrpc_local ),GFP_KERNEL );if (local) { -atomic_set (&local->usage,1 ); +refcount_set (&local->ref,1 );atomic_set (&local->active_users,1 ); local->rxnet = rxnet;INIT_HLIST_NODE (&local->link);
@@ -284,10 +284,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,struct rxrpc_local *rxrpc_get_local (struct rxrpc_local *local) {const void *here =__builtin_return_address (0 ); -int n; +int r; - n =atomic_inc_return (&local->usage); -trace_rxrpc_local (local->debug_id, rxrpc_local_got, n, here); +__refcount_inc (&local->ref, &r); +trace_rxrpc_local (local->debug_id, rxrpc_local_got, r +1 , here);return local; }
@@ -297,12 +297,12 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)struct rxrpc_local *rxrpc_get_local_maybe (struct rxrpc_local *local) {const void *here =__builtin_return_address (0 ); +int r;if (local) { -int n =atomic_fetch_add_unless (&local->usage,1 ,0 ); -if (n >0 ) +if (__refcount_inc_not_zero (&local->ref, &r))trace_rxrpc_local (local->debug_id, rxrpc_local_got, - n +1 , here); + r +1 , here);else local =NULL ; }
@@ -316,10 +316,10 @@ void rxrpc_queue_local(struct rxrpc_local *local) {const void *here =__builtin_return_address (0 );unsigned int debug_id = local->debug_id; -int n =atomic_read (&local->usage); +int r =refcount_read (&local->ref);if (rxrpc_queue_work (&local->processor)) -trace_rxrpc_local (debug_id, rxrpc_local_queued, n, here); +trace_rxrpc_local (debug_id, rxrpc_local_queued, r +1 , here);else rxrpc_put_local (local); }
@@ -331,15 +331,16 @@ void rxrpc_put_local(struct rxrpc_local *local) {const void *here =__builtin_return_address (0 );unsigned int debug_id; -int n; +bool dead; +int r;if (local) { debug_id = local->debug_id; - n =atomic_dec_return (&local->usage); -trace_rxrpc_local (debug_id, rxrpc_local_put, n, here); + dead =__refcount_dec_and_test (&local->ref, &r); +trace_rxrpc_local (debug_id, rxrpc_local_put, r, here); -if (n ==0 ) +if (dead)call_rcu (&local->rcu, rxrpc_local_rcu); } }
@@ -427,7 +428,7 @@ static void rxrpc_local_processor(struct work_struct *work)return ;trace_rxrpc_local (local->debug_id, rxrpc_local_processing, -atomic_read (&local->usage),NULL ); +refcount_read (&local->ref),NULL ); do { again = false;
@@ -483,7 +484,7 @@ void rxrpc_destroy_all_locals(struct rxrpc_net *rxnet)mutex_lock (&rxnet->local_mutex);hlist_for_each_entry (local, &rxnet->local_endpoints, link) {pr_err ("AF_RXRPC: Leaked local %p {%d}\n" , - local,atomic_read (&local->usage)); + local,refcount_read (&local->ref)); }mutex_unlock (&rxnet->local_mutex);BUG ();
net/rxrpc/peer_object.c +21 -19
@@ -121,7 +121,7 @@ static struct rxrpc_peer *__rxrpc_lookup_peer_rcu(hash_for_each_possible_rcu (rxnet->peer_hash, peer, hash_link, hash_key) {if (rxrpc_peer_cmp_key (peer, local, srx, hash_key) ==0 && -atomic_read (&peer->usage) >0 ) +refcount_read (&peer->ref) >0 )return peer; }
@@ -140,7 +140,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *local, peer =__rxrpc_lookup_peer_rcu (local, srx, hash_key);if (peer) {_net ("PEER %d {%pISp}" , peer->debug_id, &peer->srx.transport); -_leave (" = %p {u=%d}" , peer,atomic_read (&peer->usage)); +_leave (" = %p {u=%d}" , peer,refcount_read (&peer->ref)); }return peer; }
@@ -216,7 +216,7 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) peer =kzalloc (sizeof (struct rxrpc_peer ), gfp);if (peer) { -atomic_set (&peer->usage,1 ); +refcount_set (&peer->ref,1 ); peer->local =rxrpc_get_local (local);INIT_HLIST_HEAD (&peer->error_targets); peer->service_conns =RB_ROOT ;
@@ -378,7 +378,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx,_net ("PEER %d {%pISp}" , peer->debug_id, &peer->srx.transport); -_leave (" = %p {u=%d}" , peer,atomic_read (&peer->usage)); +_leave (" = %p {u=%d}" , peer,refcount_read (&peer->ref));return peer; }
@@ -388,10 +388,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx,struct rxrpc_peer *rxrpc_get_peer (struct rxrpc_peer *peer) {const void *here =__builtin_return_address (0 ); -int n; +int r; - n =atomic_inc_return (&peer->usage); -trace_rxrpc_peer (peer->debug_id, rxrpc_peer_got, n, here); +__refcount_inc (&peer->ref, &r); +trace_rxrpc_peer (peer->debug_id, rxrpc_peer_got, r +1 , here);return peer; }
@@ -401,11 +401,11 @@ struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)struct rxrpc_peer *rxrpc_get_peer_maybe (struct rxrpc_peer *peer) {const void *here =__builtin_return_address (0 ); +int r;if (peer) { -int n =atomic_fetch_add_unless (&peer->usage,1 ,0 ); -if (n >0 ) -trace_rxrpc_peer (peer->debug_id, rxrpc_peer_got, n +1 , here); +if (__refcount_inc_not_zero (&peer->ref, &r)) +trace_rxrpc_peer (peer->debug_id, rxrpc_peer_got, r +1 , here);else peer =NULL ; }
@@ -436,13 +436,14 @@ void rxrpc_put_peer(struct rxrpc_peer *peer) {const void *here =__builtin_return_address (0 );unsigned int debug_id; -int n; +bool dead; +int r;if (peer) { debug_id = peer->debug_id; - n =atomic_dec_return (&peer->usage); -trace_rxrpc_peer (debug_id, rxrpc_peer_put, n, here); -if (n ==0 ) + dead =__refcount_dec_and_test (&peer->ref, &r); +trace_rxrpc_peer (debug_id, rxrpc_peer_put, r -1 , here); +if (dead)__rxrpc_put_peer (peer); } }
@@ -455,11 +456,12 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer) {const void *here =__builtin_return_address (0 );unsigned int debug_id = peer->debug_id; -int n; +bool dead; +int r; - n =atomic_dec_return (&peer->usage); -trace_rxrpc_peer (debug_id, rxrpc_peer_put, n, here); -if (n ==0 ) { + dead =__refcount_dec_and_test (&peer->ref, &r); +trace_rxrpc_peer (debug_id, rxrpc_peer_put, r -1 , here); +if (dead) {hash_del_rcu (&peer->hash_link);list_del_init (&peer->keepalive_link);rxrpc_free_peer (peer);
@@ -481,7 +483,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet)hlist_for_each_entry (peer, &rxnet->peer_hash[i], hash_link) {pr_err ("Leaked peer %u {%u} %pISp\n" , peer->debug_id, -atomic_read (&peer->usage), +refcount_read (&peer->ref), &peer->srx.transport); } }
net/rxrpc/proc.c +4 -4
@@ -107,7 +107,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) call->cid, call->call_id,rxrpc_is_service_call (call) ?"Svc" :"Clt" , -atomic_read (&call->usage), +refcount_read (&call->ref), rxrpc_call_states[call->state], call->abort_code, call->debug_id,
@@ -189,7 +189,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) conn->service_id, conn->proto.cid,rxrpc_conn_is_service (conn) ?"Svc" :"Clt" , -atomic_read (&conn->usage), +refcount_read (&conn->ref), rxrpc_conn_states[conn->state],key_serial (conn->params.key), atomic_read(&conn->serial),
@@ -239,7 +239,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)" %3u %5u %6llus %8u %8u\n" , lbuff, rbuff, -atomic_read (&peer->usage), +refcount_read (&peer->ref), peer->cong_cwnd, peer->mtu, now - peer->last_tx_at,
@@ -357,7 +357,7 @@ static int rxrpc_local_seq_show(struct seq_file *seq, void *v)seq_printf (seq,"UDP %-47.47s %3u %3u\n" , lbuff, -atomic_read (&local->usage), +refcount_read (&local->ref),atomic_read (&local->active_users));return 0 ;
net/rxrpc/skbuff.c +0 -1
@@ -71,7 +71,6 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)const void *here =__builtin_return_address (0 );if (skb) {int n; -CHECK_SLAB_OKAY (&skb->users); n =atomic_dec_return (select_skb_count (skb));trace_rxrpc_skb (skb, op,refcount_read (&skb->users), n,rxrpc_skb (skb)->rx_flags, here);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 49/162 rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]
In reply to Greg Kroah-HartmanFrom: David Howells <[email protected]>
[ Upstream commit 3bcd6c7eaa53b56c3f584da46a1f7652e759d0e5 ]
After rxrpc_unbundle_conn() has removed a connection from a bundle, it checks to see if there are any conns with available channels and, if not, removes and attempts to destroy the bundle.
Whilst it does check after grabbing client_bundles_lock that there are no connections attached, this races with rxrpc_look_up_bundle() retrieving the bundle, but not attaching a connection for the connection to be attached later.
There is therefore a window in which the bundle can get destroyed before we manage to attach a new connection to it.
Fix this by adding an "active" counter to struct rxrpc_bundle:
(1) rxrpc_connect_call() obtains an active count by prepping/looking up a bundle and ditches it before returning.
(2) If, during rxrpc_connect_call(), a connection is added to the bundle, this obtains an active count, which is held until the connection is discarded.
(3) rxrpc_deactivate_bundle() is created to drop an active count on a bundle and destroy it when the active count reaches 0. The active count is checked inside client_bundles_lock() to prevent a race with rxrpc_look_up_bundle().
(4) rxrpc_unbundle_conn() then calls rxrpc_deactivate_bundle().
--- net/rxrpc/ar-internal.h | 1 + net/rxrpc/conn_client.c | 38 +++++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 15 deletions(-)
net/rxrpc/ar-internal.h +1 -0
@@ -384,6 +384,7 @@ enum rxrpc_conn_proto_state {struct rxrpc_bundle {struct rxrpc_conn_parameters params;refcount_t ref; +atomic_t active;/* Number of active users */ unsigned int debug_id;bool try_upgrade;/* True if the bundle is attempting upgrade */ bool alloc_conn;/* True if someone's getting a conn */
net/rxrpc/conn_client.c +23 -15
@@ -40,6 +40,8 @@ __read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ;DEFINE_IDR (rxrpc_client_conn_ids);static DEFINE_SPINLOCK (rxrpc_conn_id_lock); +static void rxrpc_deactivate_bundle (struct rxrpc_bundle *bundle); +/* * Get a connection ID and epoch for a client connection from the global pool. * The connection struct pointer is then recorded in the idr radix tree. The
@@ -123,6 +125,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp, bundle->params = *cp;rxrpc_get_peer (bundle->params.peer);refcount_set (&bundle->ref,1 ); +atomic_set (&bundle->active,1 );spin_lock_init (&bundle->channel_lock);INIT_LIST_HEAD (&bundle->waiting_calls); }
@@ -149,7 +152,7 @@ void rxrpc_put_bundle(struct rxrpc_bundle *bundle) dead =__refcount_dec_and_test (&bundle->ref, &r); -_debug ("PUT B=%x %d" , d, r); +_debug ("PUT B=%x %d" , d, r -1 );if (dead)rxrpc_free_bundle (bundle); }
@@ -344,6 +347,7 @@ static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *crxrpc_free_bundle (candidate); found_bundle:rxrpc_get_bundle (bundle); +atomic_inc (&bundle->active);spin_unlock (&local->client_bundles_lock);_leave (" = %u [found]" , bundle->debug_id);return bundle;
@@ -441,6 +445,7 @@ static void rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle, gfp_t gfp)if (old)trace_rxrpc_client (old,-1 , rxrpc_client_replace); candidate->bundle_shift = shift; +atomic_inc (&bundle->active); bundle->conns[i] = candidate;for (j =0 ; j <RXRPC_MAXCALLS ; j++)set_bit (shift + j, &bundle->avail_chans);
@@ -731,6 +736,7 @@ int rxrpc_connect_call(struct rxrpc_sock *rx,smp_rmb (); out_put_bundle: +rxrpc_deactivate_bundle (bundle);rxrpc_put_bundle (bundle); out:_leave (" = %d" , ret);
@@ -906,9 +912,8 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_callstatic void rxrpc_unbundle_conn (struct rxrpc_connection *conn) {struct rxrpc_bundle *bundle = conn->bundle; -struct rxrpc_local *local = bundle->params.local;unsigned int bindex; -bool need_drop = false, need_put = false; +bool need_drop = false;int i;_enter ("C=%x" , conn->debug_id);
@@ -927,15 +932,22 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn) }spin_unlock (&bundle->channel_lock); -/* If there are no more connections, remove the bundle */ -if (!bundle->avail_chans) { -_debug ("maybe unbundle" ); -spin_lock (&local->client_bundles_lock); +if (need_drop) { +rxrpc_deactivate_bundle (bundle); +rxrpc_put_connection (conn); + } +} -for (i =0 ; i <ARRAY_SIZE (bundle->conns); i++) -if (bundle->conns[i]) -break ; -if (i ==ARRAY_SIZE (bundle->conns) && !bundle->params.exclusive) { +/* +* Drop the active count on a bundle. +*/ +static void rxrpc_deactivate_bundle (struct rxrpc_bundle *bundle) +{ +struct rxrpc_local *local = bundle->params.local; +bool need_put = false; + +if (atomic_dec_and_lock (&bundle->active, &local->client_bundles_lock)) { +if (!bundle->params.exclusive) {_debug ("erase bundle" );rb_erase (&bundle->local_node, &local->client_bundles); need_put = true;
@@ -945,10 +957,6 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn)if (need_put)rxrpc_put_bundle (bundle); } - -if (need_drop) -rxrpc_put_connection (conn); -_leave ("" ); }/*
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 50/162 nfc/nci: fix race with opening and closing
In reply to Greg Kroah-HartmanFrom: Lin Ma <[email protected]>
[ Upstream commit 0ad6bded175e829c2ca261529c9dce39a32a042d ]
Previously we leverage NCI_UNREG and the lock inside nci_close_device to prevent the race condition between opening a device and closing a device. However, it still has problem because a failed opening command will erase the NCI_UNREG flag and allow another opening command to bypass the status checking.
This fix corrects that by making sure the NCI_UNREG is held.
--- net/nfc/nci/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/nfc/nci/core.c +1 -1
@@ -530,7 +530,7 @@ static int nci_open_device(struct nci_dev *ndev)skb_queue_purge (&ndev->tx_q); ndev->ops->close (ndev); - ndev->flags =0 ; + ndev->flags &=BIT (NCI_UNREG ); } done:
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 51/162 net: pch_gbe: fix potential memleak in pch_gbe_tx_queue()
In reply to Greg Kroah-HartmanFrom: Wang Hai <[email protected]>
[ Upstream commit 2360f9b8c4e81d242d4cbf99d630a2fffa681fab ]
In pch_gbe_xmit_frame(), NETDEV_TX_OK will be returned whether pch_gbe_tx_queue() sends data successfully or not, so pch_gbe_tx_queue() needs to free skb before returning. But pch_gbe_tx_queue() returns without freeing skb in case of dma_map_single() fails. Add dev_kfree_skb_any() to fix it.
--- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +1 -0
@@ -1166,6 +1166,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, buffer_info->dma =0 ; buffer_info->time_stamp =0 ; tx_ring->next_to_use = ring_num; +dev_kfree_skb_any (skb);return ; } buffer_info->mapped = true;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 52/162 9p/fd: fix issue of list_del corruption in p9_fd_cancel()
In reply to Greg Kroah-HartmanFrom: Zhengchao Shao <[email protected]>
[ Upstream commit 11c10956515b8ec44cf4f2a7b9d8bf8b9dc05ec4 ]
Syz reported the following issue:
kernel BUG at lib/list_debug.c:53!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN
RIP: 0010:__list_del_entry_valid.cold+0x5c/0x72 Call Trace: <TASK> p9_fd_cancel+0xb1/0x270 p9_client_rpc+0x8ea/0xba0 p9_client_create+0x9c0/0xed0 v9fs_session_init+0x1e0/0x1620 v9fs_mount+0xba/0xb80 legacy_get_tree+0x103/0x200 vfs_get_tree+0x89/0x2d0 path_mount+0x4c0/0x1ac0 __x64_sys_mount+0x33b/0x430 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 </TASK>
The process is as follows:
Thread A: Thread B:p9_poll_workfn() p9_client_create()
... ...
p9_conn_cancel() p9_fd_cancel()
list_del() ...
... list_del() //list_del
corruption
There is no lock protection when deleting list in p9_conn_cancel(). After deleting list in Thread A, thread B will delete the same list again. It will cause issue of list_del corruption.
Setting req->status to REQ_STATUS_ERROR under lock prevents other cleanup paths from trying to manipulate req_list.
The other thread can safely check req->status because it still holds a reference to req at this point.
--- net/9p/trans_fd.c | 2 ++ 1 file changed, 2 insertions(+)
net/9p/trans_fd.c +2 -0
@@ -200,9 +200,11 @@ static void p9_conn_cancel(struct p9_conn *m, int err)list_for_each_entry_safe (req, rtmp, &m->req_list, req_list) {list_move (&req->req_list, &cancel_list); + req->status =REQ_STATUS_ERROR ; }list_for_each_entry_safe (req, rtmp, &m->unsent_req_list, req_list) {list_move (&req->req_list, &cancel_list); + req->status =REQ_STATUS_ERROR ; }spin_unlock (&m->client->lock);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 53/162 netfilter: conntrack: Fix data-races around ct mark
In reply to Greg Kroah-HartmanFrom: Daniel Xu <[email protected]>
[ Upstream commit 52d1aa8b8249ff477aaa38b6f74a8ced780d079c ]
nf_conn:mark can be read from and written to in parallel. Use READ_ONCE()/WRITE_ONCE() for reads and writes to prevent unwanted compiler optimizations.
--- net/core/flow_dissector.c | 2 +- net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 ++-- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 24 ++++++++++++++---------- net/netfilter/nf_conntrack_standalone.c | 2 +- net/netfilter/nft_ct.c | 6 +++--- net/netfilter/xt_connmark.c | 18 ++++++++++-------- net/openvswitch/conntrack.c | 8 ++++---- net/sched/act_connmark.c | 4 ++-- net/sched/act_ct.c | 8 ++++---- net/sched/act_ctinfo.c | 6 +++--- 11 files changed, 45 insertions(+), 39 deletions(-)
net/core/flow_dissector.c +1 -1
@@ -263,7 +263,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb, key->ct_zone = ct->zone.id;#endif #if IS_ENABLED (CONFIG_NF_CONNTRACK_MARK ) - key->ct_mark = ct->mark; + key->ct_mark =READ_ONCE (ct->mark);#endif cl =nf_ct_labels_find (ct);
net/ipv4/netfilter/ipt_CLUSTERIP.c +2 -2
@@ -424,7 +424,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)switch (ctinfo) {case IP_CT_NEW : - ct->mark = hash; +WRITE_ONCE (ct->mark, hash);break ;case IP_CT_RELATED :case IP_CT_RELATED_REPLY :
@@ -441,7 +441,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)#ifdef DEBUG nf_ct_dump_tuple_ip (&ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple);#endif -pr_debug ("hash=%u ct_hash=%u " , hash, ct->mark); +pr_debug ("hash=%u ct_hash=%u " , hash,READ_ONCE (ct->mark));if (!clusterip_responsible (cipinfo->config, hash)) {pr_debug ("not responsible\n" );return NF_DROP ;
net/netfilter/nf_conntrack_core.c +1 -1
@@ -1598,7 +1598,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, }#ifdef CONFIG_NF_CONNTRACK_MARK - ct->mark = exp->master->mark; + ct->mark =READ_ONCE (exp->master->mark);#endif #ifdef CONFIG_NF_CONNTRACK_SECMARK ct->secmark = exp->master->secmark;
net/netfilter/nf_conntrack_netlink.c +14 -10
@@ -317,9 +317,9 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) }#ifdef CONFIG_NF_CONNTRACK_MARK -static int ctnetlink_dump_mark (struct sk_buff *skb,const struct nf_conn *ct) +static int ctnetlink_dump_mark (struct sk_buff *skb,u32 mark) { -if (nla_put_be32 (skb,CTA_MARK ,htonl (ct->mark))) +if (nla_put_be32 (skb,CTA_MARK ,htonl (mark))) goto nla_put_failure;return 0 ;
@@ -532,7 +532,7 @@ static int ctnetlink_dump_extinfo(struct sk_buff *skb,static int ctnetlink_dump_info (struct sk_buff *skb,struct nf_conn *ct) { if (ctnetlink_dump_status(skb, ct) < 0 || - ctnetlink_dump_mark(skb, ct) < 0 || + ctnetlink_dump_mark(skb, READ_ONCE(ct->mark)) < 0 || ctnetlink_dump_secctx(skb, ct) < 0 || ctnetlink_dump_id(skb, ct) < 0 || ctnetlink_dump_use(skb, ct) < 0 ||
@@ -711,6 +711,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)struct sk_buff *skb;unsigned int type;unsigned int flags =0 , group; +u32 mark;int err;if (events & (1 <<IPCT_DESTROY )) {
@@ -811,8 +812,9 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) }#ifdef CONFIG_NF_CONNTRACK_MARK -if ((events & (1 <<IPCT_MARK ) || ct->mark) - &&ctnetlink_dump_mark (skb, ct) <0 ) + mark =READ_ONCE (ct->mark); +if ((events & (1 <<IPCT_MARK ) || mark) && +ctnetlink_dump_mark (skb, mark) <0 ) goto nla_put_failure;#endif nlmsg_end (skb, nlh);
@@ -1099,7 +1101,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data) }#ifdef CONFIG_NF_CONNTRACK_MARK -if ((ct->mark & filter->mark.mask) != filter->mark.val) +if ((READ_ONCE (ct->mark) & filter->mark.mask) != filter->mark.val) goto ignore_entry;#endif
@@ -1979,9 +1981,9 @@ static void ctnetlink_change_mark(struct nf_conn *ct, mask = ~ntohl (nla_get_be32 (cda[CTA_MARK_MASK ])); mark =ntohl (nla_get_be32 (cda[CTA_MARK ])); - newmark = (ct->mark & mask) ^ mark; -if (newmark != ct->mark) - ct->mark = newmark; + newmark = (READ_ONCE (ct->mark) & mask) ^ mark; +if (newmark !=READ_ONCE (ct->mark)) + WRITE_ONCE(ct->mark, newmark); }#endif
@@ -2669,6 +2671,7 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) {const struct nf_conntrack_zone *zone;struct nlattr *nest_parms; +u32 mark; zone =nf_ct_zone (ct);
@@ -2726,7 +2729,8 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) goto nla_put_failure;#ifdef CONFIG_NF_CONNTRACK_MARK -if (ct->mark &&ctnetlink_dump_mark (skb, ct) <0 ) + mark =READ_ONCE (ct->mark); +if (mark &&ctnetlink_dump_mark (skb, mark) <0 ) goto nla_put_failure;#endif if (ctnetlink_dump_labels (skb, ct) <0 )
net/netfilter/nf_conntrack_standalone.c +1 -1
@@ -360,7 +360,7 @@ static int ct_seq_show(struct seq_file *s, void *v) goto release;#if defined(CONFIG_NF_CONNTRACK_MARK ) -seq_printf (s,"mark=%u " , ct->mark); +seq_printf (s,"mark=%u " ,READ_ONCE (ct->mark));#endif ct_show_secctx (s, ct);
net/netfilter/nft_ct.c +3 -3
@@ -97,7 +97,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr,return ;#ifdef CONFIG_NF_CONNTRACK_MARK case NFT_CT_MARK : - *dest = ct->mark; + *dest =READ_ONCE (ct->mark);return ;#endif #ifdef CONFIG_NF_CONNTRACK_SECMARK
@@ -294,8 +294,8 @@ static void nft_ct_set_eval(const struct nft_expr *expr,switch (priv->key) {#ifdef CONFIG_NF_CONNTRACK_MARK case NFT_CT_MARK : -if (ct->mark != value) { - ct->mark = value; +if (READ_ONCE (ct->mark) != value) { +WRITE_ONCE (ct->mark, value);nf_conntrack_event_cache (IPCT_MARK , ct); }break ;
net/netfilter/xt_connmark.c +10 -8
@@ -30,6 +30,7 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)u_int32_t new_targetmark;struct nf_conn *ct;u_int32_t newmark; +u_int32_t oldmark; ct =nf_ct_get (skb, &ctinfo);if (ct ==NULL )
@@ -37,14 +38,15 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)switch (info->mode) {case XT_CONNMARK_SET : - newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; + oldmark =READ_ONCE (ct->mark); + newmark = (oldmark & ~info->ctmask) ^ info->ctmark;if (info->shift_dir ==D_SHIFT_RIGHT ) newmark >>= info->shift_bits;else newmark <<= info->shift_bits; -if (ct->mark != newmark) { - ct->mark = newmark; +if (READ_ONCE (ct->mark) != newmark) { +WRITE_ONCE (ct->mark, newmark);nf_conntrack_event_cache (IPCT_MARK , ct); }break ;
@@ -55,15 +57,15 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)else new_targetmark <<= info->shift_bits; - newmark = (ct->mark & ~info->ctmask) ^ + newmark = (READ_ONCE (ct->mark) & ~info->ctmask) ^ new_targetmark; -if (ct->mark != newmark) { - ct->mark = newmark; +if (READ_ONCE (ct->mark) != newmark) { +WRITE_ONCE (ct->mark, newmark);nf_conntrack_event_cache (IPCT_MARK , ct); }break ;case XT_CONNMARK_RESTORE : - new_targetmark = (ct->mark & info->ctmask); + new_targetmark = (READ_ONCE (ct->mark) & info->ctmask);if (info->shift_dir ==D_SHIFT_RIGHT ) new_targetmark >>= info->shift_bits;else
@@ -126,7 +128,7 @@ connmark_mt(const struct sk_buff *skb, struct xt_action_param *par)if (ct ==NULL )return false; -return ((ct->mark & info->mask) == info->mark) ^ info->invert; +return ((READ_ONCE (ct->mark) & info->mask) == info->mark) ^ info->invert; }static int connmark_mt_check (const struct xt_mtchk_param *par)
net/openvswitch/conntrack.c +4 -4
@@ -150,7 +150,7 @@ static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)static u32 ovs_ct_get_mark (const struct nf_conn *ct) {#if IS_ENABLED (CONFIG_NF_CONNTRACK_MARK ) -return ct ? ct->mark :0 ; +return ct ?READ_ONCE (ct->mark) :0 ;#else return 0 ;#endif
@@ -336,9 +336,9 @@ static int ovs_ct_set_mark(struct nf_conn *ct, struct sw_flow_key *key,#if IS_ENABLED (CONFIG_NF_CONNTRACK_MARK )u32 new_mark; - new_mark = ct_mark | (ct->mark & ~(mask)); -if (ct->mark != new_mark) { - ct->mark = new_mark; + new_mark = ct_mark | (READ_ONCE (ct->mark) & ~(mask)); +if (READ_ONCE (ct->mark) != new_mark) { +WRITE_ONCE (ct->mark, new_mark);if (nf_ct_is_confirmed (ct))nf_conntrack_event_cache (IPCT_MARK , ct); key->ct.mark = new_mark;
net/sched/act_connmark.c +2 -2
@@ -62,7 +62,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, c =nf_ct_get (skb, &ctinfo);if (c) { - skb->mark = c->mark; + skb->mark =READ_ONCE (c->mark);/* using overlimits stats to count how many packets marked */ ca->tcf_qstats.overlimits++; goto out;
@@ -82,7 +82,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, c =nf_ct_tuplehash_to_ctrack (thash);/* using overlimits stats to count how many packets marked */ ca->tcf_qstats.overlimits++; - skb->mark = c->mark; + skb->mark =READ_ONCE (c->mark);nf_ct_put (c); out:
net/sched/act_ct.c +4 -4
@@ -177,7 +177,7 @@ static void tcf_ct_flow_table_add_action_meta(struct nf_conn *ct, entry =tcf_ct_flow_table_flow_action_get_next (action); entry->id =FLOW_ACTION_CT_METADATA ;#if IS_ENABLED (CONFIG_NF_CONNTRACK_MARK ) - entry->ct_metadata.mark = ct->mark; + entry->ct_metadata.mark =READ_ONCE (ct->mark);#endif ctinfo = dir ==IP_CT_DIR_ORIGINAL ?IP_CT_ESTABLISHED :IP_CT_ESTABLISHED_REPLY ;
@@ -843,9 +843,9 @@ static void tcf_ct_act_set_mark(struct nf_conn *ct, u32 mark, u32 mask)if (!mask)return ; - new_mark = mark | (ct->mark & ~(mask)); -if (ct->mark != new_mark) { - ct->mark = new_mark; + new_mark = mark | (READ_ONCE (ct->mark) & ~(mask)); +if (READ_ONCE (ct->mark) != new_mark) { +WRITE_ONCE (ct->mark, new_mark);if (nf_ct_is_confirmed (ct))nf_conntrack_event_cache (IPCT_MARK , ct); }
net/sched/act_ctinfo.c +3 -3
@@ -33,7 +33,7 @@ static void tcf_ctinfo_dscp_set(struct nf_conn *ct, struct tcf_ctinfo *ca, {u8 dscp, newdscp; - newdscp = (((ct->mark & cp->dscpmask) >> cp->dscpmaskshift) <<2 ) & + newdscp = (((READ_ONCE (ct->mark) & cp->dscpmask) >> cp->dscpmaskshift) <<2 ) & ~INET_ECN_MASK ;switch (proto) {
@@ -73,7 +73,7 @@ static void tcf_ctinfo_cpmark_set(struct nf_conn *ct, struct tcf_ctinfo *ca, struct sk_buff *skb) { ca->stats_cpmark_set++; - skb->mark = ct->mark & cp->cpmarkmask; + skb->mark =READ_ONCE (ct->mark) & cp->cpmarkmask; } static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a,
@@ -131,7 +131,7 @@ static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a, }if (cp->mode &CTINFO_MODE_DSCP ) -if (!cp->dscpstatemask || (ct->mark & cp->dscpstatemask)) +if (!cp->dscpstatemask || (READ_ONCE (ct->mark) & cp->dscpstatemask))tcf_ctinfo_dscp_set (ct, ca, cp, skb, wlen, proto);if (cp->mode &CTINFO_MODE_CPMARK )
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 54/162 ARM: mxs: fix memory leak in mxs_machine_init()
In reply to Greg Kroah-HartmanFrom: Zheng Yongjun <[email protected]>
[ Upstream commit f31e3c204d1844b8680a442a48868af5ac3d5481 ]
If of_property_read_string() failed, 'soc_dev_attr' should be freed before return. Otherwise there is a memory leak.
--- arch/arm/mach-mxs/mach-mxs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/mach-mxs/mach-mxs.c +3 -1
@@ -387,8 +387,10 @@ static void __init mxs_machine_init(void) root =of_find_node_by_path ("/" ); ret =of_property_read_string (root,"model" , &soc_dev_attr->machine); -if (ret) +if (ret) { +kfree (soc_dev_attr);return ; + } soc_dev_attr->family ="Freescale MXS Family" ; soc_dev_attr->soc_id =mxs_get_soc_id ();
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 55/162 ARM: dts: imx6q-prti6q: Fix ref/tcxo-clock-frequency properties
In reply to Greg Kroah-HartmanFrom: Fabio Estevam <[email protected]>
[ Upstream commit e68be7b39f21d8a9291a5a3019787cd3ca999dd7 ]
make dtbs_check gives the following errors:
ref-clock-frequency: size (9) error for type uint32
tcxo-clock-frequency: size (9) error for type uint32
Fix it by passing the frequencies inside < > as documented in Documentation/devicetree/bindings/net/wireless/ti,wlcore.yaml.
--- arch/arm/boot/dts/imx6q-prti6q.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/boot/dts/imx6q-prti6q.dts +2 -2
@@ -364,8 +364,8 @@ wifi { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wifi>; interrupts-extended = <&gpio1 30 IRQ_TYPE_LEVEL_HIGH>; - ref-clock-frequency = "38400000"; - tcxo-clock-frequency = "19200000"; + ref-clock-frequency = <38400000>; + tcxo-clock-frequency = <19200000>; }; };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 56/162 net: ethernet: mtk_eth_soc: fix error handling in mtk_open()
In reply to Greg Kroah-HartmanFrom: Liu Jian <[email protected]>
[ Upstream commit f70074140524c59a0935947b06dd6cb6e1ea642d ]
If mtk_start_dma() fails, invoke phylink_disconnect_phy() to perform cleanup. phylink_disconnect_phy() contains the put_device action. If phylink_disconnect_phy is not performed, the Kref of netdev will leak.
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +3 -0
@@ -2299,7 +2299,10 @@ static int mtk_open(struct net_device *dev)int err =mtk_start_dma (eth);if (err) +if (err) { +phylink_disconnect_phy (mac->phylink);return err; + }mtk_gdm_config (eth,MTK_GDMA_TO_PDMA );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 57/162 net/mlx4: Check retval of mlx4_bitmap_init
In reply to Greg Kroah-HartmanFrom: Peter Kosyh <[email protected]>
[ Upstream commit 594c61ffc77de0a197934aa0f1df9285c68801c6 ]
If mlx4_bitmap_init fails, mlx4_bitmap_alloc_range will dereference the NULL pointer (bitmap->table).
Make sure, that mlx4_bitmap_alloc_range called in no error case.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/ethernet/mellanox/mlx4/qp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx4/qp.c +2 -1
@@ -697,7 +697,8 @@ static int mlx4_create_zones(struct mlx4_dev *dev, err =mlx4_bitmap_init (*bitmap + k,1 ,MLX4_QP_TABLE_RAW_ETH_SIZE -1 ,0 ,0 ); -mlx4_bitmap_alloc_range (*bitmap + k,1 ,1 ,0 ); +if (!err) +mlx4_bitmap_alloc_range (*bitmap + k,1 ,1 ,0 ); }if (err)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 58/162 net/qla3xxx: fix potential memleak in ql3xxx_send()
In reply to Greg Kroah-HartmanFrom: Zhang Changzhong <[email protected]>
[ Upstream commit 62a7311fb96c61d281da9852dbee4712fc8c3277 ]
The ql3xxx_send() returns NETDEV_TX_OK without freeing skb in error handling case, add dev_kfree_skb_any() to fix it.
--- drivers/net/ethernet/qlogic/qla3xxx.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/qlogic/qla3xxx.c +1 -0
@@ -2475,6 +2475,7 @@ static netdev_tx_t ql3xxx_send(struct sk_buff *skb, skb_shinfo(skb)->nr_frags);if (tx_cb->seg_count ==-1 ) {netdev_err (ndev,"%s: invalid segment count!\n" , __func__); +dev_kfree_skb_any (skb);return NETDEV_TX_OK ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 59/162 net: pch_gbe: fix pci device refcount leak while module exiting
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit 5619537284f1017e9f6c7500b02b859b3830a06d ]
As comment of pci_get_domain_bus_and_slot() says, it returns a pci device with refcount increment, when finish using it, the caller must decrement the reference count by calling pci_dev_put().
In pch_gbe_probe(), pci_get_domain_bus_and_slot() is called, so in error path in probe() and remove() function, pci_dev_put() should be called to avoid refcount leak. Compile tested only.
--- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +4 -1
@@ -2482,6 +2482,7 @@ static void pch_gbe_remove(struct pci_dev *pdev)unregister_netdev (netdev);pch_gbe_phy_hw_reset (&adapter->hw); +pci_dev_put (adapter->ptp_pdev);free_netdev (netdev); }
@@ -2563,7 +2564,7 @@ static int pch_gbe_probe(struct pci_dev *pdev,/* setup the private structure */ ret =pch_gbe_sw_init (adapter);if (ret) - goto err_free_netdev; + goto err_put_dev;/* Initialize PHY */ ret =pch_gbe_init_phy (adapter);
@@ -2621,6 +2622,8 @@ static int pch_gbe_probe(struct pci_dev *pdev, err_free_adapter:pch_gbe_phy_hw_reset (&adapter->hw); +err_put_dev: +pci_dev_put (adapter->ptp_pdev); err_free_netdev:free_netdev (netdev);return ret;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 60/162 nfp: fill splittable of devlink_port_attrs correctly
In reply to Greg Kroah-HartmanFrom: Diana Wang <[email protected]>
[ Upstream commit 4abd9600b9d15d3d92a9ac25cf200422a4c415ee ]
The error is reflected in that it shows wrong splittable status of port when executing "devlink port show".
The reason which leads the error is that the assigned operation of splittable is just a simple negation operation of split and it does not consider port lanes quantity. A splittable port should have several lanes that can be split(lanes quantity > 1).
If without the judgement, it will show wrong message for some firmware, such as 2x25G, 2x10G.
--- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/netronome/nfp/nfp_devlink.c +1 -1
@@ -363,7 +363,7 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)return ret; attrs.split = eth_port.is_split; - attrs.splittable = !attrs.split; + attrs.splittable = eth_port.port_lanes >1 && !attrs.split; attrs.lanes = eth_port.port_lanes; attrs.flavour =DEVLINK_PORT_FLAVOUR_PHYSICAL ; attrs.phys.port_number = eth_port.label_port;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 61/162 nfp: add port from netdev validation for EEPROM access
In reply to Greg Kroah-HartmanFrom: Jaco Coetzee <[email protected]>
[ Upstream commit 0873016d46f6dfafd1bdf4d9b935b3331b226f7c ]
Setting of the port flag NFP_PORT_CHANGED, introduced to ensure the correct reading of EEPROM data, causes a fatal kernel NULL pointer dereference in cases where the target netdev type cannot be determined.
Add validation of port struct pointer before attempting to set the NFP_PORT_CHANGED flag. Return that operation is not supported if the netdev type cannot be determined.
--- drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +3 -0
@@ -1225,6 +1225,9 @@ nfp_port_get_module_info(struct net_device *netdev,u8 data; port =nfp_port_from_netdev (netdev); +if (!port) +return -EOPNOTSUPP ; +/* update port state to get latest interface */ set_bit (NFP_PORT_CHANGED , &port->flags); eth_port =nfp_port_get_eth_port (port);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 62/162 macsec: Fix invalid error code set
In reply to Greg Kroah-HartmanFrom: YueHaibing <[email protected]>
[ Upstream commit 7cef6b73fba96abef731a53501924fc3c4a0f947 ]
'ret' is defined twice in macsec_changelink(), when it is set in macsec_is_offloaded case, it will be invalid before return.
--- drivers/net/macsec.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/macsec.c +0 -1
@@ -3813,7 +3813,6 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],if (macsec_is_offloaded (macsec)) {const struct macsec_ops *ops;struct macsec_context ctx; -int ret; ops =macsec_get_ops (netdev_priv (dev), &ctx);if (!ops) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 63/162 Drivers: hv: vmbus: fix double free in the error path of vmbus_add_channel_work()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit f92a4b50f0bd7fd52391dc4bb9a309085d278f91 ]
In the error path of vmbus_device_register(), device_unregister() is called, which calls vmbus_device_release(). The latter frees the struct hv_device that was passed in to vmbus_device_register(). So remove the kfree() in vmbus_add_channel_work() to avoid a double free.
--- drivers/hv/channel_mgmt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/hv/channel_mgmt.c +5 -1
@@ -501,13 +501,17 @@ static void vmbus_add_channel_work(struct work_struct *work)* Add the new device to the bus. This will kick off device-driver * binding which eventually invokes the device driver's AddDevice() * method. +* +* If vmbus_device_register() fails, the 'device_obj' is freed in +* vmbus_device_release() as called by device_unregister() in the +* error path of vmbus_device_register(). In the outside error +* path, there's no need to free it. */ ret =vmbus_device_register (newchannel->device_obj);if (ret !=0 ) {pr_err ("unable to add child device object (relid %d)\n" , newchannel->offermsg.child_relid); -kfree (newchannel->device_obj); goto err_deq_chan; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 64/162 Drivers: hv: vmbus: fix possible memory leak in vmbus_device_register()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit 25c94b051592c010abe92c85b0485f1faedc83f3 ]
If device_register() returns error in vmbus_device_register(), the name allocated by dev_set_name() must be freed. As comment of device_register() says, it should use put_device() to give up the reference in the error path. So fix this by calling put_device(), then the name can be freed in kobject_cleanup().
--- drivers/hv/vmbus_drv.c | 1 + 1 file changed, 1 insertion(+)
drivers/hv/vmbus_drv.c +1 -0
@@ -2020,6 +2020,7 @@ int vmbus_device_register(struct hv_device *child_device_obj) ret =device_register (&child_device_obj->device);if (ret) {pr_err ("Unable to register child device\n" ); +put_device (&child_device_obj->device);return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 65/162 netfilter: ipset: Limit the maximal range of consecutive elements to add/delete
In reply to Greg Kroah-HartmanFrom: Jozsef Kadlecsik <[email protected]>
[ Upstream commit 5f7b51bf09baca8e4f80cbe879536842bafb5f31 ]
The range size of consecutive elements were not limited. Thus one could define a huge range which may result soft lockup errors due to the long execution time. Now the range size is limited to 2^20 entries.
Stable-dep-of: c7aa1a76d4a0 ("netfilter: ipset: regression in ip_set_hash_ip.c")
--- include/linux/netfilter/ipset/ip_set.h | 3 +++ net/netfilter/ipset/ip_set_hash_ip.c | 9 ++++++++- net/netfilter/ipset/ip_set_hash_ipmark.c | 10 +++++++++- net/netfilter/ipset/ip_set_hash_ipport.c | 3 +++ net/netfilter/ipset/ip_set_hash_ipportip.c | 3 +++ net/netfilter/ipset/ip_set_hash_ipportnet.c | 3 +++ net/netfilter/ipset/ip_set_hash_net.c | 11 ++++++++++- net/netfilter/ipset/ip_set_hash_netiface.c | 10 +++++++++- net/netfilter/ipset/ip_set_hash_netnet.c | 16 +++++++++++++++- net/netfilter/ipset/ip_set_hash_netport.c | 11 ++++++++++- net/netfilter/ipset/ip_set_hash_netportnet.c | 16 +++++++++++++++- 11 files changed, 88 insertions(+), 7 deletions(-)
include/linux/netfilter/ipset/ip_set.h +3 -0
@@ -198,6 +198,9 @@ struct ip_set_region {u32 elements;/* Number of elements vs timeout */ }; +/* Max range where every element is added/deleted in one step */ +#define IPSET_MAX_RANGE (1<<20) +/* The core set type structure */ struct ip_set_type {struct list_head list;
net/netfilter/ipset/ip_set_hash_ip.c +8 -1
@@ -131,8 +131,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], ret =ip_set_get_hostipaddr4 (tb[IPSET_ATTR_IP_TO ], &ip_to);if (ret)return ret; -if (ip > ip_to) +if (ip > ip_to) { +if (ip_to ==0 ) +return -IPSET_ERR_HASH_ELEM ;swap (ip, ip_to); + } }else if (tb[IPSET_ATTR_CIDR ]) {u8 cidr =nla_get_u8 (tb[IPSET_ATTR_CIDR ]);
@@ -143,6 +146,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], hosts = h->netmask ==32 ?1 :2 << (32 - h->netmask -1 ); +/* 64bit division is not allowed on 32bit */ +if (((u64 )ip_to - ip +1 ) >> (32 - h->netmask) >IPSET_MAX_RANGE ) +return -ERANGE ; +if (retried) { ip =ntohl (h->next.ip); e.ip =htonl (ip);
net/netfilter/ipset/ip_set_hash_ipmark.c +9 -1
@@ -120,6 +120,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], e.mark =ntohl (nla_get_be32 (tb[IPSET_ATTR_MARK ])); e.mark &= h->markmask; +if (e.mark ==0 && e.ip ==0 ) +return -IPSET_ERR_HASH_ELEM ;if (adt ==IPSET_TEST || !(tb[IPSET_ATTR_IP_TO ] || tb[IPSET_ATTR_CIDR ])) {
@@ -132,8 +134,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], ret =ip_set_get_hostipaddr4 (tb[IPSET_ATTR_IP_TO ], &ip_to);if (ret)return ret; -if (ip > ip_to) +if (ip > ip_to) { +if (e.mark ==0 && ip_to ==0 ) +return -IPSET_ERR_HASH_ELEM ;swap (ip, ip_to); + } }else if (tb[IPSET_ATTR_CIDR ]) {u8 cidr =nla_get_u8 (tb[IPSET_ATTR_CIDR ]);
@@ -142,6 +147,9 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],ip_set_mask_from_to (ip, ip_to, cidr); } +if (((u64 )ip_to - ip +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ; +if (retried) ip =ntohl (h->next.ip);for (; ip <= ip_to; ip++) {
net/netfilter/ipset/ip_set_hash_ipport.c +3 -0
@@ -172,6 +172,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],swap (port, port_to); } +if (((u64 )ip_to - ip +1 )*(port_to - port +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ; +if (retried) ip =ntohl (h->next.ip);for (; ip <= ip_to; ip++) {
net/netfilter/ipset/ip_set_hash_ipportip.c +3 -0
@@ -179,6 +179,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],swap (port, port_to); } +if (((u64 )ip_to - ip +1 )*(port_to - port +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ; +if (retried) ip =ntohl (h->next.ip);for (; ip <= ip_to; ip++) {
net/netfilter/ipset/ip_set_hash_ipportnet.c +3 -0
@@ -252,6 +252,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],swap (port, port_to); } +if (((u64 )ip_to - ip +1 )*(port_to - port +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ; + ip2_to = ip2_from;if (tb[IPSET_ATTR_IP2_TO ]) { ret =ip_set_get_hostipaddr4 (tb[IPSET_ATTR_IP2_TO ], &ip2_to);
net/netfilter/ipset/ip_set_hash_net.c +10 -1
@@ -139,7 +139,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],ipset_adtfn adtfn = set->variant->adt[adt];struct hash_net4_elem e = { .cidr =HOST_MASK };struct ip_set_ext ext =IP_SET_INIT_UEXT (set); -u32 ip =0 , ip_to =0 ; +u32 ip =0 , ip_to =0 , ipn, n =0 ;int ret;if (tb[IPSET_ATTR_LINENO ])
@@ -187,6 +187,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],if (ip +UINT_MAX == ip_to)return -IPSET_ERR_HASH_RANGE ; } + ipn = ip; +do { + ipn =ip_set_range_to_cidr (ipn, ip_to, &e.cidr); + n++; + }while (ipn++ < ip_to); + +if (n >IPSET_MAX_RANGE ) +return -ERANGE ; +if (retried) ip =ntohl (h->next.ip); do {
net/netfilter/ipset/ip_set_hash_netiface.c +9 -1
@@ -201,7 +201,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],ipset_adtfn adtfn = set->variant->adt[adt];struct hash_netiface4_elem e = { .cidr =HOST_MASK , .elem =1 };struct ip_set_ext ext =IP_SET_INIT_UEXT (set); -u32 ip =0 , ip_to =0 ; +u32 ip =0 , ip_to =0 , ipn, n =0 ;int ret;if (tb[IPSET_ATTR_LINENO ])
@@ -255,6 +255,14 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], }else {ip_set_mask_from_to (ip, ip_to, e.cidr); } + ipn = ip; +do { + ipn =ip_set_range_to_cidr (ipn, ip_to, &e.cidr); + n++; + }while (ipn++ < ip_to); + +if (n >IPSET_MAX_RANGE ) +return -ERANGE ;if (retried) ip =ntohl (h->next.ip);
net/netfilter/ipset/ip_set_hash_netnet.c +15 -1
@@ -167,7 +167,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],struct hash_netnet4_elem e = { };struct ip_set_ext ext =IP_SET_INIT_UEXT (set);u32 ip =0 , ip_to =0 ; -u32 ip2 =0 , ip2_from =0 , ip2_to =0 ; +u32 ip2 =0 , ip2_from =0 , ip2_to =0 , ipn; +u64 n =0 , m =0 ;int ret;if (tb[IPSET_ATTR_LINENO ])
@@ -243,6 +244,19 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], }else {ip_set_mask_from_to (ip2_from, ip2_to, e.cidr[1 ]); } + ipn = ip; +do { + ipn =ip_set_range_to_cidr (ipn, ip_to, &e.cidr[0 ]); + n++; + }while (ipn++ < ip_to); + ipn = ip2_from; +do { + ipn =ip_set_range_to_cidr (ipn, ip2_to, &e.cidr[1 ]); + m++; + }while (ipn++ < ip2_to); + +if (n*m >IPSET_MAX_RANGE ) +return -ERANGE ;if (retried) { ip =ntohl (h->next.ip[0 ]);
net/netfilter/ipset/ip_set_hash_netport.c +10 -1
@@ -157,7 +157,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],ipset_adtfn adtfn = set->variant->adt[adt];struct hash_netport4_elem e = { .cidr =HOST_MASK -1 };struct ip_set_ext ext =IP_SET_INIT_UEXT (set); -u32 port, port_to, p =0 , ip =0 , ip_to =0 ; +u32 port, port_to, p =0 , ip =0 , ip_to =0 , ipn; +u64 n =0 ;bool with_ports = false;u8 cidr;int ret;
@@ -234,6 +235,14 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], }else {ip_set_mask_from_to (ip, ip_to, e.cidr +1 ); } + ipn = ip; +do { + ipn =ip_set_range_to_cidr (ipn, ip_to, &cidr); + n++; + }while (ipn++ < ip_to); + +if (n*(port_to - port +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ;if (retried) { ip =ntohl (h->next.ip);
net/netfilter/ipset/ip_set_hash_netportnet.c +15 -1
@@ -181,7 +181,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],struct hash_netportnet4_elem e = { };struct ip_set_ext ext =IP_SET_INIT_UEXT (set);u32 ip =0 , ip_to =0 , p =0 , port, port_to; -u32 ip2_from =0 , ip2_to =0 , ip2; +u32 ip2_from =0 , ip2_to =0 , ip2, ipn; +u64 n =0 , m =0 ;bool with_ports = false;int ret;
@@ -283,6 +284,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], }else {ip_set_mask_from_to (ip2_from, ip2_to, e.cidr[1 ]); } + ipn = ip; +do { + ipn =ip_set_range_to_cidr (ipn, ip_to, &e.cidr[0 ]); + n++; + }while (ipn++ < ip_to); + ipn = ip2_from; +do { + ipn =ip_set_range_to_cidr (ipn, ip2_to, &e.cidr[1 ]); + m++; + }while (ipn++ < ip2_to); + +if (n*m*(port_to - port +1 ) >IPSET_MAX_RANGE ) +return -ERANGE ;if (retried) { ip =ntohl (h->next.ip[0 ]);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 66/162 netfilter: ipset: regression in ip_set_hash_ip.c
In reply to Greg Kroah-HartmanFrom: Vishwanath Pai <[email protected]>
[ Upstream commit c7aa1a76d4a0a3c401025b60c401412bbb60f8c6 ]
This patch introduced a regression: commit 48596a8ddc46 ("netfilter:
ipset: Fix adding an IPv4 range containing more than 2^31 addresses")
The variable e.ip is passed to adtfn() function which finally adds the ip address to the set. The patch above refactored the for loop and moved e.ip = htonl(ip) to the end of the for loop.
What this means is that if the value of "ip" changes between the first assignement of e.ip and the forloop, then e.ip is pointing to a different ip address than "ip".
Test case:
$ ipset create jdtest_tmp hash:ip family inet hashsize 2048 maxelem 100000 $ ipset add jdtest_tmp 10.0.1.1/31 ipset v6.21.1: Element cannot be added to the set: it's already added
The value of ip gets updated inside the "else if (tb[IPSET_ATTR_CIDR])" block but e.ip is still pointing to the old value.
--- net/netfilter/ipset/ip_set_hash_ip.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
net/netfilter/ipset/ip_set_hash_ip.c +3 -5
@@ -150,18 +150,16 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],if (((u64 )ip_to - ip +1 ) >> (32 - h->netmask) >IPSET_MAX_RANGE )return -ERANGE ; -if (retried) { +if (retried) ip =ntohl (h->next.ip); - e.ip =htonl (ip); - }for (; ip <= ip_to;) { + e.ip =htonl (ip); ret =adtfn (set, &e, &ext, &ext, flags);if (ret && !ip_set_eexist (ret, flags))return ret; ip += hosts; - e.ip =htonl (ip); -if (e.ip ==0 ) +if (ip ==0 )return 0 ; ret =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 67/162 net/mlx5: Fix FW tracer timestamp calculation
In reply to Greg Kroah-HartmanFrom: Moshe Shemesh <[email protected]>
[ Upstream commit 61db3d7b99a367416e489ccf764cc5f9b00d62a1 ]
Fix a bug in calculation of FW tracer timestamp. Decreasing one in the calculation should effect only bits 52_7 and not effect bits 6_0 of the timestamp, otherwise bits 6_0 are always set in this calculation.
--- drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +1 -1
@@ -638,7 +638,7 @@ static void mlx5_tracer_handle_timestamp_trace(struct mlx5_fw_tracer *tracer, trace_timestamp = (timestamp_event.timestamp &MASK_52_7 ) | (str_frmt->timestamp &MASK_6_0 ); else - trace_timestamp = ((timestamp_event.timestamp &MASK_52_7 ) -1 ) | + trace_timestamp = ((timestamp_event.timestamp -1 ) &MASK_52_7 ) | (str_frmt->timestamp &MASK_6_0 );mlx5_tracer_print_trace (str_frmt, dev, trace_timestamp);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 68/162 net/mlx5: Fix handling of entry refcount when command is not issued to FW
In reply to Greg Kroah-HartmanFrom: Moshe Shemesh <[email protected]>
[ Upstream commit aaf2e65cac7f2e1ae729c2fbc849091df9699f96 ]
In case command interface is down, or the command is not allowed, driver did not increment the entry refcount, but might have decrement as part of forced completion handling.
Fix that by always increment and decrement the refcount to make it symmetric for all flows.
--- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/cmd.c +3 -3
@@ -959,6 +959,7 @@ static void cmd_work_handler(struct work_struct *work)cmd_ent_get (ent);set_bit (MLX5_CMD_ENT_STATE_PENDING_COMP , &ent->state); +cmd_ent_get (ent);/* for the _real_ FW event on completion */ /* Skip sending command to fw if internal error */ if (mlx5_cmd_is_down (dev) || !opcode_allowed (&dev->cmd, ent->op)) {u8 status =0 ;
@@ -972,7 +973,6 @@ static void cmd_work_handler(struct work_struct *work)return ; } -cmd_ent_get (ent);/* for the _real_ FW event on completion */ /* ring doorbell after the descriptor is valid */ mlx5_core_dbg (dev,"writing 0x%x to command doorbell\n" ,1 << ent->idx);wmb ();
@@ -1586,8 +1586,8 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forcecmd_ent_put (ent);/* timeout work was canceled */ if (!forced ||/* Real FW completion */ -pci_channel_offline (dev->pdev) ||/* FW is inaccessible */ - dev->state ==MLX5_DEVICE_STATE_INTERNAL_ERROR ) +mlx5_cmd_is_down (dev) ||/* No real FW completion is expected */ + !opcode_allowed (cmd, ent->op))cmd_ent_put (ent); ent->ts2 =ktime_get_ns ();
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 69/162 tipc: set con sock in tipc_conn_alloc
In reply to Greg Kroah-HartmanFrom: Xin Long <[email protected]>
[ Upstream commit 0e5d56c64afcd6fd2d132ea972605b66f8a7d3c4 ]
A crash was reported by Wei Chen:
BUG: kernel NULL pointer dereference, address: 0000000000000018 RIP: 0010:tipc_conn_close+0x12/0x100 Call Trace: tipc_topsrv_exit_net+0x139/0x320 ops_exit_list.isra.9+0x49/0x80 cleanup_net+0x31a/0x540 process_one_work+0x3fa/0x9f0 worker_thread+0x42/0x5c0
It was caused by !con->sock in tipc_conn_close(). In tipc_topsrv_accept(), con is allocated in conn_idr then its sock is set:
con = tipc_conn_alloc(); ... <----[1] con->sock = newsock;
If tipc_conn_close() is called in anytime of [1], the null-pointer-def is triggered by con->sock->sk due to con->sock is not yet set.
This patch fixes it by moving the con->sock setting to tipc_conn_alloc() under s->idr_lock. So that con->sock can never be NULL when getting the con from s->conn_idr. It will be also safer to move con->server and flag CF_CONNECTED setting under s->idr_lock, as they should all be set before tipc_conn_alloc() is called.
--- net/tipc/topsrv.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
net/tipc/topsrv.c +5 -6
@@ -176,7 +176,7 @@ static void tipc_conn_close(struct tipc_conn *con)conn_put (con); } -static struct tipc_conn *tipc_conn_alloc (struct tipc_topsrv *s) +static struct tipc_conn *tipc_conn_alloc (struct tipc_topsrv *s,struct socket *sock) {struct tipc_conn *con;int ret;
@@ -202,10 +202,11 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) } con->conid = ret; s->idr_in_use++; -spin_unlock_bh (&s->idr_lock);set_bit (CF_CONNECTED , &con->flags); con->server = s; + con->sock = sock; +spin_unlock_bh (&s->idr_lock);return con; }
@@ -467,7 +468,7 @@ static void tipc_topsrv_accept(struct work_struct *work) ret =kernel_accept (lsock, &newsock,O_NONBLOCK );if (ret <0 )return ; - con =tipc_conn_alloc (srv); + con =tipc_conn_alloc (srv, newsock);if (IS_ERR (con)) { ret =PTR_ERR (con);sock_release (newsock);
@@ -479,7 +480,6 @@ static void tipc_topsrv_accept(struct work_struct *work) newsk->sk_data_ready = tipc_conn_data_ready; newsk->sk_write_space = tipc_conn_write_space; newsk->sk_user_data = con; - con->sock = newsock;write_unlock_bh (&newsk->sk_callback_lock);/* Wake up receive process in case of 'SYN+' message */
@@ -577,12 +577,11 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower, sub.filter = filter; *(u64 *)&sub.usr_handle = (u64 )port; - con =tipc_conn_alloc (tipc_topsrv (net)); + con =tipc_conn_alloc (tipc_topsrv (net),NULL );if (IS_ERR (con))return false; *conid = con->conid; - con->sock =NULL ; rc =tipc_conn_rcv_sub (tipc_topsrv (net), con, &sub);if (rc >=0 )return true;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 70/162 tipc: add an extra conn_get in tipc_conn_alloc
In reply to Greg Kroah-HartmanFrom: Xin Long <[email protected]>
[ Upstream commit a7b42969d63f47320853a802efd879fbdc4e010e ]
One extra conn_get() is needed in tipc_conn_alloc(), as after tipc_conn_alloc() is called, tipc_conn_close() may free this con before deferencing it in tipc_topsrv_accept():
tipc_conn_alloc();
newsk = newsock->sk;
<---- tipc_conn_close();
write_lock_bh(&sk->sk_callback_lock);
newsk->sk_data_ready = tipc_conn_data_ready;Then an uaf issue can be triggered:
BUG: KASAN: use-after-free in tipc_topsrv_accept+0x1e7/0x370 [tipc] Call Trace: <TASK> dump_stack_lvl+0x33/0x46 print_report+0x178/0x4b0 kasan_report+0x8c/0x100 kasan_check_range+0x179/0x1e0 tipc_topsrv_accept+0x1e7/0x370 [tipc] process_one_work+0x6a3/0x1030 worker_thread+0x8a/0xdf0
This patch fixes it by holding it in tipc_conn_alloc(), then after all accessing in tipc_topsrv_accept() releasing it. Note when does this in tipc_topsrv_kern_subscr(), as tipc_conn_rcv_sub() returns 0 or -1 only, we don't need to check for "> 0".
--- net/tipc/topsrv.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
net/tipc/topsrv.c +6 -3
@@ -206,6 +206,7 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *sset_bit (CF_CONNECTED , &con->flags); con->server = s; con->sock = sock; +conn_get (con);spin_unlock_bh (&s->idr_lock);return con;
@@ -484,6 +485,7 @@ static void tipc_topsrv_accept(struct work_struct *work)/* Wake up receive process in case of 'SYN+' message */ newsk->sk_data_ready (newsk); +conn_put (con); } }
@@ -583,10 +585,11 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower, *conid = con->conid; rc =tipc_conn_rcv_sub (tipc_topsrv (net), con, &sub); -if (rc >=0 ) -return true; +if (rc) +conn_put (con); +conn_put (con); -return false; +return !rc; }void tipc_topsrv_kern_unsubscr (struct net *net,int conid)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 71/162 tipc: check skb_linearize() return value in tipc_disc_rcv()
In reply to Greg Kroah-HartmanFrom: YueHaibing <[email protected]>
[ Upstream commit cd0f6421162201e4b22ce757a1966729323185eb ]
If skb_linearize() fails in tipc_disc_rcv(), we need to free the skb instead of handle it.
--- net/tipc/discover.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/tipc/discover.c +4 -1
@@ -210,7 +210,10 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb,u32 self;int err; -skb_linearize (skb); +if (skb_linearize (skb)) { +kfree_skb (skb); +return ; + } hdr =buf_msg (skb);if (caps &TIPC_NODE_ID128 )
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 72/162 xfrm: Fix ignored return value in xfrm6_init()
In reply to Greg Kroah-HartmanFrom: Chen Zhongjin <[email protected]>
[ Upstream commit 40781bfb836eda57d19c0baa37c7e72590e05fdc ]
When IPv6 module initializing in xfrm6_init(), register_pernet_subsys() is possible to fail but its return value is ignored.
If IPv6 initialization fails later and xfrm6_fini() is called, removing uninitialized list in xfrm6_net_ops will cause null-ptr-deref:
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 1 PID: 330 Comm: insmod RIP: 0010:unregister_pernet_operations+0xc9/0x450 Call Trace: <TASK> unregister_pernet_subsys+0x31/0x3e xfrm6_fini+0x16/0x30 [ipv6] ip6_route_init+0xcd/0x128 [ipv6] inet6_init+0x29c/0x602 [ipv6] ...
Fix it by catching the error return value of register_pernet_subsys().
--- net/ipv6/xfrm6_policy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/ipv6/xfrm6_policy.c +5 -1
@@ -289,9 +289,13 @@ int __init xfrm6_init(void)if (ret) goto out_state; -register_pernet_subsys (&xfrm6_net_ops); + ret =register_pernet_subsys (&xfrm6_net_ops); +if (ret) + goto out_protocol; out:return ret; +out_protocol: +xfrm6_protocol_fini (); out_state:xfrm6_state_fini (); out_policy:
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 73/162 sfc: fix potential memleak in __ef100_hard_start_xmit()
In reply to Greg Kroah-HartmanFrom: Zhang Changzhong <[email protected]>
[ Upstream commit aad98abd5cb8133507f22654f56bcb443aaa2d89 ]
The __ef100_hard_start_xmit() returns NETDEV_TX_OK without freeing skb in error handling case, add dev_kfree_skb_any() to fix it.
--- drivers/net/ethernet/sfc/ef100_netdev.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/sfc/ef100_netdev.c +1 -0
@@ -200,6 +200,7 @@ static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb, skb->len, skb->data_len, channel->channel);if (!efx->n_channels || !efx->n_tx_channels || !channel) {netif_stop_queue (net_dev); +dev_kfree_skb_any (skb); goto err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 74/162 net: sched: allow act_ct to be built without NF_NAT
In reply to Greg Kroah-HartmanFrom: Xin Long <[email protected]>
[ Upstream commit 8427fd100c7b7793650e212a81e42f1cf124613d ]
In commit f11fe1dae1c4 ("net/sched: Make NET_ACT_CT depends on NF_NAT"), it fixed the build failure when NF_NAT is m and NET_ACT_CT is y by adding depends on NF_NAT for NET_ACT_CT. However, it would also cause NET_ACT_CT cannot be built without NF_NAT, which is not expected. This patch fixes it by changing to use "(!NF_NAT || NF_NAT)" as the depend.
--- net/sched/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/Kconfig +1 -1
@@ -976,7 +976,7 @@ config NET_ACT_TUNNEL_KEY config NET_ACT_CT tristate "connection tracking tc action" - depends on NET_CLS_ACT && NF_CONNTRACK && NF_NAT && NF_FLOW_TABLE + depends on NET_CLS_ACT && NF_CONNTRACK && (!NF_NAT || NF_NAT) && NF_FLOW_TABLE help Say Y here to allow sending the packets to conntrack module.
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 75/162 NFC: nci: fix memory leak in nci_rx_data_packet()
In reply to Greg Kroah-HartmanFrom: Liu Shixin <[email protected]>
[ Upstream commit 53270fb0fd77fe786d8c07a0793981d797836b93 ]
Syzbot reported a memory leak about skb:
unreferenced object 0xffff88810e144e00 (size 240):
comm "syz-executor284", pid 3701, jiffies 4294952403 (age 12.620s) hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<ffffffff83ab79a9>] __alloc_skb+0x1f9/0x270 net/core/skbuff.c:497
[<ffffffff82a5cf64>] alloc_skb include/linux/skbuff.h:1267 [inline]
[<ffffffff82a5cf64>] virtual_ncidev_write+0x24/0xe0 drivers/nfc/virtual_ncidev.c:116
[<ffffffff815f6503>] do_loop_readv_writev fs/read_write.c:759 [inline]
[<ffffffff815f6503>] do_loop_readv_writev fs/read_write.c:743 [inline]
[<ffffffff815f6503>] do_iter_write+0x253/0x300 fs/read_write.c:863
[<ffffffff815f66ed>] vfs_writev+0xdd/0x240 fs/read_write.c:934
[<ffffffff815f68f6>] do_writev+0xa6/0x1c0 fs/read_write.c:977
[<ffffffff848802d5>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<ffffffff848802d5>] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
[<ffffffff84a00087>] entry_SYSCALL_64_after_hwframe+0x63/0xcdIn nci_rx_data_packet(), if we don't get a valid conn_info, we will return directly but forget to release the skb.
--- net/nfc/nci/data.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/nfc/nci/data.c +3 -1
@@ -279,8 +279,10 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) nci_plen(skb->data)); conn_info =nci_get_conn_info_by_conn_id (ndev,nci_conn_id (skb->data)); -if (!conn_info) +if (!conn_info) { +kfree_skb (skb);return ; + }/* strip the nci data header */ skb_pull (skb,NCI_DATA_HDR_SIZE );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 76/162 regulator: twl6030: re-add TWL6032_SUBCLASS
In reply to Greg Kroah-HartmanFrom: Andreas Kemnade <[email protected]>
[ Upstream commit 3d6c982b26db94cc21bc9f7784f63e8286b7be62 ]
In former times, info->feature was populated via the parent driver by pdata/regulator_init_data->driver_data for all regulators when USB_PRODUCT_ID_LSB indicates a TWL6032.
Today, the information is not set, so re-add it at the regulator definitions.
--- drivers/regulator/twl6030-regulator.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/regulator/twl6030-regulator.c +2 -0
@@ -530,6 +530,7 @@ static const struct twlreg_info TWL6030_INFO_##label = { \#define TWL6032_ADJUSTABLE_LDO (label, offset) \ static const struct twlreg_info TWL6032_INFO_##label = { \ .base = offset, \ + .features = TWL6032_SUBCLASS, \ .desc = { \ .name = #label, \ .id = TWL6032_REG_##label, \
@@ -562,6 +563,7 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \#define TWL6032_ADJUSTABLE_SMPS (label, offset) \ static const struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ + .features = TWL6032_SUBCLASS, \ .desc = { \ .name = #label, \ .id = TWL6032_REG_##label, \
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 77/162 bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit 3637a29ccbb6461b7268c5c5db525935d510afc6 ]
As comment of pci_get_domain_bus_and_slot() says, it returns a pci device with refcount increment, when finish using it, the caller must decrement the reference count by calling pci_dev_put(). Call pci_dev_put() before returning from bnx2x_vf_is_pcie_pending() to avoid refcount leak.
--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +8 -4
@@ -795,16 +795,20 @@ static void bnx2x_vf_enable_traffic(struct bnx2x *bp, struct bnx2x_virtf *vf)static u8 bnx2x_vf_is_pcie_pending (struct bnx2x *bp,u8 abs_vfid) { -struct pci_dev *dev;struct bnx2x_virtf *vf =bnx2x_vf_by_abs_fid (bp, abs_vfid); +struct pci_dev *dev; +bool pending;if (!vf)return false; dev =pci_get_domain_bus_and_slot (vf->domain, vf->bus, vf->devfn); -if (dev) -return bnx2x_is_pcie_pending (dev); -return false; +if (!dev) +return false; + pending =bnx2x_is_pcie_pending (dev); +pci_dev_put (dev); + +return pending; }int bnx2x_vf_flr_clnup_epilog (struct bnx2x *bp,u8 abs_vfid)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 78/162 dma-buf: fix racing conflict of dma_heap_add()
In reply to Greg Kroah-HartmanFrom: Dawei Li <[email protected]>
[ Upstream commit 432e25902b9651622578c6248e549297d03caf66 ]
Racing conflict could be:
task A task Blist_for_each_entrystrcmp(h->name))
list_for_each_entry
strcmp(h->name)
kzalloc kzalloc
...... .....
device_create device_createlist_add
list_add
The root cause is that task B has no idea about the fact someone else(A) has inserted heap with same name when it calls list_add, so a potential collision occurs.
--- drivers/dma-buf/dma-heap.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
drivers/dma-buf/dma-heap.c +15 -13
@@ -209,18 +209,6 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)return ERR_PTR (-EINVAL ); } -/* check the name is unique */ -mutex_lock (&heap_list_lock); -list_for_each_entry (h, &heap_list, list) { -if (!strcmp (h->name, exp_info->name)) { -mutex_unlock (&heap_list_lock); -pr_err ("dma_heap: Already registered heap named %s\n" , - exp_info->name); -return ERR_PTR (-EINVAL ); - } - } -mutex_unlock (&heap_list_lock); - heap =kzalloc (sizeof (*heap),GFP_KERNEL );if (!heap)return ERR_PTR (-ENOMEM );
@@ -259,13 +247,27 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) err_ret =ERR_CAST (dev_ret); goto err2; } -/* Add heap to the list */ +mutex_lock (&heap_list_lock); +/* check the name is unique */ +list_for_each_entry (h, &heap_list, list) { +if (!strcmp (h->name, exp_info->name)) { +mutex_unlock (&heap_list_lock); +pr_err ("dma_heap: Already registered heap named %s\n" , + exp_info->name); + err_ret =ERR_PTR (-EINVAL ); + goto err3; + } + } + +/* Add heap to the list */ list_add (&heap->list, &heap_list);mutex_unlock (&heap_list_lock);return heap; +err3: +device_destroy (dma_heap_class, heap->heap_devt); err2:cdev_del (&heap->heap_cdev); err1:
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 79/162 netfilter: flowtable_offload: add missing locking
In reply to Greg Kroah-HartmanFrom: Felix Fietkau <[email protected]>
[ Upstream commit bcd9e3c1656d0f7dd9743598c65c3ae24efb38d0 ]
nf_flow_table_block_setup and the driver TC_SETUP_FT call can modify the flow block cb list while they are being traversed elsewhere, causing a crash. Add a write lock around the calls to protect readers
--- net/netfilter/nf_flow_table_offload.c | 4 ++++ 1 file changed, 4 insertions(+)
net/netfilter/nf_flow_table_offload.c +4 -0
@@ -910,6 +910,7 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,struct flow_block_cb *block_cb, *next;int err =0 ; +down_write (&flowtable->flow_block_lock);switch (cmd) {case FLOW_BLOCK_BIND :list_splice (&bo->cb_list, &flowtable->flow_block.cb_list);
@@ -924,6 +925,7 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,WARN_ON_ONCE (1 ); err = -EOPNOTSUPP ; } +up_write (&flowtable->flow_block_lock);return err; }
@@ -980,7 +982,9 @@ static int nf_flow_table_offload_cmd(struct flow_block_offload *bo,nf_flow_table_block_offload_init (bo,dev_net (dev), cmd, flowtable, extack); +down_write (&flowtable->flow_block_lock); err = dev->netdev_ops->ndo_setup_tc (dev,TC_SETUP_FT , bo); +up_write (&flowtable->flow_block_lock);if (err <0 )return err;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 80/162 dccp/tcp: Reset saddr on failure after inet6?_hash_connect().
In reply to Greg Kroah-HartmanFrom: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 77934dc6db0d2b111a8f2759e9ad2fb67f5cffa5 ]
When connect() is called on a socket bound to the wildcard address, we change the socket's saddr to a local address. If the socket fails to connect() to the destination, we have to reset the saddr.
However, when an error occurs after inet_hash6?_connect() in (dccp|tcp)_v[46]_conect(), we forget to reset saddr and leave the socket bound to the address.
Quoted 1 line
From the user's point of view, whether saddr is reset or not varies
with errno. Let's fix this inconsistent behaviour.
Note that after this patch, the repro [0] will trigger the WARN_ON() in inet_csk_get_port() again, but this patch is not buggy and rather fixes a bug papering over the bhash2's bug for which we need another fix.
For the record, the repro causes -EADDRNOTAVAIL in inet_hash6_connect() by this sequence:
s1 = socket()
s1.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) s1.bind(('127.0.0.1', 10000)) s1.sendto(b'hello', MSG_FASTOPEN, (('127.0.0.1', 10000)))
# or s1.connect(('127.0.0.1', 10000)) s2 = socket()
s2.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) s2.bind(('0.0.0.0', 10000)) s2.connect(('127.0.0.1', 10000)) # -EADDRNOTAVAIL
s2.listen(32) # WARN_ON(inet_csk(sk)->icsk_bind2_hash != tb2);
[0]: https://syzkaller.appspot.com/bug?extid=015d756bbd1f8b5c8f09
--- net/dccp/ipv4.c | 2 ++ net/dccp/ipv6.c | 2 ++ net/ipv4/tcp_ipv4.c | 2 ++ net/ipv6/tcp_ipv6.c | 2 ++ 4 files changed, 8 insertions(+)
net/dccp/ipv4.c +2 -0
@@ -130,6 +130,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)* This unhashes the socket and releases the local port, if necessary. */ dccp_set_state (sk,DCCP_CLOSED ); +if (!(sk->sk_userlocks &SOCK_BINDADDR_LOCK )) +inet_reset_saddr (sk);ip_rt_put (rt); sk->sk_route_caps =0 ; inet->inet_dport =0 ;
net/dccp/ipv6.c +2 -0
@@ -957,6 +957,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, late_failure:dccp_set_state (sk,DCCP_CLOSED ); +if (!(sk->sk_userlocks &SOCK_BINDADDR_LOCK )) +inet_reset_saddr (sk);__sk_dst_reset (sk); failure: inet->inet_dport =0 ;
net/ipv4/tcp_ipv4.c +2 -0
@@ -322,6 +322,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)* if necessary. */ tcp_set_state (sk,TCP_CLOSE ); +if (!(sk->sk_userlocks &SOCK_BINDADDR_LOCK )) +inet_reset_saddr (sk);ip_rt_put (rt); sk->sk_route_caps =0 ; inet->inet_dport =0 ;
net/ipv6/tcp_ipv6.c +2 -0
@@ -339,6 +339,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, late_failure:tcp_set_state (sk,TCP_CLOSE ); +if (!(sk->sk_userlocks &SOCK_BINDADDR_LOCK )) +inet_reset_saddr (sk); failure: inet->inet_dport =0 ; sk->sk_route_caps =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 81/162 ipv4: Fix error return code in fib_table_insert()
In reply to Greg Kroah-HartmanFrom: Ziyang Xuan <[email protected]>
[ Upstream commit 568fe84940ac0e4e0b2cd7751b8b4911f7b9c215 ]
In fib_table_insert(), if the alias was already inserted, but node not exist, the error code should be set before return from error handling path.
--- net/ipv4/fib_trie.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv4/fib_trie.c +3 -1
@@ -1331,8 +1331,10 @@ int fib_table_insert(struct net *net, struct fib_table *tb,/* The alias was already inserted, so the node must exist. */ l = l ? l :fib_find_node (t, &tp, key); -if (WARN_ON_ONCE (!l)) +if (WARN_ON_ONCE (!l)) { + err = -ENOENT ; goto out_free_new_fa; + }if (fib_find_alias (&l->leaf, new_fa->fa_slen,0 ,0 , tb->tb_id, true) == new_fa) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 82/162 s390/dasd: fix no record found for raw_track_access
In reply to Greg Kroah-HartmanFrom: Stefan Haberland <[email protected]>
[ Upstream commit 590ce6d96d6a224b470a3862c33a483d5022bfdb ]
For DASD devices in raw_track_access mode only full track images are read and written.
For this purpose it is not necessary to do search operation in the locate record extended function. The documentation even states that this might fail if the searched record is not found on a track.
Currently the driver sets a value of 1 in the search field for the first record after record zero. This is the default for disks not in raw_track_access mode but record 1 might be missing on a completely empty track.
There has not been any problem with this on IBM storage servers but it might lead to errors with DASD devices on other vendors storage servers.
Fix this by setting the search field to 0. Record zero is always available even on a completely empty track.
--- drivers/s390/block/dasd_eckd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/s390/block/dasd_eckd.c +2 -4
@@ -4627,7 +4627,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,struct dasd_device *basedev;struct req_iterator iter;struct dasd_ccw_req *cqr; -unsigned int first_offs;unsigned int trkcount;unsigned long *idaws;unsigned int size;
@@ -4661,7 +4660,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, last_trk = (blk_rq_pos (req) +blk_rq_sectors (req) -1 ) /DASD_RAW_SECTORS_PER_TRACK ; trkcount = last_trk - first_trk +1 ; - first_offs =0 ;if (rq_data_dir (req) ==READ ) cmd =DASD_ECKD_CCW_READ_TRACK ;
@@ -4705,13 +4703,13 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,if (use_prefix) {prefix_LRE (ccw++, data, first_trk, last_trk, cmd, basedev, - startdev,1 , first_offs +1 , trkcount,0 ,0 ); + startdev,1 ,0 , trkcount,0 ,0 ); }else {define_extent (ccw++, data, first_trk, last_trk, cmd, basedev,0 ); ccw[-1 ].flags |=CCW_FLAG_CC ; data +=sizeof (struct DE_eckd_data ); -locate_record_ext (ccw++, data, first_trk, first_offs +1 , +locate_record_ext (ccw++, data, first_trk,0 , trkcount, cmd, basedev,0 ,0 ); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 83/162 net: arcnet: Fix RESET flag handling
In reply to Greg Kroah-HartmanFrom: Ahmed S. Darwish <[email protected]>
[ Upstream commit 01365633bd1c836240f9bbf86bbeee749795480a ]
The main arcnet interrupt handler calls arcnet_close() then arcnet_open(), if the RESET status flag is encountered.
This is invalid:
1) In general, interrupt handlers should never call ->ndo_stop() and ->ndo_open() functions. They are usually full of blocking calls and other methods that are expected to be called only from drivers init and exit code paths.
2) arcnet_close() contains a del_timer_sync(). If the irq handler interrupts the to-be-deleted timer, del_timer_sync() will just loop forever.
3) arcnet_close() also calls tasklet_kill(), which has a warning if called from irq context.
4) For device reset, the sequence "arcnet_close(); arcnet_open();" is not complete. Some children arcnet drivers have special init/exit code sequences, which then embed a call to arcnet_open() and arcnet_close() accordingly. Check drivers/net/arcnet/com20020.c.
Run the device RESET sequence from a scheduled workqueue instead.
Stable-dep-of: 1c40cde6b517 ("arcnet: fix potential memory leak in com20020_probe()")
--- drivers/net/arcnet/arc-rimi.c | 4 +- drivers/net/arcnet/arcdevice.h | 6 +++ drivers/net/arcnet/arcnet.c | 66 +++++++++++++++++++++++++++++-- drivers/net/arcnet/com20020-isa.c | 4 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020_cs.c | 2 +- drivers/net/arcnet/com90io.c | 4 +- drivers/net/arcnet/com90xx.c | 4 +- 8 files changed, 78 insertions(+), 14 deletions(-)
drivers/net/arcnet/arc-rimi.c +2 -2
@@ -332,7 +332,7 @@ static int __init arc_rimi_init(void) dev->irq =9 ;if (arcrimi_probe (dev)) { -free_netdev (dev); +free_arcdev (dev);return -EIO ; }
@@ -349,7 +349,7 @@ static void __exit arc_rimi_exit(void)iounmap (lp->mem_start);release_mem_region (dev->mem_start, dev->mem_end - dev->mem_start +1 );free_irq (dev->irq, dev); -free_netdev (dev); +free_arcdev (dev); }#ifndef MODULE
drivers/net/arcnet/arcdevice.h +6 -0
@@ -298,6 +298,10 @@ struct arcnet_local {int excnak_pending;/* We just got an excesive nak interrupt */ +/* RESET flag handling */ +int reset_in_progress; +struct work_struct reset_work; +struct {uint16_t sequence;/* sequence number (incs with each packet) */ __be16 aborted_seq;
@@ -350,7 +354,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)void arcnet_unregister_proto (struct ArcProto *proto);irqreturn_t arcnet_interrupt (int irq,void *dev_id); +struct net_device *alloc_arcdev (const char *name); +void free_arcdev (struct net_device *dev);int arcnet_open (struct net_device *dev);int arcnet_close (struct net_device *dev);
drivers/net/arcnet/arcnet.c +62 -4
113 lines not on this page · raw message
drivers/net/arcnet/com20020-isa.c +2 -2
@@ -169,7 +169,7 @@ static int __init com20020_init(void) dev->irq =9 ;if (com20020isa_probe (dev)) { -free_netdev (dev); +free_arcdev (dev);return -EIO ; }
@@ -182,7 +182,7 @@ static void __exit com20020_exit(void)unregister_netdev (my_dev);free_irq (my_dev->irq, my_dev);release_region (my_dev->base_addr,ARCNET_TOTAL_SIZE ); -free_netdev (my_dev); +free_arcdev (my_dev); }#ifndef MODULE
drivers/net/arcnet/com20020-pci.c +1 -1
@@ -294,7 +294,7 @@ static void com20020pci_remove(struct pci_dev *pdev)unregister_netdev (dev);free_irq (dev->irq, dev); -free_netdev (dev); +free_arcdev (dev); } }
drivers/net/arcnet/com20020_cs.c +1 -1
@@ -177,7 +177,7 @@ static void com20020_detach(struct pcmcia_device *link) dev = info->dev;if (dev) {dev_dbg (&link->dev,"kfree...\n" ); -free_netdev (dev); +free_arcdev (dev); }dev_dbg (&link->dev,"kfree2...\n" );kfree (info);
drivers/net/arcnet/com90io.c +2 -2
@@ -396,7 +396,7 @@ static int __init com90io_init(void) err =com90io_probe (dev);if (err) { -free_netdev (dev); +free_arcdev (dev);return err; }
@@ -419,7 +419,7 @@ static void __exit com90io_exit(void)free_irq (dev->irq, dev);release_region (dev->base_addr,ARCNET_TOTAL_SIZE ); -free_netdev (dev); +free_arcdev (dev); }module_init (com90io_init)
drivers/net/arcnet/com90xx.c +2 -2
@@ -554,7 +554,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, err_release_mem:release_mem_region (dev->mem_start, dev->mem_end - dev->mem_start +1 ); err_free_dev: -free_netdev (dev); +free_arcdev (dev);return -EIO ; }
@@ -672,7 +672,7 @@ static void __exit com90xx_exit(void)release_region (dev->base_addr,ARCNET_TOTAL_SIZE );release_mem_region (dev->mem_start, dev->mem_end - dev->mem_start +1 ); -free_netdev (dev); +free_arcdev (dev); } }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 84/162 arcnet: fix potential memory leak in com20020_probe()
In reply to Greg Kroah-HartmanFrom: Wang Hai <[email protected]>
[ Upstream commit 1c40cde6b5171d9c8dfc69be00464fd1c75e210b ]
In com20020_probe(), if com20020_config() fails, dev and info will not be freed, which will lead to a memory leak.
This patch adds freeing dev and info after com20020_config() fails to fix this bug.
Compile tested only.
--- drivers/net/arcnet/com20020_cs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/net/arcnet/com20020_cs.c +9 -2
@@ -113,6 +113,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)struct com20020_dev *info;struct net_device *dev;struct arcnet_local *lp; +int ret = -ENOMEM ;dev_dbg (&p_dev->dev,"com20020_attach()\n" );
@@ -142,12 +143,18 @@ static int com20020_probe(struct pcmcia_device *p_dev) info->dev = dev; p_dev->priv = info; -return com20020_config (p_dev); + ret =com20020_config (p_dev); +if (ret) + goto fail_config; + +return 0 ; +fail_config: +free_arcdev (dev); fail_alloc_dev:kfree (info); fail_alloc_info: -return -ENOMEM ; +return ret; }/* com20020_attach */ static void com20020_detach (struct pcmcia_device *link)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 85/162 nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION
In reply to Greg Kroah-HartmanFrom: Martin Faltesek <[email protected]>
[ Upstream commit c60c152230828825c06e62a8f1ce956d4b659266 ]
The first validation check for EVT_TRANSACTION has two different checks tied together with logical AND. One is a check for minimum packet length, and the other is for a valid aid_tag. If either condition is true (fails), then an error should be triggered. The fix is to change && to ||.
--- drivers/nfc/st-nci/se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nfc/st-nci/se.c +1 -1
@@ -327,7 +327,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,* AID 81 5 to 16 * PARAMETERS 82 0 to 255 */ -if (skb->len <NFC_MIN_AID_LENGTH +2 && +if (skb->len <NFC_MIN_AID_LENGTH +2 || skb->data[0 ] !=NFC_EVT_TRANSACTION_AID_TAG )return -EPROTO ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 86/162 nfc: st-nci: fix memory leaks in EVT_TRANSACTION
In reply to Greg Kroah-HartmanFrom: Martin Faltesek <[email protected]>
[ Upstream commit 440f2ae9c9f06e26f5dcea697a53717fc61a318c ]
Error path does not free previously allocated memory. Add devm_kfree() to the failure path.
--- drivers/nfc/st-nci/se.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/nfc/st-nci/se.c +3 -1
@@ -340,8 +340,10 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,/* Check next byte is PARAMETERS tag (82) */ if (skb->data[transaction->aid_len +2 ] != -NFC_EVT_TRANSACTION_PARAMS_TAG ) +NFC_EVT_TRANSACTION_PARAMS_TAG ) { +devm_kfree (dev, transaction);return -EPROTO ; + } transaction->params_len = skb->data[transaction->aid_len +3 ]; memcpy(transaction->params, skb->data +
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 87/162 net: thunderx: Fix the ACPI memory leak
In reply to Greg Kroah-HartmanFrom: Yu Liao <[email protected]>
[ Upstream commit 661e5ebbafd26d9d2e3c749f5cf591e55c7364f5 ]
The ACPI buffer memory (string.pointer) should be freed as the buffer is not used after returning from bgx_acpi_match_id(), free it to prevent memory leak.
--- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/cavium/thunder/thunder_bgx.c +3 -1
@@ -1438,8 +1438,10 @@ static acpi_status bgx_acpi_match_id(acpi_handle handle, u32 lvl,return AE_OK ; } -if (strncmp (string.pointer, bgx_sel,4 )) +if (strncmp (string.pointer, bgx_sel,4 )) { +kfree (string.pointer);return AE_OK ; + }acpi_walk_namespace (ACPI_TYPE_DEVICE , handle,1 , bgx_acpi_register_phy,NULL , bgx,NULL );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 88/162 s390/crashdump: fix TOD programmable field size
In reply to Greg Kroah-HartmanFrom: Heiko Carstens <[email protected]>
[ Upstream commit f44e07a8afdd713ddc1a8832c39372fe5dd86895 ]
The size of the TOD programmable field was incorrectly increased from four to eight bytes with commit 1a2c5840acf9 ("s390/dump: cleanup CPU save area handling").
This leads to an elf notes section NT_S390_TODPREG which has a size of eight instead of four bytes in case of kdump, however even worse is that the contents is incorrect: it is supposed to contain only the contents of the TOD programmable field, but in fact contains a mix of the TOD programmable field (32 bit upper bits) and parts of the CPU timer register (lower 32 bits).
Fix this by simply changing the size of the todpreg field within the save area structure. This will implicitly also fix the size of the corresponding elf notes sections.
This also gets rid of this compile time warning:
in function ‘fortify_memcpy_chk’,
inlined from ‘save_area_add_regs’ at arch/s390/kernel/crash_dump.c:99:2:./include/linux/fortify-string.h:413:25: error: call to ‘__read_overflow2_field’
declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning]
413 | __read_overflow2_field(q_size_field, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- arch/s390/kernel/crash_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/crash_dump.c +1 -1
@@ -44,7 +44,7 @@ struct save_area {u64 fprs[16 ];u32 fpc;u32 prefix; -u64 todpreg; +u32 todpreg;u64 timer;u64 todcmp;u64 vxrs_low[16 ];
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 89/162 net: enetc: manage ENETC_F_QBV in priv->active_offloads only when enabled
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit 32bf8e1f6fb9f6dc334b2b98dffc2e5dcd51e513 ]
Future work in this driver would like to look at priv->active_offloads & ENETC_F_QBV to determine whether a tc-taprio qdisc offload was installed, but this does not produce the intended effect.
All the other flags in priv->active_offloads are managed dynamically, except ENETC_F_QBV which is set statically based on the probed SI capability.
This change makes priv->active_offloads & ENETC_F_QBV really track the presence of a tc-taprio schedule on the port.
Some existing users, like the enetc_sched_speed_set() call from phylink_mac_link_up(), are best kept using the old logic: the tc-taprio offload does not re-trigger another link mode resolve, so the scheduler needs to be functional from the get go, as long as Qbv is supported at all on the port. So to preserve functionality there, look at the static station interface capability from pf->si->hw_features instead.
Stable-dep-of: 290b5fe096e7 ("net: enetc: preserve TX ring priority across reconfiguration")
--- drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 ++---- drivers/net/ethernet/freescale/enetc/enetc_qos.c | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-)
drivers/net/ethernet/freescale/enetc/enetc_pf.c +2 -4
@@ -748,9 +748,6 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, ndev->priv_flags |=IFF_UNICAST_FLT ; -if (si->hw_features &ENETC_SI_F_QBV ) - priv->active_offloads |=ENETC_F_QBV ; -if (si->hw_features &ENETC_SI_F_PSFP && !enetc_psfp_enable (priv)) { priv->active_offloads |=ENETC_F_QCI ; ndev->features |=NETIF_F_HW_TC ;
@@ -996,7 +993,8 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,struct enetc_ndev_priv *priv; priv =netdev_priv (pf->si->ndev); -if (priv->active_offloads &ENETC_F_QBV ) + +if (pf->si->hw_features &ENETC_SI_F_QBV )enetc_sched_speed_set (priv, speed); if (!phylink_autoneg_inband(mode) &&
drivers/net/ethernet/freescale/enetc/enetc_qos.c +6 -0
@@ -69,6 +69,9 @@ static int enetc_setup_taprio(struct net_device *ndev,enetc_wr (&priv->si->hw,ENETC_QBV_PTGCR_OFFSET , tge & (~ENETC_QBV_TGE )); + + priv->active_offloads &= ~ENETC_F_QBV ; +return 0 ; }
@@ -135,6 +138,9 @@ static int enetc_setup_taprio(struct net_device *ndev,dma_unmap_single (&priv->si->pdev->dev, dma, data_size,DMA_TO_DEVICE );kfree (gcl_data); +if (!err) + priv->active_offloads |=ENETC_F_QBV ; +return err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 90/162 net: enetc: cache accesses to &priv->si->hw
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit 715bf2610f1d1adf3d4f9b7b3dd729984ec4270a ]
The &priv->si->hw construct dereferences 2 pointers and makes lines longer than they need to be, in turn making the code harder to read.
Replace &priv->si->hw accesses with a "hw" variable when there are 2 or more accesses within a function that dereference this. This includes loops, since &priv->si->hw is a loop invariant.
Stable-dep-of: 290b5fe096e7 ("net: enetc: preserve TX ring priority across reconfiguration")
--- drivers/net/ethernet/freescale/enetc/enetc.c | 28 +++++---- drivers/net/ethernet/freescale/enetc/enetc.h | 9 +-- .../net/ethernet/freescale/enetc/enetc_qos.c | 60 +++++++++---------- 3 files changed, 49 insertions(+), 48 deletions(-)
drivers/net/ethernet/freescale/enetc/enetc.c +17 -11
@@ -1272,13 +1272,14 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)static void enetc_setup_bdrs (struct enetc_ndev_priv *priv) { +struct enetc_hw *hw = &priv->si->hw;int i;for (i =0 ; i < priv->num_tx_rings; i++) -enetc_setup_txbdr (&priv->si->hw, priv->tx_ring[i]); +enetc_setup_txbdr (hw, priv->tx_ring[i]);for (i =0 ; i < priv->num_rx_rings; i++) -enetc_setup_rxbdr (&priv->si->hw, priv->rx_ring[i]); +enetc_setup_rxbdr (hw, priv->rx_ring[i]); }static void enetc_clear_rxbdr (struct enetc_hw *hw,struct enetc_bdr *rx_ring)
@@ -1311,13 +1312,14 @@ static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)static void enetc_clear_bdrs (struct enetc_ndev_priv *priv) { +struct enetc_hw *hw = &priv->si->hw;int i;for (i =0 ; i < priv->num_tx_rings; i++) -enetc_clear_txbdr (&priv->si->hw, priv->tx_ring[i]); +enetc_clear_txbdr (hw, priv->tx_ring[i]);for (i =0 ; i < priv->num_rx_rings; i++) -enetc_clear_rxbdr (&priv->si->hw, priv->rx_ring[i]); +enetc_clear_rxbdr (hw, priv->rx_ring[i]);udelay (1 ); }
@@ -1325,13 +1327,13 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv)static int enetc_setup_irqs (struct enetc_ndev_priv *priv) {struct pci_dev *pdev = priv->si->pdev; +struct enetc_hw *hw = &priv->si->hw;int i, j, err;for (i =0 ; i < priv->bdr_int_num; i++) {int irq =pci_irq_vector (pdev,ENETC_BDR_INT_BASE_IDX + i);struct enetc_int_vector *v = priv->int_vector[i];int entry =ENETC_BDR_INT_BASE_IDX + i; -struct enetc_hw *hw = &priv->si->hw;snprintf (v->name,sizeof (v->name),"%s-rxtx%d" , priv->ndev->name, i);
@@ -1419,13 +1421,14 @@ static void enetc_setup_interrupts(struct enetc_ndev_priv *priv)static void enetc_clear_interrupts (struct enetc_ndev_priv *priv) { +struct enetc_hw *hw = &priv->si->hw;int i;for (i =0 ; i < priv->num_tx_rings; i++) -enetc_txbdr_wr (&priv->si->hw, i,ENETC_TBIER ,0 ); +enetc_txbdr_wr (hw, i,ENETC_TBIER ,0 );for (i =0 ; i < priv->num_rx_rings; i++) -enetc_rxbdr_wr (&priv->si->hw, i,ENETC_RBIER ,0 ); +enetc_rxbdr_wr (hw, i,ENETC_RBIER ,0 ); }static int enetc_phylink_connect (struct net_device *ndev)
@@ -1565,6 +1568,7 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) {struct enetc_ndev_priv *priv =netdev_priv (ndev);struct tc_mqprio_qopt *mqprio = type_data; +struct enetc_hw *hw = &priv->si->hw;struct enetc_bdr *tx_ring;u8 num_tc;int i;
@@ -1579,7 +1583,7 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)/* Reset all ring priorities to 0 */ for (i =0 ; i < priv->num_tx_rings; i++) { tx_ring = priv->tx_ring[i]; -enetc_set_bdr_prio (&priv->si->hw, tx_ring->index,0 ); +enetc_set_bdr_prio (hw, tx_ring->index,0 ); }return 0 ;
@@ -1598,7 +1602,7 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)*/ for (i =0 ; i < num_tc; i++) { tx_ring = priv->tx_ring[i]; -enetc_set_bdr_prio (&priv->si->hw, tx_ring->index, i); +enetc_set_bdr_prio (hw, tx_ring->index, i); }/* Reset the number of netdev queues based on the TC count */
@@ -1679,19 +1683,21 @@ static int enetc_set_rss(struct net_device *ndev, int en)static void enetc_enable_rxvlan (struct net_device *ndev,bool en) {struct enetc_ndev_priv *priv =netdev_priv (ndev); +struct enetc_hw *hw = &priv->si->hw;int i;for (i =0 ; i < priv->num_rx_rings; i++) -enetc_bdr_enable_rxvlan (&priv->si->hw, i, en); +enetc_bdr_enable_rxvlan (hw, i, en); }static void enetc_enable_txvlan (struct net_device *ndev,bool en) {struct enetc_ndev_priv *priv =netdev_priv (ndev); +struct enetc_hw *hw = &priv->si->hw;int i;for (i =0 ; i < priv->num_tx_rings; i++) -enetc_bdr_enable_txvlan (&priv->si->hw, i, en); +enetc_bdr_enable_txvlan (hw, i, en); }void enetc_set_features (struct net_device *ndev,netdev_features_t features)
drivers/net/ethernet/freescale/enetc/enetc.h +5 -4
@@ -338,19 +338,20 @@ int enetc_set_psfp(struct net_device *ndev, bool en);static inline void enetc_get_max_cap (struct enetc_ndev_priv *priv) { +struct enetc_hw *hw = &priv->si->hw;u32 reg; - reg =enetc_port_rd (&priv->si->hw,ENETC_PSIDCAPR ); + reg =enetc_port_rd (hw,ENETC_PSIDCAPR ); priv->psfp_cap.max_streamid = reg &ENETC_PSIDCAPR_MSK ;/* Port stream filter capability */ - reg =enetc_port_rd (&priv->si->hw,ENETC_PSFCAPR ); + reg =enetc_port_rd (hw,ENETC_PSFCAPR ); priv->psfp_cap.max_psfp_filter = reg &ENETC_PSFCAPR_MSK ;/* Port stream gate capability */ - reg =enetc_port_rd (&priv->si->hw,ENETC_PSGCAPR ); + reg =enetc_port_rd (hw,ENETC_PSGCAPR ); priv->psfp_cap.max_psfp_gate = (reg &ENETC_PSGCAPR_SGIT_MSK ); priv->psfp_cap.max_psfp_gatelist = (reg &ENETC_PSGCAPR_GCL_MSK ) >>16 ;/* Port flow meter capability */ - reg =enetc_port_rd (&priv->si->hw,ENETC_PFMCAPR ); + reg =enetc_port_rd (hw,ENETC_PFMCAPR ); priv->psfp_cap.max_psfp_meter = reg &ENETC_PFMCAPR_MSK ; }
drivers/net/ethernet/freescale/enetc/enetc_qos.c +27 -33
180 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 91/162 net: enetc: preserve TX ring priority across reconfiguration
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit 290b5fe096e7dd0aad730d1af4f7f2d9fea43e11 ]
In the blamed commit, a rudimentary reallocation procedure for RX buffer descriptors was implemented, for the situation when their format changes between normal (no PTP) and extended (PTP).
enetc_hwtstamp_set() calls enetc_close() and enetc_open() in a sequence, and this sequence loses information which was previously configured in the TX BDR Mode Register, specifically via the enetc_set_bdr_prio() call. The TX ring priority is configured by tc-mqprio and tc-taprio, and affects important things for TSN such as the TX time of packets. The issue manifests itself most visibly by the fact that isochron --txtime reports premature packet transmissions when PTP is first enabled on an enetc interface.
Save the TX ring priority in a new field in struct enetc_bdr (occupies a 2 byte hole on arm64) in order to make this survive a ring reconfiguration.
--- drivers/net/ethernet/freescale/enetc/enetc.c | 8 ++++--- drivers/net/ethernet/freescale/enetc/enetc.h | 1 + .../net/ethernet/freescale/enetc/enetc_qos.c | 21 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-)
drivers/net/ethernet/freescale/enetc/enetc.c +5 -3
@@ -1212,7 +1212,7 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)/* enable Tx ints by setting pkt thr to 1 */ enetc_txbdr_wr (hw, idx,ENETC_TBICR0 ,ENETC_TBICR0_ICEN |0x1 ); - tbmr =ENETC_TBMR_EN ; + tbmr =ENETC_TBMR_EN |ENETC_TBMR_SET_PRIO (tx_ring->prio);if (tx_ring->ndev->features &NETIF_F_HW_VLAN_CTAG_TX ) tbmr |=ENETC_TBMR_VIH ;
@@ -1583,7 +1583,8 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)/* Reset all ring priorities to 0 */ for (i =0 ; i < priv->num_tx_rings; i++) { tx_ring = priv->tx_ring[i]; -enetc_set_bdr_prio (hw, tx_ring->index,0 ); + tx_ring->prio =0 ; +enetc_set_bdr_prio (hw, tx_ring->index, tx_ring->prio); }return 0 ;
@@ -1602,7 +1603,8 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)*/ for (i =0 ; i < num_tc; i++) { tx_ring = priv->tx_ring[i]; -enetc_set_bdr_prio (hw, tx_ring->index, i); + tx_ring->prio = i; +enetc_set_bdr_prio (hw, tx_ring->index, tx_ring->prio); }/* Reset the number of netdev queues based on the TC count */
drivers/net/ethernet/freescale/enetc/enetc.h +1 -0
@@ -58,6 +58,7 @@ struct enetc_bdr {void __iomem *rcir; };u16 index; +u16 prio;int bd_count;/* # of BDs */ int next_to_use;int next_to_clean;
drivers/net/ethernet/freescale/enetc/enetc_qos.c +13 -8
@@ -144,6 +144,7 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)struct tc_taprio_qopt_offload *taprio = type_data;struct enetc_ndev_priv *priv =netdev_priv (ndev);struct enetc_hw *hw = &priv->si->hw; +struct enetc_bdr *tx_ring;int err;int i;
@@ -152,16 +153,20 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)if (priv->tx_ring[i]->tsd_enable)return -EBUSY ; -for (i =0 ; i < priv->num_tx_rings; i++) -enetc_set_bdr_prio (hw, priv->tx_ring[i]->index, - taprio->enable ? i :0 ); +for (i =0 ; i < priv->num_tx_rings; i++) { + tx_ring = priv->tx_ring[i]; + tx_ring->prio = taprio->enable ? i :0 ; +enetc_set_bdr_prio (hw, tx_ring->index, tx_ring->prio); + } err =enetc_setup_taprio (ndev, taprio); - -if (err) -for (i =0 ; i < priv->num_tx_rings; i++) -enetc_set_bdr_prio (hw, priv->tx_ring[i]->index, - taprio->enable ?0 : i); +if (err) { +for (i =0 ; i < priv->num_tx_rings; i++) { + tx_ring = priv->tx_ring[i]; + tx_ring->prio = taprio->enable ?0 : i; +enetc_set_bdr_prio (hw, tx_ring->index, tx_ring->prio); + } + }return err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 92/162 lib/vdso: use "grep -E" instead of "egrep"
In reply to Greg Kroah-HartmanFrom: Greg Kroah-Hartman <[email protected]>
commit 8ac3b5cd3e0521d92f9755e90d140382fc292510 upstream.
The latest version of grep claims the egrep is now obsolete so the build now contains warnings that look like:
egrep: warning: egrep is obsolescent; using grep -E
fix this up by moving the vdso Makefile to use "grep -E" instead.
--- lib/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/vdso/Makefile +1 -1
@@ -17,6 +17,6 @@ $(error ARCH_REL_TYPE_ABS is not set) endif quiet_cmd_vdso_check = VDSOCHK $@ - cmd_vdso_check = if $(OBJDUMP) -R $@ | egrep -h "$(ARCH_REL_TYPE_ABS)"; \ + cmd_vdso_check = if $(OBJDUMP) -R $@ | grep -E -h "$(ARCH_REL_TYPE_ABS)"; \ then (echo >&2 "$@: dynamic relocations are not supported"; \ rm -f $@; /bin/false); fi
Greg Kroah-Hartman
maintainerPATCH 93/162 usb: dwc3: exynos: Fix remove() function
In reply to Greg Kroah-HartmanFrom: Marek Szyprowski <[email protected]>
commit e0481e5b3cc12ea7ccf4552d41518c89d3509004 upstream.
The core DWC3 device node was not properly removed by the custom dwc3_exynos_remove_child() function. Replace it with generic of_platform_depopulate() which does that job right.
--- drivers/usb/dwc3/dwc3-exynos.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
drivers/usb/dwc3/dwc3-exynos.c +1 -10
@@ -37,15 +37,6 @@ struct dwc3_exynos {struct regulator *vdd10; }; -static int dwc3_exynos_remove_child (struct device *dev,void *unused) -{ -struct platform_device *pdev =to_platform_device (dev); - -platform_device_unregister (pdev); - -return 0 ; -} -static int dwc3_exynos_probe (struct platform_device *pdev) {struct dwc3_exynos *exynos;
@@ -142,7 +133,7 @@ static int dwc3_exynos_remove(struct plastruct dwc3_exynos *exynos =platform_get_drvdata (pdev);int i; -device_for_each_child (&pdev->dev,NULL , dwc3_exynos_remove_child); +of_platform_depopulate (&pdev->dev);for (i = exynos->num_clks -1 ; i >=0 ; i--)clk_disable_unprepare (exynos->clks[i]);
Greg Kroah-Hartman
maintainerPATCH 94/162 ext4: fix use-after-free in ext4_ext_shift_extents
In reply to Greg Kroah-HartmanFrom: Baokun Li <[email protected]>
commit f6b1a1cf1c3ee430d3f5e47847047ce789a690aa upstream.
If the starting position of our insert range happens to be in the hole between the two ext4_extent_idx, because the lblk of the ext4_extent in the previous ext4_extent_idx is always less than the start, which leads to the "extent" variable access across the boundary, the following UAF is triggered:
==================================================================
BUG: KASAN: use-after-free in ext4_ext_shift_extents+0x257/0x790 Read of size 4 at addr ffff88819807a008 by task fallocate/8010 CPU: 3 PID: 8010 Comm: fallocate Tainted: G E 5.10.0+ #492 Call Trace: dump_stack+0x7d/0xa3 print_address_description.constprop.0+0x1e/0x220 kasan_report.cold+0x67/0x7f ext4_ext_shift_extents+0x257/0x790 ext4_insert_range+0x5b6/0x700 ext4_fallocate+0x39e/0x3d0 vfs_fallocate+0x26f/0x470 ksys_fallocate+0x3a/0x70 __x64_sys_fallocate+0x4f/0x60 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ==================================================================
For right shifts, we can divide them into the following situations:
1. When the first ee_block of ext4_extent_idx is greater than or equal to start, make right shifts directly from the first ee_block.
1) If it is greater than start, we need to continue searching in the previous ext4_extent_idx.
2) If it is equal to start, we can exit the loop (iterator=NULL).
2. When the first ee_block of ext4_extent_idx is less than start, then traverse from the last extent to find the first extent whose ee_block is less than start.
1) If extent is still the last extent after traversal, it means that the last ee_block of ext4_extent_idx is less than start, that is, start is located in the hole between idx and (idx+1), so we can exit the loop directly (break) without right shifts.
2) Otherwise, make right shifts at the corresponding position of the found extent, and then exit the loop (iterator=NULL).
--- fs/ext4/extents.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
fs/ext4/extents.c +13 -5
@@ -5182,6 +5182,7 @@ ext4_ext_shift_extents(struct inode *ino* and it is decreased till we reach start. */ again: + ret =0 ;if (SHIFT ==SHIFT_LEFT ) iterator = &start;else
@@ -5225,14 +5226,21 @@ again:ext4_ext_get_actual_len (extent); }else { extent =EXT_FIRST_EXTENT (path[depth].p_hdr); -if (le32_to_cpu (extent->ee_block) >0 ) +if (le32_to_cpu (extent->ee_block) > start) *iterator =le32_to_cpu (extent->ee_block) -1 ; -else -/* Beginning is reached, end of the loop */ +else if (le32_to_cpu (extent->ee_block) == start) iterator =NULL ; -/* Update path extent in case we need to stop */ -while (le32_to_cpu (extent->ee_block) < start) +else { + extent =EXT_LAST_EXTENT (path[depth].p_hdr); +while (le32_to_cpu (extent->ee_block) >= start) + extent--; + +if (extent ==EXT_LAST_EXTENT (path[depth].p_hdr)) +break ; + extent++; + iterator =NULL ; + } path[depth].p_ext = extent; } ret = ext4_ext_shift_path_extents(path, shift, inode,
Greg Kroah-Hartman
maintainerPATCH 95/162 arm64: dts: rockchip: lower rk3399-puma-haikou SD controller clock frequency
In reply to Greg Kroah-HartmanFrom: Jakob Unterwurzacher <[email protected]>
commit 91e8b74fe6381e083f8aa55217bb0562785ab398 upstream.
CRC errors (code -84 EILSEQ) have been observed for some SanDisk Ultra A1 cards when running at 50MHz.
Waveform analysis suggest that the level shifters that are used on the RK3399-Q7 module for voltage translation between 3.0 and 3.3V don't handle clock rates at or above 48MHz properly. Back off to 40MHz for some safety margin.
--- arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +1 -1
@@ -203,7 +203,7 @@ cap-sd-highspeed; cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; disable-wp; - max-frequency = <150000000>; + max-frequency = <40000000>; pinctrl-names = "default"; pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; vmmc-supply = <&vcc3v3_baseboard>;
Greg Kroah-Hartman
maintainerPATCH 96/162 kbuild: fix -Wimplicit-function-declaration in license_is_gpl_compatible
In reply to Greg Kroah-HartmanFrom: Sam James <[email protected]>
commit 50c697215a8cc22f0e58c88f06f2716c05a26e85 upstream.
Add missing <linux/string.h> include for strcmp.
Clang 16 makes -Wimplicit-function-declaration an error by default. Unfortunately, out of tree modules may use this in configure scripts, which means failure might cause silent miscompilation or misconfiguration.
For more information, see LWN.net [0] or LLVM's Discourse [1], gentoo-dev@ [2], or the (new) c-std-porting mailing list [3].
[0] https://lwn.net/Articles/913505/
[1] https://discourse.llvm.org/t/configure-script-breakage-with-the-new-werror-implicit-function-declaration/65213
[2] https://archives.gentoo.org/gentoo-dev/message/dd9f2d3082b8b6f8dfbccb0639e6e240
[3] hosted at lists.linux.dev.
--- include/linux/license.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/license.h +2 -0
@@ -2,6 +2,8 @@#ifndef __LICENSE_H#define __LICENSE_H +#include <linux/string.h> +static inline int license_is_gpl_compatible (const char *license) { return (strcmp(license, "GPL") == 0
Greg Kroah-Hartman
maintainerPATCH 97/162 iio: light: apds9960: fix wrong register for gesture gain
In reply to Greg Kroah-HartmanFrom: Alejandro Concepción Rodríguez <[email protected]>
commit 0aa60ff5d996d4ecdd4a62699c01f6d00f798d59 upstream.
Gesture Gain Control is in REG_GCONF_2 (0xa3), not in REG_CONFIG_2 (0x90).
--- drivers/iio/light/apds9960.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/iio/light/apds9960.c +6 -6
@@ -53,9 +53,6 @@#define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT 2#define APDS9960_REG_CONFIG_2 0x90 -#define APDS9960_REG_CONFIG_2_GGAIN_MASK 0x60 -#define APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT 5 -#define APDS9960_REG_ID 0x92#define APDS9960_REG_STATUS 0x93
@@ -76,6 +73,9 @@#define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT 6#define APDS9960_REG_GCONF_2 0xa3 +#define APDS9960_REG_GCONF_2_GGAIN_MASK 0x60 +#define APDS9960_REG_GCONF_2_GGAIN_MASK_SHIFT 5 +#define APDS9960_REG_GOFFSET_U 0xa4#define APDS9960_REG_GOFFSET_D 0xa5#define APDS9960_REG_GPULSE 0xa6
@@ -395,9 +395,9 @@ static int apds9960_set_pxs_gain(struct } ret =regmap_update_bits (data->regmap, -APDS9960_REG_CONFIG_2 , -APDS9960_REG_CONFIG_2_GGAIN_MASK , - idx <<APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT ); +APDS9960_REG_GCONF_2 , +APDS9960_REG_GCONF_2_GGAIN_MASK , + idx <<APDS9960_REG_GCONF_2_GGAIN_MASK_SHIFT );if (!ret) data->pxs_gain = idx;mutex_unlock (&data->lock);
Greg Kroah-Hartman
maintainerPATCH 98/162 iio: core: Fix entry not deleted when iio_register_sw_trigger_type() fails
In reply to Greg Kroah-HartmanFrom: Chen Zhongjin <[email protected]>
commit 4ad09d956f8eacff61e67e5b13ba8ebec3232f76 upstream.
In iio_register_sw_trigger_type(), configfs_register_default_group() is possible to fail, but the entry add to iio_trigger_types_list is not deleted.
This leaves wild in iio_trigger_types_list, which can cause page fault when module is loading again. So fix this by list_del(&t->list) in error path.
BUG: unable to handle page fault for address: fffffbfff81d7400 Call Trace: <TASK> iio_register_sw_trigger_type do_one_initcall do_init_module load_module ...
--- drivers/iio/industrialio-sw-trigger.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iio/industrialio-sw-trigger.c +5 -1
@@ -58,8 +58,12 @@ int iio_register_sw_trigger_type(struct t->group =configfs_register_default_group (iio_triggers_group, t->name, &iio_trigger_type_group_type); -if (IS_ERR (t->group)) +if (IS_ERR (t->group)) { +mutex_lock (&iio_trigger_types_lock); +list_del (&t->list); +mutex_unlock (&iio_trigger_types_lock); ret =PTR_ERR (t->group); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 99/162 init/Kconfig: fix CC_HAS_ASM_GOTO_TIED_OUTPUT test with dash
In reply to Greg Kroah-HartmanFrom: Alexandre Belloni <[email protected]>
[ Upstream commit 534bd70374d646f17e2cebe0e6e4cdd478ce4f0c ]
When using dash as /bin/sh, the CC_HAS_ASM_GOTO_TIED_OUTPUT test fails with a syntax error which is not the one we are looking for:
<stdin>: In function ‘foo’:
<stdin>:1:29: warning: missing terminating " character <stdin>:1:29: error: missing terminating " character <stdin>:2:5: error: expected ‘:’ before ‘+’ token <stdin>:2:7: warning: missing terminating " character <stdin>:2:7: error: missing terminating " character <stdin>:2:5: error: expected declaration or statement at end of input
Removing '\n' solves this.
--- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
init/Kconfig +1 -1
@@ -71,7 +71,7 @@ config CC_HAS_ASM_GOTO_OUTPUT config CC_HAS_ASM_GOTO_TIED_OUTPUT depends on CC_HAS_ASM_GOTO_OUTPUT # Detect buggy gcc and clang, fixed in gcc-11 clang-14. - def_bool $(success,echo 'int foo(int *x) { asm goto (".long (%l[bar]) - .\n": "+m"(*x) ::: bar); return *x; bar: return 0; }' | $CC -x c - -c -o /dev/null) + def_bool $(success,echo 'int foo(int *x) { asm goto (".long (%l[bar]) - .": "+m"(*x) ::: bar); return *x; bar: return 0; }' | $CC -x c - -c -o /dev/null) config TOOLS_SUPPORT_RELR def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 100/162 nios2: add FORCE for vmlinuz.gz
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
[ Upstream commit 869e4ae4cd2a23d625aaa14ae62dbebf768cb77d ]
Add FORCE to placate a warning from make:
arch/nios2/boot/Makefile:24: FORCE prerequisite is missing
--- arch/nios2/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/nios2/boot/Makefile +1 -1
@@ -20,7 +20,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -$(obj)/vmImage: $(obj)/vmlinux.gz +$(obj)/vmImage: $(obj)/vmlinux.gz FORCE $(call if_changed,uimage) @$(kecho) 'Kernel: $@ is ready'
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 101/162 KVM: x86: emulator: update the emulation mode after rsm
In reply to Greg Kroah-HartmanFrom: Maxim Levitsky <[email protected]>
[ Upstream commit 055f37f84e304e59c046d1accfd8f08462f52c4c ]
Update the emulation mode after RSM so that RIP will be correctly written back, because the RSM instruction can switch the CPU mode from 32 bit (or less) to 64 bit.
This fixes a guest crash in case the #SMI is received while the guest runs a code from an address > 32 bit.
Message-Id: <[email protected]>
--- arch/x86/kvm/emulate.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/x86/kvm/emulate.c +9 -0
@@ -2746,6 +2746,15 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) ctxt->ops->post_leave_smm (ctxt); +/* +* Note, the ctxt->ops callbacks are responsible for handling side +* effects when writing MSRs and CRs, e.g. MMU context resets, CPUID +* runtime updates, etc... If that changes, e.g. this flow is moved +* out of the emulator to make it look more like enter_smm(), then +* those side effects need to be explicitly handled for both success +* and shutdown. +*/ +return X86EMUL_CONTINUE ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 102/162 mmc: sdhci-brcmstb: Re-organize flags
In reply to Greg Kroah-HartmanFrom: Al Cooper <[email protected]>
[ Upstream commit f3a70f991dd07330225ea11e158e1d07ad5733fb ]
Re-organize the flags by basing the bit names on the flag that they apply to. Also change the "flags" member in the "brcmstb_match_priv" struct to const.
Stable-dep-of: 56baa208f910 ("mmc: sdhci-brcmstb: Fix SDHCI_RESET_ALL for CQHCI")
--- drivers/mmc/host/sdhci-brcmstb.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci-brcmstb.c +16 -16
@@ -18,20 +18,22 @@#define SDHCI_VENDOR 0x78#define SDHCI_VENDOR_ENHANCED_STRB 0x1 -#define BRCMSTB_PRIV_FLAGS_NO_64BIT BIT(0) -#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT BIT(1) +#define BRCMSTB_MATCH_FLAGS_NO_64BIT BIT(0) +#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT BIT(1) + +#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200struct sdhci_brcmstb_priv {void __iomem *cfg_regs; -bool has_cqe; +unsigned int flags; };struct brcmstb_match_priv {void (*hs400es)(struct mmc_host *mmc,struct mmc_ios *ios);struct sdhci_ops *ops; -unsigned int flags; +const unsigned int flags; };static void sdhci_brcmstb_hs400es (struct mmc_host *mmc,struct mmc_ios *ios)
@@ -134,13 +136,13 @@ static struct sdhci_ops sdhci_brcmstb_ops_7216 = { };static struct brcmstb_match_priv match_priv_7425 = { - .flags =BRCMSTB_PRIV_FLAGS_NO_64BIT | -BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT , + .flags =BRCMSTB_MATCH_FLAGS_NO_64BIT | +BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT , .ops = &sdhci_brcmstb_ops, };static struct brcmstb_match_priv match_priv_7445 = { - .flags =BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT , + .flags =BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT , .ops = &sdhci_brcmstb_ops, };
@@ -176,7 +178,7 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host,bool dma64;int ret; -if (!priv->has_cqe) +if ((priv->flags &BRCMSTB_PRIV_FLAGS_HAS_CQE ) ==0 )return sdhci_add_host (host);dev_dbg (mmc_dev (host->mmc),"CQE is enabled\n" );
@@ -225,7 +227,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)struct sdhci_brcmstb_priv *priv;struct sdhci_host *host;struct resource *iomem; -bool has_cqe = false;struct clk *clk;int res;
@@ -244,10 +245,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)return res;memset (&brcmstb_pdata,0 ,sizeof (brcmstb_pdata)); -if (device_property_read_bool (&pdev->dev,"supports-cqe" )) { - has_cqe = true; - match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; - } brcmstb_pdata.ops = match_priv->ops; host =sdhci_pltfm_init (pdev, &brcmstb_pdata,sizeof (struct sdhci_brcmstb_priv ));
@@ -258,7 +255,10 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) pltfm_host =sdhci_priv (host); priv =sdhci_pltfm_priv (pltfm_host); - priv->has_cqe = has_cqe; +if (device_property_read_bool (&pdev->dev,"supports-cqe" )) { + priv->flags |=BRCMSTB_PRIV_FLAGS_HAS_CQE ; + match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; + }/* Map in the non-standard CFG registers */ iomem =platform_get_resource (pdev,IORESOURCE_MEM ,1 );
@@ -287,14 +287,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)* properties through mmc_of_parse(). */ host->caps =sdhci_readl (host,SDHCI_CAPABILITIES ); -if (match_priv->flags &BRCMSTB_PRIV_FLAGS_NO_64BIT ) +if (match_priv->flags &BRCMSTB_MATCH_FLAGS_NO_64BIT ) host->caps &= ~SDHCI_CAN_64BIT ; host->caps1 =sdhci_readl (host,SDHCI_CAPABILITIES_1 ); host->caps1 &= ~(SDHCI_SUPPORT_SDR50 |SDHCI_SUPPORT_SDR104 |SDHCI_SUPPORT_DDR50 ); host->quirks |=SDHCI_QUIRK_MISSING_CAPS ; -if (match_priv->flags &BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT ) +if (match_priv->flags &BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT ) host->quirks |=SDHCI_QUIRK_BROKEN_TIMEOUT_VAL ; res =sdhci_brcmstb_add_host (host, priv);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 103/162 mmc: sdhci-brcmstb: Enable Clock Gating to save power
In reply to Greg Kroah-HartmanFrom: Al Cooper <[email protected]>
[ Upstream commit 6bcc55fe648b860ef0c2b8dc23adc05bcddb93c2 ]
Enabling this feature will allow the controller to stop the bus clock when the bus is idle. The feature is not part of the standard and is unique to newer Arasan cores and is enabled with a bit in a vendor specific register. This feature will only be enabled for non-removable devices because they don't switch the voltage and clock gating breaks SD Card volatge switching.
Stable-dep-of: 56baa208f910 ("mmc: sdhci-brcmstb: Fix SDHCI_RESET_ALL for CQHCI")
--- drivers/mmc/host/sdhci-brcmstb.c | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci-brcmstb.c +34 -1
@@ -17,11 +17,14 @@#define SDHCI_VENDOR 0x78#define SDHCI_VENDOR_ENHANCED_STRB 0x1 +#define SDHCI_VENDOR_GATE_SDCLK_EN 0x2#define BRCMSTB_MATCH_FLAGS_NO_64BIT BIT(0)#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT BIT(1) +#define BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE BIT(2)#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0) +#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
@@ -36,6 +39,27 @@ struct brcmstb_match_priv {const unsigned int flags; }; +static inline void enable_clock_gating (struct sdhci_host *host) +{ +u32 reg; + + reg =sdhci_readl (host,SDHCI_VENDOR ); + reg |=SDHCI_VENDOR_GATE_SDCLK_EN ; +sdhci_writel (host, reg,SDHCI_VENDOR ); +} + +void brcmstb_reset (struct sdhci_host *host,u8 mask) +{ +struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host); +struct sdhci_brcmstb_priv *priv =sdhci_pltfm_priv (pltfm_host); + +sdhci_reset (host, mask); + +/* Reset will clear this, so re-enable it */ +if (priv->flags &BRCMSTB_PRIV_FLAGS_GATE_CLOCK ) +enable_clock_gating (host); +} +static void sdhci_brcmstb_hs400es (struct mmc_host *mmc,struct mmc_ios *ios) {struct sdhci_host *host =mmc_priv (mmc);
@@ -131,7 +155,7 @@ static struct sdhci_ops sdhci_brcmstb_ops = {static struct sdhci_ops sdhci_brcmstb_ops_7216 = { .set_clock = sdhci_brcmstb_set_clock, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = brcmstb_reset, .set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling, };
@@ -147,6 +171,7 @@ static struct brcmstb_match_priv match_priv_7445 = { };static const struct brcmstb_match_priv match_priv_7216 = { + .flags =BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE , .hs400es = sdhci_brcmstb_hs400es, .ops = &sdhci_brcmstb_ops_7216, };
@@ -273,6 +298,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)if (res) goto err; +/* +* Automatic clock gating does not work for SD cards that may +* voltage switch so only enable it for non-removable devices. +*/ +if ((match_priv->flags &BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE ) && + (host->mmc->caps &MMC_CAP_NONREMOVABLE )) + priv->flags |=BRCMSTB_PRIV_FLAGS_GATE_CLOCK ; +/* * If the chip has enhanced strobe and it's enabled, add * callback
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 104/162 mmc: sdhci-brcmstb: Fix SDHCI_RESET_ALL for CQHCI
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
[ Upstream commit 56baa208f91061ff27ec2d93fbc483f624d373b4 ]
[[ NOTE: this is completely untested by the author, but included solely
because, as noted in commit df57d73276b8 ("mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers"), "other drivers using CQHCI might benefit from a similar change, if they also have CQHCI reset by SDHCI_RESET_ALL." We've now seen the same bug on at least MSM, Arasan, and Intel hardware. ]]
SDHCI_RESET_ALL resets will reset the hardware CQE state, but we aren't tracking that properly in software. When out of sync, we may trigger various timeouts.
It's not typical to perform resets while CQE is enabled, but this may occur in some suspend or error recovery scenarios.
Include this fix by way of the new sdhci_and_cqhci_reset() helper.
I only patch the bcm7216 variant even though others potentially *could* provide the 'supports-cqe' property (and thus enable CQHCI), because d46ba2d17f90 ("mmc: sdhci-brcmstb: Add support for Command Queuing (CQE)") and some Broadcom folks confirm that only the 7216 variant actually supports it.
This patch depends on (and should not compile without) the patch entitled "mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI".
--- drivers/mmc/host/sdhci-brcmstb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci-brcmstb.c +2 -1
@@ -12,6 +12,7 @@#include <linux/bitops.h> #include <linux/delay.h> +#include "sdhci-cqhci.h" #include "sdhci-pltfm.h" #include "cqhci.h"
@@ -53,7 +54,7 @@ void brcmstb_reset(struct sdhci_host *host, u8 mask)struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct sdhci_brcmstb_priv *priv =sdhci_pltfm_priv (pltfm_host); -sdhci_reset (host, mask); +sdhci_and_cqhci_reset (host, mask);/* Reset will clear this, so re-enable it */ if (priv->flags &BRCMSTB_PRIV_FLAGS_GATE_CLOCK )
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 105/162 usb: cdns3: Add support for DRD CDNSP
In reply to Greg Kroah-HartmanFrom: Pawel Laszczak <[email protected]>
[ Upstream commit db8892bb1bb64b6e3d1381ac342a2ee31e1b76b6 ]
Patch adds support for Cadence DRD Super Speed Plus controller(CDNSP). CDNSP DRD is a part of Cadence CDNSP controller.
The DRD CDNSP controller has a lot of difference on hardware level but on software level is quite compatible with CDNS3 DRD. For this reason CDNS3 DRD part of CDNS3 driver was reused for CDNSP driver.
Stable-dep-of: 9d5333c93134 ("usb: cdns3: host: fix endless superspeed hub port reset")
--- drivers/usb/cdns3/core.c | 24 +++++++--- drivers/usb/cdns3/core.h | 5 ++ drivers/usb/cdns3/drd.c | 101 +++++++++++++++++++++++++++------------ drivers/usb/cdns3/drd.h | 67 +++++++++++++++++++++----- 4 files changed, 148 insertions(+), 49 deletions(-)
drivers/usb/cdns3/core.c +17 -7
@@ -97,13 +97,23 @@ static int cdns3_core_init_role(struct cdns3 *cdns)* can be restricted later depending on strap pin configuration. */ if (dr_mode ==USB_DR_MODE_UNKNOWN ) { -if (IS_ENABLED (CONFIG_USB_CDNS3_HOST ) && -IS_ENABLED (CONFIG_USB_CDNS3_GADGET )) - dr_mode =USB_DR_MODE_OTG ; -else if (IS_ENABLED (CONFIG_USB_CDNS3_HOST )) - dr_mode =USB_DR_MODE_HOST ; -else if (IS_ENABLED (CONFIG_USB_CDNS3_GADGET )) - dr_mode =USB_DR_MODE_PERIPHERAL ; +if (cdns->version ==CDNSP_CONTROLLER_V2 ) { +if (IS_ENABLED (CONFIG_USB_CDNSP_HOST ) && +IS_ENABLED (CONFIG_USB_CDNSP_GADGET )) + dr_mode =USB_DR_MODE_OTG ; +else if (IS_ENABLED (CONFIG_USB_CDNSP_HOST )) + dr_mode =USB_DR_MODE_HOST ; +else if (IS_ENABLED (CONFIG_USB_CDNSP_GADGET )) + dr_mode =USB_DR_MODE_PERIPHERAL ; + }else { +if (IS_ENABLED (CONFIG_USB_CDNS3_HOST ) && +IS_ENABLED (CONFIG_USB_CDNS3_GADGET )) + dr_mode =USB_DR_MODE_OTG ; +else if (IS_ENABLED (CONFIG_USB_CDNS3_HOST )) + dr_mode =USB_DR_MODE_HOST ; +else if (IS_ENABLED (CONFIG_USB_CDNS3_GADGET )) + dr_mode =USB_DR_MODE_PERIPHERAL ; + } }/*
drivers/usb/cdns3/core.h +5 -0
@@ -55,7 +55,9 @@ struct cdns3_platform_data {* @otg_res: the resource for otg * @otg_v0_regs: pointer to base of v0 otg registers * @otg_v1_regs: pointer to base of v1 otg registers +* @otg_cdnsp_regs: pointer to base of CDNSP otg registers * @otg_regs: pointer to base of otg registers +* @otg_irq_regs: pointer to interrupt registers * @otg_irq: irq number for otg controller * @dev_irq: irq number for device controller * @wakeup_irq: irq number for wakeup event, it is optional
@@ -86,9 +88,12 @@ struct cdns3 {struct resource otg_res;struct cdns3_otg_legacy_regs *otg_v0_regs;struct cdns3_otg_regs *otg_v1_regs; +struct cdnsp_otg_regs *otg_cdnsp_regs;struct cdns3_otg_common_regs *otg_regs; +struct cdns3_otg_irq_regs *otg_irq_regs;#define CDNS3_CONTROLLER_V0 0#define CDNS3_CONTROLLER_V1 1 +#define CDNSP_CONTROLLER_V2 2u32 version;bool phyrst_a_enable;
drivers/usb/cdns3/drd.c +71 -30
219 lines not on this page · raw message
drivers/usb/cdns3/drd.h +55 -12
132 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 106/162 usb: cdnsp: Device side header file for CDNSP driver
In reply to Greg Kroah-HartmanFrom: Pawel Laszczak <[email protected]>
[ Upstream commit e93e58d2740282d32c0278fab283eb0ae158bb59 ]
Patch defines macros, registers and structures used by Device side driver.
Because the size of main patch is very big, I’ve decided to create separate patch for cdnsp-gadget.h. It should simplify reviewing the code.
Stable-dep-of: 9d5333c93134 ("usb: cdns3: host: fix endless superspeed hub port reset")
--- drivers/usb/cdns3/cdnsp-gadget.h | 1463 ++++++++++++++++++++++++++++++ 1 file changed, 1463 insertions(+) create mode 100644 drivers/usb/cdns3/cdnsp-gadget.h
drivers/usb/cdns3/cdnsp-gadget.h new file +1463 -0
@@ -0,0 +1,1463 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Cadence CDNSP DRD Driver. +* +* Copyright (C) 2020 Cadence. +* +* Author: Pawel Laszczak <[email protected]> +* +* Code based on Linux XHCI driver. +* Origin: Copyright (C) 2008 Intel Corp. +*/ +#ifndef __LINUX_CDNSP_GADGET_H +#define __LINUX_CDNSP_GADGET_H + +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/usb/gadget.h> +#include <linux/irq.h> + +/* Max number slots - only 1 is allowed. */ +#define CDNSP_DEV_MAX_SLOTS 1 + +#define CDNSP_EP0_SETUP_SIZE 512 + +/* One control and 15 for in and 15 for out endpoints. */ +#define CDNSP_ENDPOINTS_NUM 31 + +/* Best Effort Service Latency. */ +#define CDNSP_DEFAULT_BESL 0 + +/* Device Controller command default timeout value in us */ +#define CDNSP_CMD_TIMEOUT (15 * 1000) + +/* Up to 16 ms to halt an device controller */ +#define CDNSP_MAX_HALT_USEC (16 * 1000) + +#define CDNSP_CTX_SIZE 2112 + +/* +* Controller register interface. +*/ + +/** +* struct cdnsp_cap_regs - CDNSP Registers. +* @hc_capbase: Length of the capabilities register and controller +* version number +* @hcs_params1: HCSPARAMS1 - Structural Parameters 1 +* @hcs_params2: HCSPARAMS2 - Structural Parameters 2 +* @hcs_params3: HCSPARAMS3 - Structural Parameters 3 +* @hcc_params: HCCPARAMS - Capability Parameters +* @db_off: DBOFF - Doorbell array offset +* @run_regs_off: RTSOFF - Runtime register space offset +* @hcc_params2: HCCPARAMS2 Capability Parameters 2, +*/ +struct cdnsp_cap_regs { +__le32 hc_capbase; +__le32 hcs_params1; +__le32 hcs_params2; +__le32 hcs_params3; +__le32 hcc_params; +__le32 db_off; +__le32 run_regs_off; +__le32 hcc_params2; +/* Reserved up to (CAPLENGTH - 0x1C) */ +}; + +/* hc_capbase bitmasks. */ +/* bits 7:0 - how long is the Capabilities register. */ +#define HC_LENGTH (p) (((p) >> 00) & GENMASK(7, 0)) +/* bits 31:16 */ +#define HC_VERSION (p) (((p) >> 16) & GENMASK(15, 1)) + +/* HCSPARAMS1 - hcs_params1 - bitmasks */ +/* bits 0:7, Max Device Endpoints */ +#define HCS_ENDPOINTS_MASK GENMASK(7, 0) +#define HCS_ENDPOINTS (p) (((p) & HCS_ENDPOINTS_MASK) >> 0) + +/* HCCPARAMS offset from PCI base address */ +#define HCC_PARAMS_OFFSET 0x10 + +/* HCCPARAMS - hcc_params - bitmasks */ +/* 1: device controller can use 64-bit address pointers. */ +#define HCC_64BIT_ADDR (p) ((p) & BIT(0)) +/* 1: device controller uses 64-byte Device Context structures. */ +#define HCC_64BYTE_CONTEXT (p) ((p) & BIT(2)) +/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15. */ +#define HCC_MAX_PSA (p) ((((p) >> 12) & 0xf) + 1) +/* Extended Capabilities pointer from PCI base. */ +#define HCC_EXT_CAPS (p) (((p) & GENMASK(31, 16)) >> 16) + +#define CTX_SIZE (_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) + +/* db_off bitmask - bits 0:1 reserved. */ +#define DBOFF_MASK GENMASK(31, 2) + +/* run_regs_off bitmask - bits 0:4 reserved. */ +#define RTSOFF_MASK GENMASK(31, 5) + +/** +* struct cdnsp_op_regs - Device Controller Operational Registers. +* @command: USBCMD - Controller command register. +* @status: USBSTS - Controller status register. +* @page_size: This indicates the page size that the device controller supports. +* If bit n is set, the controller supports a page size of 2^(n+12), +* up to a 128MB page size. 4K is the minimum page size. +* @dnctrl: DNCTRL - Device notification control register. +* @cmd_ring: CRP - 64-bit Command Ring Pointer. +* @dcbaa_ptr: DCBAAP - 64-bit Device Context Base Address Array Pointer. +* @config_reg: CONFIG - Configure Register +* @port_reg_base: PORTSCn - base address for Port Status and Control +* Each port has a Port Status and Control register, +* followed by a Port Power Management Status and Control +* register, a Port Link Info register, and a reserved +* register. +*/ +struct cdnsp_op_regs { +__le32 command; +__le32 status; +__le32 page_size; +__le32 reserved1; +__le32 reserved2; +__le32 dnctrl; +__le64 cmd_ring; +/* rsvd: offset 0x20-2F. */ +__le32 reserved3[4 ]; +__le64 dcbaa_ptr; +__le32 config_reg; +/* rsvd: offset 0x3C-3FF. */ +__le32 reserved4[241 ]; +/* port 1 registers, which serve as a base address for other ports. */ +__le32 port_reg_base; +}; + +/* Number of registers per port. */ +#define NUM_PORT_REGS 4 + +/** +* struct cdnsp_port_regs - Port Registers. +* @portsc: PORTSC - Port Status and Control Register. +* @portpmsc: PORTPMSC - Port Power Managements Status and Control Register. +* @portli: PORTLI - Port Link Info register. +*/ +struct cdnsp_port_regs { +__le32 portsc; +__le32 portpmsc; +__le32 portli; +__le32 reserved; +}; + +/* +* These bits are Read Only (RO) and should be saved and written to the +* registers: 0 (connect status) and 10:13 (port speed). +* These bits are also sticky - meaning they're in the AUX well and they aren't +* changed by a hot and warm. +*/ +#define CDNSP_PORT_RO (PORT_CONNECT | DEV_SPEED_MASK) + +/* +* These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit: +* bits 5:8 (link state), 25:26 ("wake on" enable state) +*/ +#define CDNSP_PORT_RWS (PORT_PLS_MASK | PORT_WKCONN_E | PORT_WKDISC_E) + +/* +* These bits are RW; writing a 1 clears the bit, writing a 0 has no effect: +* bits 1 (port enable/disable), 17 ( connect changed), +* 21 (port reset changed) , 22 (Port Link State Change), +*/ +#define CDNSP_PORT_RW1CS (PORT_PED | PORT_CSC | PORT_RC | PORT_PLC) + +/* USBCMD - USB command - bitmasks. */ +/* Run/Stop, controller execution - do not write unless controller is halted.*/ +#define CMD_R_S BIT(0) +/* +* Reset device controller - resets internal controller state machine and all +* registers (except PCI config regs). +*/ +#define CMD_RESET BIT(1) +/* Event Interrupt Enable - a '1' allows interrupts from the controller. */ +#define CMD_INTE BIT(2) +/* +* Device System Error Interrupt Enable - get out-of-band signal for +* controller errors. +*/ +#define CMD_DSEIE BIT(3) +/* device controller save/restore state. */ +#define CMD_CSS BIT(8) +#define CMD_CRS BIT(9) +/* +* Enable Wrap Event - '1' means device controller generates an event +* when MFINDEX wraps. +*/ +#define CMD_EWE BIT(10) +/* 1: device enabled */ +#define CMD_DEVEN BIT(17) +/* bits 18:31 are reserved (and should be preserved on writes). */ + +/* Command register values to disable interrupts. */ +#define CDNSP_IRQS (CMD_INTE | CMD_DSEIE | CMD_EWE) + +/* USBSTS - USB status - bitmasks */ +/* controller not running - set to 1 when run/stop bit is cleared. */ +#define STS_HALT BIT(0) +/* +* serious error, e.g. PCI parity error. The controller will clear +* the run/stop bit. +*/ +#define STS_FATAL BIT(2) +/* event interrupt - clear this prior to clearing any IP flags in IR set.*/ +#define STS_EINT BIT(3) +/* port change detect */ +#define STS_PCD BIT(4) +/* save state status - '1' means device controller is saving state. */ +#define STS_SSS BIT(8) +/* restore state status - '1' means controllers is restoring state. */ +#define STS_RSS BIT(9) +/* 1: save or restore error */ +#define STS_SRE BIT(10) +/* 1: device Not Ready to accept doorbell or op reg writes after reset. */ +#define STS_CNR BIT(11) +/* 1: internal Device Controller Error.*/ +#define STS_HCE BIT(12) + +/* CRCR - Command Ring Control Register - cmd_ring bitmasks. */ +/* bit 0 is the command ring cycle state. */ +#define CMD_RING_CS BIT(0) +/* stop ring immediately - abort the currently executing command. */ +#define CMD_RING_ABORT BIT(2) +/* +* Command Ring Busy. +* Set when Doorbell register is written with DB for command and cleared when +* the controller reached end of CR. +*/ +#define CMD_RING_BUSY (p) ((p) & BIT(4)) +/* 1: command ring is running */ +#define CMD_RING_RUNNING BIT(3) +/* Command Ring pointer - bit mask for the lower 32 bits. */ +#define CMD_RING_RSVD_BITS GENMASK(5, 0) + +/* CONFIG - Configure Register - config_reg bitmasks. */ +/* bits 0:7 - maximum number of device slots enabled. */ +#define MAX_DEVS GENMASK(7, 0) +/* bit 8: U3 Entry Enabled, assert PLC when controller enters U3. */ +#define CONFIG_U3E BIT(8) + +/* PORTSC - Port Status and Control Register - port_reg_base bitmasks */ +/* 1: device connected. */ +#define PORT_CONNECT BIT(0) +/* 1: port enabled. */ +#define PORT_PED BIT(1) +/* 1: port reset signaling asserted. */ +#define PORT_RESET BIT(4) +/* +* Port Link State - bits 5:8 +* A read gives the current link PM state of the port, +* a write with Link State Write Strobe sets the link state. +*/ +#define PORT_PLS_MASK GENMASK(8, 5) +#define XDEV_U0 (0x0 << 5) +#define XDEV_U1 (0x1 << 5) +#define XDEV_U2 (0x2 << 5) +#define XDEV_U3 (0x3 << 5) +#define XDEV_DISABLED (0x4 << 5) +#define XDEV_RXDETECT (0x5 << 5) +#define XDEV_INACTIVE (0x6 << 5) +#define XDEV_POLLING (0x7 << 5) +#define XDEV_RECOVERY (0x8 << 5) +#define XDEV_HOT_RESET (0x9 << 5) +#define XDEV_COMP_MODE (0xa << 5) +#define XDEV_TEST_MODE (0xb << 5) +#define XDEV_RESUME (0xf << 5) +/* 1: port has power. */ +#define PORT_POWER BIT(9) +/* +* bits 10:13 indicate device speed: +* 0 - undefined speed - port hasn't be initialized by a reset yet +* 1 - full speed +* 2 - Reserved (Low Speed not supported +* 3 - high speed +* 4 - super speed +* 5 - super speed +* 6-15 reserved +*/ +#define DEV_SPEED_MASK GENMASK(13, 10) +#define XDEV_FS (0x1 << 10) +#define XDEV_HS (0x3 << 10) +#define XDEV_SS (0x4 << 10) +#define XDEV_SSP (0x5 << 10) +#define DEV_UNDEFSPEED (p) (((p) & DEV_SPEED_MASK) == (0x0 << 10)) +#define DEV_FULLSPEED (p) (((p) & DEV_SPEED_MASK) == XDEV_FS) +#define DEV_HIGHSPEED (p) (((p) & DEV_SPEED_MASK) == XDEV_HS) +#define DEV_SUPERSPEED (p) (((p) & DEV_SPEED_MASK) == XDEV_SS) +#define DEV_SUPERSPEEDPLUS (p) (((p) & DEV_SPEED_MASK) == XDEV_SSP) +#define DEV_SUPERSPEED_ANY (p) (((p) & DEV_SPEED_MASK) >= XDEV_SS) +#define DEV_PORT_SPEED (p) (((p) >> 10) & 0x0f) +/* Port Link State Write Strobe - set this when changing link state */ +#define PORT_LINK_STROBE BIT(16) +/* 1: connect status change */ +#define PORT_CSC BIT(17) +/* 1: warm reset for a USB 3.0 device is done. */ +#define PORT_WRC BIT(19) +/* 1: reset change - 1 to 0 transition of PORT_RESET */ +#define PORT_RC BIT(21) +/* +* port link status change - set on some port link state transitions: +* Transition Reason +* ---------------------------------------------------------------------------- +* - U3 to Resume Wakeup signaling from a device +* - Resume to Recovery to U0 USB 3.0 device resume +* - Resume to U0 USB 2.0 device resume +* - U3 to Recovery to U0 Software resume of USB 3.0 device complete +* - U3 to U0 Software resume of USB 2.0 device complete +* - U2 to U0 L1 resume of USB 2.1 device complete +* - U0 to U0 L1 entry rejection by USB 2.1 device +* - U0 to disabled L1 entry error with USB 2.1 device +* - Any state to inactive Error on USB 3.0 port +*/ +#define PORT_PLC BIT(22) +/* Port configure error change - port failed to configure its link partner. */ +#define PORT_CEC BIT(23) +/* Wake on connect (enable). */ +#define PORT_WKCONN_E BIT(25) +/* Wake on disconnect (enable). */ +#define PORT_WKDISC_E BIT(26) +/* Indicates if Warm Reset is being received. */ +#define PORT_WR BIT(31) + +#define PORT_CHANGE_BITS (PORT_CSC | PORT_WRC | PORT_RC | PORT_PLC | PORT_CEC) + +/* PORTPMSCUSB3 - Port Power Management Status and Control - bitmasks. */ +/* Enables U1 entry. */ +#define PORT_U1_TIMEOUT_MASK GENMASK(7, 0) +#define PORT_U1_TIMEOUT (p) ((p) & PORT_U1_TIMEOUT_MASK) +/* Enables U2 entry .*/ +#define PORT_U2_TIMEOUT_MASK GENMASK(14, 8) +#define PORT_U2_TIMEOUT (p) (((p) << 8) & PORT_U2_TIMEOUT_MASK) + +/* PORTPMSCUSB2 - Port Power Management Status and Control - bitmasks. */ +#define PORT_L1S_MASK GENMASK(2, 0) +#define PORT_L1S (p) ((p) & PORT_L1S_MASK) +#define PORT_L1S_ACK PORT_L1S(1) +#define PORT_L1S_NYET PORT_L1S(2) +#define PORT_L1S_STALL PORT_L1S(3) +#define PORT_L1S_TIMEOUT PORT_L1S(4) +/* Remote Wake Enable. */ +#define PORT_RWE BIT(3) +/* Best Effort Service Latency (BESL). */ +#define PORT_BESL (p) (((p) << 4) & GENMASK(7, 4)) +/* Hardware LPM Enable (HLE). */ +#define PORT_HLE BIT(16) +/* Received Best Effort Service Latency (BESL). */ +#define PORT_RRBESL (p) (((p) & GENMASK(20, 17)) >> 17) +/* Port Test Control. */ +#define PORT_TEST_MODE_MASK GENMASK(31, 28) +#define PORT_TEST_MODE (p) (((p) << 28) & PORT_TEST_MODE_MASK) + +/** +* struct cdnsp_intr_reg - Interrupt Register Set. +* @irq_pending: IMAN - Interrupt Management Register. Used to enable +* interrupts and check for pending interrupts. +* @irq_control: IMOD - Interrupt Moderation Register. +* Used to throttle interrupts. +* @erst_size: Number of segments in the Event Ring Segment Table (ERST). +* @erst_base: ERST base address. +* @erst_dequeue: Event ring dequeue pointer. +* +* Each interrupter (defined by a MSI-X vector) has an event ring and an Event +* Ring Segment Table (ERST) associated with it. The event ring is comprised of +* multiple segments of the same size. The controller places events on the ring +* and "updates the Cycle bit in the TRBs to indicate to software the current +* position of the Enqueue Pointer." The driver processes those events and +* updates the dequeue pointer. +*/ +struct cdnsp_intr_reg { +__le32 irq_pending; +__le32 irq_control; +__le32 erst_size; +__le32 rsvd; +__le64 erst_base; +__le64 erst_dequeue; +}; + +/* IMAN - Interrupt Management Register - irq_pending bitmasks l. */ +#define IMAN_IE BIT(1) +#define IMAN_IP BIT(0) +/* bits 2:31 need to be preserved */ +#define IMAN_IE_SET (p) (((p) & IMAN_IE) | 0x2) +#define IMAN_IE_CLEAR (p) (((p) & IMAN_IE) & ~(0x2)) + +/* IMOD - Interrupter Moderation Register - irq_control bitmasks. */ +/* +* Minimum interval between interrupts (in 250ns intervals). The interval +* between interrupts will be longer if there are no events on the event ring. +* Default is 4000 (1 ms). +*/ +#define IMOD_INTERVAL_MASK GENMASK(15, 0) +/* Counter used to count down the time to the next interrupt - HW use only */ +#define IMOD_COUNTER_MASK GENMASK(31, 16) +#define IMOD_DEFAULT_INTERVAL 0 + +/* erst_size bitmasks. */ +/* Preserve bits 16:31 of erst_size. */ +#define ERST_SIZE_MASK GENMASK(31, 16) + +/* erst_dequeue bitmasks. */ +/* +* Dequeue ERST Segment Index (DESI) - Segment number (or alias) +* where the current dequeue pointer lies. This is an optional HW hint. +*/ +#define ERST_DESI_MASK GENMASK(2, 0) +/* Event Handler Busy (EHB) - is the event ring scheduled to be serviced. */ +#define ERST_EHB BIT(3) +#define ERST_PTR_MASK GENMASK(3, 0) + +/** +* struct cdnsp_run_regs +* @microframe_index: MFINDEX - current microframe number. +* @ir_set: Array of Interrupter registers. +* +* Device Controller Runtime Registers: +* "Software should read and write these registers using only Dword (32 bit) +* or larger accesses" +*/ +struct cdnsp_run_regs { +__le32 microframe_index; +__le32 rsvd[7 ]; +struct cdnsp_intr_reg ir_set[128 ]; +}; + +/** +* USB2.0 Port Peripheral Configuration Registers. +* @ext_cap: Header register for Extended Capability. +* @port_reg1: Timer Configuration Register. +* @port_reg2: Timer Configuration Register. +* @port_reg3: Timer Configuration Register. +* @port_reg4: Timer Configuration Register. +* @port_reg5: Timer Configuration Register. +* @port_reg6: Chicken bits for USB20PPP. +*/ +struct cdnsp_20port_cap { +__le32 ext_cap; +__le32 port_reg1; +__le32 port_reg2; +__le32 port_reg3; +__le32 port_reg4; +__le32 port_reg5; +__le32 port_reg6; +}; + +/* Extended capability register fields */ +#define EXT_CAPS_ID (p) (((p) >> 0) & GENMASK(7, 0)) +#define EXT_CAPS_NEXT (p) (((p) >> 8) & GENMASK(7, 0)) +/* Extended capability IDs - ID 0 reserved */ +#define EXT_CAPS_PROTOCOL 2 + +/* USB 2.0 Port Peripheral Configuration Extended Capability */ +#define EXT_CAP_CFG_DEV_20PORT_CAP_ID 0xC1 +/* +* Setting this bit to '1' enables automatic wakeup from L1 state on transfer +* TRB prepared when USBSSP operates in USB2.0 mode. +*/ +#define PORT_REG6_L1_L0_HW_EN BIT(1) +/* +* Setting this bit to '1' forces Full Speed when USBSSP operates in USB2.0 +* mode (disables High Speed). +*/ +#define PORT_REG6_FORCE_FS BIT(0) + +/** +* USB3.x Port Peripheral Configuration Registers. +* @ext_cap: Header register for Extended Capability. +* @mode_addr: Miscellaneous 3xPORT operation mode configuration register. +* @mode_2: 3x Port Control Register 2. +*/ +struct cdnsp_3xport_cap { +__le32 ext_cap; +__le32 mode_addr; +__le32 reserved[52 ]; +__le32 mode_2; +}; + +/* Extended Capability Header for 3XPort Configuration Registers. */ +#define D_XEC_CFG_3XPORT_CAP 0xC0 +#define CFG_3XPORT_SSP_SUPPORT BIT(31) +#define CFG_3XPORT_U1_PIPE_CLK_GATE_EN BIT(0) + +/* Revision Extended Capability ID */ +#define RTL_REV_CAP 0xC4 +#define RTL_REV_CAP_RX_BUFF_CMD_SIZE BITMASK(31, 24) +#define RTL_REV_CAP_RX_BUFF_SIZE BITMASK(15, 0) +#define RTL_REV_CAP_TX_BUFF_CMD_SIZE BITMASK(31, 24) +#define RTL_REV_CAP_TX_BUFF_SIZE BITMASK(15, 0) + +#define CDNSP_VER_1 0x00000000 +#define CDNSP_VER_2 0x10000000 + +#define CDNSP_IF_EP_EXIST (pdev, ep_num, dir) ((pdev)->rev_cap.ep_supported & \ + (BIT(ep_num) << ((dir) ? 0 : 16))) + +/** +* struct cdnsp_rev_cap - controller capabilities . +* @ext_cap: Header for RTL Revision Extended Capability. +* @rtl_revision: RTL revision. +* @rx_buff_size: Rx buffer sizes. +* @tx_buff_size: Tx buffer sizes. +* @ep_supported: Supported endpoints. +* @ctrl_revision: Controller revision ID. +*/ +struct cdnsp_rev_cap { +__le32 ext_cap; +__le32 rtl_revision; +__le32 rx_buff_size; +__le32 tx_buff_size; +__le32 ep_supported; +__le32 ctrl_revision; +}; + +/* USB2.0 Port Peripheral Configuration Registers. */ +#define D_XEC_PRE_REGS_CAP 0xC8 +#define REG_CHICKEN_BITS_2_OFFSET 0x48 +#define CHICKEN_XDMA_2_TP_CACHE_DIS BIT(28) + +/* XBUF Extended Capability ID. */ +#define XBUF_CAP_ID 0xCB +#define XBUF_RX_TAG_MASK_0_OFFSET 0x1C +#define XBUF_RX_TAG_MASK_1_OFFSET 0x24 +#define XBUF_TX_CMD_OFFSET 0x2C + +/** +* struct cdnsp_doorbell_array. +* @cmd_db: Command ring doorbell register. +* @ep_db: Endpoint ring doorbell register. +* Bits 0 - 7: Endpoint target. +* Bits 8 - 15: RsvdZ. +* Bits 16 - 31: Stream ID. +*/ +struct cdnsp_doorbell_array { +__le32 cmd_db; +__le32 ep_db; +}; + +#define DB_VALUE (ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) +#define DB_VALUE_EP0_OUT (ep, stream) ((ep) & 0xff) +#define DB_VALUE_CMD 0x00000000 + +/** +* struct cdnsp_container_ctx. +* @type: Type of context. Used to calculated offsets to contained contexts. +* @size: Size of the context data. +* @ctx_size: context data structure size - 64 or 32 bits. +* @dma: dma address of the bytes. +* @bytes: The raw context data given to HW. +* +* Represents either a Device or Input context. Holds a pointer to the raw +* memory used for the context (bytes) and dma address of it (dma). +*/ +struct cdnsp_container_ctx { +unsigned int type; +#define CDNSP_CTX_TYPE_DEVICE 0x1 +#define CDNSP_CTX_TYPE_INPUT 0x2 +int size; +int ctx_size; +dma_addr_t dma; +u8 *bytes; +}; + +/** +* struct cdnsp_slot_ctx +* @dev_info: Device speed, and last valid endpoint. +* @dev_port: Device port number that is needed to access the USB device. +* @int_target: Interrupter target number. +* @dev_state: Slot state and device address. +* +* Slot Context - This assumes the controller uses 32-byte context +* structures. If the controller uses 64-byte contexts, there is an additional +* 32 bytes reserved at the end of the slot context for controller internal use. +*/ +struct cdnsp_slot_ctx { +__le32 dev_info; +__le32 dev_port; +__le32 int_target; +__le32 dev_state; +/* offset 0x10 to 0x1f reserved for controller internal use. */ +__le32 reserved[4 ]; +}; + +/* Bits 20:23 in the Slot Context are the speed for the device. */ +#define SLOT_SPEED_FS (XDEV_FS << 10) +#define SLOT_SPEED_HS (XDEV_HS << 10) +#define SLOT_SPEED_SS (XDEV_SS << 10) +#define SLOT_SPEED_SSP (XDEV_SSP << 10) + +/* dev_info bitmasks. */ +/* Device speed - values defined by PORTSC Device Speed field - 20:23. */ +#define DEV_SPEED GENMASK(23, 20) +#define GET_DEV_SPEED (n) (((n) & DEV_SPEED) >> 20) +/* Index of the last valid endpoint context in this device context - 27:31. */ +#define LAST_CTX_MASK GENMASK(31, 27) +#define LAST_CTX (p) ((p) << 27) +#define LAST_CTX_TO_EP_NUM (p) (((p) >> 27) - 1) +#define SLOT_FLAG BIT(0) +#define EP0_FLAG BIT(1) + +/* dev_port bitmasks */ +/* Device port number that is needed to access the USB device. */ +#define DEV_PORT (p) (((p) & 0xff) << 16) + +/* dev_state bitmasks */ +/* USB device address - assigned by the controller. */ +#define DEV_ADDR_MASK GENMASK(7, 0) +/* Slot state */ +#define SLOT_STATE GENMASK(31, 27) +#define GET_SLOT_STATE (p) (((p) & SLOT_STATE) >> 27) + +#define SLOT_STATE_DISABLED 0 +#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED +#define SLOT_STATE_DEFAULT 1 +#define SLOT_STATE_ADDRESSED 2 +#define SLOT_STATE_CONFIGURED 3 + +/** +* struct cdnsp_ep_ctx. +* @ep_info: Endpoint state, streams, mult, and interval information. +* @ep_info2: Information on endpoint type, max packet size, max burst size, +* error count, and whether the controller will force an event for +* all transactions. +* @deq: 64-bit ring dequeue pointer address. If the endpoint only +* defines one stream, this points to the endpoint transfer ring. +* Otherwise, it points to a stream context array, which has a +* ring pointer for each flow. +* @tx_info: Average TRB lengths for the endpoint ring and +* max payload within an Endpoint Service Interval Time (ESIT). +* +* Endpoint Context - This assumes the controller uses 32-byte context +* structures. If the controller uses 64-byte contexts, there is an additional +* 32 bytes reserved at the end of the endpoint context for controller internal +* use. +*/ +struct cdnsp_ep_ctx { +__le32 ep_info; +__le32 ep_info2; +__le64 deq; +__le32 tx_info; +/* offset 0x14 - 0x1f reserved for controller internal use. */ +__le32 reserved[3 ]; +}; + +/* ep_info bitmasks. */ +/* +* Endpoint State - bits 0:2: +* 0 - disabled +* 1 - running +* 2 - halted due to halt condition +* 3 - stopped +* 4 - TRB error +* 5-7 - reserved +*/ +#define EP_STATE_MASK GENMASK(3, 0) +#define EP_STATE_DISABLED 0 +#define EP_STATE_RUNNING 1 +#define EP_STATE_HALTED 2 +#define EP_STATE_STOPPED 3 +#define EP_STATE_ERROR 4 +#define GET_EP_CTX_STATE (ctx) (le32_to_cpu((ctx)->ep_info) & EP_STATE_MASK) + +/* Mult - Max number of burst within an interval, in EP companion desc. */ +#define EP_MULT (p) (((p) << 8) & GENMASK(9, 8)) +#define CTX_TO_EP_MULT (p) (((p) & GENMASK(9, 8)) >> 8) +/* bits 10:14 are Max Primary Streams. */ +/* bit 15 is Linear Stream Array. */ +/* Interval - period between requests to an endpoint - 125u increments. */ +#define EP_INTERVAL (p) (((p) << 16) & GENMASK(23, 16)) +#define EP_INTERVAL_TO_UFRAMES (p) (1 << (((p) & GENMASK(23, 16)) >> 16)) +#define CTX_TO_EP_INTERVAL (p) (((p) & GENMASK(23, 16)) >> 16) +#define EP_MAXPSTREAMS_MASK GENMASK(14, 10) +#define EP_MAXPSTREAMS (p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define CTX_TO_EP_MAXPSTREAMS (p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) +/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ +#define EP_HAS_LSA BIT(15) + +/* ep_info2 bitmasks */ +#define ERROR_COUNT (p) (((p) & 0x3) << 1) +#define CTX_TO_EP_TYPE (p) (((p) >> 3) & 0x7) +#define EP_TYPE (p) ((p) << 3) +#define ISOC_OUT_EP 1 +#define BULK_OUT_EP 2 +#define INT_OUT_EP 3 +#define CTRL_EP 4 +#define ISOC_IN_EP 5 +#define BULK_IN_EP 6 +#define INT_IN_EP 7 +/* bit 6 reserved. */ +/* bit 7 is Device Initiate Disable - for disabling stream selection. */ +#define MAX_BURST (p) (((p) << 8) & GENMASK(15, 8)) +#define CTX_TO_MAX_BURST (p) (((p) & GENMASK(15, 8)) >> 8) +#define MAX_PACKET (p) (((p) << 16) & GENMASK(31, 16)) +#define MAX_PACKET_MASK GENMASK(31, 16) +#define MAX_PACKET_DECODED (p) (((p) & GENMASK(31, 16)) >> 16) + +/* tx_info bitmasks. */ +#define EP_AVG_TRB_LENGTH (p) ((p) & GENMASK(15, 0)) +#define EP_MAX_ESIT_PAYLOAD_LO (p) (((p) << 16) & GENMASK(31, 16)) +#define EP_MAX_ESIT_PAYLOAD_HI (p) ((((p) & GENMASK(23, 16)) >> 16) << 24) +#define CTX_TO_MAX_ESIT_PAYLOAD_LO (p) (((p) & GENMASK(31, 16)) >> 16) +#define CTX_TO_MAX_ESIT_PAYLOAD_HI (p) (((p) & GENMASK(31, 24)) >> 24) + +/* deq bitmasks. */ +#define EP_CTX_CYCLE_MASK BIT(0) +#define CTX_DEQ_MASK (~0xfL) + +/** +* struct cdnsp_input_control_context +* Input control context; +* +* @drop_context: Set the bit of the endpoint context you want to disable. +* @add_context: Set the bit of the endpoint context you want to enable. +*/ +struct cdnsp_input_control_ctx { +__le32 drop_flags; +__le32 add_flags; +__le32 rsvd2[6 ]; +}; + +/** +* Represents everything that is needed to issue a command on the command ring. +* +* @in_ctx: Pointer to input context structure. +* @status: Command Completion Code for last command. +* @command_trb: Pointer to command TRB. +*/ +struct cdnsp_command { +/* Input context for changing device state. */ +struct cdnsp_container_ctx *in_ctx; +u32 status; +union cdnsp_trb *command_trb; +}; + +/** +* Stream context structure. +* +* @stream_ring: 64-bit stream ring address, cycle state, and stream type. +* @reserved: offset 0x14 - 0x1f reserved for controller internal use. +*/ +struct cdnsp_stream_ctx { +__le64 stream_ring; +__le32 reserved[2 ]; +}; + +/* Stream Context Types - bits 3:1 of stream ctx deq ptr. */ +#define SCT_FOR_CTX (p) (((p) << 1) & GENMASK(3, 1)) +/* Secondary stream array type, dequeue pointer is to a transfer ring. */ +#define SCT_SEC_TR 0 +/* Primary stream array type, dequeue pointer is to a transfer ring. */ +#define SCT_PRI_TR 1 + +/** +* struct cdnsp_stream_info: Representing everything that is needed to +* supports stream capable endpoints. +* @stream_rings: Array of pointers containing Transfer rings for all +* supported streams. +* @num_streams: Number of streams, including stream 0. +* @stream_ctx_array: The stream context array may be bigger than the number +* of streams the driver asked for. +* @num_stream_ctxs: Number of streams. +* @ctx_array_dma: Dma address of Context Stream Array. +* @trb_address_map: For mapping physical TRB addresses to segments in +* stream rings. +* @td_count: Number of TDs associated with endpoint. +* @first_prime_det: First PRIME packet detected. +* @drbls_count: Number of allowed doorbells. +*/ +struct cdnsp_stream_info { +struct cdnsp_ring **stream_rings; +unsigned int num_streams; +struct cdnsp_stream_ctx *stream_ctx_array; +unsigned int num_stream_ctxs; +dma_addr_t ctx_array_dma; +struct radix_tree_root trb_address_map; +int td_count; +u8 first_prime_det; +#define STREAM_DRBL_FIFO_DEPTH 2 +u8 drbls_count; +}; + +#define STREAM_LOG_STREAMS 4 +#define STREAM_NUM_STREAMS BIT(STREAM_LOG_STREAMS) + +#if STREAM_LOG_STREAMS >16 &&STREAM_LOG_STREAMS <1 +#error "Not suupported stream value" +#endif + +/** +* struct cdnsp_ep - extended device side representation of USB endpoint. +* @endpoint: usb endpoint +* @pending_req_list: List of requests queuing on transfer ring. +* @pdev: Device associated with this endpoint. +* @number: Endpoint number (1 - 15). +* idx: The device context index (DCI). +* interval: Interval between packets used for ISOC endpoint. +* @name: A human readable name e.g. ep1out. +* @direction: Endpoint direction. +* @buffering: Number of on-chip buffers related to endpoint. +* @buffering_period; Number of on-chip buffers related to periodic endpoint. +* @in_ctx: Pointer to input endpoint context structure. +* @out_ctx: Pointer to output endpoint context structure. +* @ring: Pointer to transfer ring. +* @stream_info: Hold stream information. +* @ep_state: Current state of endpoint. +* @skip: Sometimes the controller can not process isochronous endpoint ring +* quickly enough, and it will miss some isoc tds on the ring and +* generate Missed Service Error Event. +* Set skip flag when receive a Missed Service Error Event and +* process the missed tds on the endpoint ring. +*/ +struct cdnsp_ep { +struct usb_ep endpoint; +struct list_head pending_list; +struct cdnsp_device *pdev; +u8 number; +u8 idx; +u32 interval; +char name[20 ]; +u8 direction; +u8 buffering; +u8 buffering_period; +struct cdnsp_ep_ctx *in_ctx; +struct cdnsp_ep_ctx *out_ctx; +struct cdnsp_ring *ring; +struct cdnsp_stream_info stream_info; +unsigned int ep_state; +#define EP_ENABLED BIT(0) +#define EP_DIS_IN_RROGRESS BIT(1) +#define EP_HALTED BIT(2) +#define EP_STOPPED BIT(3) +#define EP_WEDGE BIT(4) +#define EP0_HALTED_STATUS BIT(5) +#define EP_HAS_STREAMS BIT(6) + +bool skip; +}; + +/** +* struct cdnsp_device_context_array +* @dev_context_ptr: Array of 64-bit DMA addresses for device contexts. +* @dma: DMA address for device contexts structure. +*/ +struct cdnsp_device_context_array { +__le64 dev_context_ptrs[CDNSP_DEV_MAX_SLOTS +1 ]; +dma_addr_t dma; +}; + +/** +* struct cdnsp_transfer_event. +* @buffer: 64-bit buffer address, or immediate data. +* @transfer_len: Data length transferred. +* @flags: Field is interpreted differently based on the type of TRB. +*/ +struct cdnsp_transfer_event { +__le64 buffer; +__le32 transfer_len; +__le32 flags; +}; + +/* Invalidate event after disabling endpoint. */ +#define TRB_EVENT_INVALIDATE 8 + +/* Transfer event TRB length bit mask. */ +/* bits 0:23 */ +#define EVENT_TRB_LEN (p) ((p) & GENMASK(23, 0)) +/* Completion Code - only applicable for some types of TRBs */ +#define COMP_CODE_MASK (0xff << 24) +#define GET_COMP_CODE (p) (((p) & COMP_CODE_MASK) >> 24) +#define COMP_INVALID 0 +#define COMP_SUCCESS 1 +#define COMP_DATA_BUFFER_ERROR 2 +#define COMP_BABBLE_DETECTED_ERROR 3 +#define COMP_TRB_ERROR 5 +#define COMP_RESOURCE_ERROR 7 +#define COMP_NO_SLOTS_AVAILABLE_ERROR 9 +#define COMP_INVALID_STREAM_TYPE_ERROR 10 +#define COMP_SLOT_NOT_ENABLED_ERROR 11 +#define COMP_ENDPOINT_NOT_ENABLED_ERROR 12 +#define COMP_SHORT_PACKET 13 +#define COMP_RING_UNDERRUN 14 +#define COMP_RING_OVERRUN 15 +#define COMP_VF_EVENT_RING_FULL_ERROR 16 +#define COMP_PARAMETER_ERROR 17 +#define COMP_CONTEXT_STATE_ERROR 19 +#define COMP_EVENT_RING_FULL_ERROR 21 +#define COMP_INCOMPATIBLE_DEVICE_ERROR 22 +#define COMP_MISSED_SERVICE_ERROR 23 +#define COMP_COMMAND_RING_STOPPED 24 +#define COMP_COMMAND_ABORTED 25 +#define COMP_STOPPED 26 +#define COMP_STOPPED_LENGTH_INVALID 27 +#define COMP_STOPPED_SHORT_PACKET 28 +#define COMP_MAX_EXIT_LATENCY_TOO_LARGE_ERROR 29 +#define COMP_ISOCH_BUFFER_OVERRUN 31 +#define COMP_EVENT_LOST_ERROR 32 +#define COMP_UNDEFINED_ERROR 33 +#define COMP_INVALID_STREAM_ID_ERROR 34 + +/*Transfer Event NRDY bit fields */ +#define TRB_TO_DEV_STREAM (p) ((p) & GENMASK(16, 0)) +#define TRB_TO_HOST_STREAM (p) ((p) & GENMASK(16, 0)) +#define STREAM_PRIME_ACK 0xFFFE +#define STREAM_REJECTED 0xFFFF + +/** Transfer Event bit fields **/ +#define TRB_TO_EP_ID (p) (((p) & GENMASK(20, 16)) >> 16) + +/** +* struct cdnsp_link_trb +* @segment_ptr: 64-bit segment pointer. +* @intr_target: Interrupter target. +* @control: Flags. +*/ +struct cdnsp_link_trb { +__le64 segment_ptr; +__le32 intr_target; +__le32 control; +}; + +/* control bitfields */ +#define LINK_TOGGLE BIT(1) + +/** +* struct cdnsp_event_cmd - Command completion event TRB. +* cmd_trb: Pointer to command TRB, or the value passed by the event data trb +* status: Command completion parameters and error code. +* flags: Flags. +*/ +struct cdnsp_event_cmd { +__le64 cmd_trb; +__le32 status; +__le32 flags; +}; + +/* flags bitmasks */ + +/* Address device - disable SetAddress. */ +#define TRB_BSR BIT(9) + +/* Configure Endpoint - Deconfigure. */ +#define TRB_DC BIT(9) + +/* Force Header */ +#define TRB_FH_TO_PACKET_TYPE (p) ((p) & GENMASK(4, 0)) +#define TRB_FH_TR_PACKET 0x4 +#define TRB_FH_TO_DEVICE_ADDRESS (p) (((p) << 25) & GENMASK(31, 25)) +#define TRB_FH_TR_PACKET_DEV_NOT 0x6 +#define TRB_FH_TO_NOT_TYPE (p) (((p) << 4) & GENMASK(7, 4)) +#define TRB_FH_TR_PACKET_FUNCTION_WAKE 0x1 +#define TRB_FH_TO_INTERFACE (p) (((p) << 8) & GENMASK(15, 8)) + +enum cdnsp_setup_dev { +SETUP_CONTEXT_ONLY , +SETUP_CONTEXT_ADDRESS , +}; + +/* bits 24:31 are the slot ID. */ +#define TRB_TO_SLOT_ID (p) (((p) & GENMASK(31, 24)) >> 24) +#define SLOT_ID_FOR_TRB (p) (((p) << 24) & GENMASK(31, 24)) + +/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB. */ +#define TRB_TO_EP_INDEX (p) (((p) >> 16) & 0x1f) + +#define EP_ID_FOR_TRB (p) ((((p) + 1) << 16) & GENMASK(20, 16)) + +#define SUSPEND_PORT_FOR_TRB (p) (((p) & 1) << 23) +#define TRB_TO_SUSPEND_PORT (p) (((p) >> 23) & 0x1) +#define LAST_EP_INDEX 30 + +/* Set TR Dequeue Pointer command TRB fields. */ +#define TRB_TO_STREAM_ID (p) ((((p) & GENMASK(31, 16)) >> 16)) +#define STREAM_ID_FOR_TRB (p) ((((p)) << 16) & GENMASK(31, 16)) +#define SCT_FOR_TRB (p) (((p) << 1) & 0x7) + +/* Link TRB specific fields. */ +#define TRB_TC BIT(1) + +/* Port Status Change Event TRB fields. */ +/* Port ID - bits 31:24. */ +#define GET_PORT_ID (p) (((p) & GENMASK(31, 24)) >> 24) +#define SET_PORT_ID (p) (((p) << 24) & GENMASK(31, 24)) +#define EVENT_DATA BIT(2) + +/* Normal TRB fields. */ +/* transfer_len bitmasks - bits 0:16. */ +#define TRB_LEN (p) ((p) & GENMASK(16, 0)) +/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31). */ +#define TRB_TD_SIZE (p) (min((p), (u32)31) << 17) +#define GET_TD_SIZE (p) (((p) & GENMASK(21, 17)) >> 17) +/* +* Controller uses the TD_SIZE field for TBC if Extended TBC +* is enabled (ETE). +*/ +#define TRB_TD_SIZE_TBC (p) (min((p), (u32)31) << 17) +/* Interrupter Target - which MSI-X vector to target the completion event at. */ +#define TRB_INTR_TARGET (p) (((p) << 22) & GENMASK(31, 22)) +#define GET_INTR_TARGET (p) (((p) & GENMASK(31, 22)) >> 22) +/* +* Total burst count field, Rsvdz on controller with Extended TBC +* enabled (ETE). +*/ +#define TRB_TBC (p) (((p) & 0x3) << 7) +#define TRB_TLBPC (p) (((p) & 0xf) << 16) + +/* Cycle bit - indicates TRB ownership by driver or driver.*/ +#define TRB_CYCLE BIT(0) +/* +* Force next event data TRB to be evaluated before task switch. +* Used to pass OS data back after a TD completes. +*/ +#define TRB_ENT BIT(1) +/* Interrupt on short packet. */ +#define TRB_ISP BIT(2) +/* Set PCIe no snoop attribute. */ +#define TRB_NO_SNOOP BIT(3) +/* Chain multiple TRBs into a TD. */ +#define TRB_CHAIN BIT(4) +/* Interrupt on completion. */ +#define TRB_IOC BIT(5) +/* The buffer pointer contains immediate data. */ +#define TRB_IDT BIT(6) +/* 0 - NRDY during data stage, 1 - NRDY during status stage (only control). */ +#define TRB_STAT BIT(7) +/* Block Event Interrupt. */ +#define TRB_BEI BIT(9) + +/* Control transfer TRB specific fields. */ +#define TRB_DIR_IN BIT(16) + +/* TRB bit mask in Data Stage TRB */ +#define TRB_SETUPID_BITMASK GENMASK(9, 8) +#define TRB_SETUPID (p) ((p) << 8) +#define TRB_SETUPID_TO_TYPE (p) (((p) & TRB_SETUPID_BITMASK) >> 8) + +#define TRB_SETUP_SPEEDID_USB3 0x1 +#define TRB_SETUP_SPEEDID_USB2 0x0 +#define TRB_SETUP_SPEEDID (p) ((p) & (1 << 7)) + +#define TRB_SETUPSTAT_ACK 0x1 +#define TRB_SETUPSTAT_STALL 0x0 +#define TRB_SETUPSTAT (p) ((p) << 6) + +/* Isochronous TRB specific fields */ +#define TRB_SIA BIT(31) +#define TRB_FRAME_ID (p) (((p) << 20) & GENMASK(30, 20)) + +struct cdnsp_generic_trb { +__le32 field[4 ]; +}; + +union cdnsp_trb { +struct cdnsp_link_trb link; +struct cdnsp_transfer_event trans_event; +struct cdnsp_event_cmd event_cmd; +struct cdnsp_generic_trb generic; +}; + +/* TRB bit mask. */ +#define TRB_TYPE_BITMASK GENMASK(15, 10) +#define TRB_TYPE (p) ((p) << 10) +#define TRB_FIELD_TO_TYPE (p) (((p) & TRB_TYPE_BITMASK) >> 10) + +/* TRB type IDs. */ +/* bulk, interrupt, isoc scatter/gather, and control data stage. */ +#define TRB_NORMAL 1 +/* Setup Stage for control transfers. */ +#define TRB_SETUP 2 +/* Data Stage for control transfers. */ +#define TRB_DATA 3 +/* Status Stage for control transfers. */ +#define TRB_STATUS 4 +/* ISOC transfers. */ +#define TRB_ISOC 5 +/* TRB for linking ring segments. */ +#define TRB_LINK 6 +#define TRB_EVENT_DATA 7 +/* Transfer Ring No-op (not for the command ring). */ +#define TRB_TR_NOOP 8 + +/* Command TRBs */ +/* Enable Slot Command. */ +#define TRB_ENABLE_SLOT 9 +/* Disable Slot Command. */ +#define TRB_DISABLE_SLOT 10 +/* Address Device Command. */ +#define TRB_ADDR_DEV 11 +/* Configure Endpoint Command. */ +#define TRB_CONFIG_EP 12 +/* Evaluate Context Command. */ +#define TRB_EVAL_CONTEXT 13 +/* Reset Endpoint Command. */ +#define TRB_RESET_EP 14 +/* Stop Transfer Ring Command. */ +#define TRB_STOP_RING 15 +/* Set Transfer Ring Dequeue Pointer Command. */ +#define TRB_SET_DEQ 16 +/* Reset Device Command. */ +#define TRB_RESET_DEV 17 +/* Force Event Command (opt). */ +#define TRB_FORCE_EVENT 18 +/* Force Header Command - generate a transaction or link management packet. */ +#define TRB_FORCE_HEADER 22 +/* No-op Command - not for transfer rings. */ +#define TRB_CMD_NOOP 23 +/* TRB IDs 24-31 reserved. */ + +/* Event TRBS. */ +/* Transfer Event. */ +#define TRB_TRANSFER 32 +/* Command Completion Event. */ +#define TRB_COMPLETION 33 +/* Port Status Change Event. */ +#define TRB_PORT_STATUS 34 +/* Device Controller Event. */ +#define TRB_HC_EVENT 37 +/* MFINDEX Wrap Event - microframe counter wrapped. */ +#define TRB_MFINDEX_WRAP 39 +/* TRB IDs 40-47 reserved. */ +/* Endpoint Not Ready Event. */ +#define TRB_ENDPOINT_NRDY 48 +/* TRB IDs 49-53 reserved. */ +/* Halt Endpoint Command. */ +#define TRB_HALT_ENDPOINT 54 +/* Doorbell Overflow Event. */ +#define TRB_DRB_OVERFLOW 57 +/* Flush Endpoint Command. */ +#define TRB_FLUSH_ENDPOINT 58 + +#define TRB_TYPE_LINK (x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) +#define TRB_TYPE_LINK_LE32 (x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ + cpu_to_le32(TRB_TYPE(TRB_LINK))) +#define TRB_TYPE_NOOP_LE32 (x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ + cpu_to_le32(TRB_TYPE(TRB_TR_NOOP))) + +/* +* TRBS_PER_SEGMENT must be a multiple of 4. +* The command ring is 64-byte aligned, so it must also be greater than 16. +*/ +#define TRBS_PER_SEGMENT 256 +#define TRBS_PER_EVENT_SEGMENT 256 +#define TRBS_PER_EV_DEQ_UPDATE 100 +#define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT * 16) +#define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE)) +/* TRB buffer pointers can't cross 64KB boundaries. */ +#define TRB_MAX_BUFF_SHIFT 16 +#define TRB_MAX_BUFF_SIZE BIT(TRB_MAX_BUFF_SHIFT) +/* How much data is left before the 64KB boundary? */ +#define TRB_BUFF_LEN_UP_TO_BOUNDARY (addr) (TRB_MAX_BUFF_SIZE - \ + ((addr) & (TRB_MAX_BUFF_SIZE - 1))) + +/** +* struct cdnsp_segment - segment related data. +* @trbs: Array of Transfer Request Blocks. +* @next: Pointer to the next segment. +* @dma: DMA address of current segment. +* @bounce_dma: Bounce buffer DMA address . +* @bounce_buf: Bounce buffer virtual address. +* bounce_offs: Bounce buffer offset. +* bounce_len: Bounce buffer length. +*/ +struct cdnsp_segment { +union cdnsp_trb *trbs; +struct cdnsp_segment *next; +dma_addr_t dma; +/* Max packet sized bounce buffer for td-fragmant alignment */ +dma_addr_t bounce_dma; +void *bounce_buf; +unsigned int bounce_offs; +unsigned int bounce_len; +}; + +/** +* struct cdnsp_td - Transfer Descriptor object. +* @td_list: Used for binding TD with ep_ring->td_list. +* @preq: Request associated with this TD +* @start_seg: Segment containing the first_trb in TD. +* @first_trb: First TRB for this TD. +* @last_trb: Last TRB related with TD. +* @bounce_seg: Bounce segment for this TD. +* @request_length_set: actual_length of the request has already been set. +* @drbl - TD has been added to HW scheduler - only for stream capable +* endpoints. +*/ +struct cdnsp_td { +struct list_head td_list; +struct cdnsp_request *preq; +struct cdnsp_segment *start_seg; +union cdnsp_trb *first_trb; +union cdnsp_trb *last_trb; +struct cdnsp_segment *bounce_seg; +bool request_length_set; +bool drbl; +}; + +/** +* struct cdnsp_dequeue_state - New dequeue pointer for Transfer Ring. +* @new_deq_seg: New dequeue segment. +* @new_deq_ptr: New dequeue pointer. +* @new_cycle_state: New cycle state. +* @stream_id: stream id for which new dequeue pointer has been selected. +*/ +struct cdnsp_dequeue_state { +struct cdnsp_segment *new_deq_seg; +union cdnsp_trb *new_deq_ptr; +int new_cycle_state; +unsigned int stream_id; +}; + +enum cdnsp_ring_type { +TYPE_CTRL =0 , +TYPE_ISOC , +TYPE_BULK , +TYPE_INTR , +TYPE_STREAM , +TYPE_COMMAND , +TYPE_EVENT , +}; + +/** +* struct cdnsp_ring - information describing transfer, command or event ring. +* @first_seg: First segment on transfer ring. +* @last_seg: Last segment on transfer ring. +* @enqueue: SW enqueue pointer address. +* @enq_seg: SW enqueue segment address. +* @dequeue: SW dequeue pointer address. +* @deq_seg: SW dequeue segment address. +* @td_list: transfer descriptor list associated with this ring. +* @cycle_state: Current cycle bit. Write the cycle state into the TRB cycle +* field to give ownership of the TRB to the device controller +* (if we are the producer) or to check if we own the TRB +* (if we are the consumer). +* @stream_id: Stream id +* @stream_active: Stream is active - PRIME packet has been detected. +* @stream_rejected: This ring has been rejected by host. +* @num_tds: Number of TDs associated with ring. +* @num_segs: Number of segments. +* @num_trbs_free: Number of free TRBs on the ring. +* @bounce_buf_len: Length of bounce buffer. +* @type: Ring type - event, transfer, or command ring. +* @last_td_was_short - TD is short TD. +* @trb_address_map: For mapping physical TRB addresses to segments in +* stream rings. +*/ +struct cdnsp_ring { +struct cdnsp_segment *first_seg; +struct cdnsp_segment *last_seg; +union cdnsp_trb *enqueue; +struct cdnsp_segment *enq_seg; +union cdnsp_trb *dequeue; +struct cdnsp_segment *deq_seg; +struct list_head td_list; +u32 cycle_state; +unsigned int stream_id; +unsigned int stream_active; +unsigned int stream_rejected; +int num_tds; +unsigned int num_segs; +unsigned int num_trbs_free; +unsigned int bounce_buf_len; +enum cdnsp_ring_type type; +bool last_td_was_short; +struct radix_tree_root *trb_address_map; +}; + +/** +* struct cdnsp_erst_entry - even ring segment table entry object. +* @seg_addr: 64-bit event ring segment address. +* seg_size: Number of TRBs in segment.; +*/ +struct cdnsp_erst_entry { +__le64 seg_addr; +__le32 seg_size; +/* Set to zero */ +__le32 rsvd; +}; + +/** +* struct cdnsp_erst - even ring segment table for event ring. +* @entries: Array of event ring segments +* @num_entries: Number of segments in entries array. +* @erst_dma_addr: DMA address for entries array. +*/ +struct cdnsp_erst { +struct cdnsp_erst_entry *entries; +unsigned int num_entries; +dma_addr_t erst_dma_addr; +}; + +/** +* struct cdnsp_request - extended device side representation of usb_request +* object . +* @td: Transfer descriptor associated with this request. +* @request: Generic usb_request object describing single I/O request. +* @list: Used to adding request to endpoint pending_list. +* @pep: Extended representation of usb_ep object +* @epnum: Endpoint number associated with usb request. +* @direction: Endpoint direction for usb request. +*/ +struct cdnsp_request { +struct cdnsp_td td; +struct usb_request request; +struct list_head list; +struct cdnsp_ep *pep; +u8 epnum; +unsigned direction:1 ; +}; + +#define ERST_NUM_SEGS 1 + +/* Stages used during enumeration process.*/ +enum cdnsp_ep0_stage { +CDNSP_SETUP_STAGE , +CDNSP_DATA_STAGE , +CDNSP_STATUS_STAGE , +}; + +/** +* struct cdnsp_port - holds information about detected ports. +* @port_num: Port number. +* @exist: Indicate if port exist. +* maj_rev: Major revision. +* min_rev: Minor revision. +*/ +struct cdnsp_port { +struct cdnsp_port_regs __iomem *regs; +u8 port_num; +u8 exist; +u8 maj_rev; +u8 min_rev; +}; + +#define CDNSP_EXT_PORT_MAJOR (x) (((x) >> 24) & 0xff) +#define CDNSP_EXT_PORT_MINOR (x) (((x) >> 16) & 0xff) +#define CDNSP_EXT_PORT_OFF (x) ((x) & 0xff) +#define CDNSP_EXT_PORT_COUNT (x) (((x) >> 8) & 0xff) + +/** +* struct cdnsp_device - represent USB device. +* @dev: Pointer to device structure associated whit this controller. +* @gadget: Device side representation of the peripheral controller. +* @gadget_driver: Pointer to the gadget driver. +* @irq: IRQ line number used by device side. +* @regs:IO device memory. +* @cap_regs: Capability registers. +* @op_regs: Operational registers. +* @run_regs: Runtime registers. +* @dba: Device base address register. +* @ir_set: Current interrupter register set. +* @port20_regs: Port 2.0 Peripheral Configuration Registers. +* @port3x_regs: USB3.x Port Peripheral Configuration Registers. +* @hcs_params1: Cached register copies of read-only HCSPARAMS1 +* @hcc_params: Cached register copies of read-only HCCPARAMS1 +* @rev_cap: Controller capability. +* @setup: Temporary buffer for setup packet. +* @ep0_preq: Internal allocated request used during enumeration. +* @ep0_stage: ep0 stage during enumeration process. +* @three_stage_setup: Three state or two state setup. +* @ep0_expect_in: Data IN expected for control transfer. +* @setup_id: Setup identifier. +* @setup_speed - Speed detected for current SETUP packet. +* @setup_buf: Buffer for SETUP packet. +* @device_address: Current device address. +* @may_wakeup: remote wakeup enabled/disabled. +* @lock: Lock used in interrupt thread context. +* @hci_version: device controller version. +* @dcbaa: Device context base address array. +* @cmd_ring: Command ring. +* @cmd: Represent all what is needed to issue command on Command Ring. +* @event_ring: Event ring. +* @erst: Event Ring Segment table +* @slot_id: Current Slot ID. Should be 0 or 1. +* @out_ctx: Output context. +* @in_ctx: Input context. +* @eps: array of endpoints object associated with device. +* @usb2_hw_lpm_capable: hardware lpm is enabled; +* @u1_allowed: Allow device transition to U1 state. +* @u2_allowed: Allow device transition to U2 state +* @device_pool: DMA pool for allocating input and output context. +* @segment_pool: DMA pool for allocating new segments. +* @cdnsp_state: Current state of controller. +* @link_state: Current link state. +* @usb2_port - Port USB 2.0. +* @usb3_port - Port USB 3.0. +* @active_port - Current selected Port. +* @test_mode: selected Test Mode. +*/ +struct cdnsp_device { +struct device *dev; +struct usb_gadget gadget; +struct usb_gadget_driver *gadget_driver; +unsigned int irq; +void __iomem *regs; + +/* Registers map */ +struct cdnsp_cap_regs __iomem *cap_regs; +struct cdnsp_op_regs __iomem *op_regs; +struct cdnsp_run_regs __iomem *run_regs; +struct cdnsp_doorbell_array __iomem *dba; +struct cdnsp_intr_reg __iomem *ir_set; +struct cdnsp_20port_cap __iomem *port20_regs; +struct cdnsp_3xport_cap __iomem *port3x_regs; + +/* Cached register copies of read-only CDNSP data */ +__u32 hcs_params1; +__u32 hcs_params3; +__u32 hcc_params; +struct cdnsp_rev_cap rev_cap; +/* Lock used in interrupt thread context. */ +spinlock_t lock; +struct usb_ctrlrequest setup; +struct cdnsp_request ep0_preq; +enum cdnsp_ep0_stage ep0_stage; +u8 three_stage_setup; +u8 ep0_expect_in; +u8 setup_id; +u8 setup_speed; +void *setup_buf; +u8 device_address; +int may_wakeup; +u16 hci_version; + +/* data structures */ +struct cdnsp_device_context_array *dcbaa; +struct cdnsp_ring *cmd_ring; +struct cdnsp_command cmd; +struct cdnsp_ring *event_ring; +struct cdnsp_erst erst; +int slot_id; + +/* +* Commands to the hardware are passed an "input context" that +* tells the hardware what to change in its data structures. +* The hardware will return changes in an "output context" that +* software must allocate for the hardware. . +*/ +struct cdnsp_container_ctx out_ctx; +struct cdnsp_container_ctx in_ctx; +struct cdnsp_ep eps[CDNSP_ENDPOINTS_NUM ]; +u8 usb2_hw_lpm_capable:1 ; +u8 u1_allowed:1 ; +u8 u2_allowed:1 ; + +/* DMA pools */ +struct dma_pool *device_pool; +struct dma_pool *segment_pool; + +#define CDNSP_STATE_HALTED BIT(1) +#define CDNSP_STATE_DYING BIT(2) +#define CDNSP_STATE_DISCONNECT_PENDING BIT(3) +#define CDNSP_WAKEUP_PENDING BIT(4) +unsigned int cdnsp_state; +unsigned int link_state; + +struct cdnsp_port usb2_port; +struct cdnsp_port usb3_port; +struct cdnsp_port *active_port; +u16 test_mode; +}; + +#endif /* __LINUX_CDNSP_GADGET_H */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 107/162 ceph: make ceph_create_session_msg a global symbol
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit fba97e8025015b63b1bdb73cd868c8ea832a1620 ]
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/mds_client.c | 16 +++++++++------- fs/ceph/mds_client.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-)
fs/ceph/mds_client.c +9 -7
@@ -1157,7 +1157,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,/* * session messages */ -static struct ceph_msg *create_session_msg (u32 op,u64 seq) +struct ceph_msg *ceph_create_session_msg (u32 op,u64 seq) {struct ceph_msg *msg;struct ceph_mds_session_head *h;
@@ -1165,7 +1165,8 @@ static struct ceph_msg *create_session_msg(u32 op, u64 seq) msg =ceph_msg_new (CEPH_MSG_CLIENT_SESSION ,sizeof (*h),GFP_NOFS , false);if (!msg) { -pr_err ("create_session_msg ENOMEM creating msg\n" ); +pr_err ("ENOMEM creating session %s msg\n" , +ceph_session_op_name (op));return NULL ; } h = msg->front.iov_base;
@@ -1299,7 +1300,7 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6 msg =ceph_msg_new (CEPH_MSG_CLIENT_SESSION ,sizeof (*h) + extra_bytes,GFP_NOFS , false);if (!msg) { -pr_err ("create_session_msg ENOMEM creating msg\n" ); +pr_err ("ENOMEM creating session open msg\n" );return ERR_PTR (-ENOMEM ); } p = msg->front.iov_base;
@@ -1833,8 +1834,8 @@ static int send_renew_caps(struct ceph_mds_client *mdsc,dout ("send_renew_caps to mds%d (%s)\n" , session->s_mds,ceph_mds_state_name (state)); - msg =create_session_msg (CEPH_SESSION_REQUEST_RENEWCAPS , - ++session->s_renew_seq); + msg =ceph_create_session_msg (CEPH_SESSION_REQUEST_RENEWCAPS , + ++session->s_renew_seq);if (!msg)return -ENOMEM ;ceph_con_send (&session->s_con, msg);
@@ -1848,7 +1849,7 @@ static int send_flushmsg_ack(struct ceph_mds_client *mdsc,dout ("send_flushmsg_ack to mds%d (%s)s seq %lld\n" , session->s_mds,ceph_session_state_name (session->s_state), seq); - msg =create_session_msg (CEPH_SESSION_FLUSHMSG_ACK , seq); + msg =ceph_create_session_msg (CEPH_SESSION_FLUSHMSG_ACK , seq);if (!msg)return -ENOMEM ;ceph_con_send (&session->s_con, msg);
@@ -1900,7 +1901,8 @@ static int request_close_session(struct ceph_mds_session *session)dout ("request_close_session mds%d state %s seq %lld\n" , session->s_mds,ceph_session_state_name (session->s_state), session->s_seq); - msg =create_session_msg (CEPH_SESSION_REQUEST_CLOSE , session->s_seq); + msg =ceph_create_session_msg (CEPH_SESSION_REQUEST_CLOSE , + session->s_seq);if (!msg)return -ENOMEM ;ceph_con_send (&session->s_con, msg);
fs/ceph/mds_client.h +1 -0
@@ -518,6 +518,7 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)kref_put (&req->r_kref, ceph_mdsc_release_request); } +extern struct ceph_msg *ceph_create_session_msg (u32 op,u64 seq);extern void __ceph_queue_cap_release (struct ceph_mds_session *session,struct ceph_cap *cap); extern void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 108/162 ceph: make iterate_sessions a global symbol
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 59b312f36230ea91ebb6ce1b11f2781604495d30 ]
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 26 +---------------------- fs/ceph/mds_client.c | 49 +++++++++++++++++++++++++++++--------------- fs/ceph/mds_client.h | 3 +++ 3 files changed, 36 insertions(+), 42 deletions(-)
fs/ceph/caps.c +1 -25
@@ -4310,33 +4310,9 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)dout ("flush_dirty_caps done\n" ); } -static void iterate_sessions (struct ceph_mds_client *mdsc, -void (*cb)(struct ceph_mds_session *)) -{ -int mds; - -mutex_lock (&mdsc->mutex); -for (mds =0 ; mds < mdsc->max_sessions; ++mds) { -struct ceph_mds_session *s; - -if (!mdsc->sessions[mds]) -continue ; - - s =ceph_get_mds_session (mdsc->sessions[mds]); -if (!s) -continue ; - -mutex_unlock (&mdsc->mutex); -cb (s); -ceph_put_mds_session (s); -mutex_lock (&mdsc->mutex); - } -mutex_unlock (&mdsc->mutex); -} -void ceph_flush_dirty_caps (struct ceph_mds_client *mdsc) { -iterate_sessions (mdsc, flush_dirty_session_caps); +ceph_mdsc_iterate_sessions (mdsc, flush_dirty_session_caps, true); } void __ceph_touch_fmode(struct ceph_inode_info *ci,
fs/ceph/mds_client.c +32 -17
69 lines not on this page · raw message
fs/ceph/mds_client.h +3 -0
@@ -518,6 +518,9 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)kref_put (&req->r_kref, ceph_mdsc_release_request); } +extern void ceph_mdsc_iterate_sessions (struct ceph_mds_client *mdsc, +void (*cb)(struct ceph_mds_session *), +bool check_state);extern struct ceph_msg *ceph_create_session_msg (u32 op,u64 seq);extern void __ceph_queue_cap_release (struct ceph_mds_session *session,struct ceph_cap *cap);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 109/162 ceph: flush mdlog before umounting
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit d095559ce4100f0c02aea229705230deac329c97 ]
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/mds_client.c | 25 +++++++++++++++++++++++++ fs/ceph/mds_client.h | 1 + fs/ceph/strings.c | 1 + include/linux/ceph/ceph_fs.h | 1 + 4 files changed, 28 insertions(+)
fs/ceph/mds_client.c +25 -0
@@ -4664,6 +4664,30 @@ static void wait_requests(struct ceph_mds_client *mdsc)dout ("wait_requests done\n" ); } +void send_flush_mdlog (struct ceph_mds_session *s) +{ +struct ceph_msg *msg; + +/* +* Pre-luminous MDS crashes when it sees an unknown session request +*/ +if (!CEPH_HAVE_FEATURE (s->s_con.peer_features,SERVER_LUMINOUS )) +return ; + +mutex_lock (&s->s_mutex); +dout ("request mdlog flush to mds%d (%s)s seq %lld\n" , s->s_mds, +ceph_session_state_name (s->s_state), s->s_seq); + msg =ceph_create_session_msg (CEPH_SESSION_REQUEST_FLUSH_MDLOG , + s->s_seq); +if (!msg) { +pr_err ("failed to request mdlog flush to mds%d (%s) seq %lld\n" , + s->s_mds,ceph_session_state_name (s->s_state), s->s_seq); + }else { +ceph_con_send (&s->s_con, msg); + } +mutex_unlock (&s->s_mutex); +} +/* * called before mount is ro, and before dentries are torn down. * (hmm, does this still race with new lookups?)
@@ -4673,6 +4697,7 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)dout ("pre_umount\n" ); mdsc->stopping =1 ; +ceph_mdsc_iterate_sessions (mdsc, send_flush_mdlog, true);ceph_mdsc_iterate_sessions (mdsc, lock_unlock_session, false);ceph_flush_dirty_caps (mdsc);wait_requests (mdsc);
fs/ceph/mds_client.h +1 -0
@@ -518,6 +518,7 @@ static inline void ceph_mdsc_put_request(struct ceph_mds_request *req)kref_put (&req->r_kref, ceph_mdsc_release_request); } +extern void send_flush_mdlog (struct ceph_mds_session *s);extern void ceph_mdsc_iterate_sessions (struct ceph_mds_client *mdsc,void (*cb)(struct ceph_mds_session *),bool check_state);
fs/ceph/strings.c +1 -0
@@ -46,6 +46,7 @@ const char *ceph_session_op_name(int op)case CEPH_SESSION_FLUSHMSG_ACK :return "flushmsg_ack" ;case CEPH_SESSION_FORCE_RO :return "force_ro" ;case CEPH_SESSION_REJECT :return "reject" ; +case CEPH_SESSION_REQUEST_FLUSH_MDLOG :return "flush_mdlog" ; }return "???" ; }
include/linux/ceph/ceph_fs.h +1 -0
@@ -288,6 +288,7 @@ enum {CEPH_SESSION_FLUSHMSG_ACK ,CEPH_SESSION_FORCE_RO ,CEPH_SESSION_REJECT , + CEPH_SESSION_REQUEST_FLUSH_MDLOG, };extern const char *ceph_session_op_name (int op);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 110/162 ceph: flush the mdlog before waiting on unsafe reqs
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit e1a4541ec0b951685a49d1f72d183681e6433a45 ]
For the client requests who will have unsafe and safe replies from MDS daemons, in the MDS side the MDS daemons won't flush the mdlog (journal log) immediatelly, because they think it's unnecessary. That's true for most cases but not all, likes the fsync request. The fsync will wait until all the unsafe replied requests to be safely replied.
Normally if there have multiple threads or clients are running, the whole mdlog in MDS daemons could be flushed in time if any request will trigger the mdlog submit thread. So usually we won't experience the normal operations will stuck for a long time. But in case there has only one client with only thread is running, the stuck phenomenon maybe obvious and the worst case it must wait at most 5 seconds to wait the mdlog to be flushed by the MDS's tick thread periodically.
This patch will trigger to flush the mdlog in the relevant and auth MDSes to which the in-flight requests are sent just before waiting the unsafe requests to finish.
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+)
fs/ceph/caps.c +76 -0
@@ -2294,6 +2294,7 @@ static int caps_are_flushed(struct inode *inode, u64 flush_tid)*/ static int unsafe_request_wait (struct inode *inode) { +struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req1 =NULL , *req2 =NULL ;int ret, err =0 ;
@@ -2313,6 +2314,81 @@ static int unsafe_request_wait(struct inode *inode) }spin_unlock (&ci->i_unsafe_lock); +/* +* Trigger to flush the journal logs in all the relevant MDSes +* manually, or in the worst case we must wait at most 5 seconds +* to wait the journal logs to be flushed by the MDSes periodically. +*/ +if (req1 || req2) { +struct ceph_mds_session **sessions =NULL ; +struct ceph_mds_session *s; +struct ceph_mds_request *req; +unsigned int max; +int i; + +/* +* The mdsc->max_sessions is unlikely to be changed +* mostly, here we will retry it by reallocating the +* sessions arrary memory to get rid of the mdsc->mutex +* lock. +*/ +retry: + max = mdsc->max_sessions; + sessions =krealloc (sessions, max *sizeof (s), __GFP_ZERO); +if (!sessions) +return -ENOMEM ; + +spin_lock (&ci->i_unsafe_lock); +if (req1) { +list_for_each_entry (req, &ci->i_unsafe_dirops, + r_unsafe_dir_item) { + s = req->r_session; +if (unlikely (s->s_mds > max)) { +spin_unlock (&ci->i_unsafe_lock); + goto retry; + } +if (!sessions[s->s_mds]) { + s =ceph_get_mds_session (s); + sessions[s->s_mds] = s; + } + } + } +if (req2) { +list_for_each_entry (req, &ci->i_unsafe_iops, + r_unsafe_target_item) { + s = req->r_session; +if (unlikely (s->s_mds > max)) { +spin_unlock (&ci->i_unsafe_lock); + goto retry; + } +if (!sessions[s->s_mds]) { + s =ceph_get_mds_session (s); + sessions[s->s_mds] = s; + } + } + } +spin_unlock (&ci->i_unsafe_lock); + +/* the auth MDS */ +spin_lock (&ci->i_ceph_lock); +if (ci->i_auth_cap) { + s = ci->i_auth_cap->session; +if (!sessions[s->s_mds]) + sessions[s->s_mds] =ceph_get_mds_session (s); + } +spin_unlock (&ci->i_ceph_lock); + +/* send flush mdlog request to MDSes */ +for (i =0 ; i < max; i++) { + s = sessions[i]; +if (s) { +send_flush_mdlog (s); +ceph_put_mds_session (s); + } + } +kfree (sessions); + } +dout ("unsafe_request_wait %p wait on tid %llu %llu\n" , inode, req1 ? req1->r_tid :0ULL , req2 ? req2->r_tid :0ULL );if (req1) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 111/162 ceph: fix off by one bugs in unsafe_request_wait()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit 708c87168b6121abc74b2a57d0c498baaf70cbea ]
The "> max" tests should be ">= max" to prevent an out of bounds access on the next lines.
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ceph/caps.c +2 -2
@@ -2343,7 +2343,7 @@ static int unsafe_request_wait(struct inode *inode)list_for_each_entry (req, &ci->i_unsafe_dirops, r_unsafe_dir_item) { s = req->r_session; -if (unlikely (s->s_mds > max)) { +if (unlikely (s->s_mds >= max)) {spin_unlock (&ci->i_unsafe_lock); goto retry; }
@@ -2357,7 +2357,7 @@ static int unsafe_request_wait(struct inode *inode)list_for_each_entry (req, &ci->i_unsafe_iops, r_unsafe_target_item) { s = req->r_session; -if (unlikely (s->s_mds > max)) { +if (unlikely (s->s_mds >= max)) {spin_unlock (&ci->i_unsafe_lock); goto retry; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 112/162 ceph: put the requests/sessions when it fails to alloc memory
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 89d43d0551a848e70e63d9ba11534aaeabc82443 ]
When failing to allocate the sessions memory we should make sure the req1 and req2 and the sessions get put. And also in case the max_sessions decreased so when kreallocate the new memory some sessions maybe missed being put.
And if the max_sessions is 0 krealloc will return ZERO_SIZE_PTR, which will lead to a distinct access fault.
URL: https://tracker.ceph.com/issues/53819
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 55 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 18 deletions(-)
fs/ceph/caps.c +37 -18
@@ -2297,6 +2297,7 @@ static int unsafe_request_wait(struct inode *inode)struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req1 =NULL , *req2 =NULL ; +unsigned int max_sessions;int ret, err =0 ;spin_lock (&ci->i_unsafe_lock);
@@ -2314,37 +2315,45 @@ static int unsafe_request_wait(struct inode *inode) }spin_unlock (&ci->i_unsafe_lock); +/* +* The mdsc->max_sessions is unlikely to be changed +* mostly, here we will retry it by reallocating the +* sessions array memory to get rid of the mdsc->mutex +* lock. +*/ +retry: + max_sessions = mdsc->max_sessions; +/* * Trigger to flush the journal logs in all the relevant MDSes * manually, or in the worst case we must wait at most 5 seconds * to wait the journal logs to be flushed by the MDSes periodically. */ -if (req1 || req2) { +if ((req1 || req2) &&likely (max_sessions)) {struct ceph_mds_session **sessions =NULL ;struct ceph_mds_session *s;struct ceph_mds_request *req; -unsigned int max;int i; -/* -* The mdsc->max_sessions is unlikely to be changed -* mostly, here we will retry it by reallocating the -* sessions arrary memory to get rid of the mdsc->mutex -* lock. -*/ -retry: - max = mdsc->max_sessions; - sessions =krealloc (sessions, max *sizeof (s), __GFP_ZERO); -if (!sessions) -return -ENOMEM ; + sessions =kzalloc (max_sessions *sizeof (s),GFP_KERNEL ); +if (!sessions) { + err = -ENOMEM ; + goto out; + }spin_lock (&ci->i_unsafe_lock);if (req1) {list_for_each_entry (req, &ci->i_unsafe_dirops, r_unsafe_dir_item) { s = req->r_session; -if (unlikely (s->s_mds >= max)) { +if (unlikely (s->s_mds >= max_sessions)) {spin_unlock (&ci->i_unsafe_lock); +for (i =0 ; i < max_sessions; i++) { + s = sessions[i]; +if (s) +ceph_put_mds_session (s); + } +kfree (sessions); goto retry; }if (!sessions[s->s_mds]) {
@@ -2357,8 +2366,14 @@ static int unsafe_request_wait(struct inode *inode)list_for_each_entry (req, &ci->i_unsafe_iops, r_unsafe_target_item) { s = req->r_session; -if (unlikely (s->s_mds >= max)) { +if (unlikely (s->s_mds >= max_sessions)) {spin_unlock (&ci->i_unsafe_lock); +for (i =0 ; i < max_sessions; i++) { + s = sessions[i]; +if (s) +ceph_put_mds_session (s); + } +kfree (sessions); goto retry; }if (!sessions[s->s_mds]) {
@@ -2379,7 +2394,7 @@ static int unsafe_request_wait(struct inode *inode)spin_unlock (&ci->i_ceph_lock);/* send flush mdlog request to MDSes */ -for (i =0 ; i < max; i++) { +for (i =0 ; i < max_sessions; i++) { s = sessions[i];if (s) {send_flush_mdlog (s);
@@ -2396,15 +2411,19 @@ static int unsafe_request_wait(struct inode *inode) ceph_timeout_jiffies(req1->r_timeout));if (ret) err = -EIO ; -ceph_mdsc_put_request (req1); }if (req2) { ret = !wait_for_completion_timeout (&req2->r_safe_completion,ceph_timeout_jiffies (req2->r_timeout));if (ret) err = -EIO ; -ceph_mdsc_put_request (req2); } + +out: +if (req1) +ceph_mdsc_put_request (req1); +if (req2) +ceph_mdsc_put_request (req2);return err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 113/162 ceph: fix possible NULL pointer dereference for req->r_session
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 7acae6183cf37c48b8da48bbbdb78820fb3913f3 ]
The request will be inserted into the ci->i_unsafe_dirops before assigning the req->r_session, so it's possible that we will hit NULL pointer dereference bug here.
Cc: [email protected]
URL: https://tracker.ceph.com/issues/55327
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/ceph/caps.c +4 -0
@@ -2346,6 +2346,8 @@ static int unsafe_request_wait(struct inode *inode)list_for_each_entry (req, &ci->i_unsafe_dirops, r_unsafe_dir_item) { s = req->r_session; +if (!s) +continue ;if (unlikely (s->s_mds >= max_sessions)) {spin_unlock (&ci->i_unsafe_lock);for (i =0 ; i < max_sessions; i++) {
@@ -2366,6 +2368,8 @@ static int unsafe_request_wait(struct inode *inode)list_for_each_entry (req, &ci->i_unsafe_iops, r_unsafe_target_item) { s = req->r_session; +if (!s) +continue ;if (unlikely (s->s_mds >= max_sessions)) {spin_unlock (&ci->i_unsafe_lock);for (i =0 ; i < max_sessions; i++) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 114/162 ceph: Use kcalloc for allocating multiple elements
In reply to Greg Kroah-HartmanFrom: Kenneth Lee <[email protected]>
[ Upstream commit aa1d627207cace003163dee24d1c06fa4e910c6b ]
Prefer using kcalloc(a, b) over kzalloc(a * b) as this improves semantics since kcalloc is intended for allocating an array of memory.
Stable-dep-of: 5bd76b8de5b7 ("ceph: fix NULL pointer dereference for req->r_session")
--- fs/ceph/caps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ceph/caps.c +1 -1
@@ -2335,7 +2335,7 @@ static int unsafe_request_wait(struct inode *inode)struct ceph_mds_request *req;int i; - sessions =kzalloc (max_sessions *sizeof (s),GFP_KERNEL ); + sessions =kcalloc (max_sessions,sizeof (s),GFP_KERNEL );if (!sessions) { err = -ENOMEM ; goto out;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 115/162 ceph: fix NULL pointer dereference for req->r_session
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 5bd76b8de5b74fa941a6eafee87728a0fe072267 ]
The request's r_session maybe changed when it was forwarded or resent. Both the forwarding and resending cases the requests will be protected by the mdsc->mutex.
--- fs/ceph/caps.c | 48 ++++++++++++------------------------------------ 1 file changed, 12 insertions(+), 36 deletions(-)
fs/ceph/caps.c +12 -36
@@ -2297,7 +2297,6 @@ static int unsafe_request_wait(struct inode *inode)struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req1 =NULL , *req2 =NULL ; -unsigned int max_sessions;int ret, err =0 ;spin_lock (&ci->i_unsafe_lock);
@@ -2315,28 +2314,24 @@ static int unsafe_request_wait(struct inode *inode) }spin_unlock (&ci->i_unsafe_lock); -/* -* The mdsc->max_sessions is unlikely to be changed -* mostly, here we will retry it by reallocating the -* sessions array memory to get rid of the mdsc->mutex -* lock. -*/ -retry: - max_sessions = mdsc->max_sessions; -/* * Trigger to flush the journal logs in all the relevant MDSes * manually, or in the worst case we must wait at most 5 seconds * to wait the journal logs to be flushed by the MDSes periodically. */ -if ((req1 || req2) &&likely (max_sessions)) { -struct ceph_mds_session **sessions =NULL ; -struct ceph_mds_session *s; +if (req1 || req2) {struct ceph_mds_request *req; +struct ceph_mds_session **sessions; +struct ceph_mds_session *s; +unsigned int max_sessions;int i; +mutex_lock (&mdsc->mutex); + max_sessions = mdsc->max_sessions; + sessions =kcalloc (max_sessions,sizeof (s),GFP_KERNEL );if (!sessions) { +mutex_unlock (&mdsc->mutex); err = -ENOMEM ; goto out; }
@@ -2348,16 +2343,6 @@ static int unsafe_request_wait(struct inode *inode) s = req->r_session;if (!s)continue ; -if (unlikely (s->s_mds >= max_sessions)) { -spin_unlock (&ci->i_unsafe_lock); -for (i =0 ; i < max_sessions; i++) { - s = sessions[i]; -if (s) -ceph_put_mds_session (s); - } -kfree (sessions); - goto retry; - }if (!sessions[s->s_mds]) { s =ceph_get_mds_session (s); sessions[s->s_mds] = s;
@@ -2370,16 +2355,6 @@ static int unsafe_request_wait(struct inode *inode) s = req->r_session;if (!s)continue ; -if (unlikely (s->s_mds >= max_sessions)) { -spin_unlock (&ci->i_unsafe_lock); -for (i =0 ; i < max_sessions; i++) { - s = sessions[i]; -if (s) -ceph_put_mds_session (s); - } -kfree (sessions); - goto retry; - }if (!sessions[s->s_mds]) { s =ceph_get_mds_session (s); sessions[s->s_mds] = s;
@@ -2391,11 +2366,12 @@ static int unsafe_request_wait(struct inode *inode)/* the auth MDS */ spin_lock (&ci->i_ceph_lock);if (ci->i_auth_cap) { - s = ci->i_auth_cap->session; -if (!sessions[s->s_mds]) - sessions[s->s_mds] =ceph_get_mds_session (s); + s = ci->i_auth_cap->session; +if (!sessions[s->s_mds]) + sessions[s->s_mds] =ceph_get_mds_session (s); }spin_unlock (&ci->i_ceph_lock); +mutex_unlock (&mdsc->mutex);/* send flush mdlog request to MDSes */ for (i =0 ; i < max_sessions; i++) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 116/162 usb: dwc3: gadget: conditionally remove requests
In reply to Greg Kroah-HartmanFrom: Michael Grzeschik <[email protected]>
[ Upstream commit b44c0e7fef51ee7e8ca8c6efbf706f5613787100 ]
The functions stop_active_transfers and ep_disable are both calling remove_requests. This functions in both cases will giveback the requests with status ESHUTDOWN, which also represents an physical disconnection. For ep_disable this is not true. This patch adds the status parameter to remove_requests and sets the status to ECONNRESET on ep_disable.
Stable-dep-of: f90f5afd5083 ("usb: dwc3: gadget: Clear ep descriptor last")
--- drivers/usb/dwc3/gadget.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/usb/dwc3/gadget.c +6 -6
@@ -752,7 +752,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)return 0 ; } -static void dwc3_remove_requests (struct dwc3 *dwc,struct dwc3_ep *dep) +static void dwc3_remove_requests (struct dwc3 *dwc,struct dwc3_ep *dep,int status) {struct dwc3_request *req;
@@ -762,19 +762,19 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)while (!list_empty (&dep->started_list)) { req =next_request (&dep->started_list); -dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); +dwc3_gadget_giveback (dep, req, status); }while (!list_empty (&dep->pending_list)) { req =next_request (&dep->pending_list); -dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); +dwc3_gadget_giveback (dep, req, status); }while (!list_empty (&dep->cancelled_list)) { req =next_request (&dep->cancelled_list); -dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); +dwc3_gadget_giveback (dep, req, status); } }
@@ -809,7 +809,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc =NULL ; } -dwc3_remove_requests (dwc, dep); +dwc3_remove_requests (dwc, dep, -ECONNRESET ); dep->stream_capable = false; dep->type =0 ;
@@ -2067,7 +2067,7 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)if (!dep)continue ; -dwc3_remove_requests (dwc, dep); +dwc3_remove_requests (dwc, dep, -ESHUTDOWN ); } }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 117/162 usb: dwc3: gadget: Return -ESHUTDOWN on ep disable
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
[ Upstream commit ffb9da4a04c69567bad717707b6fdfbc4c216ef4 ]
The usb_request API clearly noted that removed requests due to disabled endpoint should have -ESHUTDOWN status returned. Don't change this behavior.
Stable-dep-of: f90f5afd5083 ("usb: dwc3: gadget: Clear ep descriptor last")
--- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/gadget.c +1 -1
@@ -809,7 +809,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc =NULL ; } -dwc3_remove_requests (dwc, dep, -ECONNRESET ); +dwc3_remove_requests (dwc, dep, -ESHUTDOWN ); dep->stream_capable = false; dep->type =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 118/162 usb: dwc3: gadget: Clear ep descriptor last
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
[ Upstream commit f90f5afd5083a7cb4aee13bd4cc0ae600bd381ca ]
Until the endpoint is disabled, its descriptors should remain valid. When its requests are removed from ep disable, the request completion routine may attempt to access the endpoint's descriptor. Don't clear the descriptors before that.
--- drivers/usb/dwc3/gadget.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/usb/dwc3/gadget.c +6 -6
@@ -803,18 +803,18 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) reg &= ~DWC3_DALEPENA_EP (dep->number);dwc3_writel (dwc->regs,DWC3_DALEPENA , reg); -/* Clear out the ep descriptors for non-ep0 */ -if (dep->number >1 ) { - dep->endpoint.comp_desc =NULL ; - dep->endpoint.desc =NULL ; - } -dwc3_remove_requests (dwc, dep, -ESHUTDOWN ); dep->stream_capable = false; dep->type =0 ; dep->flags =0 ; +/* Clear out the ep descriptors for non-ep0 */ +if (dep->number >1 ) { + dep->endpoint.comp_desc =NULL ; + dep->endpoint.desc =NULL ; + } +return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 119/162 nilfs2: fix nilfs_sufile_mark_dirty() not set segment usage as dirty
In reply to Greg Kroah-HartmanFrom: Chen Zhongjin <[email protected]>
commit 512c5ca01a3610ab14ff6309db363de51f1c13a6 upstream.
When extending segments, nilfs_sufile_alloc() is called to get an unassigned segment, then mark it as dirty to avoid accidentally allocating the same segment in the future.
But for some special cases such as a corrupted image it can be unreliable. If such corruption of the dirty state of the segment occurs, nilfs2 may reallocate a segment that is in use and pick the same segment for writing twice at the same time.
This will cause the problem reported by syzkaller:
https://syzkaller.appspot.com/bug?id=c7c4748e11ffcc367cef04f76e02e931833cbd24
This case started with segbuf1.segnum = 3, nextnum = 4 when constructed. It supposed segment 4 has already been allocated and marked as dirty.
However the dirty state was corrupted and segment 4 usage was not dirty. For the first time nilfs_segctor_extend_segments() segment 4 was allocated again, which made segbuf2 and next segbuf3 had same segment 4.
sb_getblk() will get same bh for segbuf2 and segbuf3, and this bh is added to both buffer lists of two segbuf. It makes the lists broken which causes NULL pointer dereference.
Fix the problem by setting usage as dirty every time in nilfs_sufile_mark_dirty(), which is called during constructing current segment to be written out and before allocating next segment.
--- fs/nilfs2/sufile.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/nilfs2/sufile.c +8 -0
@@ -495,14 +495,22 @@ void nilfs_sufile_do_free(struct inode *int nilfs_sufile_mark_dirty (struct inode *sufile,__u64 segnum) {struct buffer_head *bh; +void *kaddr; +struct nilfs_segment_usage *su;int ret; +down_write (&NILFS_MDT (sufile)->mi_sem); ret =nilfs_sufile_get_segment_usage_block (sufile, segnum,0 , &bh);if (!ret) {mark_buffer_dirty (bh);nilfs_mdt_mark_dirty (sufile); + kaddr =kmap_atomic (bh->b_page); + su =nilfs_sufile_block_get_segment_usage (sufile, segnum, bh, kaddr); +nilfs_segment_usage_set_dirty (su); +kunmap_atomic (kaddr);brelse (bh); } +up_write (&NILFS_MDT (sufile)->mi_sem);return ret; }
Greg Kroah-Hartman
maintainerPATCH 120/162 gcov: clang: fix the buffer overflow issue
In reply to Greg Kroah-HartmanFrom: Mukesh Ojha <[email protected]>
commit a6f810efabfd789d3bbafeacb4502958ec56c5ce upstream.
Currently, in clang version of gcov code when module is getting removed gcov_info_add() incorrectly adds the sfn_ptr->counter to all the dst->functions and it result in the kernel panic in below crash report. Fix this by properly handling it.
[ 8.899094][ T599] Unable to handle kernel write to read-only memory at virtual address ffffff80461cc000 [ 8.899100][ T599] Mem abort info: [ 8.899102][ T599] ESR = 0x9600004f [ 8.899103][ T599] EC = 0x25: DABT (current EL), IL = 32 bits [ 8.899105][ T599] SET = 0, FnV = 0 [ 8.899107][ T599] EA = 0, S1PTW = 0 [ 8.899108][ T599] FSC = 0x0f: level 3 permission fault [ 8.899110][ T599] Data abort info: [ 8.899111][ T599] ISV = 0, ISS = 0x0000004f [ 8.899113][ T599] CM = 0, WnR = 1 [ 8.899114][ T599] swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000ab8de000 [ 8.899116][ T599] [ffffff80461cc000] pgd=18000009ffcde003, p4d=18000009ffcde003, pud=18000009ffcde003, pmd=18000009ffcad003, pte=00600000c61cc787 [ 8.899124][ T599] Internal error: Oops: 9600004f [#1] PREEMPT SMP [ 8.899265][ T599] Skip md ftrace buffer dump for: 0x1609e0 .... .., [ 8.899544][ T599] CPU: 7 PID: 599 Comm: modprobe Tainted: G S OE 5.15.41-android13-8-g38e9b1af6bce #1 [ 8.899547][ T599] Hardware name: XXX (DT) [ 8.899549][ T599] pstate: 82400005 (Nzcv daif +PAN -UAO +TCO -DIT -SSBS BTYPE=--) [ 8.899551][ T599] pc : gcov_info_add+0x9c/0xb8 [ 8.899557][ T599] lr : gcov_event+0x28c/0x6b8 [ 8.899559][ T599] sp : ffffffc00e733b00 [ 8.899560][ T599] x29: ffffffc00e733b00 x28: ffffffc00e733d30 x27: ffffffe8dc297470 [ 8.899563][ T599] x26: ffffffe8dc297000 x25: ffffffe8dc297000 x24: ffffffe8dc297000 [ 8.899566][ T599] x23: ffffffe8dc0a6200 x22: ffffff880f68bf20 x21: 0000000000000000 [ 8.899569][ T599] x20: ffffff880f68bf00 x19: ffffff8801babc00 x18: ffffffc00d7f9058 [ 8.899572][ T599] x17: 0000000000088793 x16: ffffff80461cbe00 x15: 9100052952800785 [ 8.899575][ T599] x14: 0000000000000200 x13: 0000000000000041 x12: 9100052952800785 [ 8.899577][ T599] x11: ffffffe8dc297000 x10: ffffffe8dc297000 x9 : ffffff80461cbc80 [ 8.899580][ T599] x8 : ffffff8801babe80 x7 : ffffffe8dc2ec000 x6 : ffffffe8dc2ed000 [ 8.899583][ T599] x5 : 000000008020001f x4 : fffffffe2006eae0 x3 : 000000008020001f [ 8.899586][ T599] x2 : ffffff8027c49200 x1 : ffffff8801babc20 x0 : ffffff80461cb3a0 [ 8.899589][ T599] Call trace: [ 8.899590][ T599] gcov_info_add+0x9c/0xb8 [ 8.899592][ T599] gcov_module_notifier+0xbc/0x120 [ 8.899595][ T599] blocking_notifier_call_chain+0xa0/0x11c [ 8.899598][ T599] do_init_module+0x2a8/0x33c [ 8.899600][ T599] load_module+0x23cc/0x261c [ 8.899602][ T599] __arm64_sys_finit_module+0x158/0x194 [ 8.899604][ T599] invoke_syscall+0x94/0x2bc [ 8.899607][ T599] el0_svc_common+0x1d8/0x34c [ 8.899609][ T599] do_el0_svc+0x40/0x54 [ 8.899611][ T599] el0_svc+0x94/0x2f0 [ 8.899613][ T599] el0t_64_sync_handler+0x88/0xec [ 8.899615][ T599] el0t_64_sync+0x1b4/0x1b8 [ 8.899618][ T599] Code: f905f56c f86e69ec f86e6a0f 8b0c01ec (f82e6a0c) [ 8.899620][ T599] ---[ end trace ed5218e9e5b6e2e6 ]---
--- kernel/gcov/clang.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/gcov/clang.c +2 -0
@@ -327,6 +327,8 @@ void gcov_info_add(struct gcov_info *dstfor (i =0 ; i < sfn_ptr->num_counters; i++) dfn_ptr->counters[i] += sfn_ptr->counters[i]; + + sfn_ptr =list_next_entry (sfn_ptr, head); } }
Greg Kroah-Hartman
maintainerPATCH 121/162 mm: vmscan: fix extreme overreclaim and swap floods
In reply to Greg Kroah-HartmanFrom: Johannes Weiner <[email protected]>
commit f53af4285d775cd9a9a146fc438bd0a1bee1838a upstream.
During proactive reclaim, we sometimes observe severe overreclaim, with several thousand times more pages reclaimed than requested.
This trace was obtained from shrink_lruvec() during such an instance:
prio:0 anon_cost:1141521 file_cost:7767
nr_reclaimed:4387406 nr_to_reclaim:1047 (or_factor:4190)
nr=[7161123 345 578 1111]While he reclaimer requested 4M, vmscan reclaimed close to 16G, most of it by swapping. These requests take over a minute, during which the write() to memory.reclaim is unkillably stuck inside the kernel.
Digging into the source, this is caused by the proportional reclaim bailout logic. This code tries to resolve a fundamental conflict: to reclaim roughly what was requested, while also aging all LRUs fairly and in accordance to their size, swappiness, refault rates etc. The way it attempts fairness is that once the reclaim goal has been reached, it stops scanning the LRUs with the smaller remaining scan targets, and adjusts the remainder of the bigger LRUs according to how much of the smaller LRUs was scanned. It then finishes scanning that remainder regardless of the reclaim goal.
This works fine if priority levels are low and the LRU lists are comparable in size. However, in this instance, the cgroup that is targeted by proactive reclaim has almost no files left - they've already been squeezed out by proactive reclaim earlier - and the remaining anon pages are hot. Anon rotations cause the priority level to drop to 0, which results in reclaim targeting all of anon (a lot) and all of file (almost nothing). By the time reclaim decides to bail, it has scanned most or all of the file target, and therefor must also scan most or all of the enormous anon target. This target is thousands of times larger than the reclaim goal, thus causing the overreclaim.
The bailout code hasn't changed in years, why is this failing now? The most likely explanations are two other recent changes in anon reclaim:
1. Before the series starting with commit 5df741963d52 ("mm: fix LRU balancing effect of new transparent huge pages"), the VM was overall relatively reluctant to swap at all, even if swap was configured. This means the LRU balancing code didn't come into play as often as it does now, and mostly in high pressure situations where pronounced swap activity wouldn't be as surprising.
2. For historic reasons, shrink_lruvec() loops on the scan targets of all LRU lists except the active anon one, meaning it would bail if the only remaining pages to scan were active anon - even if there were a lot of them.
Before the series starting with commit ccc5dc67340c ("mm/vmscan:
make active/inactive ratio as 1:1 for anon lru"), most anon pages would live on the active LRU; the inactive one would contain only a handful of preselected reclaim candidates. After the series, anon gets aged similarly to file, and the inactive list is the default for new anon pages as well, making it often the much bigger list.
As a result, the VM is now more likely to actually finish large anon targets than before.
Change the code such that only one SWAP_CLUSTER_MAX-sized nudge toward the larger LRU lists is made before bailing out on a met reclaim goal.
This fixes the extreme overreclaim problem.
Fairness is more subtle and harder to evaluate. No obvious misbehavior was observed on the test workload, in any case. Conceptually, fairness should primarily be a cumulative effect from regular, lower priority scans. Once the VM is in trouble and needs to escalate scan targets to make forward progress, fairness needs to take a backseat. This is also acknowledged by the myriad exceptions in get_scan_count(). This patch makes fairness decrease gradually, as it keeps fairness work static over increasing priority levels with growing scan targets. This should make more sense - although we may have to re-visit the exact values.
--- mm/vmscan.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
mm/vmscan.c +4 -6
@@ -2439,8 +2439,8 @@ static void shrink_lruvec(struct lruvecenum lru_list lru;unsigned long nr_reclaimed =0 ;unsigned long nr_to_reclaim = sc->nr_to_reclaim; +bool proportional_reclaim;struct blk_plug plug; -bool scan_adjusted;get_scan_count (lruvec, sc, nr);
@@ -2458,8 +2458,8 @@ static void shrink_lruvec(struct lruvec* abort proportional reclaim if either the file or anon lru has already * dropped to zero at the first pass. */ - scan_adjusted = (!cgroup_reclaim (sc) && !current_is_kswapd () && - sc->priority ==DEF_PRIORITY ); + proportional_reclaim = (!cgroup_reclaim (sc) && !current_is_kswapd () && + sc->priority ==DEF_PRIORITY );blk_start_plug (&plug); while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
@@ -2479,7 +2479,7 @@ static void shrink_lruvec(struct lruveccond_resched (); -if (nr_reclaimed < nr_to_reclaim || scan_adjusted) +if (nr_reclaimed < nr_to_reclaim || proportional_reclaim)continue ;/*
@@ -2530,8 +2530,6 @@ static void shrink_lruvec(struct lruvec nr_scanned = targets[lru] - nr[lru]; nr[lru] = targets[lru] * (100 - percentage) /100 ; nr[lru] -=min (nr[lru], nr_scanned); - - scan_adjusted = true; }blk_finish_plug (&plug); sc->nr_reclaimed += nr_reclaimed;
Greg Kroah-Hartman
maintainerPATCH 122/162 KVM: x86: nSVM: leave nested mode on vCPU free
In reply to Greg Kroah-HartmanFrom: Maxim Levitsky <[email protected]>
commit 917401f26a6af5756d89b550a8e1bd50cf42b07e upstream.
If the VM was terminated while nested, we free the nested state while the vCPU still is in nested mode.
Soon a warning will be added for this condition.
Message-Id: <[email protected]>
--- arch/x86/kvm/svm/svm.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/svm/svm.c +1 -0
@@ -1357,6 +1357,7 @@ static void svm_free_vcpu(struct kvm_vcp*/ svm_clear_current_vmcb (svm->vmcb); +svm_leave_nested (vcpu);svm_free_nested (svm);__free_page (pfn_to_page (__sme_clr (svm->vmcb_pa) >>PAGE_SHIFT ));
Greg Kroah-Hartman
maintainerPATCH 123/162 KVM: x86: remove exit_int_info warning in svm_handle_exit
In reply to Greg Kroah-HartmanFrom: Maxim Levitsky <[email protected]>
commit 05311ce954aebe75935d9ae7d38ac82b5b796e33 upstream.
It is valid to receive external interrupt and have broken IDT entry, which will lead to #GP with exit_int_into that will contain the index of the IDT entry (e.g any value).
Other exceptions can happen as well, like #NP or #SS (if stack switch fails).
Thus this warning can be user triggred and has very little value.
Message-Id: <[email protected]>
--- arch/x86/kvm/svm/svm.c | 15 --------------- 1 file changed, 15 deletions(-)
arch/x86/kvm/svm/svm.c +0 -15
@@ -305,12 +305,6 @@ int svm_set_efer(struct kvm_vcpu *vcpu,return 0 ; } -static int is_external_interrupt (u32 info) -{ - info &=SVM_EVTINJ_TYPE_MASK |SVM_EVTINJ_VALID ; -return info == (SVM_EVTINJ_VALID |SVM_EVTINJ_TYPE_INTR ); -} -static u32 svm_get_interrupt_shadow (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -3116,15 +3110,6 @@ static int handle_exit(struct kvm_vcpu *return 0 ; } -if (is_external_interrupt (svm->vmcb->control.exit_int_info) && - exit_code !=SVM_EXIT_EXCP_BASE +PF_VECTOR && - exit_code !=SVM_EXIT_NPF && exit_code !=SVM_EXIT_TASK_SWITCH && - exit_code !=SVM_EXIT_INTR && exit_code !=SVM_EXIT_NMI ) -printk (KERN_ERR "%s: unexpected exit_int_info 0x%x " -"exit_code 0x%x\n" , - __func__, svm->vmcb->control.exit_int_info, - exit_code); -if (exit_fastpath !=EXIT_FASTPATH_NONE )return 1 ;
Greg Kroah-Hartman
maintainerPATCH 124/162 x86/ioremap: Fix page aligned size calculation in __ioremap_caller()
In reply to Greg Kroah-HartmanFrom: Michael Kelley <[email protected]>
commit 4dbd6a3e90e03130973688fd79e19425f720d999 upstream.
Current code re-calculates the size after aligning the starting and ending physical addresses on a page boundary. But the re-calculation also embeds the masking of high order bits that exceed the size of the physical address space (via PHYSICAL_PAGE_MASK). If the masking removes any high order bits, the size calculation results in a huge value that is likely to immediately fail.
Fix this by re-calculating the page-aligned size first. Then mask any high order bits using PHYSICAL_PAGE_MASK.
--- arch/x86/mm/ioremap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/x86/mm/ioremap.c +7 -1
@@ -216,9 +216,15 @@ __ioremap_caller(resource_size_t phys_ad* Mappings have to be page-aligned */ offset = phys_addr & ~PAGE_MASK ; - phys_addr &=PHYSICAL_PAGE_MASK ; + phys_addr &=PAGE_MASK ; size =PAGE_ALIGN (last_addr+1 ) - phys_addr; +/* +* Mask out any bits not part of the actual physical +* address, like memory encryption bits. +*/ + phys_addr &=PHYSICAL_PAGE_MASK ; + retval =memtype_reserve (phys_addr, (u64 )phys_addr + size, pcm, &new_pcm);if (retval) {
Greg Kroah-Hartman
maintainerPATCH 125/162 binder: avoid potential data leakage when copying txn
In reply to Greg Kroah-HartmanFrom: Todd Kjos <[email protected]>
commit 6d98eb95b450a75adb4516a1d33652dc78d2b20c upstream.
Transactions are copied from the sender to the target first and objects like BINDER_TYPE_PTR and BINDER_TYPE_FDA are then fixed up. This means there is a short period where the sender's version of these objects are visible to the target prior to the fixups.
Instead of copying all of the data first, copy data only after any needed fixups have been applied.
--- drivers/android/binder.c | 94 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 24 deletions(-)
drivers/android/binder.c +70 -24
@@ -2008,15 +2008,21 @@ static void binder_cleanup_transaction(s/** * binder_get_object() - gets object and checks for valid metadata * @proc: binder_proc owning the buffer +* @u: sender's user pointer to base of buffer * @buffer: binder_buffer that we're parsing. * @offset: offset in the @buffer at which to validate an object. * @object: struct binder_object to read into * -* Return: If there's a valid metadata object at @offset in @buffer, the +* Copy the binder object at the given offset into @object. If @u is +* provided then the copy is from the sender's buffer. If not, then +* it is copied from the target's @buffer. +* +* Return: If there's a valid metadata object at @offset, the * size of that object. Otherwise, it returns zero. The object * is read into the struct binder_object pointed to by @object. */ static size_t binder_get_object (struct binder_proc *proc, +const void __user *u,struct binder_buffer *buffer,unsigned long offset,struct binder_object *object)
@@ -2026,10 +2032,16 @@ static size_t binder_get_object(struct bsize_t object_size =0 ; read_size =min_t (size_t,sizeof (*object), buffer->data_size - offset); -if (offset > buffer->data_size || read_size <sizeof (*hdr) || -binder_alloc_copy_from_buffer (&proc->alloc, object, buffer, - offset, read_size)) +if (offset > buffer->data_size || read_size <sizeof (*hdr))return 0 ; +if (u) { +if (copy_from_user (object, u + offset, read_size)) +return 0 ; + }else { +if (binder_alloc_copy_from_buffer (&proc->alloc, object, buffer, + offset, read_size)) +return 0 ; + }/* Ok, now see if we read a complete object. */ hdr = &object->hdr;
@@ -2102,7 +2114,7 @@ static struct binder_buffer_object *bind b, buffer_offset, sizeof(object_offset)))return NULL ; - object_size =binder_get_object (proc, b, object_offset, object); + object_size =binder_get_object (proc,NULL , b, object_offset, object);if (!object_size || object->hdr.type !=BINDER_TYPE_PTR )return NULL ;if (object_offsetp)
@@ -2167,7 +2179,8 @@ static bool binder_validate_fixup(structunsigned long buffer_offset;struct binder_object last_object;struct binder_buffer_object *last_bbo; -size_t object_size =binder_get_object (proc, b, last_obj_offset, +size_t object_size =binder_get_object (proc,NULL , b, + last_obj_offset, &last_object);if (object_size !=sizeof (*last_bbo))return false;
@@ -2282,7 +2295,7 @@ static void binder_transaction_buffer_reif (!binder_alloc_copy_from_buffer (&proc->alloc, &object_offset, buffer, buffer_offset,sizeof (object_offset))) - object_size =binder_get_object (proc, buffer, + object_size =binder_get_object (proc,NULL , buffer, object_offset, &object);if (object_size ==0 ) { pr_err("transaction release %d bad object at offset %lld, size %zd\n",
@@ -2848,6 +2861,7 @@ static void binder_transaction(struct bibinder_size_t off_start_offset, off_end_offset;binder_size_t off_min;binder_size_t sg_buf_offset, sg_buf_end_offset; +binder_size_t user_offset =0 ;struct binder_proc *target_proc =NULL ;struct binder_thread *target_thread =NULL ;struct binder_node *target_node =NULL ;
@@ -2862,6 +2876,8 @@ static void binder_transaction(struct biint t_debug_id =atomic_inc_return (&binder_last_id);char *secctx =NULL ;u32 secctx_sz =0 ; +const void __user *user_buffer = (const void __user *) + (uintptr_t )tr->data.ptr.buffer; e =binder_transaction_log_add (&binder_transaction_log); e->debug_id = t_debug_id;
@@ -3175,19 +3191,6 @@ static void binder_transaction(struct bi if (binder_alloc_copy_user_to_buffer( &target_proc->alloc, - t->buffer,0 , - (const void __user *) - (uintptr_t )tr->data.ptr.buffer, - tr->data_size)) { -binder_user_error ("%d:%d got transaction with invalid data ptr\n" , - proc->pid, thread->pid); - return_error =BR_FAILED_REPLY ; - return_error_param = -EFAULT ; - return_error_line = __LINE__; - goto err_copy_data_failed; - } - if (binder_alloc_copy_user_to_buffer( - &target_proc->alloc, t->buffer, ALIGN(tr->data_size, sizeof(void *)), (const void __user *)
@@ -3230,6 +3233,7 @@ static void binder_transaction(struct bisize_t object_size;struct binder_object object;binder_size_t object_offset; +binder_size_t copy_size; if (binder_alloc_copy_from_buffer(&target_proc->alloc, &object_offset,
@@ -3241,8 +3245,27 @@ static void binder_transaction(struct bi return_error_line = __LINE__; goto err_bad_offset; } - object_size =binder_get_object (target_proc, t->buffer, - object_offset, &object); + +/* +* Copy the source user buffer up to the next object +* that will be processed. +*/ + copy_size = object_offset - user_offset; +if (copy_size && (user_offset > object_offset || +binder_alloc_copy_user_to_buffer ( + &target_proc->alloc, + t->buffer, user_offset, + user_buffer + user_offset, + copy_size))) { +binder_user_error ("%d:%d got transaction with invalid data ptr\n" , + proc->pid, thread->pid); + return_error =BR_FAILED_REPLY ; + return_error_param = -EFAULT ; + return_error_line = __LINE__; + goto err_copy_data_failed; + } + object_size =binder_get_object (target_proc, user_buffer, + t->buffer, object_offset, &object);if (object_size ==0 || object_offset < off_min) { binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n", proc->pid, thread->pid,
@@ -3254,6 +3277,11 @@ static void binder_transaction(struct bi return_error_line = __LINE__; goto err_bad_offset; } +/* +* Set offset to the next buffer fragment to be +* copied +*/ + user_offset = object_offset + object_size; hdr = &object.hdr; off_min = object_offset + object_size;
@@ -3349,9 +3377,14 @@ static void binder_transaction(struct bi } ret =binder_translate_fd_array (fda, parent, t, thread, in_reply_to); -if (ret <0 ) { +if (!ret) + ret =binder_alloc_copy_to_buffer (&target_proc->alloc, + t->buffer, + object_offset, + fda,sizeof (*fda)); +if (ret) { return_error =BR_FAILED_REPLY ; - return_error_param = ret; + return_error_param = ret >0 ? -EINVAL : ret; return_error_line = __LINE__; goto err_translate_failed; }
@@ -3421,6 +3454,19 @@ static void binder_transaction(struct bi goto err_bad_object_type; } } +/* Done processing objects, copy the rest of the buffer */ +if (binder_alloc_copy_user_to_buffer ( + &target_proc->alloc, + t->buffer, user_offset, + user_buffer + user_offset, + tr->data_size - user_offset)) { +binder_user_error ("%d:%d got transaction with invalid data ptr\n" , + proc->pid, thread->pid); + return_error =BR_FAILED_REPLY ; + return_error_param = -EFAULT ; + return_error_line = __LINE__; + goto err_copy_data_failed; + } tcomplete->type =BINDER_WORK_TRANSACTION_COMPLETE ; t->work.type =BINDER_WORK_TRANSACTION ;
Greg Kroah-Hartman
maintainerPATCH 126/162 binder: read pre-translated fds from sender buffer
In reply to Greg Kroah-HartmanFrom: Todd Kjos <[email protected]>
commit 656e01f3ab54afe71bed066996fc2640881e1220 upstream.
This patch is to prepare for an up coming patch where we read pre-translated fds from the sender buffer and translate them before copying them to the target. It does not change run time.
The patch adds two new parameters to binder_translate_fd_array() to hold the sender buffer and sender buffer parent. These parameters let us call copy_from_user() directly from the sender instead of using binder_alloc_copy_from_buffer() to copy from the target. Also the patch adds some new alignment checks. Previously the alignment checks would have been done in a different place, but this lets us print more useful error messages.
--- drivers/android/binder.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-)
drivers/android/binder.c +32 -7
@@ -2634,15 +2634,17 @@ err_fd_not_accepted: }static int binder_translate_fd_array (struct binder_fd_array_object *fda, +const void __user *sender_ubuffer,struct binder_buffer_object *parent, +struct binder_buffer_object *sender_uparent,struct binder_transaction *t,struct binder_thread *thread,struct binder_transaction *in_reply_to) {binder_size_t fdi, fd_buf_size;binder_size_t fda_offset; +const void __user *sender_ufda_base;struct binder_proc *proc = thread->proc; -struct binder_proc *target_proc = t->to_proc; fd_buf_size =sizeof (u32) * fda->num_fds;if (fda->num_fds >=SIZE_MAX /sizeof (u32)) {
@@ -2666,7 +2668,10 @@ static int binder_translate_fd_array(str*/ fda_offset = (parent->buffer - (uintptr_t )t->buffer->user_data) + fda->parent_offset; -if (!IS_ALIGNED ((unsigned long )fda_offset,sizeof (u32))) { + sender_ufda_base = (void __user *)sender_uparent->buffer + fda->parent_offset; + +if (!IS_ALIGNED ((unsigned long )fda_offset,sizeof (u32)) || + !IS_ALIGNED ((unsigned long )sender_ufda_base,sizeof (u32))) {binder_user_error ("%d:%d parent offset not aligned correctly.\n" , proc->pid, thread->pid);return -EINVAL ;
@@ -2675,10 +2680,9 @@ static int binder_translate_fd_array(stru32 fd;int ret;binder_size_t offset = fda_offset + fdi *sizeof (fd); +binder_size_t sender_uoffset = fdi *sizeof (fd); - ret =binder_alloc_copy_from_buffer (&target_proc->alloc, - &fd, t->buffer, - offset,sizeof (fd)); + ret =copy_from_user (&fd, sender_ufda_base + sender_uoffset,sizeof (fd));if (!ret) ret =binder_translate_fd (fd, offset, t, thread, in_reply_to);
@@ -3344,6 +3348,8 @@ static void binder_transaction(struct bicase BINDER_TYPE_FDA : {struct binder_object ptr_object;binder_size_t parent_offset; +struct binder_object user_object; +size_t user_parent_size;struct binder_fd_array_object *fda =to_binder_fd_array_object (hdr); size_t num_valid = (buffer_offset - off_start_offset) /
@@ -3375,8 +3381,27 @@ static void binder_transaction(struct bi return_error_line = __LINE__; goto err_bad_parent; } - ret =binder_translate_fd_array (fda, parent, t, thread, - in_reply_to); +/* +* We need to read the user version of the parent +* object to get the original user offset +*/ + user_parent_size = +binder_get_object (proc, user_buffer, t->buffer, + parent_offset, &user_object); +if (user_parent_size !=sizeof (user_object.bbo)) { +binder_user_error ("%d:%d invalid ptr object size: %zd vs %zd\n" , + proc->pid, thread->pid, + user_parent_size, +sizeof (user_object.bbo)); + return_error =BR_FAILED_REPLY ; + return_error_param = -EINVAL ; + return_error_line = __LINE__; + goto err_bad_parent; + } + ret =binder_translate_fd_array (fda, user_buffer, + parent, + &user_object.bbo, t, + thread, in_reply_to);if (!ret) ret = binder_alloc_copy_to_buffer(&target_proc->alloc, t->buffer,