Skip to contentSkip to conversation

6.6.141-rc1 review

PATCH In review Greg Kroah-Hartman 11 participants 522 messages May 20 – May 28 Page 1 of 4

Subsystems (8)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.6.141-rc1 review

This is the start of the stable review cycle for the 6.6.141 release. There are 508 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, 22 May 2026 16:20:16 +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/v6.x/stable-review/patch-6.6.141-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-6.6.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 6.6.141-rc1

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: resched blocked ADD_ADDR quicker

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: fix potential data-race

Johan Hovold <[email protected]>
spi: sifive: fix controller deregistration

Pei Xiao <[email protected]>
spi: sifive: Simplify clock handling with devm_clk_get_enabled()

Guoniu Zhou <[email protected]>
media: nxp: imx8-isi: Reduce minimum queued buffers from 2 to 0

Johan Hovold <[email protected]>
spi: st-ssc4: fix controller deregistration

Yang Yingliang <[email protected]>
spi: st-ssc4: switch to use modern name

Shota Zaizen <[email protected]>
ksmbd: validate inherited ACE SID length

Jason Gunthorpe <[email protected]>
RDMA/mana: Fix error unwind in mana_ib_create_qp_rss()

Chao Yu <[email protected]>
f2fs: fix false alarm of lockdep on cp_global_sem lock

Yongpeng Yang <[email protected]>
f2fs: fix incorrect file address mapping when inline inode is unwritten

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: kernel: correctly retransmit ADD_ADDR ID 0

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: prio: skip closed subflows

Paolo Abeni <[email protected]>
mptcp: fix rx timestamp corruption on fastopen

Paolo Abeni <[email protected]>
mptcp: drop __mptcp_fastopen_gen_msk_ackseq()

Jason Gunthorpe <[email protected]>
RDMA/mana: Validate rx_hash_key_len

Filipe Manana <[email protected]>
btrfs: fix missing last_unlink_trans update when removing a directory

Filipe Manana <[email protected]>
btrfs: use btrfs inodes in btrfs_rmdir() to avoid so much usage of BTRFS_I()

Filipe Manana <[email protected]>
btrfs: use inode already stored in local variable at btrfs_rmdir()

Piyush Sachdeva <[email protected]>
smb: client: Use FullSessionKey for AES-256 encryption key derivation

Ashutosh Desai <[email protected]>
drm/v3d: Reject empty multisync extension to prevent infinite loop

David Carlier <[email protected]>
eventfs: Use list_add_tail_rcu() for SRCU-protected children list

Guangshuo Li <[email protected]>
btrfs: fix double free in create_space_info_sub_group() error path

Filipe Manana <[email protected]>
btrfs: remove fs_info argument from btrfs_sysfs_add_space_info_type()

Ulf Hansson <[email protected]>
pmdomain: core: Fix detach procedure for virtual devices in genpd

Johan Hovold <[email protected]>
drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init

Johan Hovold <[email protected]>
drm/gma500/oaktrail_lvds: fix hang on init failure

Johan Hovold <[email protected]>
drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup

Gyeyoung Baek <[email protected]>
drm/panfrost: Fix wait_bo ioctl leaking positive return from dma_resv_wait_timeout()

Sebastian Brzezinka <[email protected]>
drm/i915: skip __i915_request_skip() for already signaled requests

Naval Alcalá <[email protected]>
iommu/vt-d: Disable DMAR for Intel Q35 IGFX

Raphael Zimmer <[email protected]>
libceph: handle rbtree insertion error in decode_choose_args()

Raphael Zimmer <[email protected]>
libceph: Fix potential out-of-bounds access in crush_decode()

Raphael Zimmer <[email protected]>
libceph: Fix potential null-ptr-deref in decode_choose_args()

Raphael Zimmer <[email protected]>
libceph: Fix potential out-of-bounds access in osdmap_decode()

Paulo Alcantara <[email protected]>
netfs: fix error handling in netfs_extract_user_iter()

Ma Ke <[email protected]>
powerpc/warp: Fix error handling in pika_dtm_thread

Nicholas Carlini <[email protected]>
io-wq: check that the predecessor is hashed in io_wq_remove_pending()

Viacheslav Dubeyko <[email protected]>
ceph: fix a buffer leak in __ceph_setxattr()

Cássio Gabriel <[email protected]>
ALSA: usb-audio: Bound MIDI endpoint descriptor scans

Cássio Gabriel <[email protected]>
ALSA: usb-audio: Bound MIDI 2.0 endpoint descriptor scans

Chaitanya Kumar Borah <[email protected]>
drm/i915/dp: Fix VSC dynamic range signaling for RGB formats

Ye Bin <[email protected]>
smb/client: fix possible infinite loop and oob read in symlink_data()

Ranjani Sridharan <[email protected]>
ASoC: SOF: Intel: hda: Fix NULL pointer dereference

Pierre-Louis Bossart <[email protected]>
ASoC: SOF: Intel: hda-dai: add support for dspless mode beyond HDAudio

Pierre-Louis Bossart <[email protected]>
ASoC: SOF: Intel: hda-dai: remove dspless special case

Pablo Neira Ayuso <[email protected]>

    netfilter: nf_tables: unconditionally bump set->nelems before insertion

Qiang Ma <[email protected]>
KVM: x86: Fix Xen hypercall tracepoint argument assignment

Junrui Luo <[email protected]>
KVM: s390: pci: fix GAIT table indexing due to double-scaling pointer arithmetic

Aaron Sacks <[email protected]>
KVM: Reject wrapped offset in kvm_reset_dirty_gfn()

Sergio Correia <[email protected]>
audit: enforce AUDIT_LOCKED for AUDIT_TRIM and AUDIT_MAKE_EQUIV

Zoran Ilievski <[email protected]>
net: atlantic: preserve PCI wake-from-D3 on shutdown when WOL enabled

Li Xiasong <[email protected]>
netfilter: nft_ct: fix missing expect put in obj eval

Sergio Correia <[email protected]>
audit: fix incorrect inheritable capability in CAPSET records

Li Xiasong <[email protected]>
netfilter: nf_conntrack_sip: get helper before allocating expectation

Breno Leitao <[email protected]>

    workqueue: Fix wq->cpu_pwq leak in alloc_and_link_pwqs() WQ_UNBOUND path

Matt Vollrath <[email protected]>
i40e: Cleanup PTP pins on probe failure

Herbert Xu <[email protected]>

    crypto: af_alg - Cap AEAD AD length to 0x80000000

Hangbin Liu <[email protected]>
bonding: fix NULL pointer dereference in actor_port_prio setting

Breno Leitao <[email protected]>
netconsole: avoid out-of-bounds access on empty string in trim_newline()

Eric Dumazet <[email protected]>
net/sched: sch_pie: annotate more data-races in pie_dump_stats()

Michael Bommarito <[email protected]>
ksmbd: validate response sizes in ipc_validate_msg()

Justin Chen <[email protected]>
net: bcmgenet: fix leaking free_bds

Ryo Takakura <[email protected]>
net: bcmgenet: Initialize u64 stats seq counter

Thorsten Blum <[email protected]>
crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx

Greg Kroah-Hartman <[email protected]>
smb: client: fix OOB reads parsing symlink error response

Liang Jie <[email protected]>
smb: client: correctly handle ErrorContextData as a flexible array

Sasha Levin <[email protected]>
Revert "crypto: nx - Migrate to scomp API"

Sasha Levin <[email protected]>
Revert "crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx"

Sasha Levin <[email protected]>
Revert "crypto: nx - fix context leak in nx842_crypto_free_ctx"

Al Viro <[email protected]>

    ntfs: ->d_compare() must not block

Paolo Abeni <[email protected]>
net/sched: cls_flower: revert unintended changes

Dan Carpenter <[email protected]>
sfc: fix error code in efx_devlink_info_running_versions()

Jakub Kicinski <[email protected]>
net: tls: fix strparser anchor skb leak on offload RX setup failure

Petr Oros <[email protected]>
ice: fix NULL pointer dereference in ice_reset_all_vfs()

Petr Oros <[email protected]>
iavf: add VIRTCHNL_OP_ADD_VLAN to success completion handler

Petr Oros <[email protected]>
iavf: wait for PF confirmation before removing VLAN filters

Petr Oros <[email protected]>
iavf: stop removing VLAN filters from PF on interface down

Petr Oros <[email protected]>
iavf: rename IAVF_VLAN_IS_NEW to IAVF_VLAN_ADDING

Eric Dumazet <[email protected]>

    bonding: 3ad: implement proper RCU rules for port->aggregator

Hangbin Liu <[email protected]>
bonding: print churn state via netlink

Hangbin Liu <[email protected]>
bonding: add support for per-port LACP actor priority

Tonghao Zhang <[email protected]>
net: bonding: add broadcast_neighbor option for 802.3ad

Jones Syue 薛懷宗 <[email protected]>
bonding: 802.3ad replace MAC_ADDRESS_EQUAL with __agg_has_partner

Timur Kristóf <[email protected]>
drm/amd/display: Read EDID from VBIOS embedded panel info

Timur Kristóf <[email protected]>
drm/amd/display: Allow DCE link encoder without AUX registers

Sebastian Andrzej Siewior <[email protected]>
futex: Prevent lockup in requeue-PI during signal/ timeout wakeup

wangdicheng <[email protected]>
ALSA: hda/conexant: Fix missing error check for jack detection

wangdicheng <[email protected]>

    ALSA: hda/conexant: Renaming the codec with device ID 0x1f86 and 0x1f87

Oldherl Oh <[email protected]>
ALSA: hda/conexant: fix some typos

Breno Leitao <[email protected]>
netconsole: propagate device name truncation in dev_name_store()

Matthew Wood <[email protected]>
net: netconsole: move newline trimming to function

Eric Dumazet <[email protected]>
net/sched: sch_cake: annotate data-races in cake_dump_stats() (V)

Weiming Shi <[email protected]>
bareudp: fix NULL pointer dereference in bareudp_fill_metadata_dst()

Beniamino Galvani <[email protected]>
ipv6: rename and move ip6_dst_lookup_tunnel()

Beniamino Galvani <[email protected]>
ipv4: add new arguments to udp_tunnel_dst_lookup()

Beniamino Galvani <[email protected]>
ipv4: remove "proto" argument from udp_tunnel_dst_lookup()

Beniamino Galvani <[email protected]>
ipv4: rename and move ip_route_output_tunnel()

Xin Long <[email protected]>
sctp: discard stale INIT after handshake completion

Xin Long <[email protected]>
netfilter: skip recording stale or retransmitted INIT

Christian A. Ehrhardt <[email protected]>
ASoC: codecs: ab8500: Fix casting of private data

Yinjie Yao <[email protected]>
drm/amdgpu/jpeg: set no_user_fence for JPEG v4.0.3 ring

Yinjie Yao <[email protected]>
drm/amdgpu/jpeg: set no_user_fence for JPEG v4.0 ring

Yinjie Yao <[email protected]>
drm/amdgpu/jpeg: set no_user_fence for JPEG v3.0 ring

Yinjie Yao <[email protected]>
drm/amdgpu/jpeg: set no_user_fence for JPEG v2.5 ring

Yinjie Yao <[email protected]>
drm/amdgpu/jpeg: set no_user_fence for JPEG v2.0 ring

Yinjie Yao <[email protected]>
drm/amdgpu/vcn: set no_user_fence for VCN v4.0.3 enc ring

Yinjie Yao <[email protected]>
drm/amdgpu/vcn: set no_user_fence for VCN v3.0 enc/dec rings

Yinjie Yao <[email protected]>
drm/amdgpu/vcn: set no_user_fence for VCN v2.5 enc/dec rings

Yinjie Yao <[email protected]>
drm/amdgpu/vcn: set no_user_fence for VCN v2.0 enc/dec rings

Heiko Schocher <[email protected]>
net: phy: dp83869: fix setting CLK_O_SEL field.

William A. Kennington III <[email protected]>
net: mctp i2c: check length before marking flow active

Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix potential leak of pd at parsing UAC3 streams

Florian Westphal <[email protected]>
neigh: let neigh_xmit take skb ownership

Eric Dumazet <[email protected]>

    neighbour: add RCU protection to neigh_tables[]

Weiming Shi <[email protected]>
net/sched: taprio: fix NULL pointer dereference in class dump

Paul Geurts <[email protected]>
NFC: trf7970a: Ignore antenna noise when checking for RF field

Morduan Zang <[email protected]>
net: usb: rtl8150: free skb on usb_submit_urb() failure in xmit

Zhan Jun <[email protected]>

    net: usb: rtl8150: fix use-after-free in rtl8150_start_xmit()

Ido Schimmel <[email protected]>
vrf: Fix a potential NPD when removing a port from a VRF

Eric Dumazet <[email protected]>
net/sched: sch_fq_pie: annotate data-races in fq_pie_dump_stats()

Eric Dumazet <[email protected]>
net/sched: sch_choke: annotate data-races in choke_dump_stats()

Stephen Hemminger <[email protected]>
net/sched: netem: check for negative latency and jitter

Stephen Hemminger <[email protected]>
net/sched: netem: fix slot delay calculation overflow

Stephen Hemminger <[email protected]>
net/sched: netem: validate slot configuration

Stephen Hemminger <[email protected]>
net/sched: netem: only reseed PRNG when seed is explicitly provided

Stephen Hemminger <[email protected]>
net/sched: netem: fix queue limit check to include reordered packets

Stephen Hemminger <[email protected]>
net/sched: netem: fix probability gaps in 4-state loss model

Nikola Z. Ivanov <[email protected]>
netdevsim: zero initialize struct iphdr in dummy sk_buff

Daan De Meyer <[email protected]>
cdrom, scsi: sr: propagate read-only status to block layer via set_disk_ro()

Wentao Guan <[email protected]>
arm64/scs: Fix potential sign extension issue of advance_loc4

Yuho Choi <[email protected]>
drm/sysfb: ofdrm: fix PCI device reference leaks

John Madieu <[email protected]>
spi: rockchip: Read ISR, not IMR, to detect cs-inactive IRQ

Florian Westphal <[email protected]>
netfilter: nf_conntrack_sip: don't use simple_strtoul

Jiexun Wang <[email protected]>
netfilter: xt_policy: fix strict mode inbound policy matching

Timur Kristóf <[email protected]>
drm/amdgpu/gfx6: Support harvested SI chips with disabled TCCs (v2)

Timur Kristóf <[email protected]>
drm/amdgpu/uvd3.1: Don't validate the firmware when already validated

Alexandre Demers <[email protected]>
drm/amdgpu: fix spelling typos

Christian König <[email protected]>
drm/amdgpu: fix AMDGPU_INFO_READ_MMR_REG

Keith Busch <[email protected]>
nvme-pci: fix missed admin queue sq doorbell write

Pablo Neira Ayuso <[email protected]>
netfilter: arp_tables: fix IEEE1394 ARP payload parsing

Maurizio Lombardi <[email protected]>
nvmet-tcp: propagate nvmet_tcp_build_pdu_iovec() errors to its callers

Breno Leitao <[email protected]>
tracing: branch: Fix inverted check on stat tracer registration

Mark Harmstone <[email protected]>
btrfs: fix double-decrement of bytes_may_use in submit_one_async_extent()

Wolfram Sang <[email protected]>
mailbox: mailbox-test: make data_ready a per-instance variable

Wolfram Sang <[email protected]>
mailbox: mailbox-test: initialize struct earlier

Wolfram Sang <[email protected]>
mailbox: mailbox-test: don't free the reused channel

Wolfram Sang <[email protected]>
mailbox: add sanity check for channel array

cuitao <[email protected]>
cgroup/rdma: fix integer overflow in rdmacg_try_charge()

Edward Adam Davis <[email protected]>
sched/psi: fix race between file release and pressure write

Wolfram Sang <[email protected]>
mailbox: mailbox-test: free channels on probe error

Yuho Choi <[email protected]>
fbdev: offb: fix PCI device reference leak on probe failure

Anthony Pighin (Nokia) <[email protected]>

    rtc: abx80x: Disable alarm feature if no interrupt attached

Bae Yeonju <[email protected]>
fs/adfs: validate nzones in adfs_validate_bblk()

Kohei Enju <[email protected]>
vhost_net: fix sleeping with preempt-disabled in vhost_net_busy_poll()

Lee Jones <[email protected]>
tipc: fix double-free in tipc_buf_append()

Alexey Kodanev <[email protected]>
nfp: fix swapped arguments in nfp_encode_basic_qdr() calls

Mieczyslaw Nalewaj <[email protected]>
net: dsa: realtek: rtl8365mb: fix mode mask calculation

Eric Dumazet <[email protected]>
net/sched: sch_sfb: annotate data-races in sfb_dump_stats()

Eric Dumazet <[email protected]>
net/sched: sch_red: annotate data-races in red_dump_stats()

Eric Dumazet <[email protected]>
net/sched: sch_fq_codel: remove data-races from fq_codel_dump_stats()

Eric Dumazet <[email protected]>
net/sched: sch_pie: annotate data-races in pie_dump_stats()

Eric Dumazet <[email protected]>
net_sched: sch_hhf: annotate data-races in hhf_dump_stats()

Michael Bommarito <[email protected]>
net/rds: zero per-item info buffer before handing it to visitors

Hyunwoo Kim <[email protected]>

    ksmbd: scope conn->binding slowpath to bound sessions only

DaeMyung Kang <[email protected]>
ksmbd: fix durable fd leak on ClientGUID mismatch in durable v2 open

DaeMyung Kang <[email protected]>
ksmbd: destroy async_ida in ksmbd_conn_free()

Namjae Jeon <[email protected]>
ksmbd: add support for supplementary groups

Thorsten Blum <[email protected]>
ksmbd: Use struct_size() to improve smb_direct_rdma_xmit()

DaeMyung Kang <[email protected]>
ksmbd: destroy tree_conn_ida in ksmbd_session_destroy()

Jun Yan <[email protected]>
arm64: dts: meson-gxl-p230: fix ethernet PHY interrupt number

Weiming Shi <[email protected]>
slip: bound decode() reads against the compressed packet length

Weiming Shi <[email protected]>
slip: reject VJ receive packets on instances with no rstate array

Fernando Fernandez Mancera <[email protected]>
netfilter: nfnetlink_osf: fix potential NULL dereference in ttl check

Fernando Fernandez Mancera <[email protected]>
netfilter: nfnetlink_osf: fix out-of-bounds read on option matching

Yingnan Zhang <[email protected]>
ipvs: fix MTU check for GSO packets in tunnel mode

Pablo Neira Ayuso <[email protected]>
netfilter: xtables: restrict several matches to inet family

Florian Westphal <[email protected]>
netfilter: conntrack: remove sprintf usage

Xiang Mei <[email protected]>
netfilter: nfnetlink_osf: fix divide-by-zero in OSF_WSS_MODULO

Pablo Neira Ayuso <[email protected]>
netfilter: nft_osf: restrict it to ipv4

Weiming Shi <[email protected]>
openvswitch: cap upcall PID array size and pre-size vport replies

Qingfang Deng <[email protected]>
pppoe: drop PFC frames

Michael Bommarito <[email protected]>
sctp: fix OOB write to userspace in sctp_getsockopt_peer_auth_chunks

Eric Dumazet <[email protected]>
ipv6: fix possible UAF in icmpv6_rcv()

Matt Vollrath <[email protected]>
e1000e: Unroll PTP in probe error handling

Kohei Enju <[email protected]>
i40e: don't advertise IFF_SUPP_NOFCS

Michal Schmidt <[email protected]>
ice: fix double-free of tx_buf skb

Alice Mikityanska <[email protected]>
ice: Remove jumbo_remove step from TX path

Eric Dumazet <[email protected]>

    tcp: annotate data-races around tp->plb_rehash

Eric Dumazet <[email protected]>

    tcp: annotate data-races around (tp->write_seq - tp->snd_nxt)

Eric Dumazet <[email protected]>

    tcp: annotate data-races around tp->dsack_dups

Eric Dumazet <[email protected]>

    tcp: annotate data-races around tp->bytes_retrans

Eric Dumazet <[email protected]>

    tcp: annotate data-races around tp->bytes_sent

Eric Dumazet <[email protected]>

    tcp: add data-race annotations around tp->data_segs_out and tp->total_retrans

Vinicius Costa Gomes <[email protected]>
net/sched: taprio: fix use-after-free in advance_sched() on schedule switch

Jiayuan Chen <[email protected]>
nexthop: fix IPv6 route referencing IPv4 nexthop

Dudu Lu <[email protected]>
net/sched: sch_cake: fix NAT destination port not being updated in cake_update_flowkeys

Dudu Lu <[email protected]>
macvlan: fix macvlan_get_size() not reserving space for IFLA_MACVLAN_BC_CUTOFF

Peng Fan <[email protected]>
arm64: dts: imx8mm-tqma8mqml: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mn-tqma8mqnl: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mm-emtop-som: Correct PAD settings for PMIC_nINT

René Rebe <[email protected]>
PCMCIA: Fix garbled log messages for KERN_CONT

Peng Fan <[email protected]>
arm64: dts: imx8mp-data-modul-edm-sbc: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mp-dhcom-som: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mp-icore-mx8mp: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mp-debix-som-a: Correct PAD settings for PMIC_nINT

Peng Fan <[email protected]>
arm64: dts: imx8mp-debix-model-a: Correct PAD settings for PMIC_nINT

Paul Moses <[email protected]>
crypto: ccp - copy IV using skcipher ivsize

T Pratham <[email protected]>
crypto: sa2ul - Fix AEAD fallback algorithm names

Ville Syrjälä <[email protected]>
drm/i915/wm: Verify the correct plane DDB entry

Stanislav Lisovskiy <[email protected]>
drm/i915: Loop over all active pipes in intel_mbus_dbox_update

Gustavo Sousa <[email protected]>
drm/i915: Extract intel_dbuf_mdclk_cdclk_ratio_update()

Ville Syrjälä <[email protected]>
drm/i915: Simplify watermark state checker calling convention

Ville Syrjälä <[email protected]>
drm/i915: Constify watermark state checker

Yongpeng Yang <[email protected]>
f2fs: protect extension_list reading with sb_lock in f2fs_sbi_show()

Christophe JAILLET <[email protected]>
f2fs: Use sysfs_emit_at() to simplify code

Brian Masney <[email protected]>
clk: visconti: pll: initialize clk_init_data to zero

Geert Uytterhoeven <[email protected]>
lib/hexdump: print_hex_dump_bytes() calls print_hex_dump_debug()

Konrad Dybcio <[email protected]>
clk: qcom: dispcc-sc7180: Add missing MDSS resets

Konrad Dybcio <[email protected]>
dt-bindings: clock: qcom,dispcc-sc7180: Define MDSS resets

Geert Uytterhoeven <[email protected]>
clk: xgene: Fix mapping leak in xgene_pllclk_init()

Arnd Bergmann <[email protected]>
clk: qoriq: avoid format string warning

Sebastian Krzyszkowiak <[email protected]>
clk: imx8mq: Correct the CSI PHY sels

Felix Gu <[email protected]>
clk: imx: imx6q: Fix device node reference leak in of_assigned_ldb_sels()

Felix Gu <[email protected]>
clk: imx: imx6q: Fix device node reference leak in pll6_bypassed()

Val Packett <[email protected]>
clk: qcom: dispcc-sm8250: Enable parents for pixel clocks

Val Packett <[email protected]>
clk: qcom: dispcc-sm8250: Use shared ops on the mdss vsync clk

Val Packett <[email protected]>

    clk: qcom: gcc-sc8180x: Use retention for PCIe power domains

Val Packett <[email protected]>

    clk: qcom: gcc-sc8180x: Use retention for USB power domains

Val Packett <[email protected]>

    clk: qcom: gcc-sc8180x: Add missing GDSCs

Val Packett <[email protected]>

    dt-bindings: clock: qcom,gcc-sc8180x: Add missing GDSCs

Junrui Luo <[email protected]>
scsi: target: core: Fix integer overflow in UNMAP bounds check

White Lewis <[email protected]>

    clk: qcom: dispcc-sc8280xp: remove CLK_SET_RATE_PARENT from byte_div_clk_src dividers

Yang Erkun <[email protected]>
scsi: sg: Resolve soft lockup issue when opening /dev/sgX

Yang Erkun <[email protected]>
scsi: sg: Fix sysctl sg-big-buff register during sg_init()

Ricardo B. Marliere <[email protected]>
scsi: sg: Make sg_sysfs_class constant

Dmitry Baryshkov <[email protected]>
clk: qcom: dispcc-sm8450: use RCG2 ops for DPTX1 AUX clock source

Florian Westphal <[email protected]>
RDMA/core: Prefer NLA_NUL_STRING

Pengpeng Hou <[email protected]>
platform/x86: dell-wmi-sysman: bound enumeration string aggregation

Fedor Pchelkin <[email protected]>
platform/x86: dell_rbu: avoid uninit value usage in packet_size_write()

Pengpeng Hou <[email protected]>
fs/ntfs3: terminate the cached volume label after UTF-8 conversion

Andy Shevchenko <[email protected]>
nfs/blocklayout: Fix compilation error (make W=1) in bl_write_pagelist()

Abdun Nihaal <[email protected]>
mfd: mc13xxx-core: Fix memory leak in mc13xxx_add_subdevice_pdata()

Rafael J. Wysocki <[email protected]>
platform/x86: panasonic-laptop: Fix OPTD notifier registration and cleanup

Randy Dunlap <[email protected]>
tty: hvc_iucv: fix off-by-one in number of supported devices

Chen Ni <[email protected]>

    leds: lgm-sso: Remove duplicate assignments for priv->mmap

Rafael J. Wysocki <[email protected]>
platform/surface: surfacepro3_button: Drop wakeup source on remove

Chen Ni <[email protected]>
backlight: sky81452-backlight: Check return value of devm_gpiod_get_optional() in sky81452_bl_parse_dt()

Nuno Sa <[email protected]>
dev_printk: add new dev_err_probe() helpers

Billy Tsai <[email protected]>
i3c: mipi-i3c-hci: fix IBI payload length calculation for final status

Jorge Marques <[email protected]>
i3c: master: Fix error codes at send_ccc_cmd

Arnaldo Carvalho de Melo <[email protected]>
perf util: Kill die() prototype, dead for a long time

Jian Zhang <[email protected]>
ipmi: ssif_bmc: change log level to dbg in irq callback

Jian Zhang <[email protected]>
ipmi: ssif_bmc: fix message desynchronization after truncated response

Jian Zhang <[email protected]>
ipmi: ssif_bmc: fix missing check for copy_to_user() partial failure

Leo Yan <[email protected]>
perf expr: Return -EINVAL for syntax error in expr__find_ids()

Chuck Lever <[email protected]>
perf tools: Fix module symbol resolution for non-zero .text sh_addr

Ian Rogers <[email protected]>
perf lock: Fix option value type in parse_max_stack

Yu-Chun Lin <[email protected]>
pinctrl: abx500: Fix type of 'argument' variable

Mike Leach <[email protected]>
perf: tools: cs-etm: Fix print issue for Coresight debug in ETE/TRBE trace

Ian Rogers <[email protected]>
perf branch: Avoid incrementing NULL

Andy Shevchenko <[email protected]>
pinctrl: cy8c95x0: Avoid returning positive values to user space

Andy Shevchenko <[email protected]>
pinctrl: cy8c95x0: Unify messages with help of dev_err_probe()

Andy Shevchenko <[email protected]>
pinctrl: cy8c95x0: remove duplicate error message

Ethan Tidmore <[email protected]>
pinctrl: pinctrl-pic32: Fix resource leak

Puranjay Mohan <[email protected]>
bpf, arm32: Reject BPF-to-BPF calls and callbacks in the JIT

Yihan Ding <[email protected]>
bpf: allow UTF-8 literals in bpf_bprintf_prepare()

Mykyta Yatsenko <[email protected]>
bpf: Fix NULL deref in map_kptr_match_type for scalar regs

Daniel Borkmann <[email protected]>
bpf: Fix precedence bug in convert_bpf_ld_abs alignment check

Michal Luczaj <[email protected]>
bpf, sockmap: Take state lock for af_unix iter

Michal Luczaj <[email protected]>
bpf, sockmap: Fix af_unix null-ptr-deref in proto update

Michal Luczaj <[email protected]>
bpf, sockmap: Fix af_unix iter deadlock

Puranjay Mohan <[email protected]>
bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize

Daniel Borkmann <[email protected]>
bpf, arm64: Fix off-by-one in check_imm signed range check

Oliver Neukum <[email protected]>
HID: usbhid: fix deadlock in hid_post_reset()

Richard Genoud <[email protected]>
mtd: rawnand: sunxi: fix sunxi_nfc_hw_ecc_read_extra_oob

Cosmin Tanislav <[email protected]>
mtd: parsers: ofpart: call of_node_get() for dedicated subpartitions

Cosmin Tanislav <[email protected]>
mtd: parsers: ofpart: call of_node_put() only in ofpart_fail path

Shiji Yang <[email protected]>
mtd: spi-nor: swp: check SR_TB flag when getting tb_mask

Jonas Gorski <[email protected]>
mtd: spi-nor: update spi_nor_fixups::post_sfdp() documentation

Takahiro Kuwano <[email protected]>
mtd: spi-nor: sfdp: introduce smpt_map_id fixup hook

Takahiro Kuwano <[email protected]>
mtd: spi-nor: sfdp: introduce smpt_read_dummy fixup hook

Haibo Chen <[email protected]>
mtd: spi-nor: core: correct the op.dummy.nbytes when check read operations

Geert Uytterhoeven <[email protected]>
dt-bindings: interrupt-controller: arm,gic-v3: Fix EPPI range

Chen Ni <[email protected]>
mtd: physmap_of_gemini: Fix disabled pinctrl state check

Denis Benato <[email protected]>
HID: asus: do not abort probe when not necessary

Denis Benato <[email protected]>
HID: asus: make asus_resume adhere to linux kernel coding standards

Daniel Hodges <[email protected]>
ima: check return value of crypto_shash_final() in boot aggregate

Pengpeng Hou <[email protected]>
tracing: Rebuild full_name on each hist_field_name() call

Richard Fitzgerald <[email protected]>
soundwire: cadence: Clear message complete before signaling waiting thread

Frank Li <[email protected]>
dmaengine: mxs-dma: Fix missing return value from of_dma_controller_register()

Cole Leavitt <[email protected]>
soundwire: bus: demote UNATTACHED state warnings to dev_dbg()

Khairul Anuar Romli <[email protected]>
dmaengine: dw-axi-dmac: Remove unnecessary return statement from void function

ZhengYuan Huang <[email protected]>
ocfs2: validate group add input before caching

ZhengYuan Huang <[email protected]>
ocfs2: validate bg_bits during freefrag scan

ZhengYuan Huang <[email protected]>
ocfs2: fix listxattr handling when the buffer is full

Frank Li <[email protected]>
ARM: dts: imx27-eukrea: replace interrupts with interrupts-extended

Christoph Hellwig <[email protected]>
arm64/xor: fix conflicting attributes for xor_block_template

Aaro Koskinen <[email protected]>
ARM: OMAP1: Fix DEBUG_LL and earlyprintk on OMAP16XX

Alexander Koskovich <[email protected]>

    arm64: dts: qcom: sm8250: Add missing CPU7 3.09GHz OPP

Alok Tiwari <[email protected]>
soc: qcom: aoss: compare against normalized cooling state

Alok Tiwari <[email protected]>
soc: qcom: llcc: fix v1 SB syndrome register offset

Junrui Luo <[email protected]>
ocfs2/dlm: fix off-by-one in dlm_match_regions() region comparison

Junrui Luo <[email protected]>
ocfs2/dlm: validate qr_numregions in dlm_match_regions()

Michal Grzedzicki <[email protected]>
unshare: fix nsproxy leak in ksys_unshare() on set_cred_ucounts() failure

Sumit Gupta <[email protected]>
soc/tegra: cbb: Set ERD on resume for err interrupt

Xu Yang <[email protected]>
arm64: dts: imx8qxp-mek: switch Type-C connector power-role to dual

David Heidelberg <[email protected]>
arm64: dts: qcom: sdm845-xiaomi-beryllium: Mark l1a regulator as powered during boot

Luca Weiss <[email protected]>
arm64: dts: qcom: sm7225-fairphone-fp4: Fix conflicting bias pinctrl

Vladimir Zapolskiy <[email protected]>
arm64: dts: qcom: sm8550: Enable UHS-I SDR50 and SDR104 SD card modes

Vladimir Zapolskiy <[email protected]>
arm64: dts: qcom: sm8450: Enable UHS-I SDR50 and SDR104 SD card modes

Vladimir Zapolskiy <[email protected]>
arm64: dts: qcom: sm8550: Fix xo clock supply of platform SD host controller

Konrad Dybcio <[email protected]>
arm64: dts: qcom: sm8550: Fix GIC_ITS range length

Konrad Dybcio <[email protected]>
arm64: dts: qcom: sm8450: Fix GIC_ITS range length

Dmitry Baryshkov <[email protected]>
soc: qcom: ocmem: return -EPROBE_DEFER is ocmem is not available

Dmitry Baryshkov <[email protected]>
soc: qcom: ocmem: register reasons for probe deferrals

Krzysztof Kozlowski <[email protected]>
soc: qcom: ocmem: use scoped device node handling to simplify error paths

Dmitry Baryshkov <[email protected]>
soc: qcom: ocmem: make the core clock optional

Barnabás Czémán <[email protected]>
arm64: dts: qcom: msm8953-xiaomi-daisy: fix backlight

Barnabás Czémán <[email protected]>
arm64: dts: qcom: msm8953-xiaomi-vince: correct wled ovp value

Akari Tsuyukusa <[email protected]>
arm64: dts: mediatek: mt7986a: Fix gpio-ranges pin count

Akari Tsuyukusa <[email protected]>
arm64: dts: mediatek: mt6795: Fix gpio-ranges pin count

Jacob Pan <[email protected]>
iommufd: vfio compatibility extension check for noiommu mode

Sherry Sun <[email protected]>
arm64: dts: imx8mp-evk: Enable pull select bit for PCIe regulator GPIO (M.2 W_DISABLE1)

Francesco Dolcini <[email protected]>
arm64: dts: imx8-apalis: Fix LEDs name collision

Mikko Perttunen <[email protected]>
memory: tegra30-emc: Fix dll_change check

Mikko Perttunen <[email protected]>
memory: tegra124-emc: Fix dll_change check

Rafał Miłecki <[email protected]>
ARM: dts: mediatek: mt7623: fix efuse fallback compatible

Joshua Klinesmith <[email protected]>
ksmbd: fix use-after-free from async crypto on Qualcomm crypto engine

Thomas Huth <[email protected]>
efi/capsule-loader: fix incorrect sizeof in phys array reallocation

Andreas Gruenbacher <[email protected]>
gfs2: prevent NULL pointer dereference during unmount

Andreas Gruenbacher <[email protected]>
gfs2: add some missing log locking

Jan Kara <[email protected]>
quota: Fix race of dquot_scan_active() with quota deactivation

Ricardo B. Marlière <[email protected]>
ktest: Run POST_KTEST hooks on failure and cancellation

Ricardo B. Marlière <[email protected]>
ktest: Honor empty per-test option overrides

Ricardo B. Marlière <[email protected]>
ktest: Avoid undef warning when WARNINGS_FILE is unset

Andreas Gruenbacher <[email protected]>
gfs2: Call unlock_new_inode before d_instantiate

Haixin Xu <[email protected]>
crypto: jitterentropy - replace long-held spinlock with mutex

Ming-Hung Tsai <[email protected]>
dm cache: fix missing return in invalidate_committed's error path

Cássio Gabriel <[email protected]>
ALSA: sc6000: Keep the programmed board state in card-private data

Takashi Iwai <[email protected]>
ALSA: sc6000: Use standard print API

Pei Xiao <[email protected]>
spi: mtk-snfi: unregister ECC engine on probe failure and remove() callback

Manikanta Maddireddy <[email protected]>
PCI: dwc: Apply ECRC workaround to DesignWare 5.00a as well

Manikanta Maddireddy <[email protected]>
PCI: tegra194: Use DWC IP core version

Vidya Sagar <[email protected]>
PCI: tegra194: Allow system suspend when the Endpoint link is not up

Vidya Sagar <[email protected]>
PCI: tegra194: Disable direct speed change for Endpoint mode

Vidya Sagar <[email protected]>
PCI: tegra194: Use devm_gpiod_get_optional() to parse "nvidia,refclk-select"

Manikanta Maddireddy <[email protected]>
PCI: tegra194: Disable PERST# IRQ only in Endpoint mode

Vidya Sagar <[email protected]>
PCI: tegra194: Don't force the device into the D0 state before L2

Manivannan Sadhasivam <[email protected]>
PCI: tegra194: Rename 'root_bus' to 'root_port_bus' in tegra_pcie_downstream_dev_to_D0()

Manikanta Maddireddy <[email protected]>
PCI: tegra194: Disable LTSSM after transition to Detect on surprise link down

Manikanta Maddireddy <[email protected]>
PCI: tegra194: Increase LTSSM poll time on surprise link down

Vidya Sagar <[email protected]>
PCI: tegra194: Fix polling delay for L2 state

Cássio Gabriel <[email protected]>
ASoC: SOF: compress: return the configured codec from get_params

Panagiotis Petrakopoulos <[email protected]>
ALSA: scarlett2: Add missing sentinel initializer field

Waiman Long <[email protected]>
selftest: memcg: skip memcg_sock test if address family not supported

Jane Chu <[email protected]>
Documentation: fix a hugetlbfs reservation statement

AnishMulay <[email protected]>
selftests/mm: skip migration tests if NUMA is unavailable

Chen-Yu Tsai <[email protected]>
PCI: mediatek-gen3: Prevent leaking IRQ domains when IRQ not found

Gerd Bayer <[email protected]>
PCI: Enable AtomicOps only if Root Port supports them

Denis Rastyogin <[email protected]>

    ASoC: rsnd: Fix potential out-of-bounds access of component_dais[]

Giovanni Cabiddu <[email protected]>
crypto: qat - use swab32 macro

Srinivas Kandagatla <[email protected]>
ASoC: qcom: qdsp6: topology: check widget type before accessing data

Shengjiu Wang <[email protected]>
ASoC: fsl_easrc: Change the type for iec958 channel status controls

Shengjiu Wang <[email protected]>
ASoC: fsl_easrc: Fix value type in fsl_easrc_iec958_get_bits()

Shengjiu Wang <[email protected]>
ASoC: fsl_easrc: Check the variable range in fsl_easrc_iec958_put_bits()

Shengjiu Wang <[email protected]>
ASoC: fsl_xcvr: Fix event generation in fsl_xcvr_mode_put()

Shengjiu Wang <[email protected]>
ASoC: fsl_xcvr: Fix event generation in fsl_xcvr_arc_mode_put()

Shengjiu Wang <[email protected]>
ASoC: fsl_micfil: Fix event generation in micfil_quality_set()

Shengjiu Wang <[email protected]>
ASoC: fsl_micfil: Fix event generation in micfil_put_dc_remover_state()

Shengjiu Wang <[email protected]>
ASoC: fsl_micfil: Fix event generation in hwvad_put_init_mode()

Shengjiu Wang <[email protected]>
ASoC: fsl_micfil: Fix event generation in hwvad_put_enable()

Shengjiu Wang <[email protected]>
ASoC: fsl_micfil: Add access property for "VAD Detected"

Felix Gu <[email protected]>

    pmdomain: imx: scu-pd: Fix device_node reference leak during ->probe()

Felix Gu <[email protected]>
pmdomain: ti: omap_prm: Fix a reference leak on device node

Akhil P Oommen <[email protected]>
drm/msm/a6xx: Use barriers while updating HFI Q headers

Rob Clark <[email protected]>
drm/msm/shrinker: Fix can_block() logic

Rob Clark <[email protected]>
drm/msm/a6xx: Fix HLSQ register dumping

Ethan Tidmore <[email protected]>
ASoC: SOF: Intel: hda: Place check before dereference

Lei Huang <[email protected]>
ALSA: hda/realtek: fix code style (ERROR: else should follow close brace '}')

Timur Kristóf <[email protected]>
drm/amd/pm/smu7: Add SCLK cap for quirky Hawaii board

Timur Kristóf <[email protected]>
drm/amd/pm/ci: Fill DW8 fields from SMC

Timur Kristóf <[email protected]>
drm/amd/pm/ci: Clear EnabledForActivity field for memory levels

Timur Kristóf <[email protected]>

    drm/amd/pm/ci: Fix powertune defaults for Hawaii 0x67B0

Timur Kristóf <[email protected]>
drm/amd/pm/smu7: Fix SMU7 voltage dependency on display clock

Timur Kristóf <[email protected]>
drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs

Timur Kristóf <[email protected]>
drm/amd/pm/ci: Use highest MCLK on CI when MCLK DPM is disabled

Cássio Gabriel <[email protected]>
ALSA: core: Validate compress device numbers without dynamic minors

Sebastian Reichel <[email protected]>
drm/panel: simple: Correct G190EAN01 prepare timing

Dmitry Baryshkov <[email protected]>
drm/panel: sharp-ls043t1le01: make use of prepare_prev_first

Alexander Koskovich <[email protected]>

    drm/msm/dsi: rename MSM8998 DSI version from V2_2_0 to V2_0_0

Pengyu Luo <[email protected]>
drm/msm/dsi: add the missing parameter description

Yuanjie Yang <[email protected]>
drm/msm/dpu: fix mismatch between power and frequency

Pei Xiao <[email protected]>
spi: hisi-kunpeng: prevent infinite while() loop in hisi_spi_flush_fifo

Alex Deucher <[email protected]>
drm/amdgpu/gfx10: look at the right prop for gfx queue priority

Daniel Jordan <[email protected]>
padata: Put CPU offline callback in ONLINE section to allow failure

Chuyi Zhou <[email protected]>
padata: Remove cpu online check from cpu add and removal

Thorsten Blum <[email protected]>
crypto: atmel-aes - guard unregister on error in atmel_aes_register_algs

Thorsten Blum <[email protected]>

    crypto: atmel - Use unregister_{aeads,ahashes,skciphers}

Herbert Xu <[email protected]>
crypto: atmel - Remove cfb and ofb

Andy Shevchenko <[email protected]>
fbdev: matroxfb: Mark variable with __maybe_unused to avoid W=1 build break

Guillaume Gonnet <[email protected]>
dm init: ensure device probing has finished in dm-mod.waitfor=

Srinivasan Shanmugam <[email protected]>
drm/amdgpu: Add default case in DVI mode validation

Ethan Tidmore <[email protected]>
drm/sun4i: Fix resource leaks

Felix Gu <[email protected]>
spi: fsl-qspi: Use reinit_completion() for repeated operations

Harikrishna Shenoy <[email protected]>
drm/bridge: cadence: cdns-mhdp8546-core: Handle HDCP state in bridge atomic check

Jayesh Choudhary <[email protected]>
drm/bridge: cadence: cdns-mhdp8546-core: Add mode_valid hook to drm_bridge_funcs

Jayesh Choudhary <[email protected]>
drm/bridge: cadence: cdns-mhdp8546-core: Set the mhdp connector earlier in atomic_enable()

Junrui Luo <[email protected]>
dm log: fix out-of-bounds write due to region_count overflow

Ming-Hung Tsai <[email protected]>
dm cache metadata: fix memory leak on metadata abort retry

Rafael J. Wysocki <[email protected]>
platform/chrome: chromeos_tbmc: Drop wakeup source on remove

Ming-Hung Tsai <[email protected]>
dm cache: fix dirty mapping checking in passthrough mode switching

Ming-Hung Tsai <[email protected]>
dm cache: support shrinking the origin device

Ming-Hung Tsai <[email protected]>
dm cache: fix concurrent write failure in passthrough mode

Ming-Hung Tsai <[email protected]>
dm cache policy smq: fix missing locks in invalidating cache blocks

Ming-Hung Tsai <[email protected]>
dm cache: fix write hang in passthrough mode

Ming-Hung Tsai <[email protected]>
dm cache: fix write path cache coherency in passthrough mode

Ming-Hung Tsai <[email protected]>
dm cache: fix null-deref with concurrent writes in passthrough mode

Sander Vanheule <[email protected]>
ASoC: sti: use managed regmap_field allocations

Sander Vanheule <[email protected]>
ASoC: sti: Return errors from regmap_field_alloc()

Ethan Tidmore <[email protected]>
drm/sun4i: backend: fix error pointer dereference

Alexander Konyukhov <[email protected]>
drm/komeda: fix integer overflow in AFBC framebuffer size check

Jiayuan Chen <[email protected]>
net, bpf: fix null-ptr-deref in xdp_master_redirect() for down master

Xin Long <[email protected]>
sctp: fix missing encap_port propagation for GSO fragments

Maxime Chevallier <[email protected]>
net: phy: qcom: at803x: Use the correct bit to disable extended next page

Christian Marangi <[email protected]>
net: phy: move at803x PHY driver to dedicated directory

FUJITA Tomonori <[email protected]>
net: phy: add Rust Asix PHY driver

Christian Marangi <[email protected]>
net: phy: aquantia: move to separate directory

Dudu Lu <[email protected]>
Bluetooth: l2cap: Add missing chan lock in l2cap_ecred_reconf_rsp

Pauli Virtanen <[email protected]>
Bluetooth: fix locking in hci_conn_request_evt() with HCI_PROTO_DEFER

Jonathan Rissanen <[email protected]>
Bluetooth: hci_ldisc: Clear HCI_UART_PROTO_INIT on error

Luiz Augusto von Dentz <[email protected]>
Bluetooth: L2CAP: Fix printing wrong information if SDU length exceeds MTU

Sun Jian <[email protected]>
bpf: reject short IPv4/IPv6 inputs in bpf_prog_test_run_skb

Gal Pressman <[email protected]>
net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()

Gal Pressman <[email protected]>
net/mlx5e: Fix features not applied during netdev registration

Josua Mayer <[email protected]>
dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110

Luca Weiss <[email protected]>
net: ipa: Fix decoding EV_PER_EE for IPA v5.0+

Luca Weiss <[email protected]>
net: ipa: Fix programming of QTIME_TIMESTAMP_CFG

Taegu Ha <[email protected]>
ppp: require CAP_NET_ADMIN in target netns for unattached ioctls

Lang Xu <[email protected]>
bpf: Fix OOB in pcpu_init_value

Greg Jumper <[email protected]>
net/rds: Restrict use of RDS/IB to the initial network namespace

Håkon Bugge <[email protected]>
net/rds: Optimize rds_ib_laddr_check

Jamal Hadi Salim <[email protected]>
net/sched: act_ct: Only release RCU read lock after ct_ft

Mashiro Chen <[email protected]>
net: hamradio: 6pack: fix uninit-value in sixpack_receive_buf

Jiri Slaby (SUSE) <[email protected]>
6pack: propagage new tty types

Sechang Lim <[email protected]>
bpf: Fix RCU stall in bpf_fd_array_map_clear()

Florian Westphal <[email protected]>
netfilter: nft_fwd_netdev: check ttl/hl before forwarding

Florian Westphal <[email protected]>
netfilter: xt_socket: enable defrag after all other checks

Justin Chen <[email protected]>
net: bcmgenet: fix racing timeout handler

Zak Kemble <[email protected]>
net: bcmgenet: switch to use 64bit statistics

Doug Berger <[email protected]>
net: bcmgenet: support reclaiming unsent Tx packets

Doug Berger <[email protected]>
net: bcmgenet: move DESC_INDEX flow to ring 0

Doug Berger <[email protected]>
net: bcmgenet: add bcmgenet_has_* helpers

Florian Fainelli <[email protected]>
net: bcmgenet: Remove custom ndo_poll_controller()

Justin Chen <[email protected]>
net: bcmgenet: fix off-by-one in bcmgenet_put_txcb

Wang Wensheng <[email protected]>
arm64: kexec: Remove duplicate allocation for trans_pgd

Haoyu Lu <[email protected]>
ACPI: AGDI: fix missing newline in error message

Weiming Shi <[email protected]>
bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec()

Jiayuan Chen <[email protected]>
bpf: Drop task_to_inode and inet_conn_established from lsm sleepable hooks

Ethan Tidmore <[email protected]>
wifi: brcmfmac: Fix error pointer dereference

MingTao Huang <[email protected]>

    bpf: Fix stale offload->prog pointer after constant blinding

Weiming Shi <[email protected]>
bpf: fix end-of-list detection in cgroup_storage_get_next_key()

Eric Dumazet <[email protected]>

    macvlan: annotate data-races around port->bc_queue_len_used

Amit Machhiwal <[email protected]>
selftests/powerpc: Suppress -Wmaybe-uninitialized with GCC 15

Madhavan Srinivasan <[email protected]>
selftests/powerpc: Re-order *FLAGS to follow lib.mk

Sourabh Jain <[email protected]>
powerpc/crash: fix backup region offset update to elfcorehdr

Chih Kai Hsu <[email protected]>
r8152: fix incorrect register write to USB_UPHY_XTAL

Alexey Velichayshiy <[email protected]>
wifi: rtw89: phy: fix uninitialized variable access in rtw89_phy_cfo_set_crystal_cap()

David Carlier <[email protected]>
bpf: Use RCU-safe iteration in dev_map_redirect_multi() SKB path

Thorsten Blum <[email protected]>
bpf, devmap: Remove unnecessary if check in for loop

Duoming Zhou <[email protected]>

    wifi: mt76: mt7915: fix use-after-free bugs in mt7915_mac_dump_work()

StanleyYP Wang <[email protected]>

    wifi: mt76: mt7996: fix struct mt7996_mcu_uni_event

James Clark <[email protected]>
arm64: cpufeature: Make PMUVer and PerfMon unsigned

Alok Tiwari <[email protected]>
wifi: mt76: mt7996: fix FCS error flag check in RX descriptor

Ryder Lee <[email protected]>
wifi: mt76: mt7915: fix use_cts_prot support

Ryder Lee <[email protected]>
wifi: mt76: mt7615: fix use_cts_prot support

Sean Wang <[email protected]>
wifi: mt76: mt7921: Reset ampdu_state state in case of failure in mt76_connac2_tx_check_aggr()

Petr Pavlu <[email protected]>
module: Fix freeing of charp module parameters when CONFIG_SYSFS=n

Petr Pavlu <[email protected]>
params: Replace __modinit with __init_or_module

Ilya Leoshkevich <[email protected]>
s390/bpf: Zero-extend bpf prog return values and kfunc arguments

Cai Xinchen <[email protected]>
dpaa2: compile dpaa2 even CONFIG_FSL_DPAA2_ETH=n

Cai Xinchen <[email protected]>
dpaa2: add independent dependencies for FSL_DPAA2_SWITCH

Feng Yang <[email protected]>
bpf: test_run: Fix the null pointer dereference issue in bpf_lwt_xmit_push_encap

Vadim Fedorenko <[email protected]>
bpf: Add CHECKSUM_COMPLETE to bpf test progs

Duoming Zhou <[email protected]>
wifi: rtlwifi: pci: fix possible use-after-free caused by unfinished irq_prepare_bcn_tasklet

Zilin Guan <[email protected]>
wifi: mwifiex: Fix memory leak in mwifiex_11n_aggregate_pkt()

Mario Limonciello (AMD) <[email protected]>
firmware: dmi: Correct an indexing error in dmi.h

Bart Van Assche <[email protected]>
locking: Fix rwlock support in <linux/spinlock_up.h>

Thomas Gleixner <[email protected]>
hrtimer: Reduce trace noise in hrtimer_start()

Peter Zijlstra <[email protected]>
hrtimer: Avoid pointless reprogramming in __hrtimer_start_range_ns()

Richard Clark <[email protected]>
hrtimers: Update the return type of enqueue_hrtimer()

Brian Masney <[email protected]>
irqchip/irq-pic32-evic: Address warning related to wrong printf() formatter

Danilo Krummrich <[email protected]>
s390/cio: use generic driver_override infrastructure

Li Zhijian <[email protected]>
s390/cio: convert sprintf()/snprintf() to sysfs_emit()

Halil Pasic <[email protected]>

    s390/cio: make sch->lock spinlock pointer a member

Gui-Dong Han <[email protected]>
debugfs: fix placement of EXPORT_SYMBOL_GPL for debugfs_create_str()

Gui-Dong Han <[email protected]>
debugfs: check for NULL pointer in debugfs_create_str()

Gopi Krishna Menon <[email protected]>
thermal/drivers/spear: Fix error condition for reading st,thermal-flags

Danilo Krummrich <[email protected]>
devres: fix missing node debug info in devm_krealloc()

Rafael J. Wysocki <[email protected]>
ACPI: x86: cmos_rtc: Improve coordination with ACPI TAD driver

Rafael J. Wysocki <[email protected]>
ACPI: x86: cmos_rtc: Clean up address space handler driver

Cole Leavitt <[email protected]>
pstore/ram: fix resource leak when ioremap() fails

Jackie Liu <[email protected]>
blk-cgroup: fix disk reference leak in blkcg_maybe_throttle_current()

Deepanshu Kartikey <[email protected]>
nilfs2: reject zero bd_oblocknr in nilfs_ioctl_mark_blocks_dirty()

Daan De Meyer <[email protected]>
loop: fix partition scan race between udev and loop_reread_partitions()

Bart Van Assche <[email protected]>
drbd: Balance RCU calls in drbd_adm_dump_devices()

HyungJung Joo <[email protected]>
fs/omfs: reject s_sys_blocksize smaller than OMFS_DIR_START

Ming Lei <[email protected]>
blk-cgroup: wait for blkcg cleanup before initializing new disk

-------------

Diffstat:

 .../bindings/interrupt-controller/arm,gic-v3.yaml  |   2 +-
 .../devicetree/bindings/net/dsa/nxp,sja1105.yaml   |   2 -
 Documentation/mm/hugetlbfs_reserv.rst              |   2 +-
 Documentation/networking/bonding.rst               |  15 +
 MAINTAINERS                                        |   8 +
 Makefile                                           |   4 +-
 arch/arm/boot/dts/mediatek/mt7623.dtsi             |   2 +-
 .../boot/dts/nxp/imx/imx27-eukrea-cpuimx27.dtsi    |   8 +-
 .../nxp/imx/imx27-eukrea-mbimxsd27-baseboard.dts   |   2 +-
 arch/arm/mach-omap1/clock_data.c                   |   4 +-
 arch/arm/net/bpf_jit_32.c                          |   6 +
 .../boot/dts/amlogic/meson-gxl-s905d-p230.dts      |   3 +-
 .../boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi |   4 +
 .../boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi |   4 +
 .../arm64/boot/dts/freescale/imx8mm-emtop-som.dtsi |   4 +-
 .../arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi |   2 +-
 .../arm64/boot/dts/freescale/imx8mn-tqma8mqnl.dtsi |   2 +-
 .../dts/freescale/imx8mp-data-modul-edm-sbc.dts    |   2 +-
 .../boot/dts/freescale/imx8mp-debix-model-a.dts    |   2 +-
 .../dts/freescale/imx8mp-debix-som-a-bmb-08.dts    |   2 +-
 .../boot/dts/freescale/imx8mp-debix-som-a.dtsi     |   2 +-
 .../arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi |   2 +-
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts       |   2 +-
 .../boot/dts/freescale/imx8mp-icore-mx8mp.dtsi     |   2 +-
 arch/arm64/boot/dts/freescale/imx8qxp-mek.dts      |  10 +-
 arch/arm64/boot/dts/mediatek/mt6795.dtsi           |   2 +-
 arch/arm64/boot/dts/mediatek/mt7986a.dtsi          |   2 +-
 arch/arm64/boot/dts/qcom/msm8953-xiaomi-daisy.dts  |   2 +-
 arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dts  |   2 +-
 .../dts/qcom/sdm845-xiaomi-beryllium-common.dtsi   |   1 +
 arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts  |   4 +
 arch/arm64/boot/dts/qcom/sm8250.dtsi               |   5 +
 arch/arm64/boot/dts/qcom/sm8450.dtsi               |   5 +-
 arch/arm64/boot/dts/qcom/sm8550.dtsi               |   7 +-
 arch/arm64/include/asm/xor.h                       |   2 +-
 arch/arm64/kernel/cpufeature.c                     |   4 +-
 arch/arm64/kernel/machine_kexec.c                  |   3 -
 arch/arm64/kernel/patch-scs.c                      |   4 +-
 arch/arm64/net/bpf_jit_comp.c                      |   4 +-
 arch/powerpc/kexec/file_load_64.c                  |   2 +-
 arch/powerpc/platforms/44x/warp.c                  |   2 +
 arch/riscv/net/bpf_jit.h                           |   6 -
 arch/riscv/net/bpf_jit_core.c                      |   7 -
 arch/s390/kvm/interrupt.c                          |   3 +-
 arch/s390/kvm/pci.c                                |   6 +-
 arch/s390/net/bpf_jit_comp.c                       |  39 +-
 arch/x86/kvm/trace.h                               |   2 +-
 block/blk-cgroup.c                                 |  16 +
 block/disk-events.c                                |   3 +-
 crypto/af_alg.c                                    |   2 +
 crypto/jitterentropy-kcapi.c                       |  14 +-
 drivers/acpi/acpi_cmos_rtc.c                       |  79 ++-
 drivers/acpi/arm64/agdi.c                          |   2 +-
 drivers/base/devres.c                              |   2 +
 drivers/base/power/domain.c                        |  10 +-
 drivers/block/drbd/drbd_nl.c                       |   8 +-
 drivers/bluetooth/hci_ldisc.c                      |   3 +
 drivers/cdrom/cdrom.c                              |  73 ++-
 drivers/char/ipmi/ssif_bmc.c                       |  34 +-
 drivers/clk/clk-qoriq.c                            |  17 +-
 drivers/clk/clk-xgene.c                            |   2 +
 drivers/clk/imx/clk-imx6q.c                        |  12 +-
 drivers/clk/imx/clk-imx8mq.c                       |   4 +-
 drivers/clk/qcom/dispcc-sc7180.c                   |   8 +
 drivers/clk/qcom/dispcc-sc8280xp.c                 |   4 -
 drivers/clk/qcom/dispcc-sm8250.c                   |   6 +-
 drivers/clk/qcom/dispcc-sm8450.c                   |   2 +-
 drivers/clk/qcom/gcc-sc8180x.c                     |  64 +-
 drivers/clk/visconti/pll.c                         |   2 +-
 drivers/crypto/atmel-aes.c                         | 237 +------
 drivers/crypto/atmel-sha.c                         |  27 +-
 drivers/crypto/atmel-tdes.c                        | 230 +------
 drivers/crypto/ccp/ccp-crypto-aes.c                |   7 +-
 .../intel/qat/qat_common/icp_qat_hw_20_comp.h      |  10 +-
 drivers/crypto/nx/nx-842.c                         |  37 +-
 drivers/crypto/nx/nx-842.h                         |  15 +-
 drivers/crypto/nx/nx-common-powernv.c              |  31 +-
 drivers/crypto/nx/nx-common-pseries.c              |  33 +-
 drivers/crypto/sa2ul.c                             |   4 +-
 drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c     |   2 -
 drivers/dma/mxs-dma.c                              |   1 +
 drivers/firmware/efi/capsule-loader.c              |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c     |   2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c            |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c            |  57 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c             |   2 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c              |  66 ++
 drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c             |   1 +
 drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c             |   2 +
 drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c             |   1 +
 drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c             |   1 +
 drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c           |   1 +
 drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c              |  16 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c              |   3 +-
 drivers/gpu/drm/amd/amdgpu/vce_v2_0.c              |   2 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c              |   2 +
 drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c              |   2 +
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c              |   3 +
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c            |   1 +
 drivers/gpu/drm/amd/display/dc/bios/bios_parser.c  |  62 ++
 .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c  |   4 +-
 .../amd/display/include/grph_object_ctrl_defs.h    |   4 +
 drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c     |  15 +
 .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c    | 118 +++-
 .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h    |   1 +
 drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h       |   1 +
 .../gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c    |  15 +-
 .../drm/arm/display/komeda/komeda_framebuffer.c    |   6 +-
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.c    |  72 ++-
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.h    |   1 +
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c    |  18 +-
 drivers/gpu/drm/gma500/oaktrail_hdmi.c             |   1 +
 drivers/gpu/drm/gma500/oaktrail_lvds.c             |   9 +-
 drivers/gpu/drm/i915/display/intel_dp.c            |   9 +-
 .../gpu/drm/i915/display/intel_modeset_verify.c    |   2 +-
 drivers/gpu/drm/i915/display/skl_watermark.c       |  49 +-
 drivers/gpu/drm/i915/display/skl_watermark.h       |   4 +-
 drivers/gpu/drm/i915/gt/intel_reset.c              |   3 +-
 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c        |   2 +-
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c              |  14 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c            |   2 -
 drivers/gpu/drm/msm/dsi/dsi_cfg.c                  |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h                  |   2 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c                 |   1 +
 drivers/gpu/drm/msm/msm_gem_shrinker.c             |   5 +-
 drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c    |   1 +
 drivers/gpu/drm/panel/panel-simple.c               |   2 +-
 drivers/gpu/drm/panfrost/panfrost_drv.c            |   2 +
 drivers/gpu/drm/sun4i/sun4i_backend.c              |   6 +-
 drivers/gpu/drm/tiny/ofdrm.c                       |   2 +
 drivers/gpu/drm/v3d/v3d_gem.c                      |   5 +
 drivers/hid/hid-asus.c                             |  28 +-
 drivers/hid/usbhid/hid-core.c                      |   2 +-
 drivers/i3c/master.c                               |  32 +-
 drivers/i3c/master/mipi-i3c-hci/dma.c              |   5 +-
 drivers/infiniband/core/iwpm_msg.c                 |   6 +-
 drivers/infiniband/hw/mana/qp.c                    |   7 +-
 drivers/iommu/intel/iommu.c                        |   3 +
 drivers/iommu/iommufd/vfio_compat.c                |   2 +-
 drivers/irqchip/irq-pic32-evic.c                   |   2 +-
 drivers/leds/blink/leds-lgm-sso.c                  |   2 -
 drivers/mailbox/mailbox-test.c                     |  39 +-
 drivers/mailbox/mailbox.c                          |   3 +-
 drivers/md/dm-cache-metadata.c                     |  24 +-
 drivers/md/dm-cache-metadata.h                     |   5 -
 drivers/md/dm-cache-policy-smq.c                   |   4 +
 drivers/md/dm-cache-target.c                       | 143 +++-
 drivers/md/dm-init.c                               |   4 +-
 drivers/md/dm-log.c                                |   6 +-
 .../media/platform/nxp/imx8-isi/imx8-isi-video.c   |   2 +-
 drivers/memory/tegra/tegra124-emc.c                |   2 +-
 drivers/memory/tegra/tegra30-emc.c                 |   6 +-
 drivers/mfd/mc13xxx-core.c                         |   2 +-
 drivers/mtd/maps/physmap-gemini.c                  |   2 +-
 drivers/mtd/nand/raw/sunxi_nand.c                  |   6 +-
 drivers/mtd/parsers/ofpart_core.c                  |   4 +-
 drivers/mtd/spi-nor/core.c                         |   2 +-
 drivers/mtd/spi-nor/core.h                         |   8 +-
 drivers/mtd/spi-nor/sfdp.c                         |  30 +-
 drivers/mtd/spi-nor/swp.c                          |   4 +-
 drivers/net/bareudp.c                              |  24 +-
 drivers/net/bonding/bond_3ad.c                     | 123 ++--
 drivers/net/bonding/bond_main.c                    |  74 ++-
 drivers/net/bonding/bond_netlink.c                 |  37 +-
 drivers/net/bonding/bond_options.c                 |  71 ++
 drivers/net/bonding/bond_procfs.c                  |   3 +-
 drivers/net/bonding/bond_sysfs_slave.c             |  17 +-
 drivers/net/dsa/realtek/rtl8365mb.c                |   2 +-
 .../net/ethernet/aquantia/atlantic/aq_pci_func.c   |   2 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet.c     | 718 +++++++++------------
 drivers/net/ethernet/broadcom/genet/bcmgenet.h     |  68 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c |   4 +-
 drivers/net/ethernet/broadcom/genet/bcmmii.c       |   6 +-
 drivers/net/ethernet/freescale/Makefile            |   3 +-
 drivers/net/ethernet/freescale/dpaa2/Kconfig       |   4 +
 drivers/net/ethernet/intel/e1000e/netdev.c         |   1 +
 drivers/net/ethernet/intel/i40e/i40e.h             |   1 +
 drivers/net/ethernet/intel/i40e/i40e_main.c        |   2 +-
 drivers/net/ethernet/intel/i40e/i40e_ptp.c         |   3 +-
 drivers/net/ethernet/intel/iavf/iavf.h             |   9 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c        |  52 +-
 drivers/net/ethernet/intel/iavf/iavf_virtchnl.c    |  76 ++-
 drivers/net/ethernet/intel/ice/ice_txrx.c          |   7 +-
 drivers/net/ethernet/intel/ice/ice_vf_lib.c        |   7 +-
 .../mellanox/mlx5/core/en_accel/ipsec_offload.c    |  12 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |   8 +
 .../ethernet/netronome/nfp/nfpcore/nfp_target.c    |  17 +-
 drivers/net/ethernet/sfc/efx_devlink.c             |   2 +-
 drivers/net/hamradio/6pack.c                       |  39 +-
 drivers/net/ipa/gsi.c                              |   1 +
 drivers/net/ipa/ipa_main.c                         |   6 +-
 drivers/net/macvlan.c                              |   9 +-
 drivers/net/mctp/mctp-i2c.c                        |   4 +-
 drivers/net/netconsole.c                           |  26 +-
 drivers/net/netdevsim/dev.c                        |   2 +-
 drivers/net/phy/Kconfig                            |  20 +-
 drivers/net/phy/Makefile                           |  12 +-
 drivers/net/phy/aquantia/Kconfig                   |   5 +
 drivers/net/phy/aquantia/Makefile                  |   6 +
 drivers/net/phy/{ => aquantia}/aquantia.h          |   0
 drivers/net/phy/{ => aquantia}/aquantia_hwmon.c    |   0
 drivers/net/phy/{ => aquantia}/aquantia_main.c     |   0
 drivers/net/phy/ax88796b_rust.rs                   | 135 ++++
 drivers/net/phy/dp83869.c                          |  13 +-
 drivers/net/phy/qcom/Kconfig                       |   7 +
 drivers/net/phy/qcom/Makefile                      |   2 +
 drivers/net/phy/{ => qcom}/at803x.c                |   2 +-
 drivers/net/ppp/ppp_generic.c                      |   5 +-
 drivers/net/ppp/pppoe.c                            |   8 +-
 drivers/net/slip/slhc.c                            |  49 +-
 drivers/net/usb/r8152.c                            |   2 +-
 drivers/net/usb/rtl8150.c                          |  12 +-
 drivers/net/vrf.c                                  |  15 +-
 .../wireless/broadcom/brcm80211/brcmfmac/chip.c    |  15 +
 drivers/net/wireless/marvell/mwifiex/11n_aggr.c    |   1 +
 drivers/net/wireless/mediatek/mt76/mt7615/mac.c    |  15 -
 drivers/net/wireless/mediatek/mt76/mt7615/main.c   |   7 +-
 drivers/net/wireless/mediatek/mt76/mt7615/mcu.c    |  47 ++
 drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h |   5 +-
 drivers/net/wireless/mediatek/mt76/mt7615/regs.h   |   2 -
 .../net/wireless/mediatek/mt76/mt76_connac_mac.c   |   6 +-
 drivers/net/wireless/mediatek/mt76/mt7915/init.c   |   1 +
 drivers/net/wireless/mediatek/mt76/mt7915/mac.c    |  13 -
 drivers/net/wireless/mediatek/mt76/mt7915/main.c   |   7 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mcu.c    |  62 ++
 drivers/net/wireless/mediatek/mt76/mt7915/mcu.h    |  11 +
 drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h |   4 +
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c    |   2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c    |   2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h    |   4 +-
 drivers/net/wireless/realtek/rtlwifi/pci.c         |   1 +
 drivers/net/wireless/realtek/rtw89/phy.c           |   2 +-
 drivers/nfc/trf7970a.c                             |   3 +-
 drivers/nvme/host/pci.c                            |   1 +
 drivers/nvme/target/tcp.c                          |  51 +-
 drivers/pci/controller/dwc/pcie-designware.c       |  16 +-
 drivers/pci/controller/dwc/pcie-designware.h       |   2 +
 drivers/pci/controller/dwc/pcie-tegra194.c         | 155 +++--
 drivers/pci/controller/pcie-mediatek-gen3.c        |   8 +-
 drivers/pci/pci.c                                  |  41 +-
 drivers/pcmcia/rsrc_nonstatic.c                    |   6 +-
 drivers/pinctrl/nomadik/pinctrl-abx500.c           |   2 +-
 drivers/pinctrl/pinctrl-cy8c95x0.c                 |  27 +-
 drivers/pinctrl/pinctrl-pic32.c                    |  20 +-
 drivers/platform/chrome/chromeos_tbmc.c            |   6 +
 drivers/platform/surface/surfacepro3_button.c      |   1 +
 .../x86/dell/dell-wmi-sysman/enum-attributes.c     |  34 +-
 drivers/platform/x86/dell/dell_rbu.c               |   6 +-
 drivers/platform/x86/panasonic-laptop.c            |   5 +-
 drivers/pmdomain/imx/scu-pd.c                      |   1 +
 drivers/pmdomain/ti/omap_prm.c                     |   1 +
 drivers/rtc/rtc-abx80x.c                           |   2 +
 drivers/s390/cio/chsc.c                            |  18 +-
 drivers/s390/cio/chsc_sch.c                        |   6 +-
 drivers/s390/cio/cio.c                             |   6 +-
 drivers/s390/cio/cio.h                             |   7 +-
 drivers/s390/cio/css.c                             |  82 +--
 drivers/s390/cio/device.c                          |  66 +-
 drivers/s390/cio/device_pgid.c                     |  12 +-
 drivers/s390/cio/eadm_sch.c                        |  36 +-
 drivers/s390/cio/vfio_ccw_drv.c                    |   8 +-
 drivers/s390/cio/vfio_ccw_fsm.c                    |  24 +-
 drivers/scsi/sg.c                                  |  49 +-
 drivers/scsi/sr.c                                  |  11 +-
 drivers/scsi/sr.h                                  |   1 -
 drivers/soc/qcom/llcc-qcom.c                       |   2 +-
 drivers/soc/qcom/ocmem.c                           |  24 +-
 drivers/soc/qcom/qcom_aoss.c                       |   2 +-
 drivers/soc/tegra/cbb/tegra234-cbb.c               |   4 +
 drivers/soundwire/bus.c                            |   8 +-
 drivers/soundwire/cadence_master.c                 |   8 +
 drivers/spi/spi-fsl-qspi.c                         |   3 +-
 drivers/spi/spi-hisi-kunpeng.c                     |  12 +-
 drivers/spi/spi-mtk-snfi.c                         |  14 +
 drivers/spi/spi-rockchip.c                         |   3 +-
 drivers/spi/spi-sifive.c                           |  29 +-
 drivers/spi/spi-st-ssc4.c                          |  76 ++-
 drivers/target/target_core_sbc.c                   |   3 +-
 drivers/thermal/spear_thermal.c                    |   2 +-
 drivers/tty/hvc/hvc_iucv.c                         |   2 +-
 drivers/vhost/net.c                                |   4 +-
 drivers/video/backlight/sky81452-backlight.c       |   3 +
 drivers/video/fbdev/matrox/g450_pll.c              |   2 +-
 drivers/video/fbdev/offb.c                         |   7 +-
 fs/adfs/super.c                                    |   3 +
 fs/btrfs/inode.c                                   |  36 +-
 fs/btrfs/space-info.c                              |   8 +-
 fs/btrfs/sysfs.c                                   |   5 +-
 fs/btrfs/sysfs.h                                   |   3 +-
 fs/ceph/xattr.c                                    |   1 +
 fs/debugfs/file.c                                  |   7 +-
 fs/f2fs/f2fs.h                                     |   3 +
 fs/f2fs/inline.c                                   |  13 +-
 fs/f2fs/super.c                                    |  11 +
 fs/f2fs/sysfs.c                                    |  52 +-
 fs/gfs2/inode.c                                    |   3 +-
 fs/gfs2/log.c                                      |  33 +-
 fs/netfs/iterator.c                                |  13 +-
 fs/nfs/blocklayout/blocklayout.c                   |   4 +-
 fs/nilfs2/ioctl.c                                  |   6 +
 fs/ntfs3/dir.c                                     |   5 +-
 fs/ntfs3/fsntfs.c                                  |   4 +-
 fs/ntfs3/inode.c                                   |  13 +-
 fs/ntfs3/namei.c                                   |  17 +-
 fs/ntfs3/super.c                                   |   7 +-
 fs/ntfs3/xattr.c                                   |   5 +-
 fs/ocfs2/dlm/dlmdomain.c                           |  10 +-
 fs/ocfs2/ioctl.c                                   |  18 +-
 fs/ocfs2/resize.c                                  |  12 +-
 fs/ocfs2/xattr.c                                   |   4 +-
 fs/omfs/inode.c                                    |   6 +
 fs/pstore/ram_core.c                               |   4 +
 fs/quota/dquot.c                                   |  38 +-
 fs/smb/client/ioctl.c                              |   2 +-
 fs/smb/client/smb2file.c                           |  27 +-
 fs/smb/client/smb2pdu.h                            |   2 +-
 fs/smb/client/smb2transport.c                      |  32 +-
 fs/smb/server/auth.c                               |  17 +-
 fs/smb/server/connection.c                         |   9 +
 fs/smb/server/ksmbd_netlink.h                      |  17 +
 fs/smb/server/mgmt/user_config.c                   |  39 +-
 fs/smb/server/mgmt/user_config.h                   |   5 +-
 fs/smb/server/mgmt/user_session.c                  |  12 +-
 fs/smb/server/smb2pdu.c                            |   2 +
 fs/smb/server/smb_common.c                         |  15 +-
 fs/smb/server/smbacl.c                             |  66 +-
 fs/smb/server/transport_ipc.c                      |  80 ++-
 fs/smb/server/transport_ipc.h                      |   2 +
 fs/smb/server/transport_rdma.c                     |   4 +-
 fs/tracefs/event_inode.c                           |   2 +-
 include/dt-bindings/clock/qcom,dispcc-sc7180.h     |   7 +-
 include/dt-bindings/clock/qcom,gcc-sc8180x.h       |   5 +
 include/linux/cdrom.h                              |   1 +
 include/linux/cpuhotplug.h                         |   1 -
 include/linux/dev_printk.h                         |   8 +
 include/linux/dmi.h                                |   5 +
 include/linux/moduleparam.h                        |  11 +-
 include/linux/padata.h                             |   8 +-
 include/linux/ppp_defs.h                           |  16 +
 include/linux/printk.h                             |   5 +-
 include/linux/quotaops.h                           |   9 +-
 include/linux/spinlock_up.h                        |  20 +-
 include/net/bond_3ad.h                             |   3 +-
 include/net/bond_options.h                         |   2 +
 include/net/bonding.h                              |   3 +
 include/net/ipv6.h                                 |   6 -
 include/net/pie.h                                  |   2 +-
 include/net/route.h                                |   6 -
 include/net/udp_tunnel.h                           |  15 +
 include/trace/events/timer.h                       |  11 +-
 include/uapi/linux/bpf.h                           |   2 +
 include/uapi/linux/if_link.h                       |   3 +
 include/uapi/linux/mii.h                           |   3 +-
 io_uring/io-wq.c                                   |   3 +-
 kernel/audit.c                                     |   4 +
 kernel/auditsc.c                                   |   2 +-
 kernel/bpf/arraymap.c                              |   4 +-
 kernel/bpf/bpf_lsm.c                               |   1 -
 kernel/bpf/core.c                                  |   2 +
 kernel/bpf/devmap.c                                |   8 +-
 kernel/bpf/hashtab.c                               |   2 +-
 kernel/bpf/helpers.c                               |  17 +-
 kernel/bpf/local_storage.c                         |   2 +-
 kernel/bpf/verifier.c                              |   5 +-
 kernel/cgroup/cgroup.c                             |  24 +-
 kernel/cgroup/rdma.c                               |   2 +-
 kernel/fork.c                                      |  11 +-
 kernel/futex/requeue.c                             |  13 +-
 kernel/module/main.c                               |   4 +-
 kernel/padata.c                                    | 130 ++--
 kernel/params.c                                    |  42 +-
 kernel/time/hrtimer.c                              |  56 +-
 kernel/trace/trace_branch.c                        |   8 +-
 kernel/trace/trace_events_hist.c                   |  12 +-
 kernel/workqueue.c                                 |   4 +-
 net/bluetooth/hci_event.c                          |   3 -
 net/bluetooth/l2cap_core.c                         |   8 +-
 net/bpf/test_run.c                                 |  63 +-
 net/ceph/crush/crush.c                             |   6 +-
 net/ceph/osdmap.c                                  |  14 +-
 net/core/filter.c                                  |   4 +-
 net/core/neighbour.c                               |  34 +-
 net/ipv4/netfilter/arp_tables.c                    |  18 +-
 net/ipv4/netfilter/arpt_mangle.c                   |   8 +
 net/ipv4/nexthop.c                                 |   4 +-
 net/ipv4/route.c                                   |  48 --
 net/ipv4/tcp.c                                     |  18 +-
 net/ipv4/tcp_input.c                               |   2 +-
 net/ipv4/tcp_output.c                              |  13 +-
 net/ipv4/tcp_plb.c                                 |   2 +-
 net/ipv4/udp_tunnel_core.c                         |  48 ++
 net/ipv6/icmp.c                                    |  10 +-
 net/ipv6/ip6_output.c                              |  68 --
 net/ipv6/ip6_udp_tunnel.c                          |  69 ++
 net/mptcp/fastopen.c                               |  28 +-
 net/mptcp/pm_netlink.c                             |  26 +-
 net/mptcp/protocol.c                               |   4 +-
 net/mptcp/protocol.h                               |   5 +-
 net/mptcp/subflow.c                                |   3 -
 net/netfilter/ipvs/ip_vs_xmit.c                    |  19 +-
 net/netfilter/nf_conntrack_proto_sctp.c            |  10 +-
 net/netfilter/nf_conntrack_sip.c                   | 160 +++--
 net/netfilter/nf_nat_amanda.c                      |   2 +-
 net/netfilter/nf_nat_sip.c                         |  34 +-
 net/netfilter/nf_tables_api.c                      |  28 +-
 net/netfilter/nfnetlink_osf.c                      |  45 +-
 net/netfilter/nft_ct.c                             |   2 +
 net/netfilter/nft_fwd_netdev.c                     |  10 +
 net/netfilter/nft_osf.c                            |   6 +-
 net/netfilter/xt_mac.c                             |  34 +-
 net/netfilter/xt_owner.c                           |  37 +-
 net/netfilter/xt_physdev.c                         |  29 +-
 net/netfilter/xt_policy.c                          |   2 +-
 net/netfilter/xt_realm.c                           |   2 +-
 net/netfilter/xt_socket.c                          |  23 +-
 net/openvswitch/datapath.c                         |  35 +-
 net/openvswitch/vport.c                            |   3 +
 net/rds/af_rds.c                                   |  10 +-
 net/rds/connection.c                               |  14 +
 net/rds/ib.c                                       |  24 +-
 net/rds/ib.h                                       |   1 +
 net/rds/ib_rdma.c                                  |   2 +-
 net/sched/act_ct.c                                 |   8 +-
 net/sched/sch_cake.c                               |  15 +-
 net/sched/sch_choke.c                              |  26 +-
 net/sched/sch_fq_codel.c                           |   3 +-
 net/sched/sch_fq_pie.c                             |  19 +-
 net/sched/sch_hhf.c                                |  19 +-
 net/sched/sch_netem.c                              |  76 ++-
 net/sched/sch_pie.c                                |  52 +-
 net/sched/sch_red.c                                |  31 +-
 net/sched/sch_sfb.c                                |  54 +-
 net/sched/sch_taprio.c                             |  22 +-
 net/sctp/inqueue.c                                 |   1 +
 net/sctp/sm_statefuns.c                            |   6 +
 net/sctp/socket.c                                  |   2 +-
 net/tipc/msg.c                                     |  14 +-
 net/tls/tls.h                                      |   1 +
 net/tls/tls_strp.c                                 |   6 +
 net/tls/tls_sw.c                                   |   4 +
 net/unix/af_unix.c                                 |   9 +-
 net/unix/unix_bpf.c                                |   3 +
 rust/uapi/uapi_helper.h                            |   2 +
 security/integrity/ima/ima_crypto.c                |   2 +-
 sound/core/compress_offload.c                      |   7 -
 sound/core/sound.c                                 |   7 +
 sound/isa/sc6000.c                                 | 285 ++++----
 sound/pci/hda/patch_conexant.c                     |  34 +-
 sound/pci/hda/patch_realtek.c                      |   4 +-
 sound/soc/codecs/ab8500-codec.c                    |   6 +-
 sound/soc/fsl/fsl_easrc.c                          | 123 +++-
 sound/soc/fsl/fsl_micfil.c                         |  60 +-
 sound/soc/fsl/fsl_xcvr.c                           |  22 +-
 sound/soc/qcom/qdsp6/topology.c                    |   8 +-
 sound/soc/sh/rcar/core.c                           |   2 +-
 sound/soc/sof/compress.c                           |   8 +-
 sound/soc/sof/intel/hda-dai.c                      |  29 +-
 sound/soc/sof/intel/hda-stream.c                   |  10 +-
 sound/soc/sof/sof-priv.h                           |   2 +
 sound/soc/sti/uniperif_player.c                    |   9 +-
 sound/usb/midi.c                                   |  12 +-
 sound/usb/midi2.c                                  |  12 +-
 sound/usb/mixer_scarlett2.c                        |   2 +-
 sound/usb/quirks.c                                 |   2 +-
 sound/usb/stream.c                                 |  58 +-
 sound/usb/stream.h                                 |   3 +-
 tools/include/uapi/linux/bpf.h                     |   2 +
 tools/lib/bpf/relo_core.c                          |   2 +
 tools/perf/builtin-lock.c                          |   2 +-
 tools/perf/util/branch.h                           |   3 +
 tools/perf/util/cs-etm-decoder/cs-etm-decoder.c    |  51 +-
 tools/perf/util/expr.c                             |   3 +-
 tools/perf/util/symbol-elf.c                       |   8 +-
 tools/perf/util/util.h                             |   1 -
 tools/testing/ktest/ktest.pl                       |  35 +-
 tools/testing/selftests/bpf/prog_tests/snprintf.c  |   3 +-
 tools/testing/selftests/cgroup/test_memcontrol.c   |  11 +-
 tools/testing/selftests/mm/migration.c             |   3 +-
 .../testing/selftests/powerpc/benchmarks/Makefile  |   4 +-
 tools/testing/selftests/powerpc/copyloops/Makefile |  20 +-
 tools/testing/selftests/powerpc/nx-gzip/Makefile   |   4 +-
 tools/testing/selftests/powerpc/pmu/ebb/Makefile   |  20 +-
 .../powerpc/pmu/event_code_tests/Makefile          |   4 +-
 .../selftests/powerpc/pmu/sampling_tests/Makefile  |   4 +-
 .../testing/selftests/powerpc/primitives/Makefile  |   4 +-
 tools/testing/selftests/powerpc/security/Makefile  |   4 +-
 tools/testing/selftests/powerpc/signal/Makefile    |   3 +-
 .../testing/selftests/powerpc/stringloops/Makefile |  10 +-
 .../selftests/powerpc/switch_endian/Makefile       |   4 +-
 tools/testing/selftests/powerpc/syscalls/Makefile  |   4 +-
 tools/testing/selftests/powerpc/vphn/Makefile      |   4 +-
 virt/kvm/dirty_ring.c                              |   3 +-
 492 files changed, 5183 insertions(+), 3404 deletions(-)
author maintainer
#1 lore raw

PATCH 1/508 blk-cgroup: wait for blkcg cleanup before initializing new disk

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming Lei <[email protected]>

[ Upstream commit 3dbaacf6ab68f81e3375fe769a2ecdbd3ce386fd ]

When a queue is shared across disk rebind (e.g., SCSI unbind/bind), the previous disk's blkcg state is cleaned up asynchronously via disk_release() -> blkcg_exit_disk(). If the new disk's blkcg_init_disk() runs before that cleanup finishes, we may overwrite q->root_blkg while the old one is still alive, and radix_tree_insert() in blkg_create() fails with -EEXIST because the old blkg entries still occupy the same queue id slot in blkcg->blkg_tree. This causes the sd probe to fail with -ENOMEM.

Fix it by waiting in blkcg_init_disk() for root_blkg to become NULL, which indicates the previous disk's blkcg cleanup has completed.

Fixes 1059699f87eb ("block: move blkcg initialization/destroy into disk allocation/release handler")
Cc Yi Zhang <[email protected]>
---
 block/blk-cgroup.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
block/blk-cgroup.c +15 -0
index 75e9d5a9d707c..40c9d5805b88b 100644
@@ -24,6 +24,7 @@
 #include <linux/backing-dev.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/wait_bit.h>
 #include <linux/atomic.h>
 #include <linux/ctype.h>
 #include <linux/resume_user_mode.h>
@@ -618,6 +619,8 @@ static void blkg_destroy_all(struct gendisk *disk)
 
 	q->root_blkg = NULL;
 	spin_unlock_irq(&q->queue_lock);
+
+	wake_up_var(&q->root_blkg);
 }
 
 static void blkg_iostat_set(struct blkg_iostat *dst, struct blkg_iostat *src)
@@ -1459,6 +1462,18 @@ int blkcg_init_disk(struct gendisk *disk)
 	bool preloaded;
 	int ret;
 
+	/*
+	 * If the queue is shared across disk rebind (e.g., SCSI), the
+	 * previous disk's blkcg state is cleaned up asynchronously via
+	 * disk_release() -> blkcg_exit_disk(). Wait for that cleanup to
+	 * finish (indicated by root_blkg becoming NULL) before setting up
+	 * new blkcg state. Otherwise, we may overwrite q->root_blkg while
+	 * the old one is still alive, and radix_tree_insert() in
+	 * blkg_create() will fail with -EEXIST because the old entries
+	 * still occupy the same queue id slot in blkcg->blkg_tree.
+	 */
+	wait_var_event(&q->root_blkg, !READ_ONCE(q->root_blkg));
+
 	new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
 	if (!new_blkg)
 		return -ENOMEM;
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/508 fs/omfs: reject s_sys_blocksize smaller than OMFS_DIR_START

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: HyungJung Joo <[email protected]>

[ Upstream commit 0621c385fda1376e967f37ccd534c26c3e511d14 ]

omfs_fill_super() rejects oversized s_sys_blocksize values (> PAGE_SIZE), but it does not reject values smaller than OMFS_DIR_START (0x1b8 = 440).

Later, omfs_make_empty() uses

    sbi->s_sys_blocksize - OMFS_DIR_START

as the length argument to memset(). Since s_sys_blocksize is u32, a crafted filesystem image with s_sys_blocksize < OMFS_DIR_START causes an unsigned underflow there, wrapping to a value near 2^32. That drives a ~4 GiB memset() from bh->b_data + OMFS_DIR_START and overwrites kernel memory far beyond the backing block buffer.

Add the corresponding lower-bound check alongside the existing upper-bound check in omfs_fill_super(), so that malformed images are rejected during superblock validation before any filesystem data is processed.

---
 fs/omfs/inode.c | 6 ++++++
 1 file changed, 6 insertions(+)
fs/omfs/inode.c +6 -0
index 2f8c1882f45c8..60ef691aeb702 100644
@@ -514,6 +514,12 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
 		goto out_brelse_bh;
 	}
 
+	if (sbi->s_sys_blocksize < OMFS_DIR_START) {
+		printk(KERN_ERR "omfs: sysblock size (%d) is too small\n",
+			sbi->s_sys_blocksize);
+		goto out_brelse_bh;
+	}
+
 	if (sbi->s_blocksize < sbi->s_sys_blocksize ||
 	    sbi->s_blocksize > OMFS_MAX_BLOCK_SIZE) {
 		printk(KERN_ERR "omfs: block size (%d) is out of range\n",
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/508 drbd: Balance RCU calls in drbd_adm_dump_devices()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bart Van Assche <[email protected]>

[ Upstream commit 2b31e86387e60b3689339f0f0fbb4d3623d9d494 ]

Make drbd_adm_dump_devices() call rcu_read_lock() before rcu_read_unlock() is called. This has been detected by the Clang thread-safety analyzer.

---
 drivers/block/drbd/drbd_nl.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/block/drbd/drbd_nl.c +6 -2
index d3538bd83fb3b..1ba81a5e77215 100644
@@ -3368,8 +3368,10 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb)
 		if (resource_filter) {
 			retcode = ERR_RES_NOT_KNOWN;
 			resource = drbd_find_resource(nla_data(resource_filter));
-			if (!resource)
+			if (!resource) {
+				rcu_read_lock();
 				goto put_result;
+			}
 			cb->args[0] = (long)resource;
 		}
 	}
@@ -3618,8 +3620,10 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb)
 		if (resource_filter) {
 			retcode = ERR_RES_NOT_KNOWN;
 			resource = drbd_find_resource(nla_data(resource_filter));
-			if (!resource)
+			if (!resource) {
+				rcu_read_lock();
 				goto put_result;
+			}
 		}
 		cb->args[0] = (long)resource;
 	}
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/508 loop: fix partition scan race between udev and loop_reread_partitions()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daan De Meyer <[email protected]>

[ Upstream commit 267ec4d7223a783f029a980f41b93c39b17996da ]

When LOOP_CONFIGURE is called with LO_FLAGS_PARTSCAN, the following sequence occurs:

1. disk_force_media_change() sets GD_NEED_PART_SCAN
2. Uevent suppression is lifted and a KOBJ_CHANGE uevent is sent
3. loop_global_unlock() releases the lock
4. loop_reread_partitions() calls bdev_disk_changed() to scan

There is a race between steps 2 and 4: when udev receives the uevent and opens the device before loop_reread_partitions() runs, blkdev_get_whole() in bdev.c sees GD_NEED_PART_SCAN set and calls bdev_disk_changed() for a first scan. Then loop_reread_partitions() does a second scan. The open_mutex serializes these two scans, but does not prevent both from running.

The second scan in bdev_disk_changed() drops all partition devices from the first scan (via blk_drop_partitions()) before re-adding them, causing partition block devices to briefly disappear. This breaks any systemd unit with BindsTo= on the partition device: systemd observes the device going dead, fails the dependent units, and does not retry them when the device reappears.

Fix this by removing the GD_NEED_PART_SCAN set from disk_force_media_change() entirely. None of the current callers need the lazy on-open partition scan triggered by this flag:

- floppy: sets GENHD_FL_NO_PART, so disk_has_partscan() is always false and GD_NEED_PART_SCAN has no effect.
- loop (loop_configure, loop_change_fd): when LO_FLAGS_PARTSCAN is set, loop_reread_partitions() performs an explicit scan. When not set, GD_SUPPRESS_PART_SCAN prevents the lazy scan path.
- loop (__loop_clr_fd): calls bdev_disk_changed() explicitly if LO_FLAGS_PARTSCAN is set.
- nbd (nbd_clear_sock_ioctl): capacity is set to zero immediately after; nbd manages GD_NEED_PART_SCAN explicitly elsewhere.

With GD_NEED_PART_SCAN no longer set by disk_force_media_change(), udev opening the loop device after the uevent no longer triggers a redundant scan in blkdev_get_whole(), and only the single explicit scan from loop_reread_partitions() runs.

A regression test for this bug has been submitted to blktests:
https://github.com/linux-blktests/blktests/pull/240.

---
 block/disk-events.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
block/disk-events.c +2 -1
index 13c3372c465a3..6987e4dd8d417 100644
@@ -294,13 +294,14 @@ EXPORT_SYMBOL(disk_check_media_change);
  * Should be called when the media changes for @disk.  Generates a uevent
  * and attempts to free all dentries and inodes and invalidates all block
  * device page cache entries in that case.
+ *
+ * Callers that need a partition re-scan should arrange for one explicitly.
  */
 void disk_force_media_change(struct gendisk *disk)
 {
 	disk_event_uevent(disk, DISK_EVENT_MEDIA_CHANGE);
 	inc_diskseq(disk);
 	bdev_mark_dead(disk->part0, true);
-	set_bit(GD_NEED_PART_SCAN, &disk->state);
 }
 EXPORT_SYMBOL_GPL(disk_force_media_change);
 
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/508 nilfs2: reject zero bd_oblocknr in nilfs_ioctl_mark_blocks_dirty()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Deepanshu Kartikey <[email protected]>

[ Upstream commit be3e5d10643d3be1cbac9d9939f220a99253f980 ]

nilfs_ioctl_mark_blocks_dirty() uses bd_oblocknr to detect dead blocks by comparing it with the current block number bd_blocknr. If they differ, the block is considered dead and skipped.

However, bd_oblocknr should never be 0 since block 0 typically stores the primary superblock and is never a valid GC target block. A corrupted ioctl request with bd_oblocknr set to 0 causes the comparison to incorrectly match when the lookup returns -ENOENT and sets bd_blocknr to 0, bypassing the dead block check and calling nilfs_bmap_mark() on a non-existent block. This causes nilfs_btree_do_lookup() to return -ENOENT, triggering the WARN_ON(ret == -ENOENT).

Fix this by rejecting ioctl requests with bd_oblocknr set to 0 at the beginning of each iteration.

[ryusuke: slightly modified the commit message and comments for accuracy]

---
 fs/nilfs2/ioctl.c | 6 ++++++
 1 file changed, 6 insertions(+)
fs/nilfs2/ioctl.c +6 -0
index 53022bfe0b72d..1a6868afa9143 100644
@@ -751,6 +751,12 @@ static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
 	int ret, i;
 
 	for (i = 0; i < nmembs; i++) {
+		/*
+		 * bd_oblocknr must never be 0 as block 0
+		 * is never a valid GC target block
+		 */
+		if (unlikely(!bdescs[i].bd_oblocknr))
+			return -EINVAL;
 		/* XXX: use macro or inline func to check liveness */
 		ret = nilfs_bmap_lookup_at_level(bmap,
 						 bdescs[i].bd_offset,
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/508 blk-cgroup: fix disk reference leak in blkcg_maybe_throttle_current()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jackie Liu <[email protected]>

[ Upstream commit 23308af722fefed00af5f238024c11710938fba3 ]

Add the missing put_disk() on the error path in blkcg_maybe_throttle_current(). When blkcg lookup, blkg lookup, or blkg_tryget() fails, the function jumps to the out label which only calls rcu_read_unlock() but does not release the disk reference acquired by blkcg_schedule_throttle() via get_device(). Since current->throttle_disk is already set to NULL before the lookup, blkcg_exit() cannot release this reference either, causing the disk to never be freed.

Restore the reference release that was present as blk_put_queue() in the original code but was inadvertently dropped during the conversion from request_queue to gendisk.

Fixes f05837ed73d0 ("blk-cgroup: store a gendisk to throttle in struct task_struct")
---
 block/blk-cgroup.c | 1 +
 1 file changed, 1 insertion(+)
block/blk-cgroup.c +1 -0
index 40c9d5805b88b..4ac2f53e7f51f 100644
@@ -1993,6 +1993,7 @@ void blkcg_maybe_throttle_current(void)
 	return;
 out:
 	rcu_read_unlock();
+	put_disk(disk);
 }
 
 /**
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/508 pstore/ram: fix resource leak when ioremap() fails

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cole Leavitt <[email protected]>

[ Upstream commit 2ddb69f686ef7a621645e97fc7329c50edf5d0e5 ]

In persistent_ram_iomap(), ioremap() or ioremap_wc() may return NULL on failure. Currently, if this happens, the function returns NULL without releasing the memory region acquired by request_mem_region().

This leads to a resource leak where the memory region remains reserved but unusable.

Additionally, the caller persistent_ram_buffer_map() handles NULL correctly by returning -ENOMEM, but without this check, a NULL return combined with request_mem_region() succeeding leaves resources in an inconsistent state.

This is the ioremap() counterpart to commit 05363abc7625 ("pstore:
ram_core: fix incorrect success return when vmap() fails") which fixed a similar issue in the vmap() path.

Fixes 404a6043385d ("staging: android: persistent_ram: handle reserving and mapping memory")
---
 fs/pstore/ram_core.c | 4 ++++
 1 file changed, 4 insertions(+)
fs/pstore/ram_core.c +4 -0
index 7b6d6378a3b87..95675d4bab141 100644
@@ -489,6 +489,10 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size,
 	else
 		va = ioremap_wc(start, size);
 
+	/* We must release the mem region if ioremap fails. */
+	if (!va)
+		release_mem_region(start, size);
+
 	/*
 	 * Since request_mem_region() and ioremap() are byte-granularity
 	 * there is no need handle anything special like we do when the
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/508 ACPI: x86: cmos_rtc: Clean up address space handler driver

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rafael J. Wysocki <[email protected]>

[ Upstream commit ba0b236736dde4059bdcb8e99beaa50d6e5b6e7e ]

Make multiple changes that do not alter functionality to the CMOS RTC ACPI address space handler driver, including the following:

- Drop the unused .detach() callback from cmos_rtc_handler.

- Rename acpi_cmos_rtc_attach_handler() to acpi_cmos_rtc_attach().

- Rearrange acpi_cmos_rtc_space_handler() to reduce the number of redundant checks and make white space follow the coding style.

- Adjust an error message in acpi_install_cmos_rtc_space_handler() and make the white space follow the coding style.

- Rearrange acpi_remove_cmos_rtc_space_handler() and adjust an error message in it.

No intentional functional impact.

Stable-dep-of: 6cee29ad9d7e ("ACPI: x86: cmos_rtc: Improve coordination with ACPI TAD driver")

---
 drivers/acpi/acpi_cmos_rtc.c | 61 +++++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 29 deletions(-)
drivers/acpi/acpi_cmos_rtc.c +32 -29
index 9b55d1593d160..65e89e23c5c84 100644
@@ -24,31 +24,35 @@ static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
 	{}
 };
 
-static acpi_status
-acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
-		      u32 bits, u64 *value64,
-		      void *handler_context, void *region_context)
+static acpi_status acpi_cmos_rtc_space_handler(u32 function,
+					       acpi_physical_address address,
+					       u32 bits, u64 *value64,
+					       void *handler_context,
+					       void *region_context)
 {
-	int i;
+	unsigned int i, bytes = DIV_ROUND_UP(bits, 8);
 	u8 *value = (u8 *)value64;
 
 	if (address > 0xff || !value64)
 		return AE_BAD_PARAMETER;
 
-	if (function != ACPI_WRITE && function != ACPI_READ)
-		return AE_BAD_PARAMETER;
+	guard(spinlock_irq)(&rtc_lock);
+
+	if (function == ACPI_WRITE) {
+		for (i = 0; i < bytes; i++, address++, value++)
+			CMOS_WRITE(*value, address);
 
-	spin_lock_irq(&rtc_lock);
+		return AE_OK;
+	}
 
-	for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value)
-		if (function == ACPI_READ)
+	if (function == ACPI_READ) {
+		for (i = 0; i < bytes; i++, address++, value++)
 			*value = CMOS_READ(address);
-		else
-			CMOS_WRITE(*value, address);
 
-	spin_unlock_irq(&rtc_lock);
+		return AE_OK;
+	}
 
-	return AE_OK;
+	return AE_BAD_PARAMETER;
 }
 
 int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
@@ -56,11 +60,11 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
 	acpi_status status;
 
 	status = acpi_install_address_space_handler(handle,
-			ACPI_ADR_SPACE_CMOS,
-			&acpi_cmos_rtc_space_handler,
-			NULL, NULL);
+						    ACPI_ADR_SPACE_CMOS,
+						    acpi_cmos_rtc_space_handler,
+						    NULL, NULL);
 	if (ACPI_FAILURE(status)) {
-		pr_err("Error installing CMOS-RTC region handler\n");
+		pr_err("Failed to install CMOS-RTC address space handler\n");
 		return -ENODEV;
 	}
 
@@ -70,26 +74,25 @@ EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
 
 void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
 {
-	if (ACPI_FAILURE(acpi_remove_address_space_handler(handle,
-			ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
-		pr_err("Error removing CMOS-RTC region handler\n");
+	acpi_status status;
+
+	status = acpi_remove_address_space_handler(handle,
+						   ACPI_ADR_SPACE_CMOS,
+						   acpi_cmos_rtc_space_handler);
+	if (ACPI_FAILURE(status))
+		pr_err("Failed to remove CMOS-RTC address space handler\n");
 }
 EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
 
-static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id)
+static int acpi_cmos_rtc_attach(struct acpi_device *adev,
+				const struct acpi_device_id *id)
 {
 	return acpi_install_cmos_rtc_space_handler(adev->handle);
 }
 
-static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev)
-{
-	acpi_remove_cmos_rtc_space_handler(adev->handle);
-}
-
 static struct acpi_scan_handler cmos_rtc_handler = {
 	.ids = acpi_cmos_rtc_ids,
-	.attach = acpi_cmos_rtc_attach_handler,
-	.detach = acpi_cmos_rtc_detach_handler,
+	.attach = acpi_cmos_rtc_attach,
 };
 
 void __init acpi_cmos_rtc_init(void)
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/508 ACPI: x86: cmos_rtc: Improve coordination with ACPI TAD driver

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rafael J. Wysocki <[email protected]>

[ Upstream commit 6cee29ad9d7e400d39ae0b1a54447fedcb62eecd ]

If a CMOS RTC (PNP0B00/PNP0B01/PNP0B02) device coexists with an ACPI TAD (timer and event alarm device, ACPI000E), the ACPI TAD driver will attempt to install the CMOS RTC address space hanlder that has been installed already and the TAD probing will fail.

Avoid that by changing acpi_install_cmos_rtc_space_handler() to return zero and acpi_remove_cmos_rtc_space_handler() to do nothing if the CMOS RTC address space handler has been installed already.

Fixes 596ca52a56da ("ACPI: TAD: Install SystemCMOS address space handler for ACPI000E")
---
 drivers/acpi/acpi_cmos_rtc.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/acpi/acpi_cmos_rtc.c +17 -1
index 65e89e23c5c84..594753203fdf0 100644
@@ -24,6 +24,8 @@ static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
 	{}
 };
 
+static bool cmos_rtc_space_handler_present __read_mostly;
+
 static acpi_status acpi_cmos_rtc_space_handler(u32 function,
 					       acpi_physical_address address,
 					       u32 bits, u64 *value64,
@@ -59,6 +61,9 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
 {
 	acpi_status status;
 
+	if (cmos_rtc_space_handler_present)
+		return 0;
+
 	status = acpi_install_address_space_handler(handle,
 						    ACPI_ADR_SPACE_CMOS,
 						    acpi_cmos_rtc_space_handler,
@@ -68,6 +73,8 @@ int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
 		return -ENODEV;
 	}
 
+	cmos_rtc_space_handler_present = true;
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler);
@@ -76,6 +83,9 @@ void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
 {
 	acpi_status status;
 
+	if (cmos_rtc_space_handler_present)
+		return;
+
 	status = acpi_remove_address_space_handler(handle,
 						   ACPI_ADR_SPACE_CMOS,
 						   acpi_cmos_rtc_space_handler);
@@ -87,7 +97,13 @@ EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler);
 static int acpi_cmos_rtc_attach(struct acpi_device *adev,
 				const struct acpi_device_id *id)
 {
-	return acpi_install_cmos_rtc_space_handler(adev->handle);
+	int ret;
+
+	ret = acpi_install_cmos_rtc_space_handler(adev->handle);
+	if (ret < 0)
+		return ret;
+
+	return 1;
 }
 
 static struct acpi_scan_handler cmos_rtc_handler = {
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/508 devres: fix missing node debug info in devm_krealloc()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Danilo Krummrich <[email protected]>

[ Upstream commit f813ec9e84b4d0ca81ec1da94ab07bfb4a29266c ]

Fix missing call to set_node_dbginfo() for new devres nodes created by devm_krealloc().

---
 drivers/base/devres.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/base/devres.c +2 -0
index 8a0f000221271..8069b7ca26fbc 100644
@@ -913,6 +913,8 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
 	if (!new_dr)
 		return NULL;
 
+	set_node_dbginfo(&new_dr->node, "devm_krealloc_release", new_size);
+
 	/*
 	 * The spinlock protects the linked list against concurrent
 	 * modifications but not the resource itself.
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/508 thermal/drivers/spear: Fix error condition for reading st,thermal-flags

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gopi Krishna Menon <[email protected]>

[ Upstream commit da2c4f332a0504d9c284e7626a561d343c8d6f57 ]

of_property_read_u32 returns 0 on success. The current check returns -EINVAL if the property is read successfully.

Fix the check by removing ! from of_property_read_u32

Fixes b9c7aff481f1 ("drivers/thermal/spear_thermal.c: add Device Tree probing capability")
---
 drivers/thermal/spear_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/thermal/spear_thermal.c +1 -1
index 96d99289799a1..a935002c2bdbe 100644
@@ -93,7 +93,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	int ret = 0, val;
 
-	if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
+	if (!np || of_property_read_u32(np, "st,thermal-flags", &val)) {
 		dev_err(&pdev->dev, "Failed: DT Pdata not passed\n");
 		return -EINVAL;
 	}
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/508 debugfs: check for NULL pointer in debugfs_create_str()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gui-Dong Han <[email protected]>

[ Upstream commit 31de83980d3764d784f79ff1bc93c42b324f4013 ]

Passing a NULL pointer to debugfs_create_str() leads to a NULL pointer dereference when the debugfs file is read. Following upstream discussions, forbid the creation of debugfs string files with NULL pointers. Add a WARN_ON() to expose offending callers and return early.

---
 fs/debugfs/file.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
fs/debugfs/file.c +4 -1
index e40229c47fe58..3089d7146f366 100644
@@ -987,7 +987,7 @@ static const struct file_operations fops_str_wo = {
  *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @value: a pointer to the variable that the file should read to and write
- *         from.
+ *         from. This pointer and the string it points to must not be %NULL.
  *
  * This function creates a file in debugfs with the given name that
  * contains the value of the variable @value.  If the @mode variable is so
@@ -996,6 +996,9 @@ static const struct file_operations fops_str_wo = {
 void debugfs_create_str(const char *name, umode_t mode,
 			struct dentry *parent, char **value)
 {
+	if (WARN_ON(!value || !*value))
+		return;
+
 	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_str,
 				   &fops_str_ro, &fops_str_wo);
 }
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/508 debugfs: fix placement of EXPORT_SYMBOL_GPL for debugfs_create_str()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gui-Dong Han <[email protected]>

[ Upstream commit 4afc929c0f74c4f22b055a82b371d50586da58ca ]

The EXPORT_SYMBOL_GPL() for debugfs_create_str was placed incorrectly away from the function definition. Move it immediately below the debugfs_create_str() function where it belongs.

Fixes d60b59b96795 ("debugfs: Export debugfs_create_str symbol")
---
 fs/debugfs/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/debugfs/file.c +1 -1
index 3089d7146f366..a9097a6c7b5a3 100644
@@ -907,7 +907,6 @@ ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf,
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(debugfs_create_str);
 
 static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
 				      size_t count, loff_t *ppos)
@@ -1002,6 +1001,7 @@ void debugfs_create_str(const char *name, umode_t mode,
 	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_str,
 				   &fops_str_ro, &fops_str_wo);
 }
+EXPORT_SYMBOL_GPL(debugfs_create_str);
 
 static ssize_t read_file_blob(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
Signature · 1 line
2.53.0
author maintainer
#14 lore raw

PATCH 14/508 s390/cio: make sch->lock spinlock pointer a member

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Halil Pasic <[email protected]>

[ Upstream commit b8fa3e90965eeb2f83aa637ba0d0d6fd2a524004 ]

The lock member of struct subchannel used to be a spinlock, but became a pointer to a spinlock with commit 2ec2298412e1 ("[S390] subchannel lock conversion."). This might have been justified back then, but with the current state of affairs, there is no reason to manage a separate spinlock object.

Let's simplify things and pull the spinlock back into struct subchannel.

Stable-dep-of: ac4d8bb6e2e1 ("s390/cio: use generic driver_override infrastructure")

---
 drivers/s390/cio/chsc.c         | 18 ++++-----
 drivers/s390/cio/chsc_sch.c     |  6 +--
 drivers/s390/cio/cio.c          |  6 +--
 drivers/s390/cio/cio.h          |  2 +-
 drivers/s390/cio/css.c          | 36 +++++-------------
 drivers/s390/cio/device.c       | 66 ++++++++++++++++-----------------
 drivers/s390/cio/device_pgid.c  | 12 +++---
 drivers/s390/cio/eadm_sch.c     | 36 +++++++++---------
 drivers/s390/cio/vfio_ccw_drv.c |  8 ++--
 drivers/s390/cio/vfio_ccw_fsm.c | 24 ++++++------
 10 files changed, 99 insertions(+), 115 deletions(-)
drivers/s390/cio/chsc.c +9 -9
index 0abd77f4b6646..2988a699e3ef2 100644
@@ -219,16 +219,16 @@ EXPORT_SYMBOL_GPL(chsc_sadc);
 
 static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
 {
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	if (sch->driver && sch->driver->chp_event)
 		if (sch->driver->chp_event(sch, data, CHP_OFFLINE) != 0)
 			goto out_unreg;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	return 0;
 
 out_unreg:
 	sch->lpm = 0;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	css_schedule_eval(sch->schid);
 	return 0;
 }
@@ -258,10 +258,10 @@ void chsc_chp_offline(struct chp_id chpid)
 
 static int __s390_process_res_acc(struct subchannel *sch, void *data)
 {
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	if (sch->driver && sch->driver->chp_event)
 		sch->driver->chp_event(sch, data, CHP_ONLINE);
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 
 	return 0;
 }
@@ -292,10 +292,10 @@ static void s390_process_res_acc(struct chp_link *link)
 
 static int process_fces_event(struct subchannel *sch, void *data)
 {
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	if (sch->driver && sch->driver->chp_event)
 		sch->driver->chp_event(sch, data, CHP_FCES_EVENT);
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	return 0;
 }
 
@@ -769,11 +769,11 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
 
 	memset(&link, 0, sizeof(struct chp_link));
 	link.chpid = chpid;
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 	if (sch->driver && sch->driver->chp_event)
 		sch->driver->chp_event(sch, &link,
 				       on ? CHP_VARY_ON : CHP_VARY_OFF);
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 }
 
 static int s390_subchannel_vary_chpid_off(struct subchannel *sch, void *data)
drivers/s390/cio/chsc_sch.c +3 -3
index 180ab899289c5..902237d0baefe 100644
@@ -211,10 +211,10 @@ static int chsc_async(struct chsc_async_area *chsc_area,
 
 	chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
 	while ((sch = chsc_get_next_subchannel(sch))) {
-		spin_lock(sch->lock);
+		spin_lock(&sch->lock);
 		private = dev_get_drvdata(&sch->dev);
 		if (private->request) {
-			spin_unlock(sch->lock);
+			spin_unlock(&sch->lock);
 			ret = -EBUSY;
 			continue;
 		}
@@ -239,7 +239,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
 		default:
 			ret = -ENODEV;
 		}
-		spin_unlock(sch->lock);
+		spin_unlock(&sch->lock);
 		CHSC_MSG(2, "chsc on 0.%x.%04x returned cc=%d\n",
 			 sch->schid.ssid, sch->schid.sch_no, cc);
 		if (ret == -EINPROGRESS)
drivers/s390/cio/cio.c +3 -3
index 81ef9002f0640..7843c69abee6c 100644
@@ -550,7 +550,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
 		return IRQ_HANDLED;
 	}
 	sch = phys_to_virt(tpi_info->intparm);
-	spin_lock(sch->lock);
+	spin_lock(&sch->lock);
 	/* Store interrupt response block to lowcore. */
 	if (tsch(tpi_info->schid, irb) == 0) {
 		/* Keep subchannel information word up to date. */
@@ -562,7 +562,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
 			inc_irq_stat(IRQIO_CIO);
 	} else
 		inc_irq_stat(IRQIO_CIO);
-	spin_unlock(sch->lock);
+	spin_unlock(&sch->lock);
 
 	return IRQ_HANDLED;
 }
@@ -667,7 +667,7 @@ struct subchannel *cio_probe_console(void)
 	if (IS_ERR(sch))
 		return sch;
 
-	lockdep_set_class(sch->lock, &console_sch_key);
+	lockdep_set_class(&sch->lock, &console_sch_key);
 	isc_register(CONSOLE_ISC);
 	sch->config.isc = CONSOLE_ISC;
 	sch->config.intparm = (u32)virt_to_phys(sch);
drivers/s390/cio/cio.h +1 -1
index fa8df50bb49e3..a9057a5b670a6 100644
@@ -83,7 +83,7 @@ enum sch_todo {
 /* subchannel data structure used by I/O subroutines */
 struct subchannel {
 	struct subchannel_id schid;
-	spinlock_t *lock;	/* subchannel lock */
+	spinlock_t lock;	/* subchannel lock */
 	struct mutex reg_mutex;
 	enum {
 		SUBCHANNEL_TYPE_IO = 0,
drivers/s390/cio/css.c +10 -26
index e50592c3d30ca..4e63e6d45e6e1 100644
@@ -148,16 +148,10 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
 
 static void css_sch_todo(struct work_struct *work);
 
-static int css_sch_create_locks(struct subchannel *sch)
+static void css_sch_create_locks(struct subchannel *sch)
 {
-	sch->lock = kmalloc(sizeof(*sch->lock), GFP_KERNEL);
-	if (!sch->lock)
-		return -ENOMEM;
-
-	spin_lock_init(sch->lock);
+	spin_lock_init(&sch->lock);
 	mutex_init(&sch->reg_mutex);
-
-	return 0;
 }
 
 static void css_subchannel_release(struct device *dev)
@@ -167,7 +161,6 @@ static void css_subchannel_release(struct device *dev)
 	sch->config.intparm = 0;
 	cio_commit_config(sch);
 	kfree(sch->driver_override);
-	kfree(sch->lock);
 	kfree(sch);
 }
 
@@ -219,9 +212,7 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
 	sch->schib = *schib;
 	sch->st = schib->pmcw.st;
 
-	ret = css_sch_create_locks(sch);
-	if (ret)
-		goto err;
+	css_sch_create_locks(sch);
 
 	INIT_WORK(&sch->todo_work, css_sch_todo);
 	sch->dev.release = &css_subchannel_release;
@@ -233,19 +224,17 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
 	 */
 	ret = dma_set_coherent_mask(&sch->dev, DMA_BIT_MASK(31));
 	if (ret)
-		goto err_lock;
+		goto err;
 	/*
 	 * But we don't have such restrictions imposed on the stuff that
 	 * is handled by the streaming API.
 	 */
 	ret = dma_set_mask(&sch->dev, DMA_BIT_MASK(64));
 	if (ret)
-		goto err_lock;
+		goto err;
 
 	return sch;
 
-err_lock:
-	kfree(sch->lock);
 err:
 	put_device(&sch->dev);
 	return ERR_PTR(ret);
@@ -604,12 +593,12 @@ static void css_sch_todo(struct work_struct *work)
 
 	sch = container_of(work, struct subchannel, todo_work);
 	/* Find out todo. */
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	todo = sch->todo;
 	CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid,
 		      sch->schid.sch_no, todo);
 	sch->todo = SCH_TODO_NOTHING;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	/* Perform todo. */
 	switch (todo) {
 	case SCH_TODO_NOTHING:
@@ -617,9 +606,9 @@ static void css_sch_todo(struct work_struct *work)
 	case SCH_TODO_EVAL:
 		ret = css_evaluate_known_subchannel(sch, 1);
 		if (ret == -EAGAIN) {
-			spin_lock_irq(sch->lock);
+			spin_lock_irq(&sch->lock);
 			css_sched_sch_todo(sch, todo);
-			spin_unlock_irq(sch->lock);
+			spin_unlock_irq(&sch->lock);
 		}
 		break;
 	case SCH_TODO_UNREG:
@@ -1028,12 +1017,7 @@ static int __init setup_css(int nr)
 	css->pseudo_subchannel->dev.parent = &css->device;
 	css->pseudo_subchannel->dev.release = css_subchannel_release;
 	mutex_init(&css->pseudo_subchannel->reg_mutex);
-	ret = css_sch_create_locks(css->pseudo_subchannel);
-	if (ret) {
-		kfree(css->pseudo_subchannel);
-		device_unregister(&css->device);
-		goto out_err;
-	}
+	css_sch_create_locks(css->pseudo_subchannel);
 
 	dev_set_name(&css->pseudo_subchannel->dev, "defunct");
 	ret = device_register(&css->pseudo_subchannel->dev);
drivers/s390/cio/device.c +33 -33

196 lines not on this page · raw message

drivers/s390/cio/device_pgid.c +6 -6
index 3862961697eb6..ad90045873e25 100644
@@ -698,29 +698,29 @@ int ccw_device_stlck(struct ccw_device *cdev)
 		return -ENOMEM;
 	init_completion(&data.done);
 	data.rc = -EIO;
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	rc = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
 	if (rc)
 		goto out_unlock;
 	/* Perform operation. */
 	cdev->private->state = DEV_STATE_STEAL_LOCK;
 	ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	/* Wait for operation to finish. */
 	if (wait_for_completion_interruptible(&data.done)) {
 		/* Got a signal. */
-		spin_lock_irq(sch->lock);
+		spin_lock_irq(&sch->lock);
 		ccw_request_cancel(cdev);
-		spin_unlock_irq(sch->lock);
+		spin_unlock_irq(&sch->lock);
 		wait_for_completion(&data.done);
 	}
 	rc = data.rc;
 	/* Check results. */
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	cio_disable_subchannel(sch);
 	cdev->private->state = DEV_STATE_BOXED;
 out_unlock:
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	kfree(buffer);
 
 	return rc;
drivers/s390/cio/eadm_sch.c +18 -18
index 826364d2facd8..1caedf931a5f0 100644
@@ -101,12 +101,12 @@ static void eadm_subchannel_timeout(struct timer_list *t)
 	struct eadm_private *private = from_timer(private, t, timer);
 	struct subchannel *sch = private->sch;
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	EADM_LOG(1, "timeout");
 	EADM_LOG_HEX(1, &sch->schid, sizeof(sch->schid));
 	if (eadm_subchannel_clear(sch))
 		EADM_LOG(0, "clear failed");
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 }
 
 static void eadm_subchannel_set_timeout(struct subchannel *sch, int expires)
@@ -163,16 +163,16 @@ static struct subchannel *eadm_get_idle_sch(void)
 	spin_lock_irqsave(&list_lock, flags);
 	list_for_each_entry(private, &eadm_list, head) {
 		sch = private->sch;
-		spin_lock(sch->lock);
+		spin_lock(&sch->lock);
 		if (private->state == EADM_IDLE) {
 			private->state = EADM_BUSY;
 			list_move_tail(&private->head, &eadm_list);
-			spin_unlock(sch->lock);
+			spin_unlock(&sch->lock);
 			spin_unlock_irqrestore(&list_lock, flags);
 
 			return sch;
 		}
-		spin_unlock(sch->lock);
+		spin_unlock(&sch->lock);
 	}
 	spin_unlock_irqrestore(&list_lock, flags);
 
@@ -190,7 +190,7 @@ int eadm_start_aob(struct aob *aob)
 	if (!sch)
 		return -EBUSY;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 	eadm_subchannel_set_timeout(sch, EADM_TIMEOUT);
 	ret = eadm_subchannel_start(sch, aob);
 	if (!ret)
@@ -203,7 +203,7 @@ int eadm_start_aob(struct aob *aob)
 	css_sched_sch_todo(sch, SCH_TODO_EVAL);
 
 out_unlock:
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 
 	return ret;
 }
@@ -221,7 +221,7 @@ static int eadm_subchannel_probe(struct subchannel *sch)
 	INIT_LIST_HEAD(&private->head);
 	timer_setup(&private->timer, eadm_subchannel_timeout, 0);
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	set_eadm_private(sch, private);
 	private->state = EADM_IDLE;
 	private->sch = sch;
@@ -229,11 +229,11 @@ static int eadm_subchannel_probe(struct subchannel *sch)
 	ret = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
 	if (ret) {
 		set_eadm_private(sch, NULL);
-		spin_unlock_irq(sch->lock);
+		spin_unlock_irq(&sch->lock);
 		kfree(private);
 		goto out;
 	}
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 
 	spin_lock_irq(&list_lock);
 	list_add(&private->head, &eadm_list);
@@ -248,7 +248,7 @@ static void eadm_quiesce(struct subchannel *sch)
 	DECLARE_COMPLETION_ONSTACK(completion);
 	int ret;
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	if (private->state != EADM_BUSY)
 		goto disable;
 
@@ -256,11 +256,11 @@ static void eadm_quiesce(struct subchannel *sch)
 		goto disable;
 
 	private->completion = &completion;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 
 	wait_for_completion_io(&completion);
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	private->completion = NULL;
 
 disable:
@@ -269,7 +269,7 @@ static void eadm_quiesce(struct subchannel *sch)
 		ret = cio_disable_subchannel(sch);
 	} while (ret == -EBUSY);
 
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 }
 
 static void eadm_subchannel_remove(struct subchannel *sch)
@@ -282,9 +282,9 @@ static void eadm_subchannel_remove(struct subchannel *sch)
 
 	eadm_quiesce(sch);
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	set_eadm_private(sch, NULL);
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 
 	kfree(private);
 }
@@ -309,7 +309,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
 	struct eadm_private *private;
 	unsigned long flags;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 	if (!device_is_registered(&sch->dev))
 		goto out_unlock;
 
@@ -325,7 +325,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
 		private->state = EADM_IDLE;
 
 out_unlock:
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 
 	return 0;
 }
drivers/s390/cio/vfio_ccw_drv.c +4 -4
index 43601816ea4e4..a3e25bdd6a76b 100644
@@ -65,14 +65,14 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch)
 		 * cancel/halt/clear completion.
 		 */
 		private->completion = &completion;
-		spin_unlock_irq(sch->lock);
+		spin_unlock_irq(&sch->lock);
 
 		if (ret == -EBUSY)
 			wait_for_completion_timeout(&completion, 3*HZ);
 
 		private->completion = NULL;
 		flush_workqueue(vfio_ccw_work_q);
-		spin_lock_irq(sch->lock);
+		spin_lock_irq(&sch->lock);
 		ret = cio_disable_subchannel(sch);
 	} while (ret == -EBUSY);
 
@@ -249,7 +249,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
 	unsigned long flags;
 	int rc = -EAGAIN;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 	if (!device_is_registered(&sch->dev))
 		goto out_unlock;
 
@@ -264,7 +264,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
 	}
 
 out_unlock:
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 
 	return rc;
 }
drivers/s390/cio/vfio_ccw_fsm.c +12 -12
index 757b73141246d..09877b46181d4 100644
@@ -25,7 +25,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 
 	orb = cp_get_orb(&private->cp, sch);
 	if (!orb) {
@@ -72,7 +72,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
 		ret = ccode;
 	}
 out:
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 	return ret;
 }
 
@@ -83,7 +83,7 @@ static int fsm_do_halt(struct vfio_ccw_private *private)
 	int ccode;
 	int ret;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 
 	VFIO_CCW_TRACE_EVENT(2, "haltIO");
 	VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev));
@@ -111,7 +111,7 @@ static int fsm_do_halt(struct vfio_ccw_private *private)
 	default:
 		ret = ccode;
 	}
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 	return ret;
 }
 
@@ -122,7 +122,7 @@ static int fsm_do_clear(struct vfio_ccw_private *private)
 	int ccode;
 	int ret;
 
-	spin_lock_irqsave(sch->lock, flags);
+	spin_lock_irqsave(&sch->lock, flags);
 
 	VFIO_CCW_TRACE_EVENT(2, "clearIO");
 	VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev));
@@ -147,7 +147,7 @@ static int fsm_do_clear(struct vfio_ccw_private *private)
 	default:
 		ret = ccode;
 	}
-	spin_unlock_irqrestore(sch->lock, flags);
+	spin_unlock_irqrestore(&sch->lock, flags);
 	return ret;
 }
 
@@ -376,18 +376,18 @@ static void fsm_open(struct vfio_ccw_private *private,
 	struct subchannel *sch = to_subchannel(private->vdev.dev->parent);
 	int ret;
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 	sch->isc = VFIO_CCW_ISC;
 	ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
 	if (ret)
 		goto err_unlock;
 
 	private->state = VFIO_CCW_STATE_IDLE;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	return;
 
 err_unlock:
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
 }
 
@@ -397,7 +397,7 @@ static void fsm_close(struct vfio_ccw_private *private,
 	struct subchannel *sch = to_subchannel(private->vdev.dev->parent);
 	int ret;
 
-	spin_lock_irq(sch->lock);
+	spin_lock_irq(&sch->lock);
 
 	if (!sch->schib.pmcw.ena)
 		goto err_unlock;
@@ -409,12 +409,12 @@ static void fsm_close(struct vfio_ccw_private *private,
 		goto err_unlock;
 
 	private->state = VFIO_CCW_STATE_STANDBY;
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	cp_free(&private->cp);
 	return;
 
 err_unlock:
-	spin_unlock_irq(sch->lock);
+	spin_unlock_irq(&sch->lock);
 	vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
 }
 
Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH 15/508 s390/cio: convert sprintf()/snprintf() to sysfs_emit()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Li Zhijian <[email protected]>

[ Upstream commit aaebea959efb2cccd870990f1b6016ff324b0fb6 ]

Per filesystems/sysfs.rst, show() should only use sysfs_emit() or sysfs_emit_at() when formatting the value to be returned to user space.

coccinelle complains that there are still a couple of functions that use snprintf(). Convert them to sysfs_emit().

Generally, this patch is generated by
make coccicheck M=<path/to/file> MODE=patch \
COCCI=scripts/coccinelle/api/device_attr_show.cocci

No functional change intended.

Stable-dep-of: ac4d8bb6e2e1 ("s390/cio: use generic driver_override infrastructure")

---
 drivers/s390/cio/css.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/s390/cio/css.c +7 -7
index 4e63e6d45e6e1..36c46c7f2fb80 100644
@@ -309,7 +309,7 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
 {
 	struct subchannel *sch = to_subchannel(dev);
 
-	return sprintf(buf, "%01x\n", sch->st);
+	return sysfs_emit(buf, "%01x\n", sch->st);
 }
 
 static DEVICE_ATTR_RO(type);
@@ -319,7 +319,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 {
 	struct subchannel *sch = to_subchannel(dev);
 
-	return sprintf(buf, "css:t%01X\n", sch->st);
+	return sysfs_emit(buf, "css:t%01X\n", sch->st);
 }
 
 static DEVICE_ATTR_RO(modalias);
@@ -345,7 +345,7 @@ static ssize_t driver_override_show(struct device *dev,
 	ssize_t len;
 
 	device_lock(dev);
-	len = snprintf(buf, PAGE_SIZE, "%s\n", sch->driver_override);
+	len = sysfs_emit(buf, "%s\n", sch->driver_override);
 	device_unlock(dev);
 	return len;
 }
@@ -396,8 +396,8 @@ static ssize_t pimpampom_show(struct device *dev,
 	struct subchannel *sch = to_subchannel(dev);
 	struct pmcw *pmcw = &sch->schib.pmcw;
 
-	return sprintf(buf, "%02x %02x %02x\n",
-		       pmcw->pim, pmcw->pam, pmcw->pom);
+	return sysfs_emit(buf, "%02x %02x %02x\n",
+			  pmcw->pim, pmcw->pam, pmcw->pom);
 }
 static DEVICE_ATTR_RO(pimpampom);
 
@@ -881,7 +881,7 @@ static ssize_t real_cssid_show(struct device *dev, struct device_attribute *a,
 	if (!css->id_valid)
 		return -EINVAL;
 
-	return sprintf(buf, "%x\n", css->cssid);
+	return sysfs_emit(buf, "%x\n", css->cssid);
 }
 static DEVICE_ATTR_RO(real_cssid);
 
@@ -904,7 +904,7 @@ static ssize_t cm_enable_show(struct device *dev, struct device_attribute *a,
 	int ret;
 
 	mutex_lock(&css->mutex);
-	ret = sprintf(buf, "%x\n", css->cm_enabled);
+	ret = sysfs_emit(buf, "%x\n", css->cm_enabled);
 	mutex_unlock(&css->mutex);
 	return ret;
 }
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/508 s390/cio: use generic driver_override infrastructure

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Danilo Krummrich <[email protected]>

[ Upstream commit ac4d8bb6e2e13e8684a76ea48d13ebaaaf5c24c4 ]

When a driver is probed through __driver_attach(), the bus' match() callback is called without the device lock held, thus accessing the driver_override field without a lock, which can cause a UAF.

Fix this by using the driver-core driver_override infrastructure taking care of proper locking internally.

Note that calling match() from __driver_attach() without the device lock held is intentional. [1]

---
 drivers/s390/cio/cio.h |  5 -----
 drivers/s390/cio/css.c | 34 ++++------------------------------
 2 files changed, 4 insertions(+), 35 deletions(-)
drivers/s390/cio/cio.h +0 -5
index a9057a5b670a6..23374604c6b01 100644
@@ -103,11 +103,6 @@ struct subchannel {
 	struct work_struct todo_work;
 	struct schib_config config;
 	u64 dma_mask;
-	/*
-	 * Driver name to force a match.  Do not set directly, because core
-	 * frees it.  Use driver_set_override() to set or clear it.
-	 */
-	const char *driver_override;
 } __attribute__ ((aligned(8)));
 
 DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb);
drivers/s390/cio/css.c +4 -30
index 36c46c7f2fb80..97a2c23f4ce0f 100644
@@ -160,7 +160,6 @@ static void css_subchannel_release(struct device *dev)
 
 	sch->config.intparm = 0;
 	cio_commit_config(sch);
-	kfree(sch->driver_override);
 	kfree(sch);
 }
 
@@ -324,37 +323,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR_RO(modalias);
 
-static ssize_t driver_override_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct subchannel *sch = to_subchannel(dev);
-	int ret;
-
-	ret = driver_set_override(dev, &sch->driver_override, buf, count);
-	if (ret)
-		return ret;
-
-	return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct subchannel *sch = to_subchannel(dev);
-	ssize_t len;
-
-	device_lock(dev);
-	len = sysfs_emit(buf, "%s\n", sch->driver_override);
-	device_unlock(dev);
-	return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
 static struct attribute *subch_attrs[] = {
 	&dev_attr_type.attr,
 	&dev_attr_modalias.attr,
-	&dev_attr_driver_override.attr,
 	NULL,
 };
 
@@ -1352,9 +1323,11 @@ static int css_bus_match(struct device *dev, struct device_driver *drv)
 	struct subchannel *sch = to_subchannel(dev);
 	struct css_driver *driver = to_cssdriver(drv);
 	struct css_device_id *id;
+	int ret;
 
 	/* When driver_override is set, only bind to the matching driver */
-	if (sch->driver_override && strcmp(sch->driver_override, drv->name))
+	ret = device_match_driver_override(dev, drv);
+	if (ret == 0)
 		return 0;
 
 	for (id = driver->subchannel_type; id->match_flags; id++) {
@@ -1411,6 +1384,7 @@ static int css_uevent(const struct device *dev, struct kobj_uevent_env *env)
 
 static struct bus_type css_bus_type = {
 	.name     = "css",
+	.driver_override = true,
 	.match    = css_bus_match,
 	.probe    = css_probe,
 	.remove   = css_remove,
Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/508 irqchip/irq-pic32-evic: Address warning related to wrong printf() formatter

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Brian Masney <[email protected]>

[ Upstream commit 86be659415b0ddefebc3120e309091aa215a9064 ]

This driver is currently only build on 32 bit MIPS systems. When building it on x86_64, the following warning occurs:

drivers/irqchip/irq-pic32-evic.c: In function ‘pic32_ext_irq_of_init’:
./include/linux/kern_levels.h:5:25: error: format ‘%d’ expects argument of type
‘int’, but argument 2 has type ‘long unsigned int’ [-Werror=format=]

Update the printf() formatter in preparation for allowing this driver to be compiled on all architectures.

Fixes aaa8666ada780 ("IRQCHIP: irq-pic32-evic: Add support for PIC32 interrupt controller")
---
 drivers/irqchip/irq-pic32-evic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/irqchip/irq-pic32-evic.c +1 -1
index 5d6b8e025bb87..3cc6b439f5f90 100644
@@ -196,7 +196,7 @@ static void __init pic32_ext_irq_of_init(struct irq_domain *domain)
 
 	of_property_for_each_u32(node, pname, hwirq) {
 		if (i >= ARRAY_SIZE(priv->ext_irqs)) {
-			pr_warn("More than %d external irq, skip rest\n",
+			pr_warn("More than %zu external irq, skip rest\n",
 				ARRAY_SIZE(priv->ext_irqs));
 			break;
 		}
Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/508 hrtimers: Update the return type of enqueue_hrtimer()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Richard Clark <[email protected]>

[ Upstream commit da7100d3bf7d6f5c49ef493ea963766898e9b069 ]

The return type should be 'bool' instead of 'int' according to the calling context in the kernel, and its internal implementation, i.e. :

	return timerqueue_add();

which is a bool-return function.

[ tglx: Adjust function arguments ]

Stable-dep-of: f2e388a019e4 ("hrtimer: Reduce trace noise in hrtimer_start()")

---
 kernel/time/hrtimer.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
kernel/time/hrtimer.c +3 -4
index 03f488f93cddf..9f41327d3a6d6 100644
@@ -1099,11 +1099,10 @@ EXPORT_SYMBOL_GPL(hrtimer_forward);
  * The timer is inserted in expiry order. Insertion into the
  * red black tree is O(log(n)). Must hold the base lock.
  *
- * Returns 1 when the new timer is the leftmost timer in the tree.
+ * Returns true when the new timer is the leftmost timer in the tree.
  */
-static int enqueue_hrtimer(struct hrtimer *timer,
-			   struct hrtimer_clock_base *base,
-			   enum hrtimer_mode mode)
+static bool enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
+			    enum hrtimer_mode mode)
 {
 	debug_activate(timer, mode);
 	WARN_ON_ONCE(!base->cpu_base->online);
Signature · 1 line
2.53.0
author maintainer
#19 lore raw

PATCH 19/508 hrtimer: Avoid pointless reprogramming in __hrtimer_start_range_ns()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Zijlstra <[email protected]>

[ Upstream commit d19ff16c11db38f3ee179d72751fb9b340174330 ]

Much like hrtimer_reprogram(), skip programming if the cpu_base is running the hrtimer interrupt.

Stable-dep-of: f2e388a019e4 ("hrtimer: Reduce trace noise in hrtimer_start()")

---
 kernel/time/hrtimer.c | 8 ++++++++
 1 file changed, 8 insertions(+)
kernel/time/hrtimer.c +8 -0
index 9f41327d3a6d6..3bc3111ca5317 100644
@@ -1287,6 +1287,14 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
 	}
 
 	first = enqueue_hrtimer(timer, new_base, mode);
+
+	/*
+	 * If the hrtimer interrupt is running, then it will reevaluate the
+	 * clock bases and reprogram the clock event device.
+	 */
+	if (new_base->cpu_base->in_hrtirq)
+		return false;
+
 	if (!force_local) {
 		/*
 		 * If the current CPU base is online, then the timer is
Signature · 1 line
2.53.0
author maintainer
#20 lore raw

PATCH 20/508 hrtimer: Reduce trace noise in hrtimer_start()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Gleixner <[email protected]>

[ Upstream commit f2e388a019e4cf83a15883a3d1f1384298e9a6aa ]

hrtimer_start() when invoked with an already armed timer traces like:

<comm>-.. [032] d.h2. 5.002263: hrtimer_cancel: hrtimer= ....
<comm>-.. [032] d.h1. 5.002263: hrtimer_start: hrtimer= ....

Which is incorrect as the timer doesn't get canceled. Just the expiry time changes. The internal dequeue operation which is required for that is not really interesting for trace analysis. But it makes it tedious to keep real cancellations and the above case apart.

Remove the cancel tracing in hrtimer_start() and add a 'was_armed' indicator to the hrtimer start tracepoint, which clearly indicates what the state of the hrtimer is when hrtimer_start() is invoked:

<comm>-.. [032] d.h1. 6.200103: hrtimer_start: hrtimer= .... was_armed=0
<comm>-.. [032] d.h1. 6.200558: hrtimer_start: hrtimer= .... was_armed=1

---
 include/trace/events/timer.h | 11 +++++----
 kernel/time/hrtimer.c        | 43 +++++++++++++++++-------------------
 2 files changed, 27 insertions(+), 27 deletions(-)
include/trace/events/timer.h +7 -4
index b4bc2828fa09f..ec8d0de1ad225 100644
@@ -198,12 +198,13 @@ TRACE_EVENT(hrtimer_init,
  * hrtimer_start - called when the hrtimer is started
  * @hrtimer:	pointer to struct hrtimer
  * @mode:	the hrtimers mode
+ * @was_armed:	Was armed when hrtimer_start*() was invoked
  */
 TRACE_EVENT(hrtimer_start,
 
-	TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode),
+	TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode, bool was_armed),
 
-	TP_ARGS(hrtimer, mode),
+	TP_ARGS(hrtimer, mode, was_armed),
 
 	TP_STRUCT__entry(
 		__field( void *,	hrtimer		)
@@ -211,6 +212,7 @@ TRACE_EVENT(hrtimer_start,
 		__field( s64,		expires		)
 		__field( s64,		softexpires	)
 		__field( enum hrtimer_mode,	mode	)
+		__field( bool,		was_armed	)
 	),
 
 	TP_fast_assign(
@@ -219,13 +221,14 @@ TRACE_EVENT(hrtimer_start,
 		__entry->expires	= hrtimer_get_expires(hrtimer);
 		__entry->softexpires	= hrtimer_get_softexpires(hrtimer);
 		__entry->mode		= mode;
+		__entry->was_armed	= was_armed;
 	),
 
 	TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu "
-		  "mode=%s", __entry->hrtimer, __entry->function,
+		  "mode=%s was_armed=%d", __entry->hrtimer, __entry->function,
 		  (unsigned long long) __entry->expires,
 		  (unsigned long long) __entry->softexpires,
-		  decode_hrtimer_mode(__entry->mode))
+		  decode_hrtimer_mode(__entry->mode), __entry->was_armed)
 );
 
 /**
kernel/time/hrtimer.c +20 -23

117 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#21 lore raw

PATCH 21/508 locking: Fix rwlock support in <linux/spinlock_up.h>

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bart Van Assche <[email protected]>

[ Upstream commit 756a0e011cfca0b45a48464aa25b05d9a9c2fb0b ]

Architecture support for rwlocks must be available whether or not CONFIG_DEBUG_SPINLOCK has been defined. Move the definitions of the arch_{read,write}_{lock,trylock,unlock}() macros such that these become visbile if CONFIG_DEBUG_SPINLOCK=n.

This patch prepares for converting do_raw_{read,write}_trylock() into inline functions. Without this patch that conversion triggers a build failure for UP architectures, e.g. arm-ep93xx. I used the following kernel configuration to build the kernel for that architecture:

CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_V7=n
CONFIG_ATAGS=y
CONFIG_MMU=y
CONFIG_ARCH_MULTI_V4T=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_ARCH_EP93XX=y

---
 include/linux/spinlock_up.h | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
include/linux/spinlock_up.h +10 -10
index c87204247592f..a132fc562297a 100644
@@ -48,16 +48,6 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 	lock->slock = 1;
 }
 
-/*
- * Read-write spinlocks. No debug version.
- */
-#define arch_read_lock(lock)		do { barrier(); (void)(lock); } while (0)
-#define arch_write_lock(lock)		do { barrier(); (void)(lock); } while (0)
-#define arch_read_trylock(lock)	({ barrier(); (void)(lock); 1; })
-#define arch_write_trylock(lock)	({ barrier(); (void)(lock); 1; })
-#define arch_read_unlock(lock)		do { barrier(); (void)(lock); } while (0)
-#define arch_write_unlock(lock)	do { barrier(); (void)(lock); } while (0)
-
 #else /* DEBUG_SPINLOCK */
 #define arch_spin_is_locked(lock)	((void)(lock), 0)
 /* for sched/core.c and kernel_lock.c: */
@@ -68,4 +58,14 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 
 #define arch_spin_is_contended(lock)	(((void)(lock), 0))
 
+/*
+ * Read-write spinlocks. No debug version.
+ */
+#define arch_read_lock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_write_lock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_read_trylock(lock)	({ barrier(); (void)(lock); 1; })
+#define arch_write_trylock(lock)	({ barrier(); (void)(lock); 1; })
+#define arch_read_unlock(lock)		do { barrier(); (void)(lock); } while (0)
+#define arch_write_unlock(lock)	do { barrier(); (void)(lock); } while (0)
+
 #endif /* __LINUX_SPINLOCK_UP_H */
Signature · 1 line
2.53.0
author maintainer
#22 lore raw

PATCH 22/508 firmware: dmi: Correct an indexing error in dmi.h

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mario Limonciello (AMD) <[email protected]>

[ Upstream commit c064abc68e009d2cc18416e7132d9c25e03125b6 ]

The entries later in enum dmi_entry_type don't match the SMBIOS specification¹.

The entry for type 33: 64-Bit Memory Error Information is not present and thus the index for all later entries is incorrect.

Add it.

Also, add missing entry types 43-46, while at it.

¹ Search for "System Management BIOS (SMBIOS) Reference Specification"

[ bp: Drop the flaky SMBIOS spec URL. ]

---
 include/linux/dmi.h | 5 +++++
 1 file changed, 5 insertions(+)
include/linux/dmi.h +5 -0
index 927f8a8b7a1dd..2eedf44e68012 100644
@@ -60,6 +60,7 @@ enum dmi_entry_type {
 	DMI_ENTRY_OOB_REMOTE_ACCESS,
 	DMI_ENTRY_BIS_ENTRY,
 	DMI_ENTRY_SYSTEM_BOOT,
+	DMI_ENTRY_64_MEM_ERROR,
 	DMI_ENTRY_MGMT_DEV,
 	DMI_ENTRY_MGMT_DEV_COMPONENT,
 	DMI_ENTRY_MGMT_DEV_THRES,
@@ -69,6 +70,10 @@ enum dmi_entry_type {
 	DMI_ENTRY_ADDITIONAL,
 	DMI_ENTRY_ONBOARD_DEV_EXT,
 	DMI_ENTRY_MGMT_CONTROLLER_HOST,
+	DMI_ENTRY_TPM_DEVICE,
+	DMI_ENTRY_PROCESSOR_ADDITIONAL,
+	DMI_ENTRY_FIRMWARE_INVENTORY,
+	DMI_ENTRY_STRING_PROPERTY,
 	DMI_ENTRY_INACTIVE = 126,
 	DMI_ENTRY_END_OF_TABLE = 127,
 };
Signature · 1 line
2.53.0
author maintainer
#23 lore raw

PATCH 23/508 wifi: mwifiex: Fix memory leak in mwifiex_11n_aggregate_pkt()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zilin Guan <[email protected]>

[ Upstream commit 990a73dec3fdc145fef6c827c29205437d533ece ]

In mwifiex_11n_aggregate_pkt(), skb_aggr is allocated via mwifiex_alloc_dma_align_buf(). If mwifiex_is_ralist_valid() returns false, the function currently returns -1 immediately without freeing the previously allocated skb_aggr, causing a memory leak.

Since skb_aggr has not yet been queued via skb_queue_tail(), no other references to this memory exist. Therefore, it has to be freed locally before returning the error.

Fix this by calling mwifiex_write_data_complete() to free skb_aggr before returning the error status.

Compile tested only. Issue found using a prototype static analysis tool and code review.

Fixes 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver")
---
 drivers/net/wireless/marvell/mwifiex/11n_aggr.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/marvell/mwifiex/11n_aggr.c +1 -0
index 34b4b34276d6d..042b1fe5f0d67 100644
@@ -203,6 +203,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
 		if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
 			spin_unlock_bh(&priv->wmm.ra_list_spinlock);
+			mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
 			return -1;
 		}
 
Signature · 1 line
2.53.0
author maintainer
#24 lore raw

PATCH 24/508 wifi: rtlwifi: pci: fix possible use-after-free caused by unfinished irq_prepare_bcn_tasklet

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Duoming Zhou <[email protected]>

[ Upstream commit 039cd522dc70151da13329a5e3ae19b1736f468a ]

The irq_prepare_bcn_tasklet is initialized in rtl_pci_init() and scheduled when RTL_IMR_BCNINT interrupt is triggered by hardware. But it is never killed in rtl_pci_deinit(). When the rtlwifi card probe fails or is being detached, the ieee80211_hw is deallocated. However, irq_prepare_bcn_tasklet may still be running or pending, leading to use-after-free when the freed ieee80211_hw is accessed in _rtl_pci_prepare_bcn_tasklet().

Similar to irq_tasklet, add tasklet_kill() in rtl_pci_deinit() to ensure that irq_prepare_bcn_tasklet is properly terminated before the ieee80211_hw is released.

The issue was identified through static analysis.

---
 drivers/net/wireless/realtek/rtlwifi/pci.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/realtek/rtlwifi/pci.c +1 -0
index 40112b2c37775..b978d31e47ca9 100644
@@ -1675,6 +1675,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
 
 	synchronize_irq(rtlpci->pdev->irq);
 	tasklet_kill(&rtlpriv->works.irq_tasklet);
+	tasklet_kill(&rtlpriv->works.irq_prepare_bcn_tasklet);
 	cancel_work_sync(&rtlpriv->works.lps_change_work);
 }
 
Signature · 1 line
2.53.0
author maintainer
#25 lore raw

PATCH 25/508 bpf: Add CHECKSUM_COMPLETE to bpf test progs

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vadim Fedorenko <[email protected]>

[ Upstream commit a3cfe84cca28f205761a0450016593b0d728165e ]

Add special flag to validate that TC BPF program properly updates checksum information in skb.

Stable-dep-of: 972787479ee7 ("bpf: test_run: Fix the null pointer dereference issue in bpf_lwt_xmit_push_encap")

---
 include/uapi/linux/bpf.h       |  2 ++
 net/bpf/test_run.c             | 28 +++++++++++++++++++++++++++-
 tools/include/uapi/linux/bpf.h |  2 ++
 3 files changed, 31 insertions(+), 1 deletion(-)
include/uapi/linux/bpf.h +2 -0
index 08a0494736e6e..6950169329ef1 100644
@@ -1344,6 +1344,8 @@ enum {
 #define BPF_F_TEST_RUN_ON_CPU	(1U << 0)
 /* If set, XDP frames will be transmitted after processing */
 #define BPF_F_TEST_XDP_LIVE_FRAMES	(1U << 1)
+/* If set, apply CHECKSUM_COMPLETE to skb and validate the checksum */
+#define BPF_F_TEST_SKB_CHECKSUM_COMPLETE	(1U << 2)
 
 /* type for BPF_ENABLE_STATS */
 enum bpf_stats_type {
net/bpf/test_run.c +27 -1
index 3a1c82b797a30..774287ac17955 100644
@@ -966,7 +966,8 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 	void *data;
 	int ret;
 
-	if (kattr->test.flags || kattr->test.cpu || kattr->test.batch_size)
+	if ((kattr->test.flags & ~BPF_F_TEST_SKB_CHECKSUM_COMPLETE) ||
+	    kattr->test.cpu || kattr->test.batch_size)
 		return -EINVAL;
 
 	if (size < ETH_HLEN)
@@ -1017,6 +1018,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 
 	skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
 	__skb_put(skb, size);
+
 	if (ctx && ctx->ifindex > 1) {
 		dev = dev_get_by_index(net, ctx->ifindex);
 		if (!dev) {
@@ -1052,9 +1054,19 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 		__skb_push(skb, hh_len);
 	if (is_direct_pkt_access)
 		bpf_compute_data_pointers(skb);
+
 	ret = convert___skb_to_skb(skb, ctx);
 	if (ret)
 		goto out;
+
+	if (kattr->test.flags & BPF_F_TEST_SKB_CHECKSUM_COMPLETE) {
+		const int off = skb_network_offset(skb);
+		int len = skb->len - off;
+
+		skb->csum = skb_checksum(skb, off, len, 0);
+		skb->ip_summed = CHECKSUM_COMPLETE;
+	}
+
 	ret = bpf_test_run(prog, skb, repeat, &retval, &duration, false);
 	if (ret)
 		goto out;
@@ -1069,6 +1081,20 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 		}
 		memset(__skb_push(skb, hh_len), 0, hh_len);
 	}
+
+	if (kattr->test.flags & BPF_F_TEST_SKB_CHECKSUM_COMPLETE) {
+		const int off = skb_network_offset(skb);
+		int len = skb->len - off;
+		__wsum csum;
+
+		csum = skb_checksum(skb, off, len, 0);
+
+		if (csum_fold(skb->csum) != csum_fold(csum)) {
+			ret = -EBADMSG;
+			goto out;
+		}
+	}
+
 	convert_skb_to___skb(skb, ctx);
 
 	size = skb->len;
tools/include/uapi/linux/bpf.h +2 -0
index 2e064a1032a05..8967952de0c2e 100644
@@ -1344,6 +1344,8 @@ enum {
 #define BPF_F_TEST_RUN_ON_CPU	(1U << 0)
 /* If set, XDP frames will be transmitted after processing */
 #define BPF_F_TEST_XDP_LIVE_FRAMES	(1U << 1)
+/* If set, apply CHECKSUM_COMPLETE to skb and validate the checksum */
+#define BPF_F_TEST_SKB_CHECKSUM_COMPLETE	(1U << 2)
 
 /* type for BPF_ENABLE_STATS */
 enum bpf_stats_type {
Signature · 1 line
2.53.0
author maintainer
#26 lore raw

PATCH 26/508 bpf: test_run: Fix the null pointer dereference issue in bpf_lwt_xmit_push_encap

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Feng Yang <[email protected]>

[ Upstream commit 972787479ee73006fddb5e59ab5c8e733810ff42 ]

The bpf_lwt_xmit_push_encap helper needs to access skb_dst(skb)->dev to calculate the needed headroom:

	err = skb_cow_head(skb,
			   len + LL_RESERVED_SPACE(skb_dst(skb)->dev));

But skb->_skb_refdst may not be initialized when the skb is set up by bpf_prog_test_run_skb function. Executing bpf_lwt_push_ip_encap function in this scenario will trigger null pointer dereference, causing a kernel crash as Yinhao reported:

[  105.186365] BUG: kernel NULL pointer dereference, address: 0000000000000000
[  105.186382] #PF: supervisor read access in kernel mode
[  105.186388] #PF: error_code(0x0000) - not-present page
[  105.186393] PGD 121d3d067 P4D 121d3d067 PUD 106c83067 PMD 0
[  105.186404] Oops: 0000 [#1] PREEMPT SMP NOPTI
[  105.186412] CPU: 3 PID: 3250 Comm: poc Kdump: loaded Not tainted 6.19.0-rc5 #1
[  105.186423] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[  105.186427] RIP: 0010:bpf_lwt_push_ip_encap+0x1eb/0x520
[  105.186443] Code: 0f 84 de 01 00 00 0f b7 4a 04 66 85 c9 0f 85 47 01 00 00 31 c0 5b 5d 41 5c 41 5d 41 5e c3 cc cc cc cc 48 8b 73 58 48 83 e6 fe <48> 8b 36 0f b7 be ec 00 00 00 0f b7 b6 e6 00 00 00 01 fe 83 e6 f0
[  105.186449] RSP: 0018:ffffbb0e0387bc50 EFLAGS: 00010246
[  105.186455] RAX: 000000000000004e RBX: ffff94c74e036500 RCX: ffff94c74874da00
[  105.186460] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff94c74e036500
[  105.186463] RBP: 0000000000000001 R08: 0000000000000002 R09: 0000000000000000
[  105.186467] R10: ffffbb0e0387bd50 R11: 0000000000000000 R12: ffffbb0e0387bc98
[  105.186471] R13: 0000000000000014 R14: 0000000000000000 R15: 0000000000000002
[  105.186484] FS:  00007f166aa4d680(0000) GS:ffff94c8b7780000(0000) knlGS:0000000000000000
[  105.186490] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  105.186494] CR2: 0000000000000000 CR3: 000000015eade001 CR4: 0000000000770ee0
[  105.186499] PKRU: 55555554
[  105.186502] Call Trace:
[  105.186507]  <TASK>
[  105.186513]  bpf_lwt_xmit_push_encap+0x2b/0x40
[  105.186522]  bpf_prog_a75eaad51e517912+0x41/0x49
[  105.186536]  ? kvm_clock_get_cycles+0x18/0x30
[  105.186547]  ? ktime_get+0x3c/0xa0
[  105.186554]  bpf_test_run+0x195/0x320
[  105.186563]  ? bpf_test_run+0x10f/0x320
[  105.186579]  bpf_prog_test_run_skb+0x2f5/0x4f0
[  105.186590]  __sys_bpf+0x69c/0xa40
[  105.186603]  __x64_sys_bpf+0x1e/0x30
[  105.186611]  do_syscall_64+0x59/0x110
[  105.186620]  entry_SYSCALL_64_after_hwframe+0x76/0xe0
[  105.186649] RIP: 0033:0x7f166a97455d

Temporarily add the setting of skb->_skb_refdst before bpf_test_run to resolve the issue.

---
 net/bpf/test_run.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
net/bpf/test_run.c +15 -0
index 774287ac17955..c9c6f675d8e21 100644
@@ -1067,6 +1067,21 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 		skb->ip_summed = CHECKSUM_COMPLETE;
 	}
 
+	if (prog->type == BPF_PROG_TYPE_LWT_XMIT) {
+		if (!ipv6_bpf_stub) {
+			pr_warn_once("Please test this program with the IPv6 module loaded\n");
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
+#if IS_ENABLED(CONFIG_IPV6)
+		/* For CONFIG_IPV6=n, ipv6_bpf_stub is NULL which is
+		 * handled by the above if statement.
+		 */
+		dst_hold(&net->ipv6.ip6_null_entry->dst);
+		skb_dst_set(skb, &net->ipv6.ip6_null_entry->dst);
+#endif
+	}
+
 	ret = bpf_test_run(prog, skb, repeat, &retval, &duration, false);
 	if (ret)
 		goto out;
Signature · 1 line
2.53.0
author maintainer
#27 lore raw

PATCH 27/508 dpaa2: add independent dependencies for FSL_DPAA2_SWITCH

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cai Xinchen <[email protected]>

[ Upstream commit 12589892f41c4c645c80ef9f036f7451a6045624 ]

Since the commit 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") included dpaa2-mac.o in the driver, but it didn't select PCS_LYNX, PHYLINK and FSL_XGMAC_MDIO. it will lead to link error, such as
undefined reference to phylink_ethtool_ksettings_set' undefined reference to lynx_pcs_create_fwnode'

And the same reason as the commit d2624e70a2f53 ("dpaa2-eth: select XGMAC_MDIO for MDIO bus support"), enable the FSL_XGMAC_MDIO Kconfig option in order to have MDIO access to internal and external PHYs.

Because dpaa2-switch uses fsl_mc_driver APIs, add depends on FSL_MC_BUS && FSL_MC_DPIO as FSL_DPAA2_SWITCH do.

FSL_XGMAC_MDIO and FSL_MC_BUS depend on OF, thus the dependence of FSL_MC_BUS can satisfy FSL_XGMAC_MDIO's OF requirement.

Fixes 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support")
---
 drivers/net/ethernet/freescale/dpaa2/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)
drivers/net/ethernet/freescale/dpaa2/Kconfig +4 -0
index d029b69c3f183..36280e5d99e1f 100644
@@ -34,6 +34,10 @@ config FSL_DPAA2_SWITCH
 	tristate "Freescale DPAA2 Ethernet Switch"
 	depends on BRIDGE || BRIDGE=n
 	depends on NET_SWITCHDEV
+	depends on FSL_MC_BUS && FSL_MC_DPIO
+	select PHYLINK
+	select PCS_LYNX
+	select FSL_XGMAC_MDIO
 	help
 	  Driver for Freescale DPAA2 Ethernet Switch. This driver manages
 	  switch objects discovered on the Freeescale MC bus.
Signature · 1 line
2.53.0
author maintainer
#28 lore raw

PATCH 28/508 dpaa2: compile dpaa2 even CONFIG_FSL_DPAA2_ETH=n

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cai Xinchen <[email protected]>

[ Upstream commit 97daf00745f7f9f261b0e91418de6e79d7826c36 ]

CONFIG_FSL_DPAA2_ETH and CONFIG_FSL_DPAA2_SWITCH are not associated, but the compilation of FSL_DPAA2_SWITCH depends on the compilation of the dpaa2 folder. The files controlled by CONFIG_FSL_DPAA2_SWITCH in the dpaa2 folder are not controlled by CONFIG_FSL_DPAA2_ETH, except for the files controlled by CONFIG_FSL_DPAA2_SWITCH. Therefore, removing the restriction will not affect the compilation of the files in the directory.

Fixes f48298d3fbfaa ("staging: dpaa2-switch: move the driver out of staging")
---
 drivers/net/ethernet/freescale/Makefile | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/freescale/Makefile +1 -2
index de7b318422330..d0a259e47960f 100644
@@ -22,6 +22,5 @@ ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
 obj-$(CONFIG_FSL_FMAN) += fman/
 obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/
 
-obj-$(CONFIG_FSL_DPAA2_ETH) += dpaa2/
-
+obj-y += dpaa2/
 obj-y += enetc/
Signature · 1 line
2.53.0
author maintainer
#29 lore raw

PATCH 29/508 s390/bpf: Zero-extend bpf prog return values and kfunc arguments

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ilya Leoshkevich <[email protected]>

[ Upstream commit 202e42e4aa890172366354b233c42c73107a3f59 ]

s390x ABI requires callers to zero-extend unsigned arguments and sign-extend signed arguments, and callees to zero-extend unsigned return values and sign-extend signed return values.

s390 BPF JIT currently implements only sign extension. Fix this omission and implement zero extension too.

---
 arch/s390/net/bpf_jit_comp.c | 39 ++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 15 deletions(-)
arch/s390/net/bpf_jit_comp.c +24 -15
index 5a64d34a37482..491789420d7c0 100644
@@ -759,25 +759,34 @@ static int bpf_jit_probe_mem(struct bpf_jit *jit, struct bpf_prog *fp,
 }
 
 /*
- * Sign-extend the register if necessary
+ * Sign- or zero-extend the register if necessary
  */
-static int sign_extend(struct bpf_jit *jit, int r, u8 size, u8 flags)
+static int sign_zero_extend(struct bpf_jit *jit, int r, u8 size, u8 flags)
 {
-	if (!(flags & BTF_FMODEL_SIGNED_ARG))
-		return 0;
-
 	switch (size) {
 	case 1:
-		/* lgbr %r,%r */
-		EMIT4(0xb9060000, r, r);
+		if (flags & BTF_FMODEL_SIGNED_ARG)
+			/* lgbr %r,%r */
+			EMIT4(0xb9060000, r, r);
+		else
+			/* llgcr %r,%r */
+			EMIT4(0xb9840000, r, r);
 		return 0;
 	case 2:
-		/* lghr %r,%r */
-		EMIT4(0xb9070000, r, r);
+		if (flags & BTF_FMODEL_SIGNED_ARG)
+			/* lghr %r,%r */
+			EMIT4(0xb9070000, r, r);
+		else
+			/* llghr %r,%r */
+			EMIT4(0xb9850000, r, r);
 		return 0;
 	case 4:
-		/* lgfr %r,%r */
-		EMIT4(0xb9140000, r, r);
+		if (flags & BTF_FMODEL_SIGNED_ARG)
+			/* lgfr %r,%r */
+			EMIT4(0xb9140000, r, r);
+		else
+			/* llgfr %r,%r */
+			EMIT4(0xb9160000, r, r);
 		return 0;
 	case 8:
 		return 0;
@@ -1452,9 +1461,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
 				return -1;
 
 			for (j = 0; j < m->nr_args; j++) {
-				if (sign_extend(jit, BPF_REG_1 + j,
-						m->arg_size[j],
-						m->arg_flags[j]))
+				if (sign_zero_extend(jit, BPF_REG_1 + j,
+						     m->arg_size[j],
+						     m->arg_flags[j]))
 					return -1;
 			}
 		}
@@ -2186,7 +2195,7 @@ static int invoke_bpf_prog(struct bpf_tramp_jit *tjit,
 	call_r1(jit);
 	/* stg %r2,retval_off(%r15) */
 	if (save_ret) {
-		if (sign_extend(jit, REG_2, m->ret_size, m->ret_flags))
+		if (sign_zero_extend(jit, REG_2, m->ret_size, m->ret_flags))
 			return -1;
 		EMIT6_DISP_LH(0xe3000000, 0x0024, REG_2, REG_0, REG_15,
 			      tjit->retval_off);
Signature · 1 line
2.53.0
author maintainer
#30 lore raw

PATCH 30/508 params: Replace __modinit with __init_or_module

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Petr Pavlu <[email protected]>

[ Upstream commit 3cb0c3bdea5388519bc1bf575dca6421b133302b ]

Remove the custom __modinit macro from kernel/params.c and instead use the common __init_or_module macro from include/linux/module.h. Both provide the same functionality.

Stable-dep-of: deffe1edba62 ("module: Fix freeing of charp module parameters when CONFIG_SYSFS=n")

---
 kernel/params.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
kernel/params.c +5 -10
index e39ac5420cd6d..2cfa12404ed0b 100644
@@ -593,12 +593,6 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
 }
 #endif
 
-#ifdef CONFIG_MODULES
-#define __modinit
-#else
-#define __modinit __init
-#endif
-
 #ifdef CONFIG_SYSFS
 void kernel_param_lock(struct module *mod)
 {
@@ -623,9 +617,9 @@ EXPORT_SYMBOL(kernel_param_unlock);
  * create file in sysfs.  Returns an error on out of memory.  Always cleans up
  * if there's an error.
  */
-static __modinit int add_sysfs_param(struct module_kobject *mk,
-				     const struct kernel_param *kp,
-				     const char *name)
+static __init_or_module int add_sysfs_param(struct module_kobject *mk,
+					    const struct kernel_param *kp,
+					    const char *name)
 {
 	struct module_param_attrs *new_mp;
 	struct attribute **new_attrs;
@@ -759,7 +753,8 @@ void destroy_params(const struct kernel_param *params, unsigned num)
 			params[i].ops->free(params[i].arg);
 }
 
-struct module_kobject __modinit * lookup_or_create_module_kobject(const char *name)
+struct module_kobject * __init_or_module
+lookup_or_create_module_kobject(const char *name)
 {
 	struct module_kobject *mk;
 	struct kobject *kobj;
Signature · 1 line
2.53.0
author maintainer
#31 lore raw

PATCH 31/508 module: Fix freeing of charp module parameters when CONFIG_SYSFS=n

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Petr Pavlu <[email protected]>

[ Upstream commit deffe1edba626d474fef38007c03646ca5876a0e ]

When setting a charp module parameter, the param_set_charp() function allocates memory to store a copy of the input value. Later, when the module is potentially unloaded, the destroy_params() function is called to free this allocated memory.

However, destroy_params() is available only when CONFIG_SYSFS=y, otherwise only a dummy variant is present. In the unlikely case that the kernel is configured with CONFIG_MODULES=y and CONFIG_SYSFS=n, this results in a memory leak of charp values when a module is unloaded.

Fix this issue by making destroy_params() always available when CONFIG_MODULES=y. Rename the function to module_destroy_params() to clarify that it is intended for use by the module loader.

Fixes e180a6b7759a ("param: fix charp parameters set via sysfs")
---
 include/linux/moduleparam.h | 11 +++--------
 kernel/module/main.c        |  4 ++--
 kernel/params.c             | 27 ++++++++++++++++++---------
 3 files changed, 23 insertions(+), 19 deletions(-)
include/linux/moduleparam.h +3 -8
index 061e19c94a6bc..f73ca4d62683b 100644
@@ -392,14 +392,9 @@ extern char *parse_args(const char *name,
 				     const char *doing, void *arg));
 
 /* Called by module remove. */
-#ifdef CONFIG_SYSFS
-extern void destroy_params(const struct kernel_param *params, unsigned num);
-#else
-static inline void destroy_params(const struct kernel_param *params,
-				  unsigned num)
-{
-}
-#endif /* !CONFIG_SYSFS */
+#ifdef CONFIG_MODULES
+void module_destroy_params(const struct kernel_param *params, unsigned int num);
+#endif
 
 /* All the helper functions */
 /* The macros to do compile-time type checking stolen from Jakub
kernel/module/main.c +2 -2
index 76d90c20de674..ac528fbb62824 100644
@@ -1261,7 +1261,7 @@ static void free_module(struct module *mod)
 	module_unload_free(mod);
 
 	/* Free any allocated parameters. */
-	destroy_params(mod->kp, mod->num_kp);
+	module_destroy_params(mod->kp, mod->num_kp);
 
 	if (is_livepatch_module(mod))
 		free_module_elf(mod);
@@ -2998,7 +2998,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	mod_sysfs_teardown(mod);
  coming_cleanup:
 	mod->state = MODULE_STATE_GOING;
-	destroy_params(mod->kp, mod->num_kp);
+	module_destroy_params(mod->kp, mod->num_kp);
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
 	klp_module_going(mod);
kernel/params.c +18 -9
index 2cfa12404ed0b..9d09ea99363fc 100644
@@ -744,15 +744,6 @@ void module_param_sysfs_remove(struct module *mod)
 }
 #endif
 
-void destroy_params(const struct kernel_param *params, unsigned num)
-{
-	unsigned int i;
-
-	for (i = 0; i < num; i++)
-		if (params[i].ops->free)
-			params[i].ops->free(params[i].arg);
-}
-
 struct module_kobject * __init_or_module
 lookup_or_create_module_kobject(const char *name)
 {
@@ -987,3 +978,21 @@ static int __init param_sysfs_builtin_init(void)
 late_initcall(param_sysfs_builtin_init);
 
 #endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_MODULES
+
+/*
+ * module_destroy_params - free all parameters for one module
+ * @params: module parameters (array)
+ * @num: number of module parameters
+ */
+void module_destroy_params(const struct kernel_param *params, unsigned int num)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++)
+		if (params[i].ops->free)
+			params[i].ops->free(params[i].arg);
+}
+
+#endif /* CONFIG_MODULES */
Signature · 1 line
2.53.0
author maintainer
#32 lore raw

PATCH 32/508 wifi: mt76: mt7921: Reset ampdu_state state in case of failure in mt76_connac2_tx_check_aggr()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sean Wang <[email protected]>

[ Upstream commit 53ffffeb9624ffab6d9a3b1da8635a23f1172b5e ]

Reset ampdu_state if ieee80211_start_tx_ba_session() fails in mt76_connac2_tx_check_aggr(), otherwise the driver may incorrectly assume aggregation is active and skip future BA setup attempts.

Fixes 163f4d22c118 ("mt76: mt7921: add MAC support")
---
 drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +4 -2
index 6a637d4f42360..a24b2fd3c7b82 100644
@@ -1121,8 +1121,10 @@ void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
 		return;
 
 	wcid = (struct mt76_wcid *)sta->drv_priv;
-	if (!test_and_set_bit(tid, &wcid->ampdu_state))
-		ieee80211_start_tx_ba_session(sta, tid, 0);
+	if (!test_and_set_bit(tid, &wcid->ampdu_state)) {
+		if (ieee80211_start_tx_ba_session(sta, tid, 0))
+			clear_bit(tid, &wcid->ampdu_state);
+	}
 }
 EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
 
Signature · 1 line
2.53.0
author maintainer
#33 lore raw

PATCH 33/508 wifi: mt76: mt7615: fix use_cts_prot support

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ryder Lee <[email protected]>

[ Upstream commit 1974a67d9b65c29a0a9426e32e8cd8c056de48b7 ]

Driver should not directly write WTBL to prevent overwritten issues.

With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.

---
 .../net/wireless/mediatek/mt76/mt7615/mac.c   | 15 ------
 .../net/wireless/mediatek/mt76/mt7615/main.c  |  7 +--
 .../net/wireless/mediatek/mt76/mt7615/mcu.c   | 47 +++++++++++++++++++
 .../wireless/mediatek/mt76/mt7615/mt7615.h    |  5 +-
 .../net/wireless/mediatek/mt76/mt7615/regs.h  |  2 -
 5 files changed, 53 insertions(+), 23 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mac.c +0 -15
index 7ba789834e8df..1e473f490b4bd 100644
@@ -1174,21 +1174,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
 }
 EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
 
-void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
-			      struct ieee80211_vif *vif, bool enable)
-{
-	struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
-	u32 addr;
-
-	addr = mt7615_mac_wtbl_addr(dev, mvif->sta.wcid.idx) + 3 * 4;
-
-	if (enable)
-		mt76_set(dev, addr, MT_WTBL_W3_RTS);
-	else
-		mt76_clear(dev, addr, MT_WTBL_W3_RTS);
-}
-EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
-
 static int
 mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 			   struct ieee80211_key_conf *key,
drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 -3
index dab16b5fc3861..b908ccfa48778 100644
@@ -597,9 +597,6 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT)
-		mt7615_mac_enable_rtscts(dev, vif, info->use_cts_prot);
-
 	if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
 		mt7615_mcu_add_bss_info(phy, vif, NULL, true);
 		mt7615_mcu_sta_add(phy, vif, NULL, true);
@@ -612,6 +609,10 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
 		       BSS_CHANGED_BEACON_ENABLED))
 		mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
 
+	if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+		mt7615_mcu_set_protection(phy, vif, info->ht_operation_mode,
+					  info->use_cts_prot);
+
 	if (changed & BSS_CHANGED_PS)
 		mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);
 
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +47 -0

50 lines not on this page · raw message

drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +2 -3
index fa83b255e180c..39388acfb94ba 100644
@@ -466,8 +466,6 @@ void mt7615_mac_reset_counters(struct mt7615_phy *phy);
 void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
 void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable);
 void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy);
-void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,
-			      struct ieee80211_vif *vif, bool enable);
 void mt7615_mac_sta_poll(struct mt7615_dev *dev);
 int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
 			  struct sk_buff *skb, struct mt76_wcid *wcid,
@@ -522,7 +520,8 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);
 int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
 int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
 int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
-
+int mt7615_mcu_set_protection(struct mt7615_phy *phy, struct ieee80211_vif *vif,
+			      u8 ht_mode, bool use_cts_prot);
 int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
 		       struct ieee80211_channel *chan, int duration);
 
drivers/net/wireless/mediatek/mt76/mt7615/regs.h +0 -2
index 806b3887c541c..9e6d55c91b269 100644
@@ -455,8 +455,6 @@ enum mt7615_reg_base {
 #define MT_WTBL_RIUCR3_RATE6		GENMASK(19, 8)
 #define MT_WTBL_RIUCR3_RATE7		GENMASK(31, 20)
 
-#define MT_WTBL_W3_RTS			BIT(22)
-
 #define MT_WTBL_W5_CHANGE_BW_RATE	GENMASK(7, 5)
 #define MT_WTBL_W5_SHORT_GI_20		BIT(8)
 #define MT_WTBL_W5_SHORT_GI_40		BIT(9)
Signature · 1 line
2.53.0
author maintainer
#34 lore raw

PATCH 34/508 wifi: mt76: mt7915: fix use_cts_prot support

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ryder Lee <[email protected]>

[ Upstream commit 8b2c26562b95c6397e132d21f2bd3d73aaee0c0a ]

With this fix, when driver needs to adjust its behavior for compatibility, especially concerning older 11g/n devices, by enabling or disabling CTS protection frames, often for hidden SSIDs or to manage legacy clients.

---
 .../net/wireless/mediatek/mt76/mt7915/mac.c   | 13 ----
 .../net/wireless/mediatek/mt76/mt7915/main.c  |  7 ++-
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 62 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.h   | 11 ++++
 .../wireless/mediatek/mt76/mt7915/mt7915.h    |  4 ++
 5 files changed, 81 insertions(+), 16 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +0 -13
index 92d7dc8e3cc55..e2983dbf05a90 100644
@@ -228,19 +228,6 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
 	rcu_read_unlock();
 }
 
-void mt7915_mac_enable_rtscts(struct mt7915_dev *dev,
-			      struct ieee80211_vif *vif, bool enable)
-{
-	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-	u32 addr;
-
-	addr = mt7915_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5);
-	if (enable)
-		mt76_set(dev, addr, BIT(5));
-	else
-		mt76_clear(dev, addr, BIT(5));
-}
-
 static void
 mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
 		     struct mt7915_sta *msta, struct sk_buff *skb,
drivers/net/wireless/mediatek/mt76/mt7915/main.c +4 -3
index c312a0fa199ae..bad92fa4c8fc6 100644
@@ -68,7 +68,7 @@ int mt7915_run(struct ieee80211_hw *hw)
 	if (ret)
 		goto out;
 
-	ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,
+	ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, MT7915_RTS_LEN_THRES,
 					     phy->mt76->band_idx);
 	if (ret)
 		goto out;
@@ -623,8 +623,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
 	if (set_sta == 1)
 		mt7915_mcu_add_sta(dev, vif, NULL, true);
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT)
-		mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
+	if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
+		mt7915_mcu_set_protection(phy, vif, info->ht_operation_mode,
+					  info->use_cts_prot);
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
 		int slottime = info->use_short_slot ? 9 : 20;
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +62 -0

68 lines not on this page · raw message

drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +11 -0
index 1592b5d6751a0..acc1371a94b10 100644
@@ -399,6 +399,17 @@ struct bss_info_inband_discovery {
 	__le16 prob_rsp_len;
 } __packed __aligned(4);
 
+struct bss_info_prot {
+	__le16 tag;
+	__le16 len;
+	__le32 prot_type;
+	__le32 prot_mode;
+	__le32 rts_len_thres;
+	__le16 he_rts_thres;
+	u8 rts_pkt_thres;
+	u8 rsv[5];
+} __packed;
+
 enum {
 	BSS_INFO_BCN_CSA,
 	BSS_INFO_BCN_BCC,
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +4 -0
index 14d4bbeae9d63..b16c798ec2824 100644
@@ -83,6 +83,8 @@
 #define MT7915_CRIT_TEMP		110
 #define MT7915_MAX_TEMP			120
 
+#define MT7915_RTS_LEN_THRES		0x92b
+
 struct mt7915_vif;
 struct mt7915_sta;
 struct mt7915_dfs_pulse;
@@ -453,6 +455,8 @@ int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *v
 				 u32 changed);
 int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  int enable, u32 changed);
+int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+			      u8 ht_mode, bool use_cts_prot);
 int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
 			    struct ieee80211_he_obss_pd *he_obss_pd);
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
Signature · 1 line
2.53.0
author maintainer
#35 lore raw

PATCH 35/508 wifi: mt76: mt7996: fix FCS error flag check in RX descriptor

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alok Tiwari <[email protected]>

[ Upstream commit d8db56142e531f060c938fa0b5175ed6c8cabb11 ]

The mt7996 driver currently checks the MT_RXD3_NORMAL_FCS_ERR bit in rxd1 whereas other Connac3-based drivers(mt7925) correctly check this bit in rxd3.

Since the MT_RXD3_NORMAL_FCS_ERR bit is defined in the fourth RX descriptor word (rxd3), update mt7996 to use the proper descriptor field. This change aligns mt7996 with mt7925 and the rest of the Connac3 family.

Fixes 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
---
 drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -1
index 3dd503b363ce0..9270a68e6a38d 100644
@@ -528,7 +528,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
 	    !(csum_status & (BIT(0) | BIT(2) | BIT(3))))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	if (rxd1 & MT_RXD3_NORMAL_FCS_ERR)
+	if (rxd3 & MT_RXD3_NORMAL_FCS_ERR)
 		status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
 	if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR)
Signature · 1 line
2.53.0
author maintainer
#36 lore raw

PATCH 36/508 arm64: cpufeature: Make PMUVer and PerfMon unsigned

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: James Clark <[email protected]>

[ Upstream commit d1dcc20bcc40efe1f1c71639376c91dafa489222 ]

On the host, this change doesn't make a difference because the fields are defined as FTR_EXACT. However, KVM allows userspace to set these fields for a guest and overrides the type to be FTR_LOWER_SAFE. And while KVM used to do an unsigned comparison to validate that the new value is lower than what the hardware provides, since the linked commit it uses the generic sanitization framework which does a signed comparison.

Fix it by defining these fields as unsigned. In theory, without this fix, userspace could set a higher PMU version than the hardware supports by providing any value with the top bit set.

Fixes c118cead07a7 ("KVM: arm64: Use generic sanitisation for ID_(AA64)DFR0_EL1")
---
 arch/arm64/kernel/cpufeature.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kernel/cpufeature.c +2 -2
index 4561c4a670afb..5db25bfb854ff 100644
@@ -453,7 +453,7 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
 	 * We can instantiate multiple PMU instances with different levels
 	 * of support.
 	 */
-	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_EL1_PMUVer_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_EL1_PMUVer_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_EL1_DebugVer_SHIFT, 4, 0x6),
 	ARM64_FTR_END,
 };
@@ -597,7 +597,7 @@ static const struct arm64_ftr_bits ftr_id_pfr2[] = {
 
 static const struct arm64_ftr_bits ftr_id_dfr0[] = {
 	/* [31:28] TraceFilt */
-	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_EL1_PerfMon_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_EL1_PerfMon_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MProfDbg_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
Signature · 1 line
2.53.0
author maintainer
#37 lore raw

PATCH 37/508 wifi: mt76: mt7996: fix struct mt7996_mcu_uni_event

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: StanleyYP Wang <[email protected]>

[ Upstream commit efbd5bf395f4e6b45a87f3835d4c2e28170c77c5 ]

The cid field is defined as a two-byte value in the firmware.

Fixes 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
---
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +-
 drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +1 -1
index 8ab55fc705f07..9f8c312b64d75 100644
@@ -204,7 +204,7 @@ mt7996_mcu_parse_response(struct mt76_dev *mdev, int cmd,
 		event = (struct mt7996_mcu_uni_event *)skb->data;
 		ret = le32_to_cpu(event->status);
 		/* skip invalid event */
-		if (mcu_cmd != event->cid)
+		if (mcu_cmd != le16_to_cpu(event->cid))
 			ret = -EAGAIN;
 	} else {
 		skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +2 -2
index 58504b80eae8b..fee79666fe162 100644
@@ -25,8 +25,8 @@ struct mt7996_mcu_rxd {
 };
 
 struct mt7996_mcu_uni_event {
-	u8 cid;
-	u8 __rsv[3];
+	__le16 cid;
+	u8 __rsv[2];
 	__le32 status; /* 0: success, others: fail */
 } __packed;
 
Signature · 1 line
2.53.0
author maintainer
#38 lore raw

PATCH 38/508 wifi: mt76: mt7915: fix use-after-free bugs in mt7915_mac_dump_work()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Duoming Zhou <[email protected]>

[ Upstream commit 1146d0946b5358fad24812bd39d68f31cd40cc34 ]

When the mt7915 pci chip is detaching, the mt7915_crash_data is released in mt7915_coredump_unregister(). However, the work item dump_work may still be running or pending, leading to UAF bugs when the already freed crash_data is dereferenced again in mt7915_mac_dump_work().

The race condition can occur as follows:

CPU 0 (removal path)               | CPU 1 (workqueue)
mt7915_pci_remove()                | mt7915_sys_recovery_set()
 mt7915_unregister_device()        |  mt7915_reset()
  mt7915_coredump_unregister()     |   queue_work()
   vfree(dev->coredump.crash_data) | mt7915_mac_dump_work()
                                   |  crash_data-> // UAF

Fix this by ensuring dump_work is properly canceled before the crash_data is deallocated. Add cancel_work_sync() in mt7915_unregister_device() to synchronize with any pending or executing dump work.

Fixes 4dbcb9125cc3 ("wifi: mt76: mt7915: enable coredump support")
---
 drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
index e9068718b3d1f..529a3640944b5 100644
@@ -1254,6 +1254,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
 
 void mt7915_unregister_device(struct mt7915_dev *dev)
 {
+	cancel_work_sync(&dev->dump_work);
 	mt7915_unregister_ext_phy(dev);
 	mt7915_coredump_unregister(dev);
 	mt7915_unregister_thermal(&dev->phy);
Signature · 1 line
2.53.0
author maintainer
#39 lore raw

PATCH 39/508 bpf, devmap: Remove unnecessary if check in for loop

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thorsten Blum <[email protected]>

[ Upstream commit 2317dc2c22cc353b699c7d1db47b2fe91f54055c ]

The iterator variable dst cannot be NULL and the if check can be removed. Remove it and fix the following Coccinelle/coccicheck warning reported by itnull.cocci:

ERROR: iterator variable bound on line 762 cannot be NULL

Stable-dep-of: 8ed82f807bb0 ("bpf: Use RCU-safe iteration in dev_map_redirect_multi() SKB path")

---
 kernel/bpf/devmap.c | 3 ---
 1 file changed, 3 deletions(-)
kernel/bpf/devmap.c +0 -3
index 3bdec239be610..3939221bd6098 100644
@@ -765,9 +765,6 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
 		for (i = 0; i < dtab->n_buckets; i++) {
 			head = dev_map_index_hash(dtab, i);
 			hlist_for_each_entry_safe(dst, next, head, index_hlist) {
-				if (!dst)
-					continue;
-
 				if (is_ifindex_excluded(excluded_devices, num_excluded,
 							dst->dev->ifindex))
 					continue;
Signature · 1 line
2.53.0
author maintainer
#40 lore raw

PATCH 40/508 bpf: Use RCU-safe iteration in dev_map_redirect_multi() SKB path

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Carlier <[email protected]>

[ Upstream commit 8ed82f807bb09d2c8455aaa665f2c6cb17bc6a19 ]

The DEVMAP_HASH branch in dev_map_redirect_multi() uses hlist_for_each_entry_safe() to iterate hash buckets, but this function runs under RCU protection (called from xdp_do_generic_redirect_map() in softirq context). Concurrent writers (__dev_map_hash_update_elem, dev_map_hash_delete_elem) modify the list using RCU primitives (hlist_add_head_rcu, hlist_del_rcu).

hlist_for_each_entry_safe() performs plain pointer dereferences without rcu_dereference(), missing the acquire barrier needed to pair with writers' rcu_assign_pointer(). On weakly-ordered architectures (ARM64, POWER), a reader can observe a partially-constructed node. It also defeats CONFIG_PROVE_RCU lockdep validation and KCSAN data-race detection.

Replace with hlist_for_each_entry_rcu() using rcu_read_lock_bh_held() as the lockdep condition, consistent with the rcu_dereference_check() used in the DEVMAP (non-hash) branch of the same functions. Also fix the same incorrect lockdep_is_held(&dtab->index_lock) condition in dev_map_enqueue_multi(), where the lock is not held either.

Fixes e624d4ed4aa8 ("xdp: Extend xdp_redirect_map with broadcast support")
---
 kernel/bpf/devmap.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/bpf/devmap.c +2 -3
index 3939221bd6098..c169f0624e100 100644
@@ -642,7 +642,7 @@ int dev_map_enqueue_multi(struct xdp_frame *xdpf, struct net_device *dev_rx,
 		for (i = 0; i < dtab->n_buckets; i++) {
 			head = dev_map_index_hash(dtab, i);
 			hlist_for_each_entry_rcu(dst, head, index_hlist,
-						 lockdep_is_held(&dtab->index_lock)) {
+						rcu_read_lock_bh_held()) {
 				if (!is_valid_dst(dst, xdpf))
 					continue;
 
@@ -724,7 +724,6 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
 	struct bpf_dtab_netdev *dst, *last_dst = NULL;
 	int excluded_devices[1+MAX_NEST_DEV];
 	struct hlist_head *head;
-	struct hlist_node *next;
 	int num_excluded = 0;
 	unsigned int i;
 	int err;
@@ -764,7 +763,7 @@ int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
 	} else { /* BPF_MAP_TYPE_DEVMAP_HASH */
 		for (i = 0; i < dtab->n_buckets; i++) {
 			head = dev_map_index_hash(dtab, i);
-			hlist_for_each_entry_safe(dst, next, head, index_hlist) {
+			hlist_for_each_entry_rcu(dst, head, index_hlist, rcu_read_lock_bh_held()) {
 				if (is_ifindex_excluded(excluded_devices, num_excluded,
 							dst->dev->ifindex))
 					continue;
Signature · 1 line
2.53.0
author maintainer
#41 lore raw

PATCH 41/508 wifi: rtw89: phy: fix uninitialized variable access in rtw89_phy_cfo_set_crystal_cap()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexey Velichayshiy <[email protected]>

[ Upstream commit 047cddf88c611e616d49a00311d4722e46286234 ]

In the rtw89_phy_cfo_set_crystal_cap() function, for chips other than RTL8852A/RTL8851B, the values read by rtw89_mac_read_xtal_si() are stored into the local variables sc_xi_val and sc_xo_val. If either read fails, these variables remain uninitialized, they are later used to update cfo->crystal_cap and in debug print statements. This can lead to undefined behavior.

Fix the issue by initializing sc_xi_val and sc_xo_val to zero, like is implemented in vendor driver.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes 8379fa611536 ("rtw89: 8852c: add write/read crystal function in CFO tracking")
---
 drivers/net/wireless/realtek/rtw89/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/phy.c +1 -1
index 457c1dd31bf9d..3da2f623c01c6 100644
@@ -2434,7 +2434,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
 {
 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
 	const struct rtw89_chip_info *chip = rtwdev->chip;
-	u8 sc_xi_val, sc_xo_val;
+	u8 sc_xi_val = 0, sc_xo_val = 0;
 
 	if (!force && cfo->crystal_cap == crystal_cap)
 		return;
Signature · 1 line
2.53.0
author maintainer
#42 lore raw

PATCH 42/508 r8152: fix incorrect register write to USB_UPHY_XTAL

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chih Kai Hsu <[email protected]>

[ Upstream commit 48afd5124fd6129c46fd12cb06155384b1c4a0c4 ]

The old code used ocp_write_byte() to clear the OOBS_POLLING bit (BIT(8)) in the USB_UPHY_XTAL register, but this doesn't correctly clear a bit in the upper byte of the 16-bit register.

Fix this by using ocp_write_word() instead.

---
 drivers/net/usb/r8152.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/r8152.c +1 -1
index 91cf24fb5531f..d39d66e25b01b 100644
@@ -3859,7 +3859,7 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)
 		case RTL_VER_15:
 			ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPHY_XTAL);
 			ocp_data &= ~OOBS_POLLING;
-			ocp_write_byte(tp, MCU_TYPE_USB, USB_UPHY_XTAL, ocp_data);
+			ocp_write_word(tp, MCU_TYPE_USB, USB_UPHY_XTAL, ocp_data);
 			break;
 		default:
 			break;
Signature · 1 line
2.53.0
author maintainer
#43 lore raw

PATCH 43/508 powerpc/crash: fix backup region offset update to elfcorehdr

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sourabh Jain <[email protected]>

[ Upstream commit 789335cacdf37da93bb7c70322dff8c7e82881df ]

update_backup_region_phdr() in file_load_64.c iterates over all the program headers in the kdump kernel’s elfcorehdr and updates the p_offset of the program header whose physical address starts at 0.

However, the loop logic is incorrect because the program header pointer is not updated during iteration. Since elfcorehdr typically contains PT_NOTE entries first, the PT_LOAD program header with physical address 0 is never reached. As a result, its p_offset is not updated to point to the backup region.

Because of this behavior, the capture kernel exports the first 64 KB of the crashed kernel’s memory at offset 0, even though that memory actually lives in the backup region. When a crash happens, purgatory copies the first 64 KB of the crashed kernel’s memory into the backup region so the capture kernel can safely use it.

This has not caused problems so far because the first 64 KB is usually identical in both the crashed and capture kernels. However, this is just an assumption and is not guaranteed to always hold true.

Fix update_backup_region_phdr() to correctly update the p_offset of the program header with a starting physical address of 0 by correcting the logic used to iterate over the program headers.

Fixes cb350c1f1f86 ("powerpc/kexec_file: Prepare elfcore header for crashing kernel")
---
 arch/powerpc/kexec/file_load_64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kexec/file_load_64.c +1 -1
index 7b71737ae24cc..12cbfc9fce451 100644
@@ -773,7 +773,7 @@ static void update_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr)
 	unsigned int i;
 
 	phdr = (Elf64_Phdr *)(ehdr + 1);
-	for (i = 0; i < ehdr->e_phnum; i++) {
+	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
 		if (phdr->p_paddr == BACKUP_SRC_START) {
 			phdr->p_offset = image->arch.backup_start;
 			pr_debug("Backup region offset updated to 0x%lx\n",
Signature · 1 line
2.53.0
author maintainer
#44 lore raw

PATCH 44/508 selftests/powerpc: Re-order *FLAGS to follow lib.mk

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Madhavan Srinivasan <[email protected]>

[ Upstream commit 37496845c812db2a470d51088a59ee38156e8058 ]

In some powerpc/ sub-folder Makefiles, CFLAGS are defined before lib.mk include. Clean it up by re-ordering the flags to follow after the mk include. This is needed to support sub-folders in powerpc/ buildable on its own.

Stable-dep-of: 6e65886fceb2 ("selftests/powerpc: Suppress -Wmaybe-uninitialized with GCC 15")

---
 .../selftests/powerpc/benchmarks/Makefile     |  4 ++--
 .../selftests/powerpc/copyloops/Makefile      | 20 +++++++++----------
 .../selftests/powerpc/nx-gzip/Makefile        |  4 ++--
 .../selftests/powerpc/pmu/ebb/Makefile        | 20 +++++++++----------
 .../powerpc/pmu/event_code_tests/Makefile     |  4 ++--
 .../powerpc/pmu/sampling_tests/Makefile       |  4 ++--
 .../selftests/powerpc/primitives/Makefile     |  4 ++--
 .../selftests/powerpc/security/Makefile       |  4 ++--
 .../testing/selftests/powerpc/signal/Makefile |  3 ++-
 .../selftests/powerpc/stringloops/Makefile    | 10 +++++-----
 .../selftests/powerpc/switch_endian/Makefile  |  4 ++--
 .../selftests/powerpc/syscalls/Makefile       |  4 ++--
 tools/testing/selftests/powerpc/vphn/Makefile |  4 ++--
 13 files changed, 45 insertions(+), 44 deletions(-)
tools/testing/selftests/powerpc/benchmarks/Makefile +2 -2
index a32a6ab899144..75f5232c3aeca 100644
@@ -4,11 +4,11 @@ TEST_GEN_FILES := exec_target
 
 TEST_FILES := settings
 
-CFLAGS += -O2
-
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+CFLAGS += -O2
+
 $(TEST_GEN_PROGS): ../harness.c
 
 $(OUTPUT)/context_switch: ../utils.c
tools/testing/selftests/powerpc/copyloops/Makefile +10 -10
index 77594e697f2fa..72684ed589c0a 100644
@@ -1,14 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-# The loops are all 64-bit code
-CFLAGS += -m64
-CFLAGS += -I$(CURDIR)
-CFLAGS += -D SELFTEST
-CFLAGS += -maltivec
-CFLAGS += -mcpu=power4
-
-# Use our CFLAGS for the implicit .S rule & set the asm machine type
-ASFLAGS = $(CFLAGS) -Wa,-mpower4
-
 TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \
 		copyuser_p7_t0 copyuser_p7_t1 \
 		memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \
@@ -21,6 +11,16 @@ EXTRA_SOURCES := validate.c ../harness.c stubs.S
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+# The loops are all 64-bit code
+CFLAGS += -m64
+CFLAGS += -I$(CURDIR)
+CFLAGS += -D SELFTEST
+CFLAGS += -maltivec
+CFLAGS += -mcpu=power4
+
+# Use our CFLAGS for the implicit .S rule & set the asm machine type
+ASFLAGS = $(CFLAGS) -Wa,-mpower4
+
 $(OUTPUT)/copyuser_64_t%:	copyuser_64.S $(EXTRA_SOURCES)
 	$(CC) $(CPPFLAGS) $(CFLAGS) \
 		-D COPY_LOOP=test___copy_tofrom_user_base \
tools/testing/selftests/powerpc/nx-gzip/Makefile +2 -2
index 0785c2e99d407..b40991f902b2c 100644
@@ -1,8 +1,8 @@
-CFLAGS = -O3 -m64 -I./include -I../include
-
 TEST_GEN_FILES := gzfht_test gunz_test
 TEST_PROGS := nx-gzip-test.sh
 
 include ../../lib.mk
 
+CFLAGS = -O3 -m64 -I./include -I../include
+
 $(TEST_GEN_FILES): gzip_vas.c ../utils.c
tools/testing/selftests/powerpc/pmu/ebb/Makefile +10 -10
index 0101606902272..b3946ce17e0c1 100644
@@ -4,16 +4,6 @@ include ../../../../../build/Build.include
 noarg:
 	$(MAKE) -C ../../
 
-# The EBB handler is 64-bit code and everything links against it
-CFLAGS += -m64
-
-TMPOUT = $(OUTPUT)/TMPDIR/
-# Toolchains may build PIE by default which breaks the assembly
-no-pie-option := $(call try-run, echo 'int main() { return 0; }' | \
-        $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
-
-LDFLAGS += $(no-pie-option)
-
 TEST_GEN_PROGS := reg_access_test event_attributes_test cycles_test	\
 	 cycles_with_freeze_test pmc56_overflow_test		\
 	 ebb_vs_cpu_event_test cpu_event_vs_ebb_test		\
@@ -29,6 +19,16 @@ TEST_GEN_PROGS := reg_access_test event_attributes_test cycles_test	\
 top_srcdir = ../../../../../..
 include ../../../lib.mk
 
+# The EBB handler is 64-bit code and everything links against it
+CFLAGS += -m64
+
+TMPOUT = $(OUTPUT)/TMPDIR/
+# Toolchains may build PIE by default which breaks the assembly
+no-pie-option := $(call try-run, echo 'int main() { return 0; }' | \
+        $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
+
+LDFLAGS += $(no-pie-option)
+
 $(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c \
 	       ebb.c ebb_handler.S trace.c busy_loop.S
 
tools/testing/selftests/powerpc/pmu/event_code_tests/Makefile +2 -2
index 4e07d70464574..509d4b235b9e5 100644
@@ -1,6 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-CFLAGS += -m64
-
 TEST_GEN_PROGS := group_constraint_pmc56_test group_pmc56_exclude_constraints_test group_constraint_pmc_count_test \
 	group_constraint_repeat_test group_constraint_radix_scope_qual_test reserved_bits_mmcra_sample_elig_mode_test \
 	group_constraint_mmcra_sample_test invalid_event_code_test reserved_bits_mmcra_thresh_ctl_test \
@@ -12,4 +10,6 @@ TEST_GEN_PROGS := group_constraint_pmc56_test group_pmc56_exclude_constraints_te
 top_srcdir = ../../../../../..
 include ../../../lib.mk
 
+CFLAGS += -m64
+
 $(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c ../sampling_tests/misc.h ../sampling_tests/misc.c
tools/testing/selftests/powerpc/pmu/sampling_tests/Makefile +2 -2
index 9e67351fb252b..d45892151e05d 100644
@@ -1,6 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-CFLAGS += -m64
-
 TEST_GEN_PROGS := mmcr0_exceptionbits_test mmcr0_cc56run_test mmcr0_pmccext_test \
 		   mmcr0_pmcjce_test mmcr0_fc56_pmc1ce_test mmcr0_fc56_pmc56_test \
 		   mmcr1_comb_test mmcr2_l2l3_test mmcr2_fcs_fch_test \
@@ -12,4 +10,6 @@ TEST_GEN_PROGS := mmcr0_exceptionbits_test mmcr0_cc56run_test mmcr0_pmccext_test
 top_srcdir = ../../../../../..
 include ../../../lib.mk
 
+CFLAGS += -m64
+
 $(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c misc.c misc.h ../loop.S ../branch_loops.S
tools/testing/selftests/powerpc/primitives/Makefile +2 -2
index 9b9491a632136..6dc5c5a42ca95 100644
@@ -1,9 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0-only
-CFLAGS += -I$(CURDIR)
-
 TEST_GEN_PROGS := load_unaligned_zeropad
 
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+CFLAGS += -I$(CURDIR)
+
 $(TEST_GEN_PROGS): ../harness.c
tools/testing/selftests/powerpc/security/Makefile +2 -2
index e0d979ab02040..0a08386be9696 100644
@@ -5,10 +5,10 @@ TEST_PROGS := mitigation-patching.sh
 
 top_srcdir = ../../../../..
 
-CFLAGS += $(KHDR_INCLUDES)
-
 include ../../lib.mk
 
+CFLAGS += $(KHDR_INCLUDES)
+
 $(TEST_GEN_PROGS): ../harness.c ../utils.c
 
 $(OUTPUT)/spectre_v2: CFLAGS += -m64
tools/testing/selftests/powerpc/signal/Makefile +2 -1
index f679d260afc87..b15d5dbccc24b 100644
@@ -3,7 +3,6 @@ TEST_GEN_PROGS := signal signal_tm sigfuz sigreturn_vdso sig_sc_double_restart
 TEST_GEN_PROGS += sigreturn_kernel
 TEST_GEN_PROGS += sigreturn_unaligned
 
-CFLAGS += -maltivec
 $(OUTPUT)/signal_tm: CFLAGS += -mhtm
 $(OUTPUT)/sigfuz: CFLAGS += -pthread -m64
 
@@ -12,4 +11,6 @@ TEST_FILES := settings
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+CFLAGS += -maltivec
+
 $(TEST_GEN_PROGS): ../harness.c ../utils.c signal.S
tools/testing/selftests/powerpc/stringloops/Makefile +5 -5
index 9c39f55a58ff3..87c8c8f238daa 100644
@@ -1,7 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-# The loops are all 64-bit code
-CFLAGS += -I$(CURDIR)
-
 EXTRA_SOURCES := ../harness.c
 
 build_32bit = $(shell if ($(CC) $(CFLAGS) -m32 -o /dev/null memcmp.c >/dev/null 2>&1) then echo "1"; fi)
@@ -27,9 +24,12 @@ $(OUTPUT)/strlen_32: CFLAGS += -m32
 TEST_GEN_PROGS += strlen_32
 endif
 
-ASFLAGS = $(CFLAGS)
-
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+# The loops are all 64-bit code
+CFLAGS += -I$(CURDIR)
+
+ASFLAGS = $(CFLAGS)
+
 $(TEST_GEN_PROGS): $(EXTRA_SOURCES)
tools/testing/selftests/powerpc/switch_endian/Makefile +2 -2
index bdc081afedb0f..8f0c2a1d3333b 100644
@@ -1,13 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_GEN_PROGS := switch_endian_test
 
-ASFLAGS += -O2 -Wall -g -nostdlib -m64
-
 EXTRA_CLEAN = $(OUTPUT)/*.o $(OUTPUT)/check-reversed.S
 
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+ASFLAGS += -O2 -Wall -g -nostdlib -m64
+
 $(OUTPUT)/switch_endian_test: ASFLAGS += -I $(OUTPUT)
 $(OUTPUT)/switch_endian_test: $(OUTPUT)/check-reversed.S
 
tools/testing/selftests/powerpc/syscalls/Makefile +2 -2
index ee1740ddfb0c2..83dc335007732 100644
@@ -1,9 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0-only
 TEST_GEN_PROGS := ipc_unmuxed rtas_filter
 
-CFLAGS += $(KHDR_INCLUDES)
-
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+CFLAGS += $(KHDR_INCLUDES)
+
 $(TEST_GEN_PROGS): ../harness.c ../utils.c
tools/testing/selftests/powerpc/vphn/Makefile +2 -2
index cf65cbf33085a..ddc09a20b80fb 100644
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 TEST_GEN_PROGS := test-vphn
 
-CFLAGS += -m64 -I$(CURDIR)
-
 top_srcdir = ../../../../..
 include ../../lib.mk
 
+CFLAGS += -m64 -I$(CURDIR)
+
 $(TEST_GEN_PROGS): ../harness.c
 
Signature · 1 line
2.53.0
author maintainer
#45 lore raw

PATCH 45/508 selftests/powerpc: Suppress -Wmaybe-uninitialized with GCC 15

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Amit Machhiwal <[email protected]>

[ Upstream commit 6e65886fceb23605eff952d6b1975737b4c4b154 ]

GCC 15 reports the below false positive '-Wmaybe-uninitialized' warning in vphn_unpack_associativity() when building the powerpc selftests.

  # make -C tools/testing/selftests TARGETS="powerpc"
  [...]
    CC       test-vphn
  In file included from test-vphn.c:3:
  In function ‘vphn_unpack_associativity’,
      inlined from ‘test_one’ at test-vphn.c:371:2,
      inlined from ‘test_vphn’ at test-vphn.c:399:9:
  test-vphn.c:10:33: error: ‘be_packed’ may be used uninitialized [-Werror=maybe-uninitialized]
     10 | #define be16_to_cpup(x)         bswap_16(*x)
        |                                 ^~~~~~~~
  vphn.c:42:27: note: in expansion of macro ‘be16_to_cpup’
     42 |                 u16 new = be16_to_cpup(field++);
        |                           ^~~~~~~~~~~~
  In file included from test-vphn.c:19:
  vphn.c: In function ‘test_vphn’:
  vphn.c:27:16: note: ‘be_packed’ declared here
     27 |         __be64 be_packed[VPHN_REGISTER_COUNT];
        |                ^~~~~~~~~
  cc1: all warnings being treated as errors

When vphn_unpack_associativity() is called from hcall_vphn() in kernel the error is not seen while building vphn.c during kernel compilation. This is because the top level Makefile includes '-fno-strict-aliasing' flag always.

The issue here is that GCC 15 emits '-Wmaybe-uninitialized' due to type punning between __be64[] and __b16* when accessing the buffer via be16_to_cpup(). The underlying object is fully initialized but GCC 15 fails to track the aliasing due to the strict aliasing violation here. Please refer [1] and [2]. This results in a false positive warning which is promoted to an error under '-Werror'. This problem is not seen when the compilation is performed with GCC 13 and 14. An issue [1] has also been created on GCC bugzilla.

The selftest compiles fine with '-fno-strict-aliasing'. Since this GCC flag is used to compile vphn.c in kernel too, the same flag should be used to build vphn tests when compiling vphn.c in the selftest as well.

Fix this by including '-fno-strict-aliasing' during vphn.c compilation in the selftest. This keeps the build working while limiting the scope of the suppression to building vphn tests.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124427
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99768

---
 tools/testing/selftests/powerpc/vphn/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/powerpc/vphn/Makefile +1 -1
index ddc09a20b80fb..873bc6b3739a6 100644
@@ -4,7 +4,7 @@ TEST_GEN_PROGS := test-vphn
 top_srcdir = ../../../../..
 include ../../lib.mk
 
-CFLAGS += -m64 -I$(CURDIR)
+CFLAGS += -m64 -I$(CURDIR) -fno-strict-aliasing
 
 $(TEST_GEN_PROGS): ../harness.c
 
Signature · 1 line
2.53.0
author maintainer
#46 lore raw

PATCH 46/508 macvlan: annotate data-races around port->bc_queue_len_used

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 1ef5789d9906df3771c99b7f413caaf2bf473ca5 ]

port->bc_queue_len_used is read and written locklessly, add READ_ONCE()/WRITE_ONCE() annotations.

While WRITE_ONCE() in macvlan_fill_info() is not yet needed, it is a prereq for future RTNL avoidance.

Fixes d4bff72c8401 ("macvlan: Support for high multicast packet rate")
---
 drivers/net/macvlan.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/macvlan.c +5 -3
index 4e28fcbf13c74..1035a95beee6f 100644
@@ -351,6 +351,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
 				      const struct macvlan_dev *src,
 				      struct sk_buff *skb)
 {
+	u32 bc_queue_len_used = READ_ONCE(port->bc_queue_len_used);
 	struct sk_buff *nskb;
 	int err = -ENOMEM;
 
@@ -361,7 +362,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
 	MACVLAN_SKB_CB(nskb)->src = src;
 
 	spin_lock(&port->bc_queue.lock);
-	if (skb_queue_len(&port->bc_queue) < port->bc_queue_len_used) {
+	if (skb_queue_len(&port->bc_queue) < bc_queue_len_used) {
 		if (src)
 			dev_hold(src->dev);
 		__skb_queue_tail(&port->bc_queue, nskb);
@@ -1732,7 +1733,8 @@ static int macvlan_fill_info(struct sk_buff *skb,
 	}
 	if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN, vlan->bc_queue_len_req))
 		goto nla_put_failure;
-	if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED, port->bc_queue_len_used))
+	if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED,
+			READ_ONCE(port->bc_queue_len_used)))
 		goto nla_put_failure;
 	if (port->bc_cutoff != 1 &&
 	    nla_put_s32(skb, IFLA_MACVLAN_BC_CUTOFF, port->bc_cutoff))
@@ -1792,7 +1794,7 @@ static void update_port_bc_queue_len(struct macvlan_port *port)
 		if (vlan->bc_queue_len_req > max_bc_queue_len_req)
 			max_bc_queue_len_req = vlan->bc_queue_len_req;
 	}
-	port->bc_queue_len_used = max_bc_queue_len_req;
+	WRITE_ONCE(port->bc_queue_len_used, max_bc_queue_len_req);
 }
 
 static int macvlan_device_event(struct notifier_block *unused,
Signature · 1 line
2.53.0
author maintainer
#47 lore raw

PATCH 47/508 bpf: fix end-of-list detection in cgroup_storage_get_next_key()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Weiming Shi <[email protected]>

[ Upstream commit 5828b9e5b272ecff7cf5d345128d3de7324117f7 ]

list_next_entry() never returns NULL -- when the current element is the last entry it wraps to the list head via container_of(). The subsequent NULL check is therefore dead code and get_next_key() never returns -ENOENT for the last element, instead reading storage->key from a bogus pointer that aliases internal map fields and copying the result to userspace.

Replace it with list_entry_is_head() so the function correctly returns -ENOENT when there are no more entries.

---
 kernel/bpf/local_storage.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/local_storage.c +1 -1
index a04f505aefe9b..c8b8dcc37ed4a 100644
@@ -259,7 +259,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,
 			goto enoent;
 
 		storage = list_next_entry(storage, list_map);
-		if (!storage)
+		if (list_entry_is_head(storage, &map->list, list_map))
 			goto enoent;
 	} else {
 		storage = list_first_entry(&map->list,
Signature · 1 line
2.53.0
author maintainer
#48 lore raw

PATCH 48/508 bpf: Fix stale offload->prog pointer after constant blinding

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: MingTao Huang <[email protected]>

[ Upstream commit a1aa9ef47c299c5bbc30594d3c2f0589edf908e6 ]

When a dev-bound-only BPF program (BPF_F_XDP_DEV_BOUND_ONLY) undergoes JIT compilation with constant blinding enabled (bpf_jit_harden >= 2), bpf_jit_blind_constants() clones the program. The original prog is then freed in bpf_jit_prog_release_other(), which updates aux->prog to point to the surviving clone, but fails to update offload->prog.

This leaves offload->prog pointing to the freed original program. When the network namespace is subsequently destroyed, cleanup_net() triggers bpf_dev_bound_netdev_unregister(), which iterates ondev->progs and calls __bpf_prog_offload_destroy(offload->prog). Accessing the freed prog causes a page fault:

BUG: unable to handle page fault for address: ffffc900085f1038
Workqueue: netns cleanup_net
RIP: 0010:__bpf_prog_offload_destroy+0xc/0x80
Call Trace:
__bpf_offload_dev_netdev_unregister+0x257/0x350
bpf_dev_bound_netdev_unregister+0x4a/0x90
unregister_netdevice_many_notify+0x2a2/0x660

...
cleanup_net+0x21a/0x320

The test sequence that triggers this reliably is:

1. Set net.core.bpf_jit_harden=2 (echo 2 > /proc/sys/net/core/bpf_jit_harden)
2. Run xdp_metadata selftest, which creates a dev-bound-only XDP program on a veth inside a netns (./test_progs -t xdp_metadata)
3. cleanup_net -> page fault in __bpf_prog_offload_destroy

Dev-bound-only programs are unique in that they have an offload structure but go through the normal JIT path instead of bpf_prog_offload_compile(). This means they are subject to constant blinding's prog clone-and-replace, while also having offload->prog that must stay in sync.

Fix this by updating offload->prog in bpf_jit_prog_release_other(), alongside the existing aux->prog update. Both are back-pointers to the prog that must be kept in sync when the prog is replaced.

Fixes 2b3486bc2d23 ("bpf: Introduce device-bound XDP programs")
---
 kernel/bpf/core.c | 2 ++
 1 file changed, 2 insertions(+)
kernel/bpf/core.c +2 -0
index 3011add7c4a88..d708cf3e6207f 100644
@@ -1422,6 +1422,8 @@ void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)
 	 * know whether fp here is the clone or the original.
 	 */
 	fp->aux->prog = fp;
+	if (fp->aux->offload)
+		fp->aux->offload->prog = fp;
 	bpf_prog_clone_free(fp_other);
 }
 
Signature · 1 line
2.53.0
author maintainer
#49 lore raw

PATCH 49/508 wifi: brcmfmac: Fix error pointer dereference

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ethan Tidmore <[email protected]>

[ Upstream commit dd8592fc6007a451c3e4b9025de365e39de8178a ]

The function brcmf_chip_add_core() can return an error pointer and is not checked. Add checks for error pointer.

Detected by Smatch:
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1010 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()

drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1013 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()

drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1016 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()

drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1019 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()

drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1022 brcmf_chip_recognition() error:
'core' dereferencing possible ERR_PTR()

Fixes cb7cf7be9eba7 ("brcmfmac: make chip related functions host interface independent")
[add missing wifi: prefix]
---
 .../wireless/broadcom/brcm80211/brcmfmac/chip.c   | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +15 -0
index 2ef92ef25517e..4dbb1898f3065 100644
@@ -1006,18 +1006,33 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
 
 		core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
 					   SI_ENUM_BASE_DEFAULT, 0);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
 		brcmf_chip_sb_corerev(ci, core);
 		core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
 					   BCM4329_CORE_BUS_BASE, 0);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
 		brcmf_chip_sb_corerev(ci, core);
 		core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
 					   BCM4329_CORE_SOCRAM_BASE, 0);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
 		brcmf_chip_sb_corerev(ci, core);
 		core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
 					   BCM4329_CORE_ARM_BASE, 0);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
 		brcmf_chip_sb_corerev(ci, core);
 
 		core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
 		brcmf_chip_sb_corerev(ci, core);
 	} else if (socitype == SOCI_AI) {
 		ci->iscoreup = brcmf_chip_ai_iscoreup;
Signature · 1 line
2.53.0
author maintainer
#50 lore raw

PATCH 50/508 bpf: Drop task_to_inode and inet_conn_established from lsm sleepable hooks

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiayuan Chen <[email protected]>

[ Upstream commit beaf0e96b1da74549a6cabd040f9667d83b2e97e ]

bpf_lsm_task_to_inode() is called under rcu_read_lock() and bpf_lsm_inet_conn_established() is called from softirq context, so neither hook can be used by sleepable LSM programs.

---
 kernel/bpf/bpf_lsm.c | 1 -
 1 file changed, 1 deletion(-)
kernel/bpf/bpf_lsm.c +0 -1
index e14c822f8911c..92486a7b916e3 100644
@@ -340,7 +340,6 @@ BTF_ID(func, bpf_lsm_current_getsecid_subj)
 BTF_ID(func, bpf_lsm_task_getsecid_obj)
 BTF_ID(func, bpf_lsm_task_prctl)
 BTF_ID(func, bpf_lsm_task_setscheduler)
-BTF_ID(func, bpf_lsm_task_to_inode)
 BTF_ID(func, bpf_lsm_userns_create)
 BTF_SET_END(sleepable_lsm_hooks)
 
Signature · 1 line
2.53.0
author maintainer
#51 lore raw

PATCH 51/508 bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Weiming Shi <[email protected]>

[ Upstream commit 1c22483a2c4bbf747787f328392ca3e68619c4dc ]

CO-RE accessor strings are colon-separated indices that describe a path from a root BTF type to a target field, e.g. "0:1:2" walks through nested struct members. bpf_core_parse_spec() parses each component with sscanf("%d"), so negative values like -1 are silently accepted. The subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the upper bound and always pass for negative values because C integer promotion converts the __u16 btf_vlen result to int, making the comparison (int)(-1) >= (int)(N) false for any positive N.

When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, producing an out-of-bounds read far past the members array. A crafted BPF program with a negative CO-RE accessor on any struct that exists in vmlinux BTF (e.g. task_struct) crashes the kernel deterministically during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y (default on major distributions). The bug is reachable with CAP_BPF:

 BUG: unable to handle page fault for address: ffffed11818b6626
 #PF: supervisor read access in kernel mode
 #PF: error_code(0x0000) - not-present page
 Oops: Oops: 0000 [#1] SMP KASAN NOPTI
 CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full)
 RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354)
 RAX: 00000000ffffffff
 Call Trace:
  <TASK>
  bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321)
  bpf_core_apply (kernel/bpf/btf.c:9507)
  check_core_relo (kernel/bpf/verifier.c:19475)
  bpf_check (kernel/bpf/verifier.c:26031)
  bpf_prog_load (kernel/bpf/syscall.c:3089)
  __sys_bpf (kernel/bpf/syscall.c:6228)
  </TASK>

CO-RE accessor indices are inherently non-negative (struct member index, array element index, or enumerator index), so reject them immediately after parsing.

---
 tools/lib/bpf/relo_core.c | 2 ++
 1 file changed, 2 insertions(+)
tools/lib/bpf/relo_core.c +2 -0
index 63a4d5ad12d1a..04c8febfc0aa7 100644
@@ -293,6 +293,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf,
 			++spec_str;
 		if (sscanf(spec_str, "%d%n", &access_idx, &parsed_len) != 1)
 			return -EINVAL;
+		if (access_idx < 0)
+			return -EINVAL;
 		if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN)
 			return -E2BIG;
 		spec_str += parsed_len;
Signature · 1 line
2.53.0
author maintainer
#52 lore raw

PATCH 52/508 ACPI: AGDI: fix missing newline in error message

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Haoyu Lu <[email protected]>

[ Upstream commit b178330b67abb7293b6de28b2a49d49c83962db5 ]

Add the missing trailing newline to the dev_err() message printed when SDEI event registration fails.

This keeps the error output as a properly terminated log line.

Fixes a2a591fb76e6 ("ACPI: AGDI: Add driver for Arm Generic Diagnostic Dump and Reset device")
---
 drivers/acpi/arm64/agdi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/arm64/agdi.c +1 -1
index 8b3c7d42b41bc..419a9f6c0a827 100644
@@ -32,7 +32,7 @@ static int agdi_sdei_probe(struct platform_device *pdev,
 
 	err = sdei_event_register(adata->sdei_event, agdi_sdei_handler, pdev);
 	if (err) {
-		dev_err(&pdev->dev, "Failed to register for SDEI event %d",
+		dev_err(&pdev->dev, "Failed to register for SDEI event %d\n",
 			adata->sdei_event);
 		return err;
 	}
Signature · 1 line
2.53.0
author maintainer
#53 lore raw

PATCH 53/508 arm64: kexec: Remove duplicate allocation for trans_pgd

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wang Wensheng <[email protected]>

[ Upstream commit ee020bf6f14094c9ae434bb37e6957a1fdad513c ]

trans_pgd would be allocated in trans_pgd_create_copy(), so remove the duplicate allocation before calling trans_pgd_create_copy().

Fixes 3744b5280e67 ("arm64: kexec: install a copy of the linear-map")
---
 arch/arm64/kernel/machine_kexec.c | 3 ---
 1 file changed, 3 deletions(-)
arch/arm64/kernel/machine_kexec.c +0 -3
index 078910db77a41..9307a1421d67e 100644
@@ -143,9 +143,6 @@ int machine_kexec_post_load(struct kimage *kimage)
 	}
 
 	/* Create a copy of the linear map */
-	trans_pgd = kexec_page_alloc(kimage);
-	if (!trans_pgd)
-		return -ENOMEM;
 	rc = trans_pgd_create_copy(&info, &trans_pgd, PAGE_OFFSET, PAGE_END);
 	if (rc)
 		return rc;
Signature · 1 line
2.53.0
author maintainer
#54 lore raw

PATCH 54/508 net: bcmgenet: fix off-by-one in bcmgenet_put_txcb

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Justin Chen <[email protected]>

[ Upstream commit 57f3f53d2c9c5a9e133596e2f7bc1c50688a6d38 ]

The write_ptr points to the next open tx_cb. We want to return the tx_cb that gets rewinded, so we must rewind the pointer first then return the tx_cb that it points to. That way the txcb can be correctly cleaned up.

Fixes 876dbadd53a7 ("net: bcmgenet: Fix unmapping of fragments in bcmgenet_xmit()")
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +3 -3
index 79d096a371ae7..cdbe47c7ba280 100644
@@ -1749,15 +1749,15 @@ static struct enet_cb *bcmgenet_put_txcb(struct bcmgenet_priv *priv,
 {
 	struct enet_cb *tx_cb_ptr;
 
-	tx_cb_ptr = ring->cbs;
-	tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
-
 	/* Rewinding local write pointer */
 	if (ring->write_ptr == ring->cb_ptr)
 		ring->write_ptr = ring->end_ptr;
 	else
 		ring->write_ptr--;
 
+	tx_cb_ptr = ring->cbs;
+	tx_cb_ptr += ring->write_ptr - ring->cb_ptr;
+
 	return tx_cb_ptr;
 }
 
Signature · 1 line
2.53.0
author maintainer
#55 lore raw

PATCH 55/508 net: bcmgenet: Remove custom ndo_poll_controller()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Fainelli <[email protected]>

[ Upstream commit 19537e125cc7cf2da43a606f5bcebbe0c9aea4cc ]

The driver gained a .ndo_poll_controller() at a time where the TX cleaning process was always done from NAPI which makes this unnecessary. See commit ac3d9dd034e5 ("netpoll: make ndo_poll_controller() optional") for more background.

Stable-dep-of: 5393b2b5bee2 ("net: bcmgenet: fix racing timeout handler")

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 20 -------------------
 1 file changed, 20 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +0 -20
index cdbe47c7ba280..6ba26feed4588 100644
@@ -3255,23 +3255,6 @@ static irqreturn_t bcmgenet_wol_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void bcmgenet_poll_controller(struct net_device *dev)
-{
-	struct bcmgenet_priv *priv = netdev_priv(dev);
-
-	/* Invoke the main RX/TX interrupt handler */
-	disable_irq(priv->irq0);
-	bcmgenet_isr0(priv->irq0, priv);
-	enable_irq(priv->irq0);
-
-	/* And the interrupt handler for RX/TX priority queues */
-	disable_irq(priv->irq1);
-	bcmgenet_isr1(priv->irq1, priv);
-	enable_irq(priv->irq1);
-}
-#endif
-
 static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
 {
 	u32 reg;
@@ -3741,9 +3724,6 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
 	.ndo_set_mac_address	= bcmgenet_set_mac_addr,
 	.ndo_eth_ioctl		= phy_do_ioctl_running,
 	.ndo_set_features	= bcmgenet_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= bcmgenet_poll_controller,
-#endif
 	.ndo_get_stats		= bcmgenet_get_stats,
 	.ndo_change_carrier	= bcmgenet_change_carrier,
 };
Signature · 1 line
2.53.0
author maintainer
#56 lore raw

PATCH 56/508 net: bcmgenet: add bcmgenet_has_* helpers

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Doug Berger <[email protected]>

[ Upstream commit 07c1a756a50b1180a085ab61819a388bbb906a95 ]

Introduce helper functions to indicate whether the driver should make use of a particular feature that it supports. These helpers abstract the implementation of how the feature availability is encoded.

Stable-dep-of: 5393b2b5bee2 ("net: bcmgenet: fix racing timeout handler")

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 20 +++++++-------
 .../net/ethernet/broadcom/genet/bcmgenet.h    | 27 ++++++++++++++++++-
 drivers/net/ethernet/broadcom/genet/bcmmii.c  |  6 ++---
 3 files changed, 39 insertions(+), 14 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +10 -10
index 6ba26feed4588..1046b4f8544c9 100644
@@ -104,7 +104,7 @@ static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,
 	 * the platform is explicitly configured for 64-bits/LPAE.
 	 */
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-	if (priv->hw_params->flags & GENET_HAS_40BITS)
+	if (bcmgenet_has_40bits(priv))
 		bcmgenet_writel(upper_32_bits(addr), d + DMA_DESC_ADDRESS_HI);
 #endif
 }
@@ -1653,9 +1653,9 @@ static int bcmgenet_power_down(struct bcmgenet_priv *priv,
 
 	case GENET_POWER_PASSIVE:
 		/* Power down LED */
-		if (priv->hw_params->flags & GENET_HAS_EXT) {
+		if (bcmgenet_has_ext(priv)) {
 			reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-			if (GENET_IS_V5(priv) && !priv->ephy_16nm)
+			if (GENET_IS_V5(priv) && !bcmgenet_has_ephy_16nm(priv))
 				reg |= EXT_PWR_DOWN_PHY_EN |
 				       EXT_PWR_DOWN_PHY_RD |
 				       EXT_PWR_DOWN_PHY_SD |
@@ -1683,7 +1683,7 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
 {
 	u32 reg;
 
-	if (!(priv->hw_params->flags & GENET_HAS_EXT))
+	if (!bcmgenet_has_ext(priv))
 		return;
 
 	reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
@@ -1692,7 +1692,7 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
 	case GENET_POWER_PASSIVE:
 		reg &= ~(EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS |
 			 EXT_ENERGY_DET_MASK);
-		if (GENET_IS_V5(priv) && !priv->ephy_16nm) {
+		if (GENET_IS_V5(priv) && !bcmgenet_has_ephy_16nm(priv)) {
 			reg &= ~(EXT_PWR_DOWN_PHY_EN |
 				 EXT_PWR_DOWN_PHY_RD |
 				 EXT_PWR_DOWN_PHY_SD |
@@ -2525,7 +2525,7 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
 	} else if (priv->ext_phy) {
 		int0_enable |= UMAC_IRQ_LINK_EVENT;
 	} else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
-		if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+		if (bcmgenet_has_moca_link_det(priv))
 			int0_enable |= UMAC_IRQ_LINK_EVENT;
 	}
 	bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
@@ -2590,7 +2590,7 @@ static void init_umac(struct bcmgenet_priv *priv)
 	}
 
 	/* Enable MDIO interrupts on GENET v3+ */
-	if (priv->hw_params->flags & GENET_HAS_MDIO_INTR)
+	if (bcmgenet_has_mdio_intr(priv))
 		int0_enable |= (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
 
 	bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
@@ -3230,7 +3230,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
 		}
 	}
 
-	if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
+	if (bcmgenet_has_mdio_intr(priv) &&
 		status & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
 		wake_up(&priv->wq);
 	}
@@ -3900,7 +3900,7 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
 	}
 
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
-	if (!(params->flags & GENET_HAS_40BITS))
+	if (!bcmgenet_has_40bits(priv))
 		pr_warn("GENET does not support 40-bits PA\n");
 #endif
 
@@ -4079,7 +4079,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
 	bcmgenet_set_hw_params(priv);
 
 	err = -EIO;
-	if (priv->hw_params->flags & GENET_HAS_40BITS)
+	if (bcmgenet_has_40bits(priv))
 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 	if (err)
 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
drivers/net/ethernet/broadcom/genet/bcmgenet.h +26 -1
index 28e2c94ef835c..ba83819210aa8 100644
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2014-2024 Broadcom
+ * Copyright (c) 2014-2025 Broadcom
  */
 
 #ifndef __BCMGENET_H__
@@ -650,6 +650,31 @@ struct bcmgenet_priv {
 	struct ethtool_eee eee;
 };
 
+static inline bool bcmgenet_has_40bits(struct bcmgenet_priv *priv)
+{
+	return !!(priv->hw_params->flags & GENET_HAS_40BITS);
+}
+
+static inline bool bcmgenet_has_ext(struct bcmgenet_priv *priv)
+{
+	return !!(priv->hw_params->flags & GENET_HAS_EXT);
+}
+
+static inline bool bcmgenet_has_mdio_intr(struct bcmgenet_priv *priv)
+{
+	return !!(priv->hw_params->flags & GENET_HAS_MDIO_INTR);
+}
+
+static inline bool bcmgenet_has_moca_link_det(struct bcmgenet_priv *priv)
+{
+	return !!(priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET);
+}
+
+static inline bool bcmgenet_has_ephy_16nm(struct bcmgenet_priv *priv)
+{
+	return priv->ephy_16nm;
+}
+
 #define GENET_IO_MACRO(name, offset)					\
 static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv,	\
 					u32 off)			\
drivers/net/ethernet/broadcom/genet/bcmmii.c +3 -3
index e7c659cd39746..e4b498d6bd914 100644
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET MDIO routines
  *
- * Copyright (c) 2014-2024 Broadcom
+ * Copyright (c) 2014-2025 Broadcom
  */
 
 #include <linux/acpi.h>
@@ -153,7 +153,7 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
 	u32 reg = 0;
 
 	/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
-	if (GENET_IS_V4(priv) || priv->ephy_16nm) {
+	if (GENET_IS_V4(priv) || bcmgenet_has_ephy_16nm(priv)) {
 		reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
 		if (enable) {
 			reg &= ~EXT_CK25_DIS;
@@ -183,7 +183,7 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
 
 static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
 {
-	if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+	if (bcmgenet_has_moca_link_det(priv))
 		fixed_phy_set_link_update(priv->dev->phydev,
 					  bcmgenet_fixed_phy_link_update);
 }
Signature · 1 line
2.53.0
author maintainer
#57 lore raw

PATCH 57/508 net: bcmgenet: move DESC_INDEX flow to ring 0

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Doug Berger <[email protected]>

[ Upstream commit 3b5d4f5a820d362dd46472542b2e961fb1f93515 ]

The default transmit and receive packet handling is moved from the DESC_INDEX (i.e. 16) descriptor rings to the Ring 0 queues. This saves a fair amount of special case code by unifying the handling.

A default dummy filter is enabled in the Hardware Filter Block to route default receive packets to Ring 0.

Stable-dep-of: 5393b2b5bee2 ("net: bcmgenet: fix racing timeout handler")

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 369 +++++-------------
 .../net/ethernet/broadcom/genet/bcmgenet.h    |  12 +-
 .../ethernet/broadcom/genet/bcmgenet_wol.c    |   4 +-
 3 files changed, 110 insertions(+), 275 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +103 -266
index 1046b4f8544c9..ed66ae393100e 100644
@@ -41,15 +41,13 @@
 
 #include "bcmgenet.h"
 
-/* Maximum number of hardware queues, downsized if needed */
-#define GENET_MAX_MQ_CNT	4
-
 /* Default highest priority queue for multi queue support */
-#define GENET_Q0_PRIORITY	0
+#define GENET_Q1_PRIORITY	0
+#define GENET_Q0_PRIORITY	1
 
-#define GENET_Q16_RX_BD_CNT	\
+#define GENET_Q0_RX_BD_CNT	\
 	(TOTAL_DESC - priv->hw_params->rx_queues * priv->hw_params->rx_bds_per_q)
-#define GENET_Q16_TX_BD_CNT	\
+#define GENET_Q0_TX_BD_CNT	\
 	(TOTAL_DESC - priv->hw_params->tx_queues * priv->hw_params->tx_bds_per_q)
 
 #define RX_BUF_LENGTH		2048
@@ -585,7 +583,7 @@ static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
 	u16 mask_16;
 	size_t size;
 
-	f = fs->location;
+	f = fs->location + 1;
 	if (fs->flow_type & FLOW_MAC_EXT) {
 		bcmgenet_hfb_insert_data(priv, f, 0,
 					 &fs->h_ext.h_dest, &fs->m_ext.h_dest,
@@ -667,19 +665,14 @@ static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv,
 	}
 
 	bcmgenet_hfb_set_filter_length(priv, f, 2 * f_length);
-	if (!fs->ring_cookie || fs->ring_cookie == RX_CLS_FLOW_WAKE) {
-		/* Ring 0 flows can be handled by the default Descriptor Ring
-		 * We'll map them to ring 0, but don't enable the filter
-		 */
+	if (fs->ring_cookie == RX_CLS_FLOW_WAKE)
 		bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f, 0);
-		rule->state = BCMGENET_RXNFC_STATE_DISABLED;
-	} else {
+	else
 		/* Other Rx rings are direct mapped here */
 		bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f,
 							 fs->ring_cookie);
-		bcmgenet_hfb_enable_filter(priv, f);
-		rule->state = BCMGENET_RXNFC_STATE_ENABLED;
-	}
+	bcmgenet_hfb_enable_filter(priv, f);
+	rule->state = BCMGENET_RXNFC_STATE_ENABLED;
 }
 
 /* bcmgenet_hfb_clear
@@ -715,6 +708,10 @@ static void bcmgenet_hfb_clear(struct bcmgenet_priv *priv)
 
 	for (i = 0; i < priv->hw_params->hfb_filter_cnt; i++)
 		bcmgenet_hfb_clear_filter(priv, i);
+
+	/* Enable filter 0 to send default flow to ring 0 */
+	bcmgenet_hfb_set_filter_length(priv, 0, 4);
+	bcmgenet_hfb_enable_filter(priv, 0);
 }
 
 static void bcmgenet_hfb_init(struct bcmgenet_priv *priv)
@@ -819,20 +816,16 @@ static int bcmgenet_get_coalesce(struct net_device *dev,
 	unsigned int i;
 
 	ec->tx_max_coalesced_frames =
-		bcmgenet_tdma_ring_readl(priv, DESC_INDEX,
-					 DMA_MBUF_DONE_THRESH);
+		bcmgenet_tdma_ring_readl(priv, 0, DMA_MBUF_DONE_THRESH);
 	ec->rx_max_coalesced_frames =
-		bcmgenet_rdma_ring_readl(priv, DESC_INDEX,
-					 DMA_MBUF_DONE_THRESH);
+		bcmgenet_rdma_ring_readl(priv, 0, DMA_MBUF_DONE_THRESH);
 	ec->rx_coalesce_usecs =
-		bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT) * 8192 / 1000;
+		bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT) * 8192 / 1000;
 
-	for (i = 0; i < priv->hw_params->rx_queues; i++) {
+	for (i = 0; i <= priv->hw_params->rx_queues; i++) {
 		ring = &priv->rx_rings[i];
 		ec->use_adaptive_rx_coalesce |= ring->dim.use_dim;
 	}
-	ring = &priv->rx_rings[DESC_INDEX];
-	ec->use_adaptive_rx_coalesce |= ring->dim.use_dim;
 
 	return 0;
 }
@@ -902,17 +895,13 @@ static int bcmgenet_set_coalesce(struct net_device *dev,
 	/* Program all TX queues with the same values, as there is no
 	 * ethtool knob to do coalescing on a per-queue basis
 	 */
-	for (i = 0; i < priv->hw_params->tx_queues; i++)
+	for (i = 0; i <= priv->hw_params->tx_queues; i++)
 		bcmgenet_tdma_ring_writel(priv, i,
 					  ec->tx_max_coalesced_frames,
 					  DMA_MBUF_DONE_THRESH);
-	bcmgenet_tdma_ring_writel(priv, DESC_INDEX,
-				  ec->tx_max_coalesced_frames,
-				  DMA_MBUF_DONE_THRESH);
 
-	for (i = 0; i < priv->hw_params->rx_queues; i++)
+	for (i = 0; i <= priv->hw_params->rx_queues; i++)
 		bcmgenet_set_ring_rx_coalesce(&priv->rx_rings[i], ec);
-	bcmgenet_set_ring_rx_coalesce(&priv->rx_rings[DESC_INDEX], ec);
 
 	return 0;
 }
@@ -1120,7 +1109,7 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
 	STAT_GENET_Q(1),
 	STAT_GENET_Q(2),
 	STAT_GENET_Q(3),
-	STAT_GENET_Q(16),
+	STAT_GENET_Q(4),
 };
 
 #define BCMGENET_STATS_LEN	ARRAY_SIZE(bcmgenet_gstrings_stats)
@@ -1474,10 +1463,10 @@ static int bcmgenet_insert_flow(struct net_device *dev,
 		loc_rule = &priv->rxnfc_rules[cmd->fs.location];
 	}
 	if (loc_rule->state == BCMGENET_RXNFC_STATE_ENABLED)
-		bcmgenet_hfb_disable_filter(priv, cmd->fs.location);
+		bcmgenet_hfb_disable_filter(priv, cmd->fs.location + 1);
 	if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED) {
 		list_del(&loc_rule->list);
-		bcmgenet_hfb_clear_filter(priv, cmd->fs.location);
+		bcmgenet_hfb_clear_filter(priv, cmd->fs.location + 1);
 	}
 	loc_rule->state = BCMGENET_RXNFC_STATE_UNUSED;
 	memcpy(&loc_rule->fs, &cmd->fs,
@@ -1507,10 +1496,10 @@ static int bcmgenet_delete_flow(struct net_device *dev,
 	}
 
 	if (rule->state == BCMGENET_RXNFC_STATE_ENABLED)
-		bcmgenet_hfb_disable_filter(priv, cmd->fs.location);
+		bcmgenet_hfb_disable_filter(priv, cmd->fs.location + 1);
 	if (rule->state != BCMGENET_RXNFC_STATE_UNUSED) {
 		list_del(&rule->list);
-		bcmgenet_hfb_clear_filter(priv, cmd->fs.location);
+		bcmgenet_hfb_clear_filter(priv, cmd->fs.location + 1);
 	}
 	rule->state = BCMGENET_RXNFC_STATE_UNUSED;
 	memset(&rule->fs, 0, sizeof(struct ethtool_rx_flow_spec));
@@ -1761,18 +1750,6 @@ static struct enet_cb *bcmgenet_put_txcb(struct bcmgenet_priv *priv,
 	return tx_cb_ptr;
 }
 
-static inline void bcmgenet_rx_ring16_int_disable(struct bcmgenet_rx_ring *ring)
-{
-	bcmgenet_intrl2_0_writel(ring->priv, UMAC_IRQ_RXDMA_DONE,
-				 INTRL2_CPU_MASK_SET);
-}
-
-static inline void bcmgenet_rx_ring16_int_enable(struct bcmgenet_rx_ring *ring)
-{
-	bcmgenet_intrl2_0_writel(ring->priv, UMAC_IRQ_RXDMA_DONE,
-				 INTRL2_CPU_MASK_CLEAR);
-}
-
 static inline void bcmgenet_rx_ring_int_disable(struct bcmgenet_rx_ring *ring)
 {
 	bcmgenet_intrl2_1_writel(ring->priv,
@@ -1787,18 +1764,6 @@ static inline void bcmgenet_rx_ring_int_enable(struct bcmgenet_rx_ring *ring)
 				 INTRL2_CPU_MASK_CLEAR);
 }
 
-static inline void bcmgenet_tx_ring16_int_disable(struct bcmgenet_tx_ring *ring)
-{
-	bcmgenet_intrl2_0_writel(ring->priv, UMAC_IRQ_TXDMA_DONE,
-				 INTRL2_CPU_MASK_SET);
-}
-
-static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_tx_ring *ring)
-{
-	bcmgenet_intrl2_0_writel(ring->priv, UMAC_IRQ_TXDMA_DONE,
-				 INTRL2_CPU_MASK_CLEAR);
-}
-
 static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_tx_ring *ring)
 {
 	bcmgenet_intrl2_1_writel(ring->priv, 1 << ring->index,
@@ -1879,12 +1844,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 	struct sk_buff *skb;
 
 	/* Clear status before servicing to reduce spurious interrupts */
-	if (ring->index == DESC_INDEX)
-		bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_TXDMA_DONE,
-					 INTRL2_CPU_CLEAR);
-	else
-		bcmgenet_intrl2_1_writel(priv, (1 << ring->index),
-					 INTRL2_CPU_CLEAR);
+	bcmgenet_intrl2_1_writel(priv, (1 << ring->index), INTRL2_CPU_CLEAR);
 
 	/* Compute how many buffers are transmitted since last xmit call */
 	c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX)
@@ -1918,7 +1878,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 	ring->packets += pkts_compl;
 	ring->bytes += bytes_compl;
 
-	netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->queue),
+	netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->index),
 				  pkts_compl, bytes_compl);
 
 	return txbds_processed;
@@ -1946,14 +1906,14 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
 	spin_lock(&ring->lock);
 	work_done = __bcmgenet_tx_reclaim(ring->priv->dev, ring);
 	if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
-		txq = netdev_get_tx_queue(ring->priv->dev, ring->queue);
+		txq = netdev_get_tx_queue(ring->priv->dev, ring->index);
 		netif_tx_wake_queue(txq);
 	}
 	spin_unlock(&ring->lock);
 
 	if (work_done == 0) {
 		napi_complete(napi);
-		ring->int_enable(ring);
+		bcmgenet_tx_ring_int_enable(ring);
 
 		return 0;
 	}
@@ -1964,14 +1924,11 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
 static void bcmgenet_tx_reclaim_all(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	int i;
-
-	if (netif_is_multiqueue(dev)) {
-		for (i = 0; i < priv->hw_params->tx_queues; i++)
-			bcmgenet_tx_reclaim(dev, &priv->tx_rings[i]);
-	}
+	int i = 0;
 
-	bcmgenet_tx_reclaim(dev, &priv->tx_rings[DESC_INDEX]);
+	do {
+		bcmgenet_tx_reclaim(dev, &priv->tx_rings[i++]);
+	} while (i <= priv->hw_params->tx_queues && netif_is_multiqueue(dev));
 }
 
 /* Reallocate the SKB to put enough headroom in front of it and insert
@@ -2059,19 +2016,14 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	index = skb_get_queue_mapping(skb);
 	/* Mapping strategy:
-	 * queue_mapping = 0, unclassified, packet xmited through ring16
-	 * queue_mapping = 1, goes to ring 0. (highest priority queue
-	 * queue_mapping = 2, goes to ring 1.
-	 * queue_mapping = 3, goes to ring 2.
-	 * queue_mapping = 4, goes to ring 3.
+	 * queue_mapping = 0, unclassified, packet xmited through ring 0
+	 * queue_mapping = 1, goes to ring 1. (highest priority queue)
+	 * queue_mapping = 2, goes to ring 2.
+	 * queue_mapping = 3, goes to ring 3.
+	 * queue_mapping = 4, goes to ring 4.
 	 */
-	if (index == 0)
-		index = DESC_INDEX;
-	else
-		index -= 1;
-
 	ring = &priv->tx_rings[index];
-	txq = netdev_get_tx_queue(dev, ring->queue);
+	txq = netdev_get_tx_queue(dev, index);
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
 
@@ -2244,15 +2196,8 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 	unsigned int discards;
 
 	/* Clear status before servicing to reduce spurious interrupts */
-	if (ring->index == DESC_INDEX) {
-		bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_DONE,
-					 INTRL2_CPU_CLEAR);
-	} else {
-		mask = 1 << (UMAC_IRQ1_RX_INTR_SHIFT + ring->index);
-		bcmgenet_intrl2_1_writel(priv,
-					 mask,
-					 INTRL2_CPU_CLEAR);
-	}
+	mask = 1 << (UMAC_IRQ1_RX_INTR_SHIFT + ring->index);
+	bcmgenet_intrl2_1_writel(priv, mask, INTRL2_CPU_CLEAR);
 
 	p_index = bcmgenet_rdma_ring_readl(priv, ring->index, RDMA_PROD_INDEX);
 
@@ -2401,7 +2346,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
 
 	if (work_done < budget) {
 		napi_complete_done(napi, work_done);
-		ring->int_enable(ring);
+		bcmgenet_rx_ring_int_enable(ring);
 	}
 
 	if (ring->dim.use_dim) {
@@ -2641,15 +2586,6 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
 	spin_lock_init(&ring->lock);
 	ring->priv = priv;
 	ring->index = index;
-	if (index == DESC_INDEX) {
-		ring->queue = 0;
-		ring->int_enable = bcmgenet_tx_ring16_int_enable;
-		ring->int_disable = bcmgenet_tx_ring16_int_disable;
-	} else {
-		ring->queue = index + 1;
-		ring->int_enable = bcmgenet_tx_ring_int_enable;
-		ring->int_disable = bcmgenet_tx_ring_int_disable;
-	}
 	ring->cbs = priv->tx_cbs + start_ptr;
 	ring->size = size;
 	ring->clean_ptr = start_ptr;
@@ -2660,8 +2596,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
 	ring->end_ptr = end_ptr - 1;
 	ring->prod_index = 0;
 
-	/* Set flow period for ring != 16 */
-	if (index != DESC_INDEX)
+	/* Set flow period for ring != 0 */
+	if (index)
 		flow_period_val = ENET_MAX_MTU_SIZE << 16;
 
 	bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX);
@@ -2699,13 +2635,6 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
 
 	ring->priv = priv;
 	ring->index = index;
-	if (index == DESC_INDEX) {
-		ring->int_enable = bcmgenet_rx_ring16_int_enable;
-		ring->int_disable = bcmgenet_rx_ring16_int_disable;
-	} else {
-		ring->int_enable = bcmgenet_rx_ring_int_enable;
-		ring->int_disable = bcmgenet_rx_ring_int_disable;
-	}
 	ring->cbs = priv->rx_cbs + start_ptr;
 	ring->size = size;
 	ring->c_index = 0;
@@ -2751,15 +2680,11 @@ static void bcmgenet_enable_tx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_tx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->tx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->tx_queues; ++i) {
 		ring = &priv->tx_rings[i];
 		napi_enable(&ring->napi);
-		ring->int_enable(ring);
+		bcmgenet_tx_ring_int_enable(ring);
 	}
-
-	ring = &priv->tx_rings[DESC_INDEX];
-	napi_enable(&ring->napi);
-	ring->int_enable(ring);
 }
 
 static void bcmgenet_disable_tx_napi(struct bcmgenet_priv *priv)
@@ -2767,13 +2692,10 @@ static void bcmgenet_disable_tx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_tx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->tx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->tx_queues; ++i) {
 		ring = &priv->tx_rings[i];
 		napi_disable(&ring->napi);
 	}
-
-	ring = &priv->tx_rings[DESC_INDEX];
-	napi_disable(&ring->napi);
 }
 
 static void bcmgenet_fini_tx_napi(struct bcmgenet_priv *priv)
@@ -2781,33 +2703,31 @@ static void bcmgenet_fini_tx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_tx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->tx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->tx_queues; ++i) {
 		ring = &priv->tx_rings[i];
 		netif_napi_del(&ring->napi);
 	}
-
-	ring = &priv->tx_rings[DESC_INDEX];
-	netif_napi_del(&ring->napi);
 }
 
 /* Initialize Tx queues
  *
- * Queues 0-3 are priority-based, each one has 32 descriptors,
- * with queue 0 being the highest priority queue.
+ * Queues 1-4 are priority-based, each one has 32 descriptors,
+ * with queue 1 being the highest priority queue.
  *
- * Queue 16 is the default Tx queue with
- * GENET_Q16_TX_BD_CNT = 256 - 4 * 32 = 128 descriptors.
+ * Queue 0 is the default Tx queue with
+ * GENET_Q0_TX_BD_CNT = 256 - 4 * 32 = 128 descriptors.
  *
  * The transmit control block pool is then partitioned as follows:
- * - Tx queue 0 uses tx_cbs[0..31]
- * - Tx queue 1 uses tx_cbs[32..63]
- * - Tx queue 2 uses tx_cbs[64..95]
- * - Tx queue 3 uses tx_cbs[96..127]
- * - Tx queue 16 uses tx_cbs[128..255]
+ * - Tx queue 0 uses tx_cbs[0..127]
+ * - Tx queue 1 uses tx_cbs[128..159]
+ * - Tx queue 2 uses tx_cbs[160..191]
+ * - Tx queue 3 uses tx_cbs[192..223]
+ * - Tx queue 4 uses tx_cbs[224..255]
  */
 static void bcmgenet_init_tx_queues(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
+	unsigned int start = 0, end = GENET_Q0_TX_BD_CNT;
 	u32 i, dma_enable;
 	u32 dma_ctrl, ring_cfg;
 	u32 dma_priority[3] = {0, 0, 0};
@@ -2824,27 +2744,17 @@ static void bcmgenet_init_tx_queues(struct net_device *dev)
 	bcmgenet_tdma_writel(priv, DMA_ARBITER_SP, DMA_ARB_CTRL);
 
 	/* Initialize Tx priority queues */
-	for (i = 0; i < priv->hw_params->tx_queues; i++) {
-		bcmgenet_init_tx_ring(priv, i, priv->hw_params->tx_bds_per_q,
-				      i * priv->hw_params->tx_bds_per_q,
-				      (i + 1) * priv->hw_params->tx_bds_per_q);
+	for (i = 0; i <= priv->hw_params->tx_queues; i++) {
+		bcmgenet_init_tx_ring(priv, i, end - start, start, end);
+		start = end;
+		end += priv->hw_params->tx_bds_per_q;
 		ring_cfg |= (1 << i);
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 		dma_priority[DMA_PRIO_REG_INDEX(i)] |=
-			((GENET_Q0_PRIORITY + i) << DMA_PRIO_REG_SHIFT(i));
+			(i ? GENET_Q1_PRIORITY : GENET_Q0_PRIORITY)
+			<< DMA_PRIO_REG_SHIFT(i);
 	}
 
-	/* Initialize Tx default queue 16 */
-	bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_Q16_TX_BD_CNT,
-			      priv->hw_params->tx_queues *
-			      priv->hw_params->tx_bds_per_q,
-			      TOTAL_DESC);
-	ring_cfg |= (1 << DESC_INDEX);
-	dma_ctrl |= (1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT));
-	dma_priority[DMA_PRIO_REG_INDEX(DESC_INDEX)] |=
-		((GENET_Q0_PRIORITY + priv->hw_params->tx_queues) <<
-		 DMA_PRIO_REG_SHIFT(DESC_INDEX));
-
 	/* Set Tx queue priorities */
 	bcmgenet_tdma_writel(priv, dma_priority[0], DMA_PRIORITY_0);
 	bcmgenet_tdma_writel(priv, dma_priority[1], DMA_PRIORITY_1);
@@ -2864,15 +2774,11 @@ static void bcmgenet_enable_rx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_rx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->rx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->rx_queues; ++i) {
 		ring = &priv->rx_rings[i];
 		napi_enable(&ring->napi);
-		ring->int_enable(ring);
+		bcmgenet_rx_ring_int_enable(ring);
 	}
-
-	ring = &priv->rx_rings[DESC_INDEX];
-	napi_enable(&ring->napi);
-	ring->int_enable(ring);
 }
 
 static void bcmgenet_disable_rx_napi(struct bcmgenet_priv *priv)
@@ -2880,15 +2786,11 @@ static void bcmgenet_disable_rx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_rx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->rx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->rx_queues; ++i) {
 		ring = &priv->rx_rings[i];
 		napi_disable(&ring->napi);
 		cancel_work_sync(&ring->dim.dim.work);
 	}
-
-	ring = &priv->rx_rings[DESC_INDEX];
-	napi_disable(&ring->napi);
-	cancel_work_sync(&ring->dim.dim.work);
 }
 
 static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
@@ -2896,13 +2798,10 @@ static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
 	unsigned int i;
 	struct bcmgenet_rx_ring *ring;
 
-	for (i = 0; i < priv->hw_params->rx_queues; ++i) {
+	for (i = 0; i <= priv->hw_params->rx_queues; ++i) {
 		ring = &priv->rx_rings[i];
 		netif_napi_del(&ring->napi);
 	}
-
-	ring = &priv->rx_rings[DESC_INDEX];
-	netif_napi_del(&ring->napi);
 }
 
 /* Initialize Rx queues
@@ -2910,15 +2809,13 @@ static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
  * Queues 0-15 are priority queues. Hardware Filtering Block (HFB) can be
  * used to direct traffic to these queues.
  *
- * Queue 16 is the default Rx queue with GENET_Q16_RX_BD_CNT descriptors.
+ * Queue 0 is also the default Rx queue with GENET_Q0_RX_BD_CNT descriptors.
  */
 static int bcmgenet_init_rx_queues(struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	u32 i;
-	u32 dma_enable;
-	u32 dma_ctrl;
-	u32 ring_cfg;
+	unsigned int start = 0, end = GENET_Q0_RX_BD_CNT;
+	u32 i, dma_enable, dma_ctrl = 0, ring_cfg = 0;
 	int ret;
 
 	dma_ctrl = bcmgenet_rdma_readl(priv, DMA_CTRL);
@@ -2930,34 +2827,21 @@ static int bcmgenet_init_rx_queues(struct net_device *dev)
 	ring_cfg = 0;
 
 	/* Initialize Rx priority queues */
-	for (i = 0; i < priv->hw_params->rx_queues; i++) {
-		ret = bcmgenet_init_rx_ring(priv, i,
-					    priv->hw_params->rx_bds_per_q,
-					    i * priv->hw_params->rx_bds_per_q,
-					    (i + 1) *
-					    priv->hw_params->rx_bds_per_q);
+	for (i = 0; i <= priv->hw_params->rx_queues; i++) {
+		ret = bcmgenet_init_rx_ring(priv, i, end - start, start, end);
 		if (ret)
 			return ret;
 
+		start = end;
+		end += priv->hw_params->rx_bds_per_q;
 		ring_cfg |= (1 << i);
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	}
 
-	/* Initialize Rx default queue 16 */
-	ret = bcmgenet_init_rx_ring(priv, DESC_INDEX, GENET_Q16_RX_BD_CNT,
-				    priv->hw_params->rx_queues *
-				    priv->hw_params->rx_bds_per_q,
-				    TOTAL_DESC);
-	if (ret)
-		return ret;
-
-	ring_cfg |= (1 << DESC_INDEX);
-	dma_ctrl |= (1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT));
-
-	/* Enable rings */
+	/* Configure Rx queues as descriptor rings */
 	bcmgenet_rdma_writel(priv, ring_cfg, DMA_RING_CFG);
 
-	/* Configure ring as descriptor ring and re-enable DMA if enabled */
+	/* Enable Rx rings */
 	if (dma_enable)
 		dma_ctrl |= DMA_EN;
 	bcmgenet_rdma_writel(priv, dma_ctrl, DMA_CTRL);
@@ -3016,14 +2900,14 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
 	}
 
 	dma_ctrl = 0;
-	for (i = 0; i < priv->hw_params->rx_queues; i++)
+	for (i = 0; i <= priv->hw_params->rx_queues; i++)
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
 	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
 
 	dma_ctrl = 0;
-	for (i = 0; i < priv->hw_params->tx_queues; i++)
+	for (i = 0; i <= priv->hw_params->tx_queues; i++)
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
@@ -3044,14 +2928,11 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
 		dev_kfree_skb(bcmgenet_free_tx_cb(&priv->pdev->dev,
 						  priv->tx_cbs + i));
 
-	for (i = 0; i < priv->hw_params->tx_queues; i++) {
-		txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[i].queue);
+	for (i = 0; i <= priv->hw_params->tx_queues; i++) {
+		txq = netdev_get_tx_queue(priv->dev, i);
 		netdev_tx_reset_queue(txq);
 	}
 
-	txq = netdev_get_tx_queue(priv->dev, priv->tx_rings[DESC_INDEX].queue);
-	netdev_tx_reset_queue(txq);
-
 	bcmgenet_free_rx_buffers(priv);
 	kfree(priv->rx_cbs);
 	kfree(priv->tx_cbs);
@@ -3144,7 +3025,7 @@ static void bcmgenet_irq_task(struct work_struct *work)
 
 }
 
-/* bcmgenet_isr1: handle Rx and Tx priority queues */
+/* bcmgenet_isr1: handle Rx and Tx queues */
 static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
 {
 	struct bcmgenet_priv *priv = dev_id;
@@ -3163,7 +3044,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
 		  "%s: IRQ=0x%x\n", __func__, status);
 
 	/* Check Rx priority queue interrupts */
-	for (index = 0; index < priv->hw_params->rx_queues; index++) {
+	for (index = 0; index <= priv->hw_params->rx_queues; index++) {
 		if (!(status & BIT(UMAC_IRQ1_RX_INTR_SHIFT + index)))
 			continue;
 
@@ -3171,20 +3052,20 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
 		rx_ring->dim.event_ctr++;
 
 		if (likely(napi_schedule_prep(&rx_ring->napi))) {
-			rx_ring->int_disable(rx_ring);
+			bcmgenet_rx_ring_int_disable(rx_ring);
 			__napi_schedule_irqoff(&rx_ring->napi);
 		}
 	}
 
 	/* Check Tx priority queue interrupts */
-	for (index = 0; index < priv->hw_params->tx_queues; index++) {
+	for (index = 0; index <= priv->hw_params->tx_queues; index++) {
 		if (!(status & BIT(index)))
 			continue;
 
 		tx_ring = &priv->tx_rings[index];
 
 		if (likely(napi_schedule_prep(&tx_ring->napi))) {
-			tx_ring->int_disable(tx_ring);
+			bcmgenet_tx_ring_int_disable(tx_ring);
 			__napi_schedule_irqoff(&tx_ring->napi);
 		}
 	}
@@ -3192,12 +3073,10 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-/* bcmgenet_isr0: handle Rx and Tx default queues + other stuff */
+/* bcmgenet_isr0: handle other stuff */
 static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
 {
 	struct bcmgenet_priv *priv = dev_id;
-	struct bcmgenet_rx_ring *rx_ring;
-	struct bcmgenet_tx_ring *tx_ring;
 	unsigned int status;
 	unsigned long flags;
 
@@ -3211,25 +3090,6 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
 	netif_dbg(priv, intr, priv->dev,
 		  "IRQ=0x%x\n", status);
 
-	if (status & UMAC_IRQ_RXDMA_DONE) {
-		rx_ring = &priv->rx_rings[DESC_INDEX];
-		rx_ring->dim.event_ctr++;
-
-		if (likely(napi_schedule_prep(&rx_ring->napi))) {
-			rx_ring->int_disable(rx_ring);
-			__napi_schedule_irqoff(&rx_ring->napi);
-		}
-	}
-
-	if (status & UMAC_IRQ_TXDMA_DONE) {
-		tx_ring = &priv->tx_rings[DESC_INDEX];
-
-		if (likely(napi_schedule_prep(&tx_ring->napi))) {
-			tx_ring->int_disable(tx_ring);
-			__napi_schedule_irqoff(&tx_ring->napi);
-		}
-	}
-
 	if (bcmgenet_has_mdio_intr(priv) &&
 		status & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
 		wake_up(&priv->wq);
@@ -3295,15 +3155,15 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx)
 	u32 dma_ctrl;
 
 	/* disable DMA */
-	dma_ctrl = 1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT) | DMA_EN;
-	for (i = 0; i < priv->hw_params->tx_queues; i++)
+	dma_ctrl = DMA_EN;
+	for (i = 0; i <= priv->hw_params->tx_queues; i++)
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
 	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
 
-	dma_ctrl = 1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT) | DMA_EN;
-	for (i = 0; i < priv->hw_params->rx_queues; i++)
+	dma_ctrl = DMA_EN;
+	for (i = 0; i <= priv->hw_params->rx_queues; i++)
 		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
@@ -3386,6 +3246,9 @@ static int bcmgenet_open(struct net_device *dev)
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
+	/* HFB init */
+	bcmgenet_hfb_init(priv);
+
 	/* Disable RX/TX DMA and flush TX and RX queues */
 	dma_ctrl = bcmgenet_dma_disable(priv, true);
 
@@ -3396,12 +3259,8 @@ static int bcmgenet_open(struct net_device *dev)
 		goto err_clk_disable;
 	}
 
-	/* Always enable ring 16 - descriptor ring */
 	bcmgenet_enable_dma(priv, dma_ctrl);
 
-	/* HFB init */
-	bcmgenet_hfb_init(priv);
-
 	ret = request_irq(priv->irq0, bcmgenet_isr0, IRQF_SHARED,
 			  dev->name, priv);
 	if (ret < 0) {
@@ -3508,16 +3367,11 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)
 	if (!netif_msg_tx_err(priv))
 		return;
 
-	txq = netdev_get_tx_queue(priv->dev, ring->queue);
+	txq = netdev_get_tx_queue(priv->dev, ring->index);
 
 	spin_lock(&ring->lock);
-	if (ring->index == DESC_INDEX) {
-		intsts = ~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
-		intmsk = UMAC_IRQ_TXDMA_DONE | UMAC_IRQ_TXDMA_MBDONE;
-	} else {
-		intsts = ~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS);
-		intmsk = 1 << ring->index;
-	}
+	intsts = ~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS);
+	intmsk = 1 << ring->index;
 	c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX);
 	p_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_PROD_INDEX);
 	txq_stopped = netif_tx_queue_stopped(txq);
@@ -3531,7 +3385,7 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)
 		  "(sw)c_index: %d (hw)c_index: %d\n"
 		  "(sw)clean_p: %d (sw)write_p: %d\n"
 		  "(sw)cb_ptr: %d (sw)end_ptr: %d\n",
-		  ring->index, ring->queue,
+		  ring->index, ring->index,
 		  txq_stopped ? "stopped" : "active",
 		  intsts & intmsk ? "enabled" : "disabled",
 		  free_bds, ring->size,
@@ -3544,25 +3398,20 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)
 static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	u32 int0_enable = 0;
 	u32 int1_enable = 0;
 	unsigned int q;
 
 	netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");
 
-	for (q = 0; q < priv->hw_params->tx_queues; q++)
+	for (q = 0; q <= priv->hw_params->tx_queues; q++)
 		bcmgenet_dump_tx_queue(&priv->tx_rings[q]);
-	bcmgenet_dump_tx_queue(&priv->tx_rings[DESC_INDEX]);
 
 	bcmgenet_tx_reclaim_all(dev);
 
-	for (q = 0; q < priv->hw_params->tx_queues; q++)
+	for (q = 0; q <= priv->hw_params->tx_queues; q++)
 		int1_enable |= (1 << q);
 
-	int0_enable = UMAC_IRQ_TXDMA_DONE;
-
 	/* Re-enable TX interrupts if disabled */
-	bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
 	bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
 
 	netif_trans_update(dev);
@@ -3666,16 +3515,13 @@ static struct net_device_stats *bcmgenet_get_stats(struct net_device *dev)
 	struct bcmgenet_rx_ring *rx_ring;
 	unsigned int q;
 
-	for (q = 0; q < priv->hw_params->tx_queues; q++) {
+	for (q = 0; q <= priv->hw_params->tx_queues; q++) {
 		tx_ring = &priv->tx_rings[q];
 		tx_bytes += tx_ring->bytes;
 		tx_packets += tx_ring->packets;
 	}
-	tx_ring = &priv->tx_rings[DESC_INDEX];
-	tx_bytes += tx_ring->bytes;
-	tx_packets += tx_ring->packets;
 
-	for (q = 0; q < priv->hw_params->rx_queues; q++) {
+	for (q = 0; q <= priv->hw_params->rx_queues; q++) {
 		rx_ring = &priv->rx_rings[q];
 
 		rx_bytes += rx_ring->bytes;
@@ -3683,11 +3529,6 @@ static struct net_device_stats *bcmgenet_get_stats(struct net_device *dev)
 		rx_errors += rx_ring->errors;
 		rx_dropped += rx_ring->dropped;
 	}
-	rx_ring = &priv->rx_rings[DESC_INDEX];
-	rx_bytes += rx_ring->bytes;
-	rx_packets += rx_ring->packets;
-	rx_errors += rx_ring->errors;
-	rx_dropped += rx_ring->dropped;
 
 	dev->stats.tx_bytes = tx_bytes;
 	dev->stats.tx_packets = tx_packets;
@@ -4134,16 +3975,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
 	if (err)
 		goto err_clk_disable;
 
-	/* setup number of real queues  + 1 (GENET_V1 has 0 hardware queues
-	 * just the ring 16 descriptor based TX
-	 */
+	/* setup number of real queues + 1 */
 	netif_set_real_num_tx_queues(priv->dev, priv->hw_params->tx_queues + 1);
 	netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1);
 
 	/* Set default coalescing parameters */
-	for (i = 0; i < priv->hw_params->rx_queues; i++)
+	for (i = 0; i <= priv->hw_params->rx_queues; i++)
 		priv->rx_rings[i].rx_max_coalesced_frames = 1;
-	priv->rx_rings[DESC_INDEX].rx_max_coalesced_frames = 1;
 
 	/* libphy will determine the link state */
 	netif_carrier_off(dev);
@@ -4268,7 +4106,6 @@ static int bcmgenet_resume(struct device *d)
 		goto out_clk_disable;
 	}
 
-	/* Always enable ring 16 - descriptor ring */
 	bcmgenet_enable_dma(priv, dma_ctrl);
 
 	if (!device_may_wakeup(d))
drivers/net/ethernet/broadcom/genet/bcmgenet.h +5 -7
index ba83819210aa8..f3a1139cb7108 100644
@@ -18,6 +18,9 @@
 
 #include "../unimac.h"
 
+/* Maximum number of hardware queues, downsized if needed */
+#define GENET_MAX_MQ_CNT	4
+
 /* total number of Buffer Descriptors, same for Rx/Tx */
 #define TOTAL_DESC				256
 
@@ -513,7 +516,6 @@ struct bcmgenet_tx_ring {
 	unsigned long	packets;
 	unsigned long	bytes;
 	unsigned int	index;		/* ring index */
-	unsigned int	queue;		/* queue index */
 	struct enet_cb	*cbs;		/* tx ring buffer control block*/
 	unsigned int	size;		/* size of each tx ring */
 	unsigned int    clean_ptr;      /* Tx ring clean pointer */
@@ -523,8 +525,6 @@ struct bcmgenet_tx_ring {
 	unsigned int	prod_index;	/* Tx ring producer index SW copy */
 	unsigned int	cb_ptr;		/* Tx ring initial CB ptr */
 	unsigned int	end_ptr;	/* Tx ring end CB ptr */
-	void (*int_enable)(struct bcmgenet_tx_ring *);
-	void (*int_disable)(struct bcmgenet_tx_ring *);
 	struct bcmgenet_priv *priv;
 };
 
@@ -553,8 +553,6 @@ struct bcmgenet_rx_ring {
 	struct bcmgenet_net_dim dim;
 	u32		rx_max_coalesced_frames;
 	u32		rx_coalesce_usecs;
-	void (*int_enable)(struct bcmgenet_rx_ring *);
-	void (*int_disable)(struct bcmgenet_rx_ring *);
 	struct bcmgenet_priv *priv;
 };
 
@@ -583,7 +581,7 @@ struct bcmgenet_priv {
 	struct enet_cb *tx_cbs;
 	unsigned int num_tx_bds;
 
-	struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
+	struct bcmgenet_tx_ring tx_rings[GENET_MAX_MQ_CNT + 1];
 
 	/* receive variables */
 	void __iomem *rx_bds;
@@ -593,7 +591,7 @@ struct bcmgenet_priv {
 	struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
 	struct list_head rxnfc_list;
 
-	struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
+	struct bcmgenet_rx_ring rx_rings[GENET_MAX_MQ_CNT + 1];
 
 	/* other misc variables */
 	struct bcmgenet_hw_params *hw_params;
drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +2 -2
index 2033fb9d893e0..98358b71cef5c 100644
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
  *
- * Copyright (c) 2014-2024 Broadcom
+ * Copyright (c) 2014-2025 Broadcom
  */
 
 #define pr_fmt(fmt)				"bcmgenet_wol: " fmt
@@ -180,7 +180,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
 	if (priv->wolopts & WAKE_FILTER) {
 		list_for_each_entry(rule, &priv->rxnfc_list, list)
 			if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
-				hfb_enable |= (1 << rule->fs.location);
+				hfb_enable |= (1 << (rule->fs.location + 1));
 		reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
 		bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
 	}
Signature · 1 line
2.53.0
author maintainer
#58 lore raw

PATCH 58/508 net: bcmgenet: support reclaiming unsent Tx packets

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Doug Berger <[email protected]>

[ Upstream commit f1bacae8b655163dcbc3c54b9e714ef1a8986d7b ]

When disabling the transmitter any outstanding packets can now be reclaimed by bcmgenet_tx_reclaim_all() rather than by the bcmgenet_fini_dma() function.

Stable-dep-of: 5393b2b5bee2 ("net: bcmgenet: fix racing timeout handler")

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 37 +++++++++++++++----
 1 file changed, 30 insertions(+), 7 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +30 -7
index ed66ae393100e..de15243c52a62 100644
@@ -1885,12 +1885,39 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 }
 
 static unsigned int bcmgenet_tx_reclaim(struct net_device *dev,
-				struct bcmgenet_tx_ring *ring)
+				struct bcmgenet_tx_ring *ring,
+				bool all)
 {
-	unsigned int released;
+	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct device *kdev = &priv->pdev->dev;
+	unsigned int released, drop, wr_ptr;
+	struct enet_cb *cb_ptr;
+	struct sk_buff *skb;
 
 	spin_lock_bh(&ring->lock);
 	released = __bcmgenet_tx_reclaim(dev, ring);
+	if (all) {
+		skb = NULL;
+		drop = (ring->prod_index - ring->c_index) & DMA_C_INDEX_MASK;
+		released += drop;
+		ring->prod_index = ring->c_index & DMA_C_INDEX_MASK;
+		while (drop--) {
+			cb_ptr = bcmgenet_put_txcb(priv, ring);
+			skb = cb_ptr->skb;
+			bcmgenet_free_tx_cb(kdev, cb_ptr);
+			if (skb && cb_ptr == GENET_CB(skb)->first_cb) {
+				dev_consume_skb_any(skb);
+				skb = NULL;
+			}
+		}
+		if (skb)
+			dev_consume_skb_any(skb);
+		bcmgenet_tdma_ring_writel(priv, ring->index,
+					  ring->prod_index, TDMA_PROD_INDEX);
+		wr_ptr = ring->write_ptr * WORDS_PER_BD(priv);
+		bcmgenet_tdma_ring_writel(priv, ring->index, wr_ptr,
+					  TDMA_WRITE_PTR);
+	}
 	spin_unlock_bh(&ring->lock);
 
 	return released;
@@ -1927,7 +1954,7 @@ static void bcmgenet_tx_reclaim_all(struct net_device *dev)
 	int i = 0;
 
 	do {
-		bcmgenet_tx_reclaim(dev, &priv->tx_rings[i++]);
+		bcmgenet_tx_reclaim(dev, &priv->tx_rings[i++], true);
 	} while (i <= priv->hw_params->tx_queues && netif_is_multiqueue(dev));
 }
 
@@ -2924,10 +2951,6 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv)
 	bcmgenet_fini_rx_napi(priv);
 	bcmgenet_fini_tx_napi(priv);
 
-	for (i = 0; i < priv->num_tx_bds; i++)
-		dev_kfree_skb(bcmgenet_free_tx_cb(&priv->pdev->dev,
-						  priv->tx_cbs + i));
-
 	for (i = 0; i <= priv->hw_params->tx_queues; i++) {
 		txq = netdev_get_tx_queue(priv->dev, i);
 		netdev_tx_reset_queue(txq);
Signature · 1 line
2.53.0
author maintainer
#59 lore raw

PATCH 59/508 net: bcmgenet: switch to use 64bit statistics

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zak Kemble <[email protected]>

[ Upstream commit 59aa6e3072aa7e51e9040e8c342d0c0825c5f48f ]

Update the driver to use ndo_get_stats64, rtnl_link_stats64 and u64_stats_t counters for statistics.

Stable-dep-of: 5393b2b5bee2 ("net: bcmgenet: fix racing timeout handler")

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 246 ++++++++++++------
 .../net/ethernet/broadcom/genet/bcmgenet.h    |  29 ++-
 2 files changed, 187 insertions(+), 88 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +164 -82
index de15243c52a62..a5166582e0ab7 100644
@@ -950,12 +950,13 @@ static int bcmgenet_set_pauseparam(struct net_device *dev,
 
 /* standard ethtool support functions. */
 enum bcmgenet_stat_type {
-	BCMGENET_STAT_NETDEV = -1,
+	BCMGENET_STAT_RTNL = -1,
 	BCMGENET_STAT_MIB_RX,
 	BCMGENET_STAT_MIB_TX,
 	BCMGENET_STAT_RUNT,
 	BCMGENET_STAT_MISC,
 	BCMGENET_STAT_SOFT,
+	BCMGENET_STAT_SOFT64,
 };
 
 struct bcmgenet_stats {
@@ -965,13 +966,15 @@ struct bcmgenet_stats {
 	enum bcmgenet_stat_type type;
 	/* reg offset from UMAC base for misc counters */
 	u16 reg_offset;
+	/* sync for u64 stats counters */
+	int syncp_offset;
 };
 
-#define STAT_NETDEV(m) { \
+#define STAT_RTNL(m) { \
 	.stat_string = __stringify(m), \
-	.stat_sizeof = sizeof(((struct net_device_stats *)0)->m), \
-	.stat_offset = offsetof(struct net_device_stats, m), \
-	.type = BCMGENET_STAT_NETDEV, \
+	.stat_sizeof = sizeof(((struct rtnl_link_stats64 *)0)->m), \
+	.stat_offset = offsetof(struct rtnl_link_stats64, m), \
+	.type = BCMGENET_STAT_RTNL, \
 }
 
 #define STAT_GENET_MIB(str, m, _type) { \
@@ -981,6 +984,14 @@ struct bcmgenet_stats {
 	.type = _type, \
 }
 
+#define STAT_GENET_SOFT_MIB64(str, s, m) { \
+	.stat_string = str, \
+	.stat_sizeof = sizeof(((struct bcmgenet_priv *)0)->s.m), \
+	.stat_offset = offsetof(struct bcmgenet_priv, s.m), \
+	.type = BCMGENET_STAT_SOFT64, \
+	.syncp_offset = offsetof(struct bcmgenet_priv, s.syncp), \
+}
+
 #define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX)
 #define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX)
 #define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT)
@@ -995,18 +1006,18 @@ struct bcmgenet_stats {
 }
 
 #define STAT_GENET_Q(num) \
-	STAT_GENET_SOFT_MIB("txq" __stringify(num) "_packets", \
-			tx_rings[num].packets), \
-	STAT_GENET_SOFT_MIB("txq" __stringify(num) "_bytes", \
-			tx_rings[num].bytes), \
-	STAT_GENET_SOFT_MIB("rxq" __stringify(num) "_bytes", \
-			rx_rings[num].bytes),	 \
-	STAT_GENET_SOFT_MIB("rxq" __stringify(num) "_packets", \
-			rx_rings[num].packets), \
-	STAT_GENET_SOFT_MIB("rxq" __stringify(num) "_errors", \
-			rx_rings[num].errors), \
-	STAT_GENET_SOFT_MIB("rxq" __stringify(num) "_dropped", \
-			rx_rings[num].dropped)
+	STAT_GENET_SOFT_MIB64("txq" __stringify(num) "_packets", \
+			tx_rings[num].stats64, packets), \
+	STAT_GENET_SOFT_MIB64("txq" __stringify(num) "_bytes", \
+			tx_rings[num].stats64, bytes), \
+	STAT_GENET_SOFT_MIB64("rxq" __stringify(num) "_bytes", \
+			rx_rings[num].stats64, bytes),	 \
+	STAT_GENET_SOFT_MIB64("rxq" __stringify(num) "_packets", \
+			rx_rings[num].stats64, packets), \
+	STAT_GENET_SOFT_MIB64("rxq" __stringify(num) "_errors", \
+			rx_rings[num].stats64, errors), \
+	STAT_GENET_SOFT_MIB64("rxq" __stringify(num) "_dropped", \
+			rx_rings[num].stats64, dropped)
 
 /* There is a 0xC gap between the end of RX and beginning of TX stats and then
  * between the end of TX stats and the beginning of the RX RUNT
@@ -1018,15 +1029,15 @@ struct bcmgenet_stats {
  */
 static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
 	/* general stats */
-	STAT_NETDEV(rx_packets),
-	STAT_NETDEV(tx_packets),
-	STAT_NETDEV(rx_bytes),
-	STAT_NETDEV(tx_bytes),
-	STAT_NETDEV(rx_errors),
-	STAT_NETDEV(tx_errors),
-	STAT_NETDEV(rx_dropped),
-	STAT_NETDEV(tx_dropped),
-	STAT_NETDEV(multicast),
+	STAT_RTNL(rx_packets),
+	STAT_RTNL(tx_packets),
+	STAT_RTNL(rx_bytes),
+	STAT_RTNL(tx_bytes),
+	STAT_RTNL(rx_errors),
+	STAT_RTNL(tx_errors),
+	STAT_RTNL(rx_dropped),
+	STAT_RTNL(tx_dropped),
+	STAT_RTNL(multicast),
 	/* UniMAC RSV counters */
 	STAT_GENET_MIB_RX("rx_64_octets", mib.rx.pkt_cnt.cnt_64),
 	STAT_GENET_MIB_RX("rx_65_127_oct", mib.rx.pkt_cnt.cnt_127),
@@ -1114,6 +1125,20 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
 
 #define BCMGENET_STATS_LEN	ARRAY_SIZE(bcmgenet_gstrings_stats)
 
+#define BCMGENET_STATS64_ADD(stats, m, v) \
+	do { \
+		u64_stats_update_begin(&stats->syncp); \
+		u64_stats_add(&stats->m, v); \
+		u64_stats_update_end(&stats->syncp); \
+	} while (0)
+
+#define BCMGENET_STATS64_INC(stats, m) \
+	do { \
+		u64_stats_update_begin(&stats->syncp); \
+		u64_stats_inc(&stats->m); \
+		u64_stats_update_end(&stats->syncp); \
+	} while (0)
+
 static void bcmgenet_get_drvinfo(struct net_device *dev,
 				 struct ethtool_drvinfo *info)
 {
@@ -1197,8 +1222,9 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
 
 		s = &bcmgenet_gstrings_stats[i];
 		switch (s->type) {
-		case BCMGENET_STAT_NETDEV:
+		case BCMGENET_STAT_RTNL:
 		case BCMGENET_STAT_SOFT:
+		case BCMGENET_STAT_SOFT64:
 			continue;
 		case BCMGENET_STAT_RUNT:
 			offset += BCMGENET_STAT_OFFSET;
@@ -1236,28 +1262,40 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev,
 				       u64 *data)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
+	struct rtnl_link_stats64 stats64;
+	struct u64_stats_sync *syncp;
+	unsigned int start;
 	int i;
 
 	if (netif_running(dev))
 		bcmgenet_update_mib_counters(priv);
 
-	dev->netdev_ops->ndo_get_stats(dev);
+	dev_get_stats(dev, &stats64);
 
 	for (i = 0; i < BCMGENET_STATS_LEN; i++) {
 		const struct bcmgenet_stats *s;
 		char *p;
 
 		s = &bcmgenet_gstrings_stats[i];
-		if (s->type == BCMGENET_STAT_NETDEV)
-			p = (char *)&dev->stats;
-		else
-			p = (char *)priv;
-		p += s->stat_offset;
-		if (sizeof(unsigned long) != sizeof(u32) &&
-		    s->stat_sizeof == sizeof(unsigned long))
-			data[i] = *(unsigned long *)p;
-		else
-			data[i] = *(u32 *)p;
+		p = (char *)priv;
+
+		if (s->type == BCMGENET_STAT_SOFT64) {
+			syncp = (struct u64_stats_sync *)(p + s->syncp_offset);
+			do {
+				start = u64_stats_fetch_begin(syncp);
+				data[i] = u64_stats_read((u64_stats_t *)(p + s->stat_offset));
+			} while (u64_stats_fetch_retry(syncp, start));
+		} else {
+			if (s->type == BCMGENET_STAT_RTNL)
+				p = (char *)&stats64;
+
+			p += s->stat_offset;
+			if (sizeof(unsigned long) != sizeof(u32) &&
+				s->stat_sizeof == sizeof(unsigned long))
+				data[i] = *(unsigned long *)p;
+			else
+				data[i] = *(u32 *)p;
+		}
 	}
 }
 
@@ -1835,6 +1873,7 @@ static struct sk_buff *bcmgenet_free_rx_cb(struct device *dev,
 static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 					  struct bcmgenet_tx_ring *ring)
 {
+	struct bcmgenet_tx_stats64 *stats = &ring->stats64;
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	unsigned int txbds_processed = 0;
 	unsigned int bytes_compl = 0;
@@ -1875,8 +1914,10 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
 	ring->free_bds += txbds_processed;
 	ring->c_index = c_index;
 
-	ring->packets += pkts_compl;
-	ring->bytes += bytes_compl;
+	u64_stats_update_begin(&stats->syncp);
+	u64_stats_add(&stats->packets, pkts_compl);
+	u64_stats_add(&stats->bytes, bytes_compl);
+	u64_stats_update_end(&stats->syncp);
 
 	netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->index),
 				  pkts_compl, bytes_compl);
@@ -1962,8 +2003,10 @@ static void bcmgenet_tx_reclaim_all(struct net_device *dev)
  * the transmit checksum offsets in the descriptors
  */
 static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,
-					struct sk_buff *skb)
+					struct sk_buff *skb,
+					struct bcmgenet_tx_ring *ring)
 {
+	struct bcmgenet_tx_stats64 *stats = &ring->stats64;
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	struct status_64 *status = NULL;
 	struct sk_buff *new_skb;
@@ -1980,7 +2023,7 @@ static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,
 		if (!new_skb) {
 			dev_kfree_skb_any(skb);
 			priv->mib.tx_realloc_tsb_failed++;
-			dev->stats.tx_dropped++;
+			BCMGENET_STATS64_INC(stats, dropped);
 			return NULL;
 		}
 		dev_consume_skb_any(skb);
@@ -2068,7 +2111,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
 	GENET_CB(skb)->bytes_sent = skb->len;
 
 	/* add the Transmit Status Block */
-	skb = bcmgenet_add_tsb(dev, skb);
+	skb = bcmgenet_add_tsb(dev, skb, ring);
 	if (!skb) {
 		ret = NETDEV_TX_OK;
 		goto out;
@@ -2210,6 +2253,7 @@ static struct sk_buff *bcmgenet_rx_refill(struct bcmgenet_priv *priv,
 static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 				     unsigned int budget)
 {
+	struct bcmgenet_rx_stats64 *stats = &ring->stats64;
 	struct bcmgenet_priv *priv = ring->priv;
 	struct net_device *dev = priv->dev;
 	struct enet_cb *cb;
@@ -2232,7 +2276,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 		   DMA_P_INDEX_DISCARD_CNT_MASK;
 	if (discards > ring->old_discards) {
 		discards = discards - ring->old_discards;
-		ring->errors += discards;
+		BCMGENET_STATS64_ADD(stats, errors, discards);
 		ring->old_discards += discards;
 
 		/* Clear HW register when we reach 75% of maximum 0xFFFF */
@@ -2258,7 +2302,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 		skb = bcmgenet_rx_refill(priv, cb);
 
 		if (unlikely(!skb)) {
-			ring->dropped++;
+			BCMGENET_STATS64_INC(stats, dropped);
 			goto next;
 		}
 
@@ -2285,8 +2329,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 
 		if (unlikely(len > RX_BUF_LENGTH)) {
 			netif_err(priv, rx_status, dev, "oversized packet\n");
-			dev->stats.rx_length_errors++;
-			dev->stats.rx_errors++;
+			BCMGENET_STATS64_INC(stats, length_errors);
 			dev_kfree_skb_any(skb);
 			goto next;
 		}
@@ -2294,7 +2337,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 		if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
 			netif_err(priv, rx_status, dev,
 				  "dropping fragmented packet!\n");
-			ring->errors++;
+			BCMGENET_STATS64_INC(stats, errors);
 			dev_kfree_skb_any(skb);
 			goto next;
 		}
@@ -2307,15 +2350,22 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 						DMA_RX_RXER))) {
 			netif_err(priv, rx_status, dev, "dma_flag=0x%x\n",
 				  (unsigned int)dma_flag);
+			u64_stats_update_begin(&stats->syncp);
 			if (dma_flag & DMA_RX_CRC_ERROR)
-				dev->stats.rx_crc_errors++;
+				u64_stats_inc(&stats->crc_errors);
 			if (dma_flag & DMA_RX_OV)
-				dev->stats.rx_over_errors++;
+				u64_stats_inc(&stats->over_errors);
 			if (dma_flag & DMA_RX_NO)
-				dev->stats.rx_frame_errors++;
+				u64_stats_inc(&stats->frame_errors);
 			if (dma_flag & DMA_RX_LG)
-				dev->stats.rx_length_errors++;
-			dev->stats.rx_errors++;
+				u64_stats_inc(&stats->length_errors);
+			if ((dma_flag & (DMA_RX_CRC_ERROR |
+						DMA_RX_OV |
+						DMA_RX_NO |
+						DMA_RX_LG |
+						DMA_RX_RXER)) == DMA_RX_RXER)
+				u64_stats_inc(&stats->errors);
+			u64_stats_update_end(&stats->syncp);
 			dev_kfree_skb_any(skb);
 			goto next;
 		} /* error packet */
@@ -2335,10 +2385,13 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
 
 		/*Finish setting up the received SKB and send it to the kernel*/
 		skb->protocol = eth_type_trans(skb, priv->dev);
-		ring->packets++;
-		ring->bytes += len;
+
+		u64_stats_update_begin(&stats->syncp);
+		u64_stats_inc(&stats->packets);
+		u64_stats_add(&stats->bytes, len);
 		if (dma_flag & DMA_RX_MULT)
-			dev->stats.multicast++;
+			u64_stats_inc(&stats->multicast);
+		u64_stats_update_end(&stats->syncp);
 
 		/* Notify kernel */
 		napi_gro_receive(&ring->napi, skb);
@@ -3439,7 +3492,7 @@ static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue)
 
 	netif_trans_update(dev);
 
-	dev->stats.tx_errors++;
+	BCMGENET_STATS64_INC((&priv->tx_rings[txqueue].stats64), errors);
 
 	netif_tx_wake_all_queues(dev);
 }
@@ -3528,39 +3581,68 @@ static int bcmgenet_set_mac_addr(struct net_device *dev, void *p)
 	return 0;
 }
 
-static struct net_device_stats *bcmgenet_get_stats(struct net_device *dev)
+static void bcmgenet_get_stats64(struct net_device *dev,
+				 struct rtnl_link_stats64 *stats)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	unsigned long tx_bytes = 0, tx_packets = 0;
-	unsigned long rx_bytes = 0, rx_packets = 0;
-	unsigned long rx_errors = 0, rx_dropped = 0;
-	struct bcmgenet_tx_ring *tx_ring;
-	struct bcmgenet_rx_ring *rx_ring;
+	struct bcmgenet_tx_stats64 *tx_stats;
+	struct bcmgenet_rx_stats64 *rx_stats;
+	u64 rx_length_errors, rx_over_errors;
+	u64 rx_crc_errors, rx_frame_errors;
+	u64 tx_errors, tx_dropped;
+	u64 rx_errors, rx_dropped;
+	u64 tx_bytes, tx_packets;
+	u64 rx_bytes, rx_packets;
+	unsigned int start;
 	unsigned int q;
+	u64 multicast;
 
 	for (q = 0; q <= priv->hw_params->tx_queues; q++) {
-		tx_ring = &priv->tx_rings[q];
-		tx_bytes += tx_ring->bytes;
-		tx_packets += tx_ring->packets;
+		tx_stats = &priv->tx_rings[q].stats64;
+		do {
+			start = u64_stats_fetch_begin(&tx_stats->syncp);
+			tx_bytes = u64_stats_read(&tx_stats->bytes);
+			tx_packets = u64_stats_read(&tx_stats->packets);
+			tx_errors = u64_stats_read(&tx_stats->errors);
+			tx_dropped = u64_stats_read(&tx_stats->dropped);
+		} while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+		stats->tx_bytes += tx_bytes;
+		stats->tx_packets += tx_packets;
+		stats->tx_errors += tx_errors;
+		stats->tx_dropped += tx_dropped;
 	}
 
 	for (q = 0; q <= priv->hw_params->rx_queues; q++) {
-		rx_ring = &priv->rx_rings[q];
-
-		rx_bytes += rx_ring->bytes;
-		rx_packets += rx_ring->packets;
-		rx_errors += rx_ring->errors;
-		rx_dropped += rx_ring->dropped;
+		rx_stats = &priv->rx_rings[q].stats64;
+		do {
+			start = u64_stats_fetch_begin(&rx_stats->syncp);
+			rx_bytes = u64_stats_read(&rx_stats->bytes);
+			rx_packets = u64_stats_read(&rx_stats->packets);
+			rx_errors = u64_stats_read(&rx_stats->errors);
+			rx_dropped = u64_stats_read(&rx_stats->dropped);
+			rx_length_errors = u64_stats_read(&rx_stats->length_errors);
+			rx_over_errors = u64_stats_read(&rx_stats->over_errors);
+			rx_crc_errors = u64_stats_read(&rx_stats->crc_errors);
+			rx_frame_errors = u64_stats_read(&rx_stats->frame_errors);
+			multicast = u64_stats_read(&rx_stats->multicast);
+		} while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+		rx_errors += rx_length_errors;
+		rx_errors += rx_crc_errors;
+		rx_errors += rx_frame_errors;
+
+		stats->rx_bytes += rx_bytes;
+		stats->rx_packets += rx_packets;
+		stats->rx_errors += rx_errors;
+		stats->rx_dropped += rx_dropped;
+		stats->rx_missed_errors += rx_errors;
+		stats->rx_length_errors += rx_length_errors;
+		stats->rx_over_errors += rx_over_errors;
+		stats->rx_crc_errors += rx_crc_errors;
+		stats->rx_frame_errors += rx_frame_errors;
+		stats->multicast += multicast;
 	}
-
-	dev->stats.tx_bytes = tx_bytes;
-	dev->stats.tx_packets = tx_packets;
-	dev->stats.rx_bytes = rx_bytes;
-	dev->stats.rx_packets = rx_packets;
-	dev->stats.rx_errors = rx_errors;
-	dev->stats.rx_missed_errors = rx_errors;
-	dev->stats.rx_dropped = rx_dropped;
-	return &dev->stats;
 }
 
 static int bcmgenet_change_carrier(struct net_device *dev, bool new_carrier)
@@ -3588,7 +3670,7 @@ static const struct net_device_ops bcmgenet_netdev_ops = {
 	.ndo_set_mac_address	= bcmgenet_set_mac_addr,
 	.ndo_eth_ioctl		= phy_do_ioctl_running,
 	.ndo_set_features	= bcmgenet_set_features,
-	.ndo_get_stats		= bcmgenet_get_stats,
+	.ndo_get_stats64	= bcmgenet_get_stats64,
 	.ndo_change_carrier	= bcmgenet_change_carrier,
 };
 
drivers/net/ethernet/broadcom/genet/bcmgenet.h +23 -6
index f3a1139cb7108..94957dfa55b6f 100644
@@ -155,6 +155,27 @@ struct bcmgenet_mib_counters {
 	u32	tx_realloc_tsb_failed;
 };
 
+struct bcmgenet_tx_stats64 {
+	struct u64_stats_sync syncp;
+	u64_stats_t	packets;
+	u64_stats_t	bytes;
+	u64_stats_t	errors;
+	u64_stats_t	dropped;
+};
+
+struct bcmgenet_rx_stats64 {
+	struct u64_stats_sync syncp;
+	u64_stats_t	bytes;
+	u64_stats_t	packets;
+	u64_stats_t	errors;
+	u64_stats_t	dropped;
+	u64_stats_t	multicast;
+	u64_stats_t	length_errors;
+	u64_stats_t	over_errors;
+	u64_stats_t	crc_errors;
+	u64_stats_t	frame_errors;
+};
+
 #define UMAC_MIB_START			0x400
 
 #define UMAC_MDIO_CMD			0x614
@@ -513,8 +534,7 @@ struct bcmgenet_skb_cb {
 struct bcmgenet_tx_ring {
 	spinlock_t	lock;		/* ring lock */
 	struct napi_struct napi;	/* NAPI per tx queue */
-	unsigned long	packets;
-	unsigned long	bytes;
+	struct bcmgenet_tx_stats64 stats64;
 	unsigned int	index;		/* ring index */
 	struct enet_cb	*cbs;		/* tx ring buffer control block*/
 	unsigned int	size;		/* size of each tx ring */
@@ -538,10 +558,7 @@ struct bcmgenet_net_dim {
 
 struct bcmgenet_rx_ring {
 	struct napi_struct napi;	/* Rx NAPI struct */
-	unsigned long	bytes;
-	unsigned long	packets;
-	unsigned long	errors;
-	unsigned long	dropped;
+	struct bcmgenet_rx_stats64 stats64;
 	unsigned int	index;		/* Rx ring index */
 	struct enet_cb	*cbs;		/* Rx ring buffer control block */
 	unsigned int	size;		/* Rx ring size */
Signature · 1 line
2.53.0
author maintainer
#60 lore raw

PATCH 60/508 net: bcmgenet: fix racing timeout handler

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Justin Chen <[email protected]>

[ Upstream commit 5393b2b5bee2ac51a0043dc7f4ac3475f053d08d ]

The bcmgenet_timeout handler tries to take down all tx queues when a single queue times out. This is over zealous and causes many race conditions with queues that are still chugging along. Instead lets only restart the timed out queue.

---
 .../net/ethernet/broadcom/genet/bcmgenet.c    | 22 ++++++++-----------
 1 file changed, 9 insertions(+), 13 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +9 -13
index a5166582e0ab7..e08abde4685ac 100644
@@ -3474,27 +3474,23 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)
 static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	u32 int1_enable = 0;
-	unsigned int q;
+	struct bcmgenet_tx_ring *ring = &priv->tx_rings[txqueue];
+	struct netdev_queue *txq = netdev_get_tx_queue(dev, txqueue);
 
 	netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");
 
-	for (q = 0; q <= priv->hw_params->tx_queues; q++)
-		bcmgenet_dump_tx_queue(&priv->tx_rings[q]);
-
-	bcmgenet_tx_reclaim_all(dev);
+	bcmgenet_dump_tx_queue(ring);
 
-	for (q = 0; q <= priv->hw_params->tx_queues; q++)
-		int1_enable |= (1 << q);
+	bcmgenet_tx_reclaim(dev, ring, true);
 
-	/* Re-enable TX interrupts if disabled */
-	bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
+	/* Re-enable the TX interrupt for this ring */
+	bcmgenet_intrl2_1_writel(priv, 1 << txqueue, INTRL2_CPU_MASK_CLEAR);
 
-	netif_trans_update(dev);
+	txq_trans_cond_update(txq);
 
-	BCMGENET_STATS64_INC((&priv->tx_rings[txqueue].stats64), errors);
+	BCMGENET_STATS64_INC((&ring->stats64), errors);
 
-	netif_tx_wake_all_queues(dev);
+	netif_tx_wake_queue(txq);
 }
 
 #define MAX_MDF_FILTER	17
Signature · 1 line
2.53.0
author maintainer
#61 lore raw

PATCH 61/508 netfilter: xt_socket: enable defrag after all other checks

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Westphal <[email protected]>

[ Upstream commit 542be3fa5aff54210a02954c38f07e53ea9bdafd ]

Originally this did not matter because defrag was enabled once per netns and only disabled again on netns dismantle. When this got changed I should have adjusted checkentry to not leave defrag enabled on error.

Fixes de8c12110a13 ("netfilter: disable defrag once its no longer needed")
---
 net/netfilter/xt_socket.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)
net/netfilter/xt_socket.c +6 -17
index 76e01f292aaff..811e53bee4085 100644
@@ -168,52 +168,41 @@ static int socket_mt_enable_defrag(struct net *net, int family)
 static int socket_mt_v1_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
-	int err;
-
-	err = socket_mt_enable_defrag(par->net, par->family);
-	if (err)
-		return err;
 
 	if (info->flags & ~XT_SOCKET_FLAGS_V1) {
 		pr_info_ratelimited("unknown flags 0x%x\n",
 				    info->flags & ~XT_SOCKET_FLAGS_V1);
 		return -EINVAL;
 	}
-	return 0;
+
+	return socket_mt_enable_defrag(par->net, par->family);
 }
 
 static int socket_mt_v2_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
-	int err;
-
-	err = socket_mt_enable_defrag(par->net, par->family);
-	if (err)
-		return err;
 
 	if (info->flags & ~XT_SOCKET_FLAGS_V2) {
 		pr_info_ratelimited("unknown flags 0x%x\n",
 				    info->flags & ~XT_SOCKET_FLAGS_V2);
 		return -EINVAL;
 	}
-	return 0;
+
+	return socket_mt_enable_defrag(par->net, par->family);
 }
 
 static int socket_mt_v3_check(const struct xt_mtchk_param *par)
 {
 	const struct xt_socket_mtinfo3 *info =
 				    (struct xt_socket_mtinfo3 *)par->matchinfo;
-	int err;
 
-	err = socket_mt_enable_defrag(par->net, par->family);
-	if (err)
-		return err;
 	if (info->flags & ~XT_SOCKET_FLAGS_V3) {
 		pr_info_ratelimited("unknown flags 0x%x\n",
 				    info->flags & ~XT_SOCKET_FLAGS_V3);
 		return -EINVAL;
 	}
-	return 0;
+
+	return socket_mt_enable_defrag(par->net, par->family);
 }
 
 static void socket_mt_destroy(const struct xt_mtdtor_param *par)
Signature · 1 line
2.53.0
author maintainer
#62 lore raw

PATCH 62/508 netfilter: nft_fwd_netdev: check ttl/hl before forwarding

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Westphal <[email protected]>

[ Upstream commit 1dfd95bdf4d18d263aa8fad06bfb9f4d9c992b18 ]

Drop packets if their ttl/hl is too small for forwarding.

Fixes d32de98ea70f ("netfilter: nft_fwd_netdev: allow to forward packets via neighbour layer")
---
 net/netfilter/nft_fwd_netdev.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
net/netfilter/nft_fwd_netdev.c +10 -0
index 42ba31dfc0359..1223bdea1f00d 100644
@@ -116,6 +116,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
 			goto out;
 		}
 		iph = ip_hdr(skb);
+		if (iph->ttl <= 1) {
+			verdict = NF_DROP;
+			goto out;
+		}
+
 		ip_decrease_ttl(iph);
 		neigh_table = NEIGH_ARP_TABLE;
 		break;
@@ -132,6 +137,11 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
 			goto out;
 		}
 		ip6h = ipv6_hdr(skb);
+		if (ip6h->hop_limit <= 1) {
+			verdict = NF_DROP;
+			goto out;
+		}
+
 		ip6h->hop_limit--;
 		neigh_table = NEIGH_ND_TABLE;
 		break;
Signature · 1 line
2.53.0
author maintainer
#63 lore raw

PATCH 63/508 bpf: Fix RCU stall in bpf_fd_array_map_clear()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sechang Lim <[email protected]>

[ Upstream commit 4406942e65ca128c56c67443832988873c21d2e9 ]

Add a missing cond_resched() in bpf_fd_array_map_clear() loop.

For PROG_ARRAY maps with many entries this loop calls prog_array_map_poke_run() per entry which can be expensive, and without yielding this can cause RCU stalls under load:

rcu: Stack dump where RCU GP kthread last ran:

  CPU: 0 UID: 0 PID: 30932 Comm: kworker/0:2 Not tainted 6.14.0-13195-g967e8def1100 #2 PREEMPT(undef)
  Workqueue: events prog_array_map_clear_deferred
  RIP: 0010:write_comp_data+0x38/0x90 kernel/kcov.c:246
  Call Trace:
   <TASK>
   prog_array_map_poke_run+0x77/0x380 kernel/bpf/arraymap.c:1096
   __fd_array_map_delete_elem+0x197/0x310 kernel/bpf/arraymap.c:925
   bpf_fd_array_map_clear kernel/bpf/arraymap.c:1000 [inline]
   prog_array_map_clear_deferred+0x119/0x1b0 kernel/bpf/arraymap.c:1141
   process_one_work+0x898/0x19d0 kernel/workqueue.c:3238
   process_scheduled_works kernel/workqueue.c:3319 [inline]
   worker_thread+0x770/0x10b0 kernel/workqueue.c:3400
   kthread+0x465/0x880 kernel/kthread.c:464
   ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:153
   ret_from_fork_asm+0x19/0x30 arch/x86/entry/entry_64.S:245
   </TASK>
Fixes da765a2f5993 ("bpf: Add poke dependency tracking for prog array maps")
---
 kernel/bpf/arraymap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/bpf/arraymap.c +3 -1
index 1811efcfbd6e3..ec5c489ed3131 100644
@@ -938,8 +938,10 @@ static void bpf_fd_array_map_clear(struct bpf_map *map, bool need_defer)
 	struct bpf_array *array = container_of(map, struct bpf_array, map);
 	int i;
 
-	for (i = 0; i < array->map.max_entries; i++)
+	for (i = 0; i < array->map.max_entries; i++) {
 		__fd_array_map_delete_elem(map, &i, need_defer);
+		cond_resched();
+	}
 }
 
 static void prog_array_map_seq_show_elem(struct bpf_map *map, void *key,
Signature · 1 line
2.53.0
author maintainer
#64 lore raw

PATCH 64/508 6pack: propagage new tty types

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiri Slaby (SUSE) <[email protected]>

[ Upstream commit 1241b384efa53f4b7a95fe2b34d69359bb3ae1b5 ]

In tty, u8 is now used for data, ssize_t for sizes (with possible negative error codes). Propagate these types to 6pack.

Stable-dep-of: bf9a38803b26 ("net: hamradio: 6pack: fix uninit-value in sixpack_receive_buf")

---
 drivers/net/hamradio/6pack.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/net/hamradio/6pack.c +16 -16
index 6cecdfa8631d7..3145dadf99290 100644
@@ -94,8 +94,8 @@ struct sixpack {
 	unsigned char		*xhead;         /* next byte to XMIT */
 	int			xleft;          /* bytes left in XMIT queue  */
 
-	unsigned char		raw_buf[4];
-	unsigned char		cooked_buf[400];
+	u8			raw_buf[4];
+	u8			cooked_buf[400];
 
 	unsigned int		rx_count;
 	unsigned int		rx_count_cooked;
@@ -113,8 +113,8 @@ struct sixpack {
 	unsigned char		slottime;
 	unsigned char		duplex;
 	unsigned char		led_state;
-	unsigned char		status;
-	unsigned char		status1;
+	u8			status;
+	u8			status1;
 	unsigned char		status2;
 	unsigned char		tx_enable;
 	unsigned char		tnc_state;
@@ -126,7 +126,7 @@ struct sixpack {
 
 #define AX25_6PACK_HEADER_LEN 0
 
-static void sixpack_decode(struct sixpack *, const unsigned char[], int);
+static void sixpack_decode(struct sixpack *, const u8 *, size_t);
 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
 
 /*
@@ -331,7 +331,7 @@ static void sp_bump(struct sixpack *sp, char cmd)
 {
 	struct sk_buff *skb;
 	int count;
-	unsigned char *ptr;
+	u8 *ptr;
 
 	count = sp->rcount + 1;
 
@@ -397,7 +397,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
 				const u8 *fp, size_t count)
 {
 	struct sixpack *sp;
-	int count1;
+	size_t count1;
 
 	if (!count)
 		return;
@@ -773,9 +773,9 @@ static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
 
 /* decode 4 sixpack-encoded bytes into 3 data bytes */
 
-static void decode_data(struct sixpack *sp, unsigned char inbyte)
+static void decode_data(struct sixpack *sp, u8 inbyte)
 {
-	unsigned char *buf;
+	u8 *buf;
 
 	if (sp->rx_count != 3) {
 		sp->raw_buf[sp->rx_count++] = inbyte;
@@ -801,9 +801,9 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte)
 
 /* identify and execute a 6pack priority command byte */
 
-static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
+static void decode_prio_command(struct sixpack *sp, u8 cmd)
 {
-	int actual;
+	ssize_t actual;
 
 	if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {     /* idle ? */
 
@@ -851,9 +851,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
 
 /* identify and execute a standard 6pack command byte */
 
-static void decode_std_command(struct sixpack *sp, unsigned char cmd)
+static void decode_std_command(struct sixpack *sp, u8 cmd)
 {
-	unsigned char checksum = 0, rest = 0;
+	u8 checksum = 0, rest = 0;
 	short i;
 
 	switch (cmd & SIXP_CMD_MASK) {     /* normal command */
@@ -901,10 +901,10 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
 /* decode a 6pack packet */
 
 static void
-sixpack_decode(struct sixpack *sp, const unsigned char *pre_rbuff, int count)
+sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count)
 {
-	unsigned char inbyte;
-	int count1;
+	size_t count1;
+	u8 inbyte;
 
 	for (count1 = 0; count1 < count; count1++) {
 		inbyte = pre_rbuff[count1];
Signature · 1 line
2.53.0
author maintainer
#65 lore raw

PATCH 65/508 net: hamradio: 6pack: fix uninit-value in sixpack_receive_buf

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mashiro Chen <[email protected]>

[ Upstream commit bf9a38803b2626b01cc769aaf13485d8650f576f ]

sixpack_receive_buf() does not properly skip bytes with TTY error flags. The while loop iterates through the flags buffer but never advances the data pointer (cp), and passes the original count (including error bytes) to sixpack_decode(). This causes sixpack_decode() to process bytes that should have been skipped due to TTY errors. The TTY layer does not guarantee that cp[i] holds a meaningful value when fp[i] is set, so passing those positions to sixpack_decode() results in KMSAN reporting an uninit-value read.

Fix this by processing bytes one at a time, advancing cp on each iteration, and only passing valid (non-error) bytes to sixpack_decode(). This matches the pattern used by slip_receive_buf() and mkiss_receive_buf() for the same purpose.

---
 drivers/net/hamradio/6pack.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/hamradio/6pack.c +4 -5
index 3145dadf99290..1b8680923919d 100644
@@ -397,7 +397,6 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
 				const u8 *fp, size_t count)
 {
 	struct sixpack *sp;
-	size_t count1;
 
 	if (!count)
 		return;
@@ -407,16 +406,16 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
 		return;
 
 	/* Read the characters out of the buffer */
-	count1 = count;
-	while (count) {
-		count--;
+	while (count--) {
 		if (fp && *fp++) {
 			if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
 				sp->dev->stats.rx_errors++;
+			cp++;
 			continue;
 		}
+		sixpack_decode(sp, cp, 1);
+		cp++;
 	}
-	sixpack_decode(sp, cp, count1);
 
 	tty_unthrottle(tty);
 }
Signature · 1 line
2.53.0
author maintainer
#66 lore raw

PATCH 66/508 net/sched: act_ct: Only release RCU read lock after ct_ft

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jamal Hadi Salim <[email protected]>

[ Upstream commit f462dca0c8415bf0058d0ffa476354c4476d0f09 ]

When looking up a flow table in act_ct in tcf_ct_flow_table_get(), rhashtable_lookup_fast() internally opens and closes an RCU read critical section before returning ct_ft.
The tcf_ct_flow_table_cleanup_work() can complete before refcount_inc_not_zero() is invoked on the returned ct_ft resulting in a UAF on the already freed ct_ft object. This vulnerability can lead to privilege escalation.

Analysis from [email protected]:
When initializing act_ct, tcf_ct_init() is called, which internally triggers tcf_ct_flow_table_get().

static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)

{
                struct zones_ht_key key = { .net = net, .zone = params->zone };
                struct tcf_ct_flow_table *ct_ft;
                int err = -ENOMEM;

                mutex_lock(&zones_mutex);
                ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params); // [1]
                if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) // [2]
                                goto out_unlock;
                ...
}

static __always_inline void *rhashtable_lookup_fast(
struct rhashtable *ht, const void *key, const struct rhashtable_params params)

{
                void *obj;

                rcu_read_lock();
                obj = rhashtable_lookup(ht, key, params);
                rcu_read_unlock();

                return obj;
}

At [1], rhashtable_lookup_fast() looks up and returns the corresponding ct_ft from zones_ht . The lookup is performed within an RCU read critical section through rcu_read_lock() / rcu_read_unlock(), which prevents the object from being freed. However, at the point of function return, rcu_read_unlock() has already been called, and there is nothing preventing ct_ft from being freed before reaching refcount_inc_not_zero(&ct_ft->ref) at [2]. This interval becomes the race window, during which ct_ft can be freed.

Free Process:

tcf_ct_flow_table_put() is executed through the path tcf_ct_cleanup() call_rcu() tcf_ct_params_free_rcu() tcf_ct_params_free() tcf_ct_flow_table_put().

static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft)

{
                if (refcount_dec_and_test(&ct_ft->ref)) {
                                rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params);
                                INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work); // [3]
                                queue_rcu_work(act_ct_wq, &ct_ft->rwork);
                }
}

At [3], tcf_ct_flow_table_cleanup_work() is scheduled as RCU work

static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)

{
                struct tcf_ct_flow_table *ct_ft;
                struct flow_block *block;

                ct_ft = container_of(to_rcu_work(work), struct tcf_ct_flow_table,
                                                                rwork);
                nf_flow_table_free(&ct_ft->nf_ft);
                block = &ct_ft->nf_ft.flow_block;
                down_write(&ct_ft->nf_ft.flow_block_lock);
                WARN_ON(!list_empty(&block->cb_list));
                up_write(&ct_ft->nf_ft.flow_block_lock);
                kfree(ct_ft); // [4]

                module_put(THIS_MODULE);
}

tcf_ct_flow_table_cleanup_work() frees ct_ft at [4]. When this function executes between [1] and [2], UAF occurs.

This race condition has a very short race window, making it generally difficult to trigger. Therefore, to trigger the vulnerability an msleep(100) was inserted after[1]

Fixes 138470a9b2cc2 ("net/sched: act_ct: fix lockdep splat in tcf_ct_flow_table_get")
Reported-by [email protected]
---
 net/sched/act_ct.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
net/sched/act_ct.c +6 -2
index a5f4a27c8dd31..7810c9d64ff3a 100644
@@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
 	int err = -ENOMEM;
 
 	mutex_lock(&zones_mutex);
-	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
-	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
+	rcu_read_lock();
+	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
+	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
+		rcu_read_unlock();
 		goto out_unlock;
+	}
+	rcu_read_unlock();
 
 	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
 	if (!ct_ft)
Signature · 1 line
2.53.0
author maintainer
#67 lore raw

PATCH 67/508 net/rds: Optimize rds_ib_laddr_check

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Håkon Bugge <[email protected]>

[ Upstream commit 236f718ac885965fa886440b9898dfae185c9733 ]

rds_ib_laddr_check() creates a CM_ID and attempts to bind the address in question to it. This in order to qualify the allegedly local address as a usable IB/RoCE address.

In the field, ExaWatcher runs rds-ping to all ports in the fabric from all local ports. This using all active ToS'es. In a full rack system, we have 14 cell servers and eight db servers. Typically, 6 ToS'es are used. This implies 528 rds-ping invocations per ExaWatcher's "RDSinfo" interval.

Adding to this, each rds-ping invocation creates eight sockets and binds the local address to them:

socket(AF_RDS, SOCK_SEQPACKET, 0) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0),

	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 4
bind(4, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 5
bind(5, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 6
bind(6, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 7
bind(7, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 8
bind(8, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 9
bind(9, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0
socket(AF_RDS, SOCK_SEQPACKET, 0)       = 10
bind(10, {sa_family=AF_INET, sin_port=htons(0),
	sin_addr=inet_addr("192.168.36.2")}, 16) = 0

So, at every interval ExaWatcher executes rds-ping's, 4224 CM_IDs are allocated, considering this full-rack system. After the a CM_ID has been allocated, rdma_bind_addr() is called, with the port number being zero. This implies that the CMA will attempt to search for an un-used ephemeral port. Simplified, the algorithm is to start at a random position in the available port space, and then if needed, iterate until an un-used port is found.

The book-keeping of used ports uses the idr system, which again uses slab to allocate new struct idr_layer's. The size is 2092 bytes and slab tries to reduce the wasted space. Hence, it chooses an order:3 allocation, for which 15 idr_layer structs will fit and only 1388 bytes are wasted per the 32KiB order:3 chunk.

Although this order:3 allocation seems like a good space/speed trade-off, it does not resonate well with how it used by the CMA. The combination of the randomized starting point in the port space (which has close to zero spatial locality) and the close proximity in time of the 4224 invocations of the rds-ping's, creates a memory hog for order:3 allocations.

These costly allocations may need reclaims and/or compaction. At worst, they may fail and produce a stack trace such as (from uek4):

[<ffffffff811a72d5>] __inc_zone_page_state+0x35/0x40
[<ffffffff811c2e97>] page_add_file_rmap+0x57/0x60
[<ffffffffa37ca1df>] remove_migration_pte+0x3f/0x3c0 [ksplice_6cn872bt_vmlinux_new]
[<ffffffff811c3de8>] rmap_walk+0xd8/0x340
[<ffffffff811e8860>] remove_migration_ptes+0x40/0x50
[<ffffffff811ea83c>] migrate_pages+0x3ec/0x890
[<ffffffff811afa0d>] compact_zone+0x32d/0x9a0
[<ffffffff811b00ed>] compact_zone_order+0x6d/0x90
[<ffffffff811b03b2>] try_to_compact_pages+0x102/0x270
[<ffffffff81190e56>] __alloc_pages_direct_compact+0x46/0x100
[<ffffffff8119165b>] __alloc_pages_nodemask+0x74b/0xaa0
[<ffffffff811d8411>] alloc_pages_current+0x91/0x110
[<ffffffff811e3b0b>] new_slab+0x38b/0x480
[<ffffffffa41323c7>] __slab_alloc+0x3b7/0x4a0 [ksplice_s0dk66a8_vmlinux_new]
[<ffffffff811e42ab>] kmem_cache_alloc+0x1fb/0x250
[<ffffffff8131fdd6>] idr_layer_alloc+0x36/0x90
[<ffffffff8132029c>] idr_get_empty_slot+0x28c/0x3d0
[<ffffffff813204ad>] idr_alloc+0x4d/0xf0
[<ffffffffa051727d>] cma_alloc_port+0x4d/0xa0 [rdma_cm]
[<ffffffffa0517cbe>] rdma_bind_addr+0x2ae/0x5b0 [rdma_cm]
[<ffffffffa09d8083>] rds_ib_laddr_check+0x83/0x2c0 [ksplice_6l2xst5i_rds_rdma_new]
[<ffffffffa05f892b>] rds_trans_get_preferred+0x5b/0xa0 [rds]
[<ffffffffa05f09f2>] rds_bind+0x212/0x280 [rds]
[<ffffffff815b4016>] SYSC_bind+0xe6/0x120
[<ffffffff815b4d3e>] SyS_bind+0xe/0x10
[<ffffffff816b031a>] system_call_fastpath+0x18/0xd4

To avoid these excessive calls to rdma_bind_addr(), we optimize rds_ib_laddr_check() by simply checking if the address in question has been used before. The rds_rdma module keeps track of addresses associated with IB devices, and the function rds_ib_get_device() is used to determine if the address already has been qualified as a valid local address. If not found, we call the legacy rds_ib_laddr_check(), now renamed to rds_ib_laddr_check_cm().

Stable-dep-of: ebf71dd4aff4 ("net/rds: Restrict use of RDS/IB to the initial network namespace")

---
 net/rds/ib.c      | 20 ++++++++++++++++++--
 net/rds/ib.h      |  1 +
 net/rds/ib_rdma.c |  2 +-
 3 files changed, 20 insertions(+), 3 deletions(-)
net/rds/ib.c +18 -2
index 9826fe7f9d008..996f007cd516b 100644
@@ -403,8 +403,8 @@ static void rds6_ib_ic_info(struct socket *sock, unsigned int len,
  * allowed to influence which paths have priority.  We could call userspace
  * asserting this policy "routing".
  */
-static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
-			      __u32 scope_id)
+static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
+				 __u32 scope_id)
 {
 	int ret;
 	struct rdma_cm_id *cm_id;
@@ -489,6 +489,22 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
 	return ret;
 }
 
+static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
+			      __u32 scope_id)
+{
+	struct rds_ib_device *rds_ibdev = NULL;
+
+	if (ipv6_addr_v4mapped(addr)) {
+		rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]);
+		if (rds_ibdev) {
+			rds_ib_dev_put(rds_ibdev);
+			return 0;
+		}
+	}
+
+	return rds_ib_laddr_check_cm(net, addr, scope_id);
+}
+
 static void rds_ib_unregister_client(void)
 {
 	ib_unregister_client(&rds_ib_client);
net/rds/ib.h +1 -0
index 2ba71102b1f1f..d6c1197731c1c 100644
@@ -384,6 +384,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn,
 	__rds_ib_conn_error(conn, KERN_WARNING "RDS/IB: " fmt)
 
 /* ib_rdma.c */
+struct rds_ib_device *rds_ib_get_device(__be32 ipaddr);
 int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
 			 struct in6_addr *ipaddr);
 void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn);
net/rds/ib_rdma.c +1 -1
index 30fca2169aa7a..468fd60d818ff 100644
@@ -47,7 +47,7 @@ struct rds_ib_dereg_odp_mr {
 
 static void rds_ib_odp_mr_worker(struct work_struct *work);
 
-static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
+struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
 {
 	struct rds_ib_device *rds_ibdev;
 	struct rds_ib_ipaddr *i_ipaddr;
Signature · 1 line
2.53.0
author maintainer
#68 lore raw

PATCH 68/508 net/rds: Restrict use of RDS/IB to the initial network namespace

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Greg Jumper <[email protected]>

[ Upstream commit ebf71dd4aff46e8e421d455db3e231ba43d2fa8a ]

Prevent using RDS/IB in network namespaces other than the initial one. The existing RDS/IB code will not work properly in non-initial network namespaces.

Fixes d5a8ac28a7ff ("RDS-TCP: Make RDS-TCP work correctly when it is set up in a netns other than init_net")
Reported-by [email protected]
---
 net/rds/af_rds.c | 10 ++++++++--
 net/rds/ib.c     |  4 ++++
 2 files changed, 12 insertions(+), 2 deletions(-)
net/rds/af_rds.c +8 -2
index 8435a20968ef5..f0840169d5e31 100644
@@ -357,7 +357,8 @@ static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen)
 	return ret;
 }
 
-static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)
+static int rds_set_transport(struct net *net, struct rds_sock *rs,
+			     sockptr_t optval, int optlen)
 {
 	int t_type;
 
@@ -373,6 +374,10 @@ static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen)
 	if (t_type < 0 || t_type >= RDS_TRANS_COUNT)
 		return -EINVAL;
 
+	/* RDS/IB is restricted to the initial network namespace */
+	if (t_type != RDS_TRANS_TCP && !net_eq(net, &init_net))
+		return -EPROTOTYPE;
+
 	rs->rs_transport = rds_trans_get(t_type);
 
 	return rs->rs_transport ? 0 : -ENOPROTOOPT;
@@ -433,6 +438,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
 			  sockptr_t optval, unsigned int optlen)
 {
 	struct rds_sock *rs = rds_sk_to_rs(sock->sk);
+	struct net *net = sock_net(sock->sk);
 	int ret;
 
 	if (level != SOL_RDS) {
@@ -461,7 +467,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
 		break;
 	case SO_RDS_TRANSPORT:
 		lock_sock(sock->sk);
-		ret = rds_set_transport(rs, optval, optlen);
+		ret = rds_set_transport(net, rs, optval, optlen);
 		release_sock(sock->sk);
 		break;
 	case SO_TIMESTAMP_OLD:
net/rds/ib.c +4 -0
index 996f007cd516b..ce5be43c5fbac 100644
@@ -494,6 +494,10 @@ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr,
 {
 	struct rds_ib_device *rds_ibdev = NULL;
 
+	/* RDS/IB is restricted to the initial network namespace */
+	if (!net_eq(net, &init_net))
+		return -EPROTOTYPE;
+
 	if (ipv6_addr_v4mapped(addr)) {
 		rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]);
 		if (rds_ibdev) {
Signature · 1 line
2.53.0
author maintainer
#69 lore raw

PATCH 69/508 bpf: Fix OOB in pcpu_init_value

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Lang Xu <[email protected]>

[ Upstream commit 576afddfee8d1108ee299bf10f581593540d1a36 ]

An out-of-bounds read occurs when copying element from a BPF_MAP_TYPE_CGROUP_STORAGE map to another pcpu map with the same value_size that is not rounded up to 8 bytes.

The issue happens when:
1. A CGROUP_STORAGE map is created with value_size not aligned to 8 bytes (e.g., 4 bytes)
2. A pcpu map is created with the same value_size (e.g., 4 bytes)
3. Update element in 2 with data in 1

pcpu_init_value assumes that all sources are rounded up to 8 bytes, and invokes copy_map_value_long to make a data copy, However, the assumption doesn't stand since there are some cases where the source may not be rounded up to 8 bytes, e.g., CGROUP_STORAGE, skb->data. the verifier verifies exactly the size that the source claims, not the size rounded up to 8 bytes by kernel, an OOB happens when the source has only 4 bytes while the copy size(4) is rounded up to 8.

---
 kernel/bpf/hashtab.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/hashtab.c +1 -1
index 8bac6ae1204dc..934fdc688d7c1 100644
@@ -991,7 +991,7 @@ static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,
 
 		for_each_possible_cpu(cpu) {
 			if (cpu == current_cpu)
-				copy_map_value_long(&htab->map, per_cpu_ptr(pptr, cpu), value);
+				copy_map_value(&htab->map, per_cpu_ptr(pptr, cpu), value);
 			else /* Since elem is preallocated, we cannot touch special fields */
 				zero_map_value(&htab->map, per_cpu_ptr(pptr, cpu));
 		}
Signature · 1 line
2.53.0
author maintainer
#70 lore raw

PATCH 70/508 ppp: require CAP_NET_ADMIN in target netns for unattached ioctls

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Taegu Ha <[email protected]>

[ Upstream commit 2bb6379416fd19f44c3423a00bfd8626259f6067 ]

/dev/ppp open is currently authorized against file->f_cred->user_ns, while unattached administrative ioctls operate on current->nsproxy->net_ns.

As a result, a local unprivileged user can create a new user namespace with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace, and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against an inherited network namespace.

Require CAP_NET_ADMIN in the user namespace that owns the target network namespace before handling unattached PPP administrative ioctls.

This preserves normal pppd operation in the network namespace it is actually privileged in, while rejecting the userns-only inherited-netns case.

Fixes 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2")
---
 drivers/net/ppp/ppp_generic.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/net/ppp/ppp_generic.c +3 -0
index 46ac51217114b..7c863cb99383b 100644
@@ -1062,6 +1062,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
 	struct ppp_net *pn;
 	int __user *p = (int __user *)arg;
 
+	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+
 	switch (cmd) {
 	case PPPIOCNEWUNIT:
 		/* Create a new ppp unit */
Signature · 1 line
2.53.0
author maintainer
#71 lore raw

PATCH 71/508 net: ipa: Fix programming of QTIME_TIMESTAMP_CFG

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luca Weiss <[email protected]>

[ Upstream commit de08f9585692813bd41ee654fca0487664c4de30 ]

The 'val' variable gets overwritten multiple times, discarding previous values. Looking at the git log shows these should be combined with |= instead.

---
 drivers/net/ipa/ipa_main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ipa/ipa_main.c +3 -3
index da853353a5c72..f5924142021d2 100644
@@ -369,7 +369,7 @@ static void ipa_qtime_config(struct ipa *ipa)
 {
 	const struct reg *reg;
 	u32 offset;
-	u32 val;
+	u32 val = 0;
 
 	/* Timer clock divider must be disabled when we change the rate */
 	reg = ipa_reg(ipa, TIMERS_XO_CLK_DIV_CFG);
@@ -380,8 +380,8 @@ static void ipa_qtime_config(struct ipa *ipa)
 	val = reg_encode(reg, DPL_TIMESTAMP_LSB, DPL_TIMESTAMP_SHIFT);
 	val |= reg_bit(reg, DPL_TIMESTAMP_SEL);
 	/* Configure tag and NAT Qtime timestamp resolution as well */
-	val = reg_encode(reg, TAG_TIMESTAMP_LSB, TAG_TIMESTAMP_SHIFT);
-	val = reg_encode(reg, NAT_TIMESTAMP_LSB, NAT_TIMESTAMP_SHIFT);
+	val |= reg_encode(reg, TAG_TIMESTAMP_LSB, TAG_TIMESTAMP_SHIFT);
+	val |= reg_encode(reg, NAT_TIMESTAMP_LSB, NAT_TIMESTAMP_SHIFT);
 
 	iowrite32(val, ipa->reg_virt + reg_offset(reg));
 
Signature · 1 line
2.53.0
author maintainer
#72 lore raw

PATCH 72/508 net: ipa: Fix decoding EV_PER_EE for IPA v5.0+

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luca Weiss <[email protected]>

[ Upstream commit 1335b903cf2e8aeaca87fd665683384c731ec941 ]

Initially 'reg' and 'val' are assigned from HW_PARAM_2.

But since IPA v5.0+ takes EV_PER_EE from HW_PARAM_4 (instead of NUM_EV_PER_EE from HW_PARAM_2), we not only need to re-assign 'reg' but also read the register value of that register into 'val' so that reg_decode() works on the correct value.

---
 drivers/net/ipa/gsi.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/ipa/gsi.c +1 -0
index 9a0b1fe4a93a8..05157492f99b4 100644
@@ -2046,6 +2046,7 @@ static int gsi_ring_setup(struct gsi *gsi)
 		count = reg_decode(reg, NUM_EV_PER_EE, val);
 	} else {
 		reg = gsi_reg(gsi, HW_PARAM_4);
+		val = ioread32(gsi->virt + reg_offset(reg));
 		count = reg_decode(reg, EV_PER_EE, val);
 	}
 	if (!count) {
Signature · 1 line
2.53.0
author maintainer
#73 lore raw

PATCH 73/508 dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Josua Mayer <[email protected]>

[ Upstream commit 600f01dc4bd0c736b3ffea9f7976136d8bf1b136 ]

Currently, the binding requires 'spi-cpha' for SJA1105 and 'spi-cpol' for SJA1110.

However, the SJA1110 supports both SPI modes 0 and 2. Mode 2 (cpha=0, cpol=1) is used by the NXP LX2160 Bluebox 3.

On the SolidRun i.MX8DXL HummingBoard Telematics, mode 0 is stable, while forcing mode 2 introduces CRC errors especially during bursts.

Drop the requirement on spi-cpol for SJA1110.

Fixes af2eab1a8243 ("dt-bindings: net: nxp,sja1105: document spi-cpol/cpha")
---
 Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml | 2 --
 1 file changed, 2 deletions(-)
Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml +0 -2
index 4d5f5cc6d031e..155719453b704 100644
@@ -129,8 +129,6 @@ allOf:
     else:
       properties:
         spi-cpha: false
-      required:
-        - spi-cpol
 
 unevaluatedProperties: false
 
Signature · 1 line
2.53.0
author maintainer
#74 lore raw

PATCH 74/508 net/mlx5e: Fix features not applied during netdev registration

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gal Pressman <[email protected]>

[ Upstream commit 9994ad4df82d64e57135c0f0906897685f5a9e87 ]

mlx5e_fix_features() returns early when the netdevice is not present. This is correct during profile transitions where priv is cleared, but it also incorrectly blocks feature fixups during register_netdev(), when the device is also not yet present.

It is not trivial to distinguish between both cases as we cannot use priv to carry state, and in both cases reg_state == NETREG_REGISTERED.

Force a netdev features update after register_netdev() completes, where the device is present and fix_features() can actually work.

This is not a pretty solution, as it results in an additional features update call (register_netdevice() already calls __netdev_update_features() internally), but it is the simplest, cleanest, and most robust way I found to fix this issue after multiple attempts.

This fixes an issue on systems where CQE compression is enabled by default, RXHASH remains enabled after registration despite the two features being mutually exclusive.

Fixes ab4b01bfdaa6 ("net/mlx5e: Verify dev is present for fix features ndo")
---
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +8 -0
index 71749497ec27a..97fa2095498cc 100644
@@ -6093,6 +6093,14 @@ static int mlx5e_probe(struct auxiliary_device *adev,
 		goto err_resume;
 	}
 
+	/* mlx5e_fix_features() returns early when the device is not present
+	 * to avoid dereferencing cleared priv during profile changes.
+	 * This also causes it to be a no-op during register_netdev(), where
+	 * the device is not yet present.
+	 * Trigger an additional features update that will actually work.
+	 */
+	mlx5e_update_features(netdev);
+
 	mlx5e_dcbnl_init_app(priv);
 	mlx5_core_uplink_netdev_set(mdev, netdev);
 	mlx5e_params_print_info(mdev, &priv->channels.params);
Signature · 1 line
2.53.0
author maintainer
#75 lore raw

PATCH 75/508 net/mlx5e: IPsec, fix ASO poll timeout with read_poll_timeout_atomic()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gal Pressman <[email protected]>

[ Upstream commit edccdd1eb94712da97a6ce71123ec27890add754 ]

The do-while poll loop uses jiffies for its timeout:
expires = jiffies + msecs_to_jiffies(10);

jiffies is sampled at an arbitrary point within the current tick, so the first partial tick contributes anywhere from a full tick down to nearly zero real time. For small msecs_to_jiffies() results this is significant, the effective poll window can be much shorter than the requested 10ms, and in the worst case the loop exits after a single iteration (e.g., when HZ=100), well before the device has delivered the CQE.

Replace the loop with read_poll_timeout_atomic(), which counts elapsed time via udelay() accounting rather than jiffies, guaranteeing the full poll window regardless of HZ.

Additionally, read_poll_timeout_atomic() executes the poll operation one more time after the timeout has expired, giving the CQE a final chance to be detected. The old do-while loop could exit without a final poll if the timeout expired during the udelay() between iterations.

Fixes 76e463f6508b ("net/mlx5e: Overcome slow response for first IPsec ASO WQE")
---
 .../mellanox/mlx5/core/en_accel/ipsec_offload.c      | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +4 -8
index fd03aa4f47b5a..004cf295eb249 100644
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */
 
+#include <linux/iopoll.h>
+
 #include "mlx5_core.h"
 #include "en.h"
 #include "ipsec.h"
@@ -591,7 +593,6 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
 	struct mlx5_wqe_aso_ctrl_seg *ctrl;
 	struct mlx5e_hw_objs *res;
 	struct mlx5_aso_wqe *wqe;
-	unsigned long expires;
 	u8 ds_cnt;
 	int ret;
 
@@ -613,13 +614,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
 	mlx5e_ipsec_aso_copy(ctrl, data);
 
 	mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
-	expires = jiffies + msecs_to_jiffies(10);
-	do {
-		ret = mlx5_aso_poll_cq(aso->aso, false);
-		if (ret)
-			/* We are in atomic context */
-			udelay(10);
-	} while (ret && time_is_after_jiffies(expires));
+	read_poll_timeout_atomic(mlx5_aso_poll_cq, ret, !ret, 10,
+				 10 * USEC_PER_MSEC, false, aso->aso, false);
 	if (!ret)
 		memcpy(sa_entry->ctx, aso->ctx, MLX5_ST_SZ_BYTES(ipsec_aso));
 	spin_unlock_bh(&aso->lock);
Signature · 1 line
2.53.0
author maintainer
#76 lore raw

PATCH 76/508 bpf: reject short IPv4/IPv6 inputs in bpf_prog_test_run_skb

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sun Jian <[email protected]>

[ Upstream commit 12bec2bd4b76d81c5d3996bd14ec1b7f4d983747 ]

bpf_prog_test_run_skb() calls eth_type_trans() first and then uses skb->protocol to initialize sk family and address fields for the test run.

For IPv4 and IPv6 packets, it may access ip_hdr(skb) or ipv6_hdr(skb) even when the provided test input only contains an Ethernet header.

Reject the input earlier if the Ethernet frame carries IPv4/IPv6 EtherType but the L3 header is too short.

Fold the IPv4/IPv6 header length checks into the existing protocol switch and return -EINVAL before accessing the network headers.

---
 net/bpf/test_run.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)
net/bpf/test_run.c +12 -8
index c9c6f675d8e21..8e665cee22503 100644
@@ -1031,19 +1031,23 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
 
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
-		sk->sk_family = AF_INET;
-		if (sizeof(struct iphdr) <= skb_headlen(skb)) {
-			sk->sk_rcv_saddr = ip_hdr(skb)->saddr;
-			sk->sk_daddr = ip_hdr(skb)->daddr;
+		if (skb_headlen(skb) < sizeof(struct iphdr)) {
+			ret = -EINVAL;
+			goto out;
 		}
+		sk->sk_family = AF_INET;
+		sk->sk_rcv_saddr = ip_hdr(skb)->saddr;
+		sk->sk_daddr = ip_hdr(skb)->daddr;
 		break;
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6):
-		sk->sk_family = AF_INET6;
-		if (sizeof(struct ipv6hdr) <= skb_headlen(skb)) {
-			sk->sk_v6_rcv_saddr = ipv6_hdr(skb)->saddr;
-			sk->sk_v6_daddr = ipv6_hdr(skb)->daddr;
+		if (skb_headlen(skb) < sizeof(struct ipv6hdr)) {
+			ret = -EINVAL;
+			goto out;
 		}
+		sk->sk_family = AF_INET6;
+		sk->sk_v6_rcv_saddr = ipv6_hdr(skb)->saddr;
+		sk->sk_v6_daddr = ipv6_hdr(skb)->daddr;
 		break;
 #endif
 	default:
Signature · 1 line
2.53.0
author maintainer
#77 lore raw

PATCH 77/508 Bluetooth: L2CAP: Fix printing wrong information if SDU length exceeds MTU

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luiz Augusto von Dentz <[email protected]>

[ Upstream commit 15bf35a660eb82a49f8397fc3d3acada8dae13db ]

The code was printing skb->len and sdu_len in the places where it should be sdu_len and chan->imtu respectively to match the if conditions.

---
 net/bluetooth/l2cap_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +1 -1
index 3da3e9fddd049..2a15863a882d6 100644
@@ -6658,7 +6658,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 
 		if (sdu_len > chan->imtu) {
 			BT_ERR("Too big LE L2CAP SDU length: len %u > %u",
-			       skb->len, sdu_len);
+			       sdu_len, chan->imtu);
 			l2cap_send_disconn_req(chan, ECONNRESET);
 			err = -EMSGSIZE;
 			goto failed;
Signature · 1 line
2.53.0
author maintainer
#78 lore raw

PATCH 78/508 Bluetooth: hci_ldisc: Clear HCI_UART_PROTO_INIT on error

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jonathan Rissanen <[email protected]>

[ Upstream commit 68d39ea5e0adc9ecaea1ce8abd842ec972eb8718 ]

When hci_register_dev() fails in hci_uart_register_dev() HCI_UART_PROTO_INIT is not cleared before calling hu->proto->close(hu) and setting hu->hdev to NULL. This means incoming UART data will reach the protocol-specific recv handler in hci_uart_tty_receive() after resources are freed.

Clear HCI_UART_PROTO_INIT with a write lock before calling hu->proto->close() and setting hu->hdev to NULL. The write lock ensures all active readers have completed and no new reader can enter the protocol recv path before resources are freed.

This allows the protocol-specific recv functions to remove the "HCI_UART_REGISTERED" guard without risking a null pointer dereference if hci_register_dev() fails.

Fixes 5df5dafc171b ("Bluetooth: hci_uart: Fix another race during initialization")
---
 drivers/bluetooth/hci_ldisc.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/bluetooth/hci_ldisc.c +3 -0
index e38f3c4458c90..85baba91aaa97 100644
@@ -689,6 +689,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
 
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
+		percpu_down_write(&hu->proto_lock);
+		clear_bit(HCI_UART_PROTO_INIT, &hu->flags);
+		percpu_up_write(&hu->proto_lock);
 		hu->proto->close(hu);
 		hu->hdev = NULL;
 		hci_free_dev(hdev);
Signature · 1 line
2.53.0
author maintainer
#79 lore raw

PATCH 79/508 Bluetooth: fix locking in hci_conn_request_evt() with HCI_PROTO_DEFER

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pauli Virtanen <[email protected]>

[ Upstream commit 5c7209a341ff2ac338b2b0375c34a307b37c9ac2 ]

When protocol sets HCI_PROTO_DEFER, hci_conn_request_evt() calls hci_connect_cfm(conn) without hdev->lock. Generally hci_connect_cfm() assumes it is held, and if conn is deleted concurrently -> UAF.

Only SCO and ISO set HCI_PROTO_DEFER and only for defer setup listen, and HCI_EV_CONN_REQUEST is not generated for ISO. In the non-deferred listening socket code paths, hci_connect_cfm(conn) is called with hdev->lock held.

Fix by holding the lock.

Fixes 70c464256310 ("Bluetooth: Refactor connection request handling")
---
 net/bluetooth/hci_event.c | 3 ---
 1 file changed, 3 deletions(-)
net/bluetooth/hci_event.c +0 -3
index f6285c4325d63..4607db3037bd9 100644
@@ -3282,8 +3282,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
 
 	memcpy(conn->dev_class, ev->dev_class, 3);
 
-	hci_dev_unlock(hdev);
-
 	if (ev->link_type == ACL_LINK ||
 	    (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
 		struct hci_cp_accept_conn_req cp;
@@ -3317,7 +3315,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
 		hci_connect_cfm(conn, 0);
 	}
 
-	return;
 unlock:
 	hci_dev_unlock(hdev);
 }
Signature · 1 line
2.53.0
author maintainer
#80 lore raw

PATCH 80/508 Bluetooth: l2cap: Add missing chan lock in l2cap_ecred_reconf_rsp

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dudu Lu <[email protected]>

[ Upstream commit 42776497cdbc9a665b384a6dcb85f0d4bd927eab ]

l2cap_ecred_reconf_rsp() calls l2cap_chan_del() without holding l2cap_chan_lock(). Every other l2cap_chan_del() caller in the file acquires the lock first. A remote BLE device can send a crafted L2CAP ECRED reconfiguration response to corrupt the channel list while another thread is iterating it.

Add l2cap_chan_hold() and l2cap_chan_lock() before l2cap_chan_del(), and l2cap_chan_unlock() and l2cap_chan_put() after, matching the pattern used in l2cap_ecred_conn_rsp() and l2cap_conn_del().

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c | 6 ++++++
 1 file changed, 6 insertions(+)
net/bluetooth/l2cap_core.c +6 -0
index 2a15863a882d6..bbaf0070ca617 100644
@@ -5400,7 +5400,13 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
 		if (chan->ident != cmd->ident)
 			continue;
 
+		l2cap_chan_hold(chan);
+		l2cap_chan_lock(chan);
+
 		l2cap_chan_del(chan, ECONNRESET);
+
+		l2cap_chan_unlock(chan);
+		l2cap_chan_put(chan);
 	}
 
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#81 lore raw

PATCH 81/508 net: phy: aquantia: move to separate directory

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christian Marangi <[email protected]>

[ Upstream commit d2213db3f49bce8e7a87c8de05b9a091f78f654e ]

Move aquantia PHY driver to separate driectory in preparation for firmware loading support to keep things tidy.

Stable-dep-of: e7a62edd34b1 ("net: phy: qcom: at803x: Use the correct bit to disable extended next page")

---
 drivers/net/phy/Kconfig                         | 5 +----
 drivers/net/phy/Makefile                        | 6 +-----
 drivers/net/phy/aquantia/Kconfig                | 5 +++++
 drivers/net/phy/aquantia/Makefile               | 6 ++++++
 drivers/net/phy/{ => aquantia}/aquantia.h       | 0
 drivers/net/phy/{ => aquantia}/aquantia_hwmon.c | 0
 drivers/net/phy/{ => aquantia}/aquantia_main.c  | 0
 7 files changed, 13 insertions(+), 9 deletions(-)
 create mode 100644 drivers/net/phy/aquantia/Kconfig
 create mode 100644 drivers/net/phy/aquantia/Makefile
 rename drivers/net/phy/{ => aquantia}/aquantia.h (100%)
 rename drivers/net/phy/{ => aquantia}/aquantia_hwmon.c (100%)
 rename drivers/net/phy/{ => aquantia}/aquantia_main.c (100%)
drivers/net/phy/Kconfig +1 -4
index 107880d13d219..aa5491aaaab40 100644
@@ -96,10 +96,7 @@ config ADIN1100_PHY
 	  Currently supports the:
 	  - ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY
 
-config AQUANTIA_PHY
-	tristate "Aquantia PHYs"
-	help
-	  Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
+source "drivers/net/phy/aquantia/Kconfig"
 
 config AX88796B_PHY
 	tristate "Asix PHYs"
drivers/net/phy/Makefile +1 -5
index c945ed9bd14b3..f65e85c91fc10 100644
@@ -35,11 +35,7 @@ obj-y				+= $(sfp-obj-y) $(sfp-obj-m)
 obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
-aquantia-objs			+= aquantia_main.o
-ifdef CONFIG_HWMON
-aquantia-objs			+= aquantia_hwmon.o
-endif
-obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
+obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia/
 obj-$(CONFIG_AT803X_PHY)	+= at803x.o
 obj-$(CONFIG_AX88796B_PHY)	+= ax88796b.o
 obj-$(CONFIG_BCM54140_PHY)	+= bcm54140.o
drivers/net/phy/aquantia/Kconfig new file +5 -0
new file mode 100644
index 0000000000000..226146417a6a7
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config AQUANTIA_PHY
+	tristate "Aquantia PHYs"
+	help
+	  Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
drivers/net/phy/aquantia/Makefile new file +6 -0
new file mode 100644
index 0000000000000..346f350bc0846
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+aquantia-objs			+= aquantia_main.o
+ifdef CONFIG_HWMON
+aquantia-objs			+= aquantia_hwmon.o
+endif
+obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia.o
drivers/net/phy/aquantia/aquantia.h renamed from drivers/net/phy/aquantia.h +0 -0
similarity index 100%
rename from drivers/net/phy/aquantia.h
rename to drivers/net/phy/aquantia/aquantia.h
drivers/net/phy/aquantia/aquantia_hwmon.c renamed from drivers/net/phy/aquantia_hwmon.c +0 -0
similarity index 100%
rename from drivers/net/phy/aquantia_hwmon.c
rename to drivers/net/phy/aquantia/aquantia_hwmon.c
drivers/net/phy/aquantia/aquantia_main.c renamed from drivers/net/phy/aquantia_main.c +0 -0
similarity index 100%
rename from drivers/net/phy/aquantia_main.c
rename to drivers/net/phy/aquantia/aquantia_main.c
Signature · 1 line
2.53.0
author maintainer
#82 lore raw

PATCH 82/508 net: phy: add Rust Asix PHY driver

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: FUJITA Tomonori <[email protected]>

[ Upstream commit cbe0e415089636170aa6eb540ca4af5dc9842a60 ]

This is the Rust implementation of drivers/net/phy/ax88796b.c. The features are equivalent. You can choose C or Rust version kernel configuration.

Stable-dep-of: e7a62edd34b1 ("net: phy: qcom: at803x: Use the correct bit to disable extended next page")

---
 MAINTAINERS                      |   8 ++
 drivers/net/phy/Kconfig          |   8 ++
 drivers/net/phy/Makefile         |   6 +-
 drivers/net/phy/ax88796b_rust.rs | 135 +++++++++++++++++++++++++++++++
 rust/uapi/uapi_helper.h          |   2 +
 5 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/phy/ax88796b_rust.rs
MAINTAINERS +8 -0
index e700dca4974b3..8b1ee5b11eca2 100644
@@ -3060,6 +3060,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/net/asix,ax88796c.yaml
 F:	drivers/net/ethernet/asix/ax88796c_*
 
+ASIX PHY DRIVER [RUST]
+M:	FUJITA Tomonori <[email protected]>
+R:	Trevor Gross <[email protected]>
+L:	[email protected]
+L:	[email protected]
+S:	Maintained
+F:	drivers/net/phy/ax88796b_rust.rs
+
 ASPEED CRYPTO DRIVER
 M:	Neal Liu <[email protected]>
 L:	[email protected] (moderated for non-subscribers)
drivers/net/phy/Kconfig +8 -0
index aa5491aaaab40..466d3dff60744 100644
@@ -104,6 +104,14 @@ config AX88796B_PHY
 	  Currently supports the Asix Electronics PHY found in the X-Surf 100
 	  AX88796B package.
 
+config AX88796B_RUST_PHY
+	bool "Rust reference driver for Asix PHYs"
+	depends on RUST_PHYLIB_ABSTRACTIONS && AX88796B_PHY
+	help
+	  Uses the Rust reference driver for Asix PHYs (ax88796b_rust.ko).
+	  The features are equivalent. It supports the Asix Electronics PHY
+	  found in the X-Surf 100 AX88796B package.
+
 config BROADCOM_PHY
 	tristate "Broadcom 54XX PHYs"
 	select BCM_NET_PHYLIB
drivers/net/phy/Makefile +5 -1
index f65e85c91fc10..ab450a46b8550 100644
@@ -37,7 +37,11 @@ obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia/
 obj-$(CONFIG_AT803X_PHY)	+= at803x.o
-obj-$(CONFIG_AX88796B_PHY)	+= ax88796b.o
+ifdef CONFIG_AX88796B_RUST_PHY
+  obj-$(CONFIG_AX88796B_PHY)	+= ax88796b_rust.o
+else
+  obj-$(CONFIG_AX88796B_PHY)	+= ax88796b.o
+endif
 obj-$(CONFIG_BCM54140_PHY)	+= bcm54140.o
 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 obj-$(CONFIG_BCM7XXX_PHY)	+= bcm7xxx.o
drivers/net/phy/ax88796b_rust.rs new file +135 -0

135 lines not on this page · raw message

rust/uapi/uapi_helper.h +2 -0
index 301f5207f0238..08f5e9334c9e8 100644
@@ -7,3 +7,5 @@
  */
 
 #include <uapi/asm-generic/ioctl.h>
+#include <uapi/linux/mii.h>
+#include <uapi/linux/ethtool.h>
Signature · 1 line
2.53.0
author maintainer
#83 lore raw

PATCH 83/508 net: phy: move at803x PHY driver to dedicated directory

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Christian Marangi <[email protected]>

[ Upstream commit 9e56ff53b4115875667760445b028357848b4748 ]

In preparation for addition of other Qcom PHY and to tidy things up, move the at803x PHY driver to dedicated directory.

The same order in the Kconfig selection is saved.

Stable-dep-of: e7a62edd34b1 ("net: phy: qcom: at803x: Use the correct bit to disable extended next page")

---
 drivers/net/phy/Kconfig             | 7 +------
 drivers/net/phy/Makefile            | 2 +-
 drivers/net/phy/qcom/Kconfig        | 7 +++++++
 drivers/net/phy/qcom/Makefile       | 2 ++
 drivers/net/phy/{ => qcom}/at803x.c | 0
 5 files changed, 11 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/phy/qcom/Kconfig
 create mode 100644 drivers/net/phy/qcom/Makefile
 rename drivers/net/phy/{ => qcom}/at803x.c (100%)
drivers/net/phy/Kconfig +1 -6
index 466d3dff60744..e49131cef9570 100644
@@ -326,12 +326,7 @@ config NCN26000_PHY
 	  Currently supports the NCN26000 10BASE-T1S Industrial PHY
 	  with MII interface.
 
-config AT803X_PHY
-	tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs"
-	depends on REGULATOR
-	help
-	  Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
-	  QCA8337(Internal qca8k PHY) model
+source "drivers/net/phy/qcom/Kconfig"
 
 config QSEMI_PHY
 	tristate "Quality Semiconductor PHYs"
drivers/net/phy/Makefile +1 -1
index ab450a46b8550..6e4493e26816d 100644
@@ -36,7 +36,6 @@ obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia/
-obj-$(CONFIG_AT803X_PHY)	+= at803x.o
 ifdef CONFIG_AX88796B_RUST_PHY
   obj-$(CONFIG_AX88796B_PHY)	+= ax88796b_rust.o
 else
@@ -86,6 +85,7 @@ obj-$(CONFIG_NCN26000_PHY)	+= ncn26000.o
 obj-$(CONFIG_NXP_C45_TJA11XX_PHY)	+= nxp-c45-tja11xx.o
 obj-$(CONFIG_NXP_CBTX_PHY)	+= nxp-cbtx.o
 obj-$(CONFIG_NXP_TJA11XX_PHY)	+= nxp-tja11xx.o
+obj-y				+= qcom/
 obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 obj-$(CONFIG_RENESAS_PHY)	+= uPD60620.o
drivers/net/phy/qcom/Kconfig new file +7 -0
new file mode 100644
index 0000000000000..2c274fbbe410d
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config AT803X_PHY
+	tristate "Qualcomm Atheros AR803X PHYs and QCA833x PHYs"
+	depends on REGULATOR
+	help
+	  Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
+	  QCA8337(Internal qca8k PHY) model
drivers/net/phy/qcom/Makefile new file +2 -0
new file mode 100644
index 0000000000000..6a68da8aaa7bf
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_AT803X_PHY)	+= at803x.o
drivers/net/phy/qcom/at803x.c renamed from drivers/net/phy/at803x.c +0 -0
similarity index 100%
rename from drivers/net/phy/at803x.c
rename to drivers/net/phy/qcom/at803x.c
Signature · 1 line
2.53.0
author maintainer
#84 lore raw

PATCH 84/508 net: phy: qcom: at803x: Use the correct bit to disable extended next page

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Maxime Chevallier <[email protected]>

[ Upstream commit e7a62edd34b1b4bc5f979988efc2f81c075733fd ]

As noted in the blamed commit, the AR8035 and other PHYs from this family advertise the Extended Next Page support by default, which may be understood by some partners as this PHY being multi-gig capable.

The fix is to disable XNP advertising, which is done by setting bit 12 of the Auto-Negotiation Advertisement Register (MII_ADVERTISE).

The blamed commit incorrectly uses MDIO_AN_CTRL1_XNP, which is bit 13 as per 802.3 : 45.2.7.1 AN control register (Register 7.0)

BIT 12 in MII_ADVERTISE is wrapped by ADVERTISE_RESV, used by some drivers such as the aquantia one. 802.3 Clause 28 defines bit 12 as Extended Next Page ability, at least in recent versions of the standard.

Let's add a define for it and use it in the at803x driver.

Fixes 3c51fa5d2afe ("net: phy: ar803x: disable extended next page bit")
---
 drivers/net/phy/qcom/at803x.c | 2 +-
 include/uapi/linux/mii.h      | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/net/phy/qcom/at803x.c +1 -1
index ef203b0807e58..0b01b6ff0a4b5 100644
@@ -1064,7 +1064,7 @@ static int at803x_config_init(struct phy_device *phydev)
 	 * behaviour but we still need to accommodate it. XNP is only needed
 	 * for 10Gbps support, so disable XNP.
 	 */
-	return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
+	return phy_modify(phydev, MII_ADVERTISE, ADVERTISE_XNP, 0);
 }
 
 static int at803x_ack_interrupt(struct phy_device *phydev)
include/uapi/linux/mii.h +2 -1
index 39f7c44baf535..61d6edad4b94a 100644
@@ -82,7 +82,8 @@
 #define ADVERTISE_100BASE4	0x0200	/* Try for 100mbps 4k packets  */
 #define ADVERTISE_PAUSE_CAP	0x0400	/* Try for pause               */
 #define ADVERTISE_PAUSE_ASYM	0x0800	/* Try for asymetric pause     */
-#define ADVERTISE_RESV		0x1000	/* Unused...                   */
+#define ADVERTISE_XNP		0x1000  /* Extended Next Page */
+#define ADVERTISE_RESV		ADVERTISE_XNP /* Used to be reserved */
 #define ADVERTISE_RFAULT	0x2000	/* Say we can detect faults    */
 #define ADVERTISE_LPACK		0x4000	/* Ack link partners response  */
 #define ADVERTISE_NPAGE		0x8000	/* Next page bit               */
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 85/508 sctp: fix missing encap_port propagation for GSO fragments

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Xin Long <[email protected]>

[ Upstream commit bf6f95ae3b8b2638c0e1d6d802d50983ce5d0f45 ]

encap_port in SCTP_INPUT_CB(skb) is used by sctp_vtag_verify() for SCTP-over-UDP processing. In the GSO case, it is only set on the head skb, while fragment skbs leave it 0.

This results in fragment skbs seeing encap_port == 0, breaking SCTP-over-UDP connections.

Fix it by propagating encap_port from the head skb cb when initializing fragment skbs in sctp_inq_pop().

---
 net/sctp/inqueue.c | 1 +
 1 file changed, 1 insertion(+)
net/sctp/inqueue.c +1 -0
index f5a7d5a387555..a024c08432471 100644
@@ -201,6 +201,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
 
 			cb->chunk = head_cb->chunk;
 			cb->af = head_cb->af;
+			cb->encap_port = head_cb->encap_port;
 		}
 	}
 
Signature · 1 line
2.53.0
author maintainer
#86 lore raw

PATCH 86/508 net, bpf: fix null-ptr-deref in xdp_master_redirect() for down master

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiayuan Chen <[email protected]>

[ Upstream commit 1921f91298d1388a0bb9db8f83800c998b649cb3 ]

syzkaller reported a kernel panic in bond_rr_gen_slave_id() reached via xdp_master_redirect(). Full decoded trace:

https://syzkaller.appspot.com/bug?extid=80e046b8da2820b6ba73

bond_rr_gen_slave_id() dereferences bond->rr_tx_counter, a per-CPU counter that bonding only allocates in bond_open() when the mode is round-robin. If the bond device was never brought up, rr_tx_counter stays NULL.

The XDP redirect path can still reach that code on a bond that was never opened: bpf_master_redirect_enabled_key is a global static key, so as soon as any bond device has native XDP attached, the XDP_TX -> xdp_master_redirect() interception is enabled for every slave system-wide. The path xdp_master_redirect() -> bond_xdp_get_xmit_slave() -> bond_xdp_xmit_roundrobin_slave_get() -> bond_rr_gen_slave_id() then runs against a bond that has no rr_tx_counter and crashes.

Fix this in the generic xdp_master_redirect() by refusing to call into the master's ->ndo_xdp_get_xmit_slave() when the master device is not up. IFF_UP is only set after ->ndo_open() has successfully returned, so this reliably excludes masters whose XDP state has not been fully initialized. Drop the frame with XDP_ABORTED so the exception is visible via trace_xdp_exception() rather than silently falling through. This is not specific to bonding: any current or future master that defers XDP state allocation to ->ndo_open() is protected.

---
 net/core/filter.c | 2 ++
 1 file changed, 2 insertions(+)
net/core/filter.c +2 -0
index 2cd58d1d4a7aa..c24510037334c 100644
@@ -4354,6 +4354,8 @@ u32 xdp_master_redirect(struct xdp_buff *xdp)
 	struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
 
 	master = netdev_master_upper_dev_get_rcu(xdp->rxq->dev);
+	if (unlikely(!(master->flags & IFF_UP)))
+		return XDP_ABORTED;
 	slave = master->netdev_ops->ndo_xdp_get_xmit_slave(master, xdp);
 	if (slave && slave != xdp->rxq->dev) {
 		/* The target device is different from the receiving device, so
Signature · 1 line
2.53.0
author maintainer
#87 lore raw

PATCH 87/508 drm/komeda: fix integer overflow in AFBC framebuffer size check

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Konyukhov <[email protected]>

[ Upstream commit 779ec12c85c9e4547519e3903a371a3b26a289de ]

The AFBC framebuffer size validation calculates the minimum required buffer size by adding the AFBC payload size to the framebuffer offset. This addition is performed without checking for integer overflow.

If the addition oveflows, the size check may incorrectly succed and allow userspace to provide an undersized drm_gem_object, potentially leading to out-of-bounds memory access.

Add usage of check_add_overflow() to safely compute the minimum required size and reject the framebuffer if an overflow is detected. This makes the AFBC size validation more robust against malformed.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes 65ad2392dd6d ("drm/komeda: Added AFBC support for komeda driver")
---
 drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +5 -1
index df5da5a447555..b4f2b89651ff2 100644
@@ -4,6 +4,8 @@
  * Author: James.Qian.Wang <[email protected]>
  *
  */
+#include <linux/overflow.h>
+
 #include <drm/drm_device.h>
 #include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_gem.h>
@@ -92,7 +94,9 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
 	kfb->afbc_size = kfb->offset_payload + n_blocks *
 			 ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8,
 			       AFBC_SUPERBLK_ALIGNMENT);
-	min_size = kfb->afbc_size + fb->offsets[0];
+	if (check_add_overflow(kfb->afbc_size, fb->offsets[0], &min_size)) {
+		goto check_failed;
+	}
 	if (min_size > obj->size) {
 		DRM_DEBUG_KMS("afbc size check failed, obj_size: 0x%zx. min_size 0x%llx.\n",
 			      obj->size, min_size);
Signature · 1 line
2.53.0
author maintainer
#88 lore raw

PATCH 88/508 drm/sun4i: backend: fix error pointer dereference

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ethan Tidmore <[email protected]>

[ Upstream commit 06277983eca4a31d3c2114fa33d99a6e82484b11 ]

The function drm_atomic_get_plane_state() can return an error pointer and is not checked for it. Add error pointer check.

Detected by Smatch:
drivers/gpu/drm/sun4i/sun4i_backend.c:496 sun4i_backend_atomic_check() error:
'plane_state' dereferencing possible ERR_PTR()

Fixes 96180dde23b79 ("drm/sun4i: backend: Add a custom atomic_check for the frontend")
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/sun4i/sun4i_backend.c +3 -0
index 335fd0edb904c..6a2ffaa477ab8 100644
@@ -488,6 +488,9 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
 	drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) {
 		struct drm_plane_state *plane_state =
 			drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state))
+			return PTR_ERR(plane_state);
+
 		struct sun4i_layer_state *layer_state =
 			state_to_sun4i_layer_state(plane_state);
 		struct drm_framebuffer *fb = plane_state->fb;
Signature · 1 line
2.53.0
author maintainer
#89 lore raw

PATCH 89/508 ASoC: sti: Return errors from regmap_field_alloc()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sander Vanheule <[email protected]>

[ Upstream commit 272aabef50bc3fe58edd26de000f4cdd41bdbe60 ]

When regmap_field_alloc() fails, it can return an error. Specifically, it will return PTR_ERR(-ENOMEM) when the allocation returns a NULL pointer. The code then uses these allocations with a simple NULL check:

    if (player->clk_sel) {
        // May dereference invalid pointer (-ENOMEM)
        err = regmap_field_write(player->clk_sel, ...);
    }

Ensure initialization fails by forwarding the errors from regmap_field_alloc(), thus avoiding the use of the invalid pointers.

Fixes 76c2145ded6b ("ASoC: sti: Add CPU DAI driver for playback")
---
 sound/soc/sti/uniperif_player.c | 5 +++++
 1 file changed, 5 insertions(+)
sound/soc/sti/uniperif_player.c +5 -0
index 6d1ce030963c6..f1b7e76f97b58 100644
@@ -1029,7 +1029,12 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
 	}
 
 	player->clk_sel = regmap_field_alloc(regmap, regfield[0]);
+	if (IS_ERR(player->clk_sel))
+		return PTR_ERR(player->clk_sel);
+
 	player->valid_sel = regmap_field_alloc(regmap, regfield[1]);
+	if (IS_ERR(player->valid_sel))
+		return PTR_ERR(player->valid_sel);
 
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#90 lore raw

PATCH 90/508 ASoC: sti: use managed regmap_field allocations

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sander Vanheule <[email protected]>

[ Upstream commit 1696fad8b259a2d46e51cd6e17e4bcdbe02279fa ]

The regmap_field objects allocated at player init are never freed and may leak resources if the driver is removed.

Switch to devm_regmap_field_alloc() to automatically limit the lifetime of the allocations the lifetime of the device.

Fixes 76c2145ded6b ("ASoC: sti: Add CPU DAI driver for playback")
---
 sound/soc/sti/uniperif_player.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/sti/uniperif_player.c +2 -2
index f1b7e76f97b58..45d35b887e4eb 100644
@@ -1028,11 +1028,11 @@ static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
 		return PTR_ERR(regmap);
 	}
 
-	player->clk_sel = regmap_field_alloc(regmap, regfield[0]);
+	player->clk_sel = devm_regmap_field_alloc(&pdev->dev, regmap, regfield[0]);
 	if (IS_ERR(player->clk_sel))
 		return PTR_ERR(player->clk_sel);
 
-	player->valid_sel = regmap_field_alloc(regmap, regfield[1]);
+	player->valid_sel = devm_regmap_field_alloc(&pdev->dev, regmap, regfield[1]);
 	if (IS_ERR(player->valid_sel))
 		return PTR_ERR(player->valid_sel);
 
Signature · 1 line
2.53.0
author maintainer
#91 lore raw

PATCH 91/508 dm cache: fix null-deref with concurrent writes in passthrough mode

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 7d1f98d668ee34c1d15bdc0420fdd062f24a27c0 ]

In passthrough mode, when dm-cache starts to invalidate a cache entry and bio prison cell lock fails due to concurrent write to the same cached block, mg->cell remains NULL. The error path in invalidate_complete() attempts to unlock and free the cell unconditionally, causing a NULL pointer dereference:

KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
CPU: 0 UID: 0 PID: 134 Comm: fio Not tainted 6.19.0-rc7 #3 PREEMPT
RIP: 0010:dm_cell_unlock_v2+0x3f/0x210
<snip>
Call Trace:
 invalidate_complete+0xef/0x430
 map_bio+0x130f/0x1a10
 cache_map+0x320/0x6b0
 __map_bio+0x458/0x510
 dm_submit_bio+0x40e/0x16d0
 __submit_bio+0x419/0x870

<snip>

Reproduce steps:

1. Create a cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. Promote the first data block into cache

fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k

3. Reload the cache into passthrough mode

dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache

4. Write to the first cached block concurrently

fio --filename=/dev/mapper/cache --name test --rw=randwrite --bs=4k \
--randrepeat=0 --direct=1 --numjobs=2 --size 64k

Fix by checking if mg->cell is valid before attempting to unlock it.

Fixes b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
---
 drivers/md/dm-cache-target.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/md/dm-cache-target.c +4 -2
index 0d002d50329da..9c4aa5180a70e 100644
@@ -1458,8 +1458,10 @@ static void invalidate_complete(struct dm_cache_migration *mg, bool success)
 	struct cache *cache = mg->cache;
 
 	bio_list_init(&bios);
-	if (dm_cell_unlock_v2(cache->prison, mg->cell, &bios))
-		free_prison_cell(cache, mg->cell);
+	if (mg->cell) {
+		if (dm_cell_unlock_v2(cache->prison, mg->cell, &bios))
+			free_prison_cell(cache, mg->cell);
+	}
 
 	if (!success && mg->overwrite_bio)
 		bio_io_error(mg->overwrite_bio);
Signature · 1 line
2.53.0
author maintainer
#92 lore raw

PATCH 92/508 dm cache: fix write path cache coherency in passthrough mode

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 0c5eef0aad508231d8e43ff8392692925e131b68 ]

In passthrough mode, dm-cache defers write bio submission until cache invalidation completes to maintain existing coherency, requiring the target map function to return DM_MAPIO_SUBMITTED. The current map_bio() returns DM_MAPIO_REMAPPED, violating the required ordering constraint.

Reproduce steps:

1. Create a cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. Promote the first data block into the cache

fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k

3. Reload the cache into passthrough mode

dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache

4. Write to the first data block, and check io ordering using ftrace

echo 1 > /sys/kernel/debug/tracing/events/block/block_bio_queue/enable echo 1 > /sys/kernel/debug/tracing/events/block/block_bio_complete/enable echo 1 > /sys/kernel/debug/tracing/events/block/block_rq_complete/enable fio --filename=/dev/mapper/cache --name=test --rw=write --bs=64k \
--direct=1 --size 64k

5. ftrace logs show that write operations to the cache origin (252:2) and metadata operations (252:0) are unsynchronized: the origin write occurs before metadata commit.

<snip>

       fio-146  [000] .....  420.139562: block_bio_queue: 252,3 WS 0 + 128 [fio]
       fio-146  [000] .....  420.149395: block_bio_queue: 252,2 WS 0 + 128 [fio]
       fio-146  [000] .....  420.149763: block_bio_queue: 8,32 WS 262144 + 128 [fio]
       fio-146  [000] dNh1.  420.151446: block_rq_complete: 8,32 WS () 262144 + 128 be,0,4 [0]
       fio-146  [000] dNh1.  420.152731: block_bio_complete: 252,2 WS 0 + 128 [0]
       fio-146  [000] dNh1.  420.154229: block_bio_complete: 252,3 WS 0 + 128 [0]
 kworker/0:0-9  [000] .....  420.160530: block_bio_queue: 252,0 W 408 + 8 [kworker/0:0]
 kworker/0:0-9  [000] .....  420.161641: block_bio_queue: 8,32 W 408 + 8 [kworker/0:0]
 kworker/0:0-9  [000] .....  420.162533: block_bio_queue: 252,0 W 416 + 8 [kworker/0:0]
 kworker/0:0-9  [000] .....  420.162821: block_bio_queue: 8,32 W 416 + 8 [kworker/0:0]

<snip>

Fixes b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
---
 drivers/md/dm-cache-target.c | 1 +
 1 file changed, 1 insertion(+)
drivers/md/dm-cache-target.c +1 -0
index 9c4aa5180a70e..a2fba4ce40d7d 100644
@@ -1699,6 +1699,7 @@ static int map_bio(struct cache *cache, struct bio *bio, dm_oblock_t block,
 				bio_drop_shared_lock(cache, bio);
 				atomic_inc(&cache->stats.demotion);
 				invalidate_start(cache, cblock, block, bio);
+				return DM_MAPIO_SUBMITTED;
 			} else
 				remap_to_origin_clear_discard(cache, bio, block);
 		} else {
Signature · 1 line
2.53.0
author maintainer
#93 lore raw

PATCH 93/508 dm cache: fix write hang in passthrough mode

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 4ca8b8bd952df7c3ccdc68af9bd3419d0839a04b ]

The invalidate_remove() function has incomplete logic for handling write hit bios after cache invalidation. It sets up the remapping for the overwrite_bio but then drops it immediately without submission, causing write operations to hang.

Fix by adding a new invalidate_committed() continuation that submits the remapped writes to the cache origin after metadata commit completes, while using the overwrite_endio hook to ensure proper completion sequencing. This maintains existing coherency. Also improve error handling in invalidate_complete() to preserve the original error status instead of using bio_io_error() unconditionally.

Fixes b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
---
 drivers/md/dm-cache-target.c | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)
drivers/md/dm-cache-target.c +25 -5
index a2fba4ce40d7d..a3a8623eff297 100644
@@ -1463,8 +1463,14 @@ static void invalidate_complete(struct dm_cache_migration *mg, bool success)
 			free_prison_cell(cache, mg->cell);
 	}
 
-	if (!success && mg->overwrite_bio)
-		bio_io_error(mg->overwrite_bio);
+	if (mg->overwrite_bio) {
+		// Set generic error if the bio hasn't been issued yet,
+		// e.g., invalidation or metadata commit failed before bio
+		// submission. Otherwise preserve the bio's own error status.
+		if (!success && !mg->overwrite_bio->bi_status)
+			mg->overwrite_bio->bi_status = BLK_STS_IOERR;
+		bio_endio(mg->overwrite_bio);
+	}
 
 	free_migration(mg);
 	defer_bios(cache, &bios);
@@ -1504,6 +1510,22 @@ static int invalidate_cblock(struct cache *cache, dm_cblock_t cblock)
 	return r;
 }
 
+static void invalidate_committed(struct work_struct *ws)
+{
+	struct dm_cache_migration *mg = ws_to_mg(ws);
+	struct cache *cache = mg->cache;
+	struct bio *bio = mg->overwrite_bio;
+	struct per_bio_data *pb = get_per_bio_data(bio);
+
+	if (mg->k.input)
+		invalidate_complete(mg, false);
+
+	init_continuation(&mg->k, invalidate_completed);
+	remap_to_origin_clear_discard(cache, bio, mg->invalidate_oblock);
+	dm_hook_bio(&pb->hook_info, bio, overwrite_endio, mg);
+	dm_submit_bio_remap(bio, NULL);
+}
+
 static void invalidate_remove(struct work_struct *ws)
 {
 	int r;
@@ -1516,10 +1538,8 @@ static void invalidate_remove(struct work_struct *ws)
 		return;
 	}
 
-	init_continuation(&mg->k, invalidate_completed);
+	init_continuation(&mg->k, invalidate_committed);
 	continue_after_commit(&cache->committer, &mg->k);
-	remap_to_origin_clear_discard(cache, mg->overwrite_bio, mg->invalidate_oblock);
-	mg->overwrite_bio = NULL;
 	schedule_commit(&cache->committer);
 }
 
Signature · 1 line
2.53.0
author maintainer
#94 lore raw

PATCH 94/508 dm cache policy smq: fix missing locks in invalidating cache blocks

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 2d1f7b65f5deedd2e6b09fdc6ea27f8375f24b45 ]

In passthrough mode, the policy invalidate_mapping operation is called simultaneously from multiple workers, thus it should be protected by a lock. Otherwise, we might end up with data races on the allocated blocks counter, or even use-after-free issues with internal data structures when doing concurrent writes.

Note that the existing FIXME in smq_invalidate_mapping() doesn't affect passthrough mode since migration tasks don't exist there, but would need attention if supporting fast device shrinking via suspend/resume without target reloading.

Reproduce steps:

1. Create a cache device consisting of 1024 cache entries

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. Populate the cache, and record the number of cached blocks

fio --name=populate --filename=/dev/mapper/cache --rw=randwrite --bs=4k \
--size=64m --direct=1
nr_cached=$(dmsetup status cache | awk '{split($7, a, "/"); print a[1]}')

3. Reload the cache into passthrough mode

dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache

4. Write to the passthrough cache. By setting multiple jobs with I/O size equal to the cache block size, cache blocks are invalidated concurrently from different workers.

fio --filename=/dev/mapper/cache --name=test --rw=randwrite --bs=64k \
--direct=1 --numjobs=2 --randrepeat=0 --size=64m

5. Check if demoted matches cached block count. These numbers should match but may differ due to the data race.

nr_demoted=$(dmsetup status cache | awk '{print $12}') echo "$nr_cached, $nr_demoted"

Fixes b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
---
 drivers/md/dm-cache-policy-smq.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/md/dm-cache-policy-smq.c +4 -0
index 8bd2ad743d9ae..1566e040f7aac 100644
@@ -1589,14 +1589,18 @@ static int smq_invalidate_mapping(struct dm_cache_policy *p, dm_cblock_t cblock)
 {
 	struct smq_policy *mq = to_smq_policy(p);
 	struct entry *e = get_entry(&mq->cache_alloc, from_cblock(cblock));
+	unsigned long flags;
 
 	if (!e->allocated)
 		return -ENODATA;
 
+	spin_lock_irqsave(&mq->lock, flags);
 	// FIXME: what if this block has pending background work?
 	del_queue(mq, e);
 	h_remove(&mq->table, e);
 	free_entry(&mq->cache_alloc, e);
+	spin_unlock_irqrestore(&mq->lock, flags);
+
 	return 0;
 }
 
Signature · 1 line
2.53.0
author maintainer
#95 lore raw

PATCH 95/508 dm cache: fix concurrent write failure in passthrough mode

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit e4f66341779d0cf4c83c74793753a84094286d9e ]

When bio prison cell lock acquisition fails due to concurrent writes to the same block in passthrough mode, dm-cache incorrectly returns an I/O error instead of properly handling the concurrency. This can occur in both process and workqueue contexts when invalidate_lock() is called for exclusive access to a data block. Fix this by deferring the write bios to ensure proper block device behavior.

Reproduce steps:

1. Create a cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. Promote the first data block into cache

fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k

3. Reload the cache into passthrough mode

dmsetup suspend cache
dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0" dmsetup resume cache

4. Write to the first cached block concurrently. Sometimes one of the processes will receive I/O errors.

fio --filename=/dev/mapper/cache --name test --rw=randwrite --bs=4k \
--randrepeat=0 --direct=1 --numjobs=2 --size 64k

<snip>
fio-3.41
fio: io_u error on file /dev/mapper/cache: Input/output error: write offset=4096, buflen=4096
fio: pid=106, err=5/file:io_u.c:2008, func=io_u error, error=Input/output error
test: (groupid=0, jobs=1): err= 0: pid=105
test: (groupid=0, jobs=1): err= 5 (file:io_u.c:2008, func=io_u error, error=Input/output error): pid=106 <snip>

Fixes b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
---
 drivers/md/dm-cache-target.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/md/dm-cache-target.c +9 -0
index a3a8623eff297..65ae94f64c11b 100644
@@ -1557,6 +1557,15 @@ static int invalidate_lock(struct dm_cache_migration *mg)
 			    READ_WRITE_LOCK_LEVEL, prealloc, &mg->cell);
 	if (r < 0) {
 		free_prison_cell(cache, prealloc);
+
+		/* Defer the bio for retrying the cell lock */
+		if (mg->overwrite_bio) {
+			struct bio *bio = mg->overwrite_bio;
+
+			mg->overwrite_bio = NULL;
+			defer_bio(cache, bio);
+		}
+
 		invalidate_complete(mg, false);
 		return r;
 	}
Signature · 1 line
2.53.0
author maintainer
#96 lore raw

PATCH 96/508 dm cache: support shrinking the origin device

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit c2662b1544cbd8ea3181381bb899b8e681dfedc7 ]

This patch introduces formal support for shrinking the cache origin by reducing the cache target length via table reloads. Cache blocks mapped beyond the new target length must be clean and are invalidated during preresume. If any dirty blocks exist in the area being removed, the preresume operation fails without setting the NEEDS_CHECK flag in superblock, and the resume ioctl returns EFBIG. The cache device remains suspended until a table reload with target length that fits existing mappings is performed.

Without this patch, reducing the cache target length could result in io errors (RHBZ: 2134334), out-of-bounds memory access to the discard bitset, and security concerns regarding data leakage.

Verification steps:

1. create a cache metadata with some cached blocks mapped to the tail of the origin device. Here we use cache_restore v1.0 to build a metadata with one clean block mapped to the last origin block.

cat <<EOF >> cmeta.xml
<superblock uuid="" block_size="128" nr_cache_blocks="512" \
policy="smq" hint_width="4">
<mappings>

    <mapping cache_block="0" origin_block="4095" dirty="false"/>

</mappings>
</superblock>
EOF
dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2 dmsetup remove cmeta

2. bring up the cache whilst shrinking the cache origin by one block:

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 65536 linear /dev/sdc 8192" dmsetup create corig --table "0 524160 linear /dev/sdc 262144" dmsetup create cache --table "0 524160 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

3. check the number of cached data blocks via dmsetup status. It is expected to be zero.

dmsetup status cache | cut -d ' ' -f 7

In addition to the script above, this patch can be verified using the "cache/resize" tests in dmtest-python:

./dmtest run --rx cache/resize/shrink_origin --result-set default

Stable-dep-of: 322586745bd1 ("dm cache: fix dirty mapping checking in passthrough mode switching")

---
 drivers/md/dm-cache-target.c | 72 ++++++++++++++++++++++++++++++++++--
 1 file changed, 69 insertions(+), 3 deletions(-)
drivers/md/dm-cache-target.c +69 -3
index 65ae94f64c11b..77953a171860e 100644
@@ -407,6 +407,12 @@ struct cache {
 	mempool_t migration_pool;
 
 	struct bio_set bs;
+
+	/*
+	 * Cache_size entries. Set bits indicate blocks mapped beyond the
+	 * target length, which are marked for invalidation.
+	 */
+	unsigned long *invalid_bitset;
 };
 
 struct per_bio_data {
@@ -1958,6 +1964,9 @@ static void __destroy(struct cache *cache)
 	if (cache->discard_bitset)
 		free_bitset(cache->discard_bitset);
 
+	if (cache->invalid_bitset)
+		free_bitset(cache->invalid_bitset);
+
 	if (cache->copier)
 		dm_kcopyd_client_destroy(cache->copier);
 
@@ -2546,6 +2555,13 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 	}
 	clear_bitset(cache->discard_bitset, from_dblock(cache->discard_nr_blocks));
 
+	cache->invalid_bitset = alloc_bitset(from_cblock(cache->cache_size));
+	if (!cache->invalid_bitset) {
+		*error = "could not allocate bitset for invalid blocks";
+		goto bad;
+	}
+	clear_bitset(cache->invalid_bitset, from_cblock(cache->cache_size));
+
 	cache->copier = dm_kcopyd_client_create(&dm_kcopyd_throttle);
 	if (IS_ERR(cache->copier)) {
 		*error = "could not create kcopyd client";
@@ -2844,6 +2860,24 @@ static int load_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock,
 	return policy_load_mapping(cache->policy, oblock, cblock, dirty, hint, hint_valid);
 }
 
+static int load_filtered_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock,
+				 bool dirty, uint32_t hint, bool hint_valid)
+{
+	struct cache *cache = context;
+
+	if (from_oblock(oblock) >= from_oblock(cache->origin_blocks)) {
+		if (dirty) {
+			DMERR("%s: unable to shrink origin; cache block %u is dirty",
+			      cache_device_name(cache), from_cblock(cblock));
+			return -EFBIG;
+		}
+		set_bit(from_cblock(cblock), cache->invalid_bitset);
+		return 0;
+	}
+
+	return load_mapping(context, oblock, cblock, dirty, hint, hint_valid);
+}
+
 /*
  * The discard block size in the on disk metadata is not
  * necessarily the same as we're currently using.  So we have to
@@ -2998,6 +3032,24 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size)
 	return 0;
 }
 
+static int truncate_oblocks(struct cache *cache)
+{
+	uint32_t nr_blocks = from_cblock(cache->cache_size);
+	uint32_t i;
+	int r;
+
+	for_each_set_bit(i, cache->invalid_bitset, nr_blocks) {
+		r = dm_cache_remove_mapping(cache->cmd, to_cblock(i));
+		if (r) {
+			DMERR_LIMIT("%s: invalidation failed; couldn't update on disk metadata",
+				    cache_device_name(cache));
+			return r;
+		}
+	}
+
+	return 0;
+}
+
 static int cache_preresume(struct dm_target *ti)
 {
 	int r = 0;
@@ -3022,11 +3074,25 @@ static int cache_preresume(struct dm_target *ti)
 	}
 
 	if (!cache->loaded_mappings) {
+		/*
+		 * The fast device could have been resized since the last
+		 * failed preresume attempt.  To be safe we start by a blank
+		 * bitset for cache blocks.
+		 */
+		clear_bitset(cache->invalid_bitset, from_cblock(cache->cache_size));
+
 		r = dm_cache_load_mappings(cache->cmd, cache->policy,
-					   load_mapping, cache);
+					   load_filtered_mapping, cache);
 		if (r) {
 			DMERR("%s: could not load cache mappings", cache_device_name(cache));
-			metadata_operation_failed(cache, "dm_cache_load_mappings", r);
+			if (r != -EFBIG)
+				metadata_operation_failed(cache, "dm_cache_load_mappings", r);
+			return r;
+		}
+
+		r = truncate_oblocks(cache);
+		if (r) {
+			metadata_operation_failed(cache, "dm_cache_remove_mapping", r);
 			return r;
 		}
 
@@ -3492,7 +3558,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type cache_target = {
 	.name = "cache",
-	.version = {2, 2, 0},
+	.version = {2, 3, 0},
 	.module = THIS_MODULE,
 	.ctr = cache_ctr,
 	.dtr = cache_dtr,
Signature · 1 line
2.53.0
author maintainer
#97 lore raw

PATCH 97/508 dm cache: fix dirty mapping checking in passthrough mode switching

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 322586745bd1a0e5f3559fd1635fdeb4dbd1d6b8 ]

As mentioned in commit 9b1cc9f251af ("dm cache: share cache-metadata object across inactive and active DM tables"), dm-cache assumed table reload occurs after suspension, while LVM's table preload breaks this assumption. The dirty mapping check for passthrough mode was designed around this assumption and is performed during table creation, causing the check to fail with preload while metadata updates are ongoing. This risks loading dirty mappings into passthrough mode, resulting in data loss.

Reproduce steps:

1. Create a writeback cache with zero migration_threshold to produce dirty mappings

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writeback smq \
2 migration_threshold 0"

2. Preload a table in passthrough mode

dmsetup reload cache --table "0 262144 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0"

3. Write to the first cache block to make it dirty

fio --filename=/dev/mapper/cache --name=populate --rw=write --bs=4k \
--direct=1 --size=64k

4. Resume the inactive table. Now it's possible to load the dirty block into passthrough mode.

dmsetup resume cache

Fix by moving the checks to the preresume phase to support table preloading. Also remove the unused function dm_cache_metadata_all_clean.

Fixes 2ee57d587357 ("dm cache: add passthrough mode")
---
 drivers/md/dm-cache-metadata.c | 11 -----------
 drivers/md/dm-cache-metadata.h |  5 -----
 drivers/md/dm-cache-target.c   | 25 ++++++++-----------------
 3 files changed, 8 insertions(+), 33 deletions(-)
drivers/md/dm-cache-metadata.c +0 -11
index acffed750e3ed..c9d13a30ce86d 100644
@@ -1756,17 +1756,6 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
 	return r;
 }
 
-int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
-{
-	int r;
-
-	READ_LOCK(cmd);
-	r = blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
-	READ_UNLOCK(cmd);
-
-	return r;
-}
-
 void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd)
 {
 	WRITE_LOCK_VOID(cmd);
drivers/md/dm-cache-metadata.h +0 -5
index 57afc70479472..24e4af14fcca4 100644
@@ -138,11 +138,6 @@ void dm_cache_dump(struct dm_cache_metadata *cmd);
  */
 int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *p);
 
-/*
- * Query method.  Are all the blocks in the cache clean?
- */
-int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result);
-
 int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result);
 int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd);
 void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd);
drivers/md/dm-cache-target.c +8 -17
index 77953a171860e..8db906ea3bef0 100644
@@ -2510,23 +2510,8 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 		goto bad;
 	}
 
-	if (passthrough_mode(cache)) {
-		bool all_clean;
-
-		r = dm_cache_metadata_all_clean(cache->cmd, &all_clean);
-		if (r) {
-			*error = "dm_cache_metadata_all_clean() failed";
-			goto bad;
-		}
-
-		if (!all_clean) {
-			*error = "Cannot enter passthrough mode unless all blocks are clean";
-			r = -EINVAL;
-			goto bad;
-		}
-
+	if (passthrough_mode(cache))
 		policy_allow_migrations(cache->policy, false);
-	}
 
 	spin_lock_init(&cache->lock);
 	bio_list_init(&cache->deferred_bios);
@@ -2852,6 +2837,12 @@ static int load_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock,
 	struct cache *cache = context;
 
 	if (dirty) {
+		if (passthrough_mode(cache)) {
+			DMERR("%s: cannot enter passthrough mode unless all blocks are clean",
+			      cache_device_name(cache));
+			return -EBUSY;
+		}
+
 		set_bit(from_cblock(cblock), cache->dirty_bitset);
 		atomic_inc(&cache->nr_dirty);
 	} else
@@ -3085,7 +3076,7 @@ static int cache_preresume(struct dm_target *ti)
 					   load_filtered_mapping, cache);
 		if (r) {
 			DMERR("%s: could not load cache mappings", cache_device_name(cache));
-			if (r != -EFBIG)
+			if (r != -EFBIG && r != -EBUSY)
 				metadata_operation_failed(cache, "dm_cache_load_mappings", r);
 			return r;
 		}
Signature · 1 line
2.53.0
author maintainer
#98 lore raw

PATCH 98/508 platform/chrome: chromeos_tbmc: Drop wakeup source on remove

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rafael J. Wysocki <[email protected]>

[ Upstream commit 5d441a4bc93642ed6f41da87327a39946b4e1455 ]

The wakeup source added by device_init_wakeup() in chromeos_tbmc_add() needs to be dropped during driver removal, so add a .remove() callback to the driver for this purpose.

Fixes 0144c00ed86b ("platform/chrome: chromeos_tbmc: Report wake events")
---
 drivers/platform/chrome/chromeos_tbmc.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/platform/chrome/chromeos_tbmc.c +6 -0
index d1cf8f3463ce3..e248567c0a182 100644
@@ -95,6 +95,11 @@ static int chromeos_tbmc_add(struct acpi_device *adev)
 	return 0;
 }
 
+static void chromeos_tbmc_remove(struct acpi_device *adev)
+{
+	device_init_wakeup(&adev->dev, false);
+}
+
 static const struct acpi_device_id chromeos_tbmc_acpi_device_ids[] = {
 	{ ACPI_DRV_NAME, 0 },
 	{ }
@@ -110,6 +115,7 @@ static struct acpi_driver chromeos_tbmc_driver = {
 	.ids = chromeos_tbmc_acpi_device_ids,
 	.ops = {
 		.add = chromeos_tbmc_add,
+		.remove = chromeos_tbmc_remove,
 		.notify = chromeos_tbmc_notify,
 	},
 	.drv.pm = &chromeos_tbmc_pm_ops,
Signature · 1 line
2.53.0
author maintainer
#99 lore raw

PATCH 99/508 dm cache metadata: fix memory leak on metadata abort retry

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <[email protected]>

[ Upstream commit 044ca491d4086dc5bf233e9fcb71db52df32f633 ]

When failing to acquire the root_lock in dm_cache_metadata_abort because the block_manager is read-only, the temporary block_manager created outside the root_lock is not properly released, causing a memory leak.

Reproduce steps:

This can be reproduced by reloading a new table while the metadata is read-only. While the second call to dm_cache_metadata_abort is caused by lack of support for table preload in dm-cache, mentioned in commit 9b1cc9f251af ("dm cache: share cache-metadata object across inactive and active DM tables"), it exposes the memory leak in dm_cache_metadata_abort when the function is called multiple times. Specifically, dm-cache fails to sync the new cache object's mode during preresume, creating the reproducer condition.

This issue could also occur through concurrent metadata_operation_failed calls due to races in cache mode updates, but the table preload scenario below provides a reliable reproducer.

1. Create a cache device with some faulty trailing metadata blocks

dmsetup create cmeta <<EOF
0 200 linear /dev/sdc 0
200 7992 error
EOF
dmsetup create cdata --table "0 131072 linear /dev/sdc 8192" dmsetup create corig --table "0 262144 linear /dev/sdc 262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct dmsetup create cache --table "0 131072 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 1 writethrough smq 0"

2. Suspend and resume the cache to start a new metadata transaction and trigger metadata io errors on the next metadata commit.

dmsetup suspend cache
dmsetup resume cache

3. Write to the cache device to update metadata

fio --filename=/dev/mapper/cache --name test --rw=randwrite --bs=4k \
--randrepeat=0 --direct=1 --size 64k

4. Preload the same table

dmsetup reload cache --table "$(dmsetup table cache)"

5. Resume the new table. This triggers the memory leak.

dmsetup suspend cache
dmsetup resume cache

kmemleak logs:

<snip>
unreferenced object 0xffff8880080c2010 (size 16):
comm "dmsetup", pid 132, jiffies 4294982580
hex dump (first 16 bytes):

    00 38 b9 07 80 88 ff ff 6a 6b 6b 6b 6b 6b 6b a5 ...
  backtrace (crc 3118f31c):
    kmemleak_alloc+0x28/0x40
    __kmalloc_cache_noprof+0x3d9/0x510
    dm_block_manager_create+0x51/0x140
    dm_cache_metadata_abort+0x85/0x320
    metadata_operation_failed+0x103/0x1e0
    cache_preresume+0xacd/0xe70
    dm_table_resume_targets+0xd3/0x320
    __dm_resume+0x1b/0xf0
    dm_resume+0x127/0x170

<snip>

Fixes 352b837a5541 ("dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort")
---
 drivers/md/dm-cache-metadata.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/md/dm-cache-metadata.c +8 -5
index c9d13a30ce86d..74078b90653f3 100644
@@ -1023,6 +1023,12 @@ static bool cmd_write_lock(struct dm_cache_metadata *cmd)
 			return;			\
 	} while (0)
 
+#define WRITE_LOCK_OR_GOTO(cmd, label)		\
+	do {					\
+		if (!cmd_write_lock((cmd)))	\
+			goto label;		\
+	} while (0)
+
 #define WRITE_UNLOCK(cmd) \
 	up_write(&(cmd)->root_lock)
 
@@ -1822,11 +1828,8 @@ int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
 	new_bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
 					 CACHE_MAX_CONCURRENT_LOCKS);
 
-	WRITE_LOCK(cmd);
-	if (cmd->fail_io) {
-		WRITE_UNLOCK(cmd);
-		goto out;
-	}
+	/* cmd_write_lock() already checks fail_io with cmd->root_lock held */
+	WRITE_LOCK_OR_GOTO(cmd, out);
 
 	__destroy_persistent_data_objects(cmd, false);
 	old_bm = cmd->bm;
Signature · 1 line
2.53.0
author maintainer
#100 lore raw

PATCH 100/508 dm log: fix out-of-bounds write due to region_count overflow

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Junrui Luo <[email protected]>

[ Upstream commit c20e36b7631d83e7535877f08af8b0af72c44b1a ]

The local variable region_count in create_log_context() is declared as unsigned int (32-bit), but dm_sector_div_up() returns sector_t (64-bit). When a device-mapper target has a sufficiently large ti->len with a small region_size, the division result can exceed UINT_MAX. The truncated value is then used to calculate bitset_size, causing clean_bits, sync_bits, and recovering_bits to be allocated far smaller than needed for the actual number of regions.

Subsequent log operations (log_set_bit, log_clear_bit, log_test_bit) use region indices derived from the full untruncated region space, causing out-of-bounds writes to kernel heap memory allocated by vmalloc.

This can be reproduced by creating a mirror target whose region_count overflows 32 bits:

  dmsetup create bigzero --table '0 8589934594 zero'
  dmsetup create mymirror --table '0 8589934594 mirror \
    core 2 2 nosync 2 /dev/mapper/bigzero 0 \
    /dev/mapper/bigzero 0'

The status output confirms the truncation (sync_count=1 instead of 4294967297, because 0x100000001 was truncated to 1):

  $ dmsetup status mymirror
  0 8589934594 mirror 2 254:1 254:1 1/4294967297 ...

This leads to a kernel crash in core_in_sync:

  BUG: scheduling while atomic: (udev-worker)/9150/0x00000000
  RIP: 0010:core_in_sync+0x14/0x30 [dm_log]
  CR2: 0000000000000008
  Fixing recursive fault but reboot is needed!

Fix by widening the local region_count to sector_t and adding an explicit overflow check before the value is assigned to lc->region_count.

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
---
 drivers/md/dm-log.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/md/dm-log.c +5 -1
index e215478bcee04..94d3f13e673e9 100644
@@ -373,7 +373,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
 
 	struct log_c *lc;
 	uint32_t region_size;
-	unsigned int region_count;
+	sector_t region_count;
 	size_t bitset_size, buf_size;
 	int r;
 	char dummy;
@@ -401,6 +401,10 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
 	}
 
 	region_count = dm_sector_div_up(ti->len, region_size);
+	if (region_count > UINT_MAX) {
+		DMWARN("region count exceeds limit of %u", UINT_MAX);
+		return -EINVAL;
+	}
 
 	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
 	if (!lc) {
Signature · 1 line
2.53.0
author maintainer
#101 lore raw

PATCH 101/508 drm/bridge: cadence: cdns-mhdp8546-core: Set the mhdp connector earlier in atomic_enable()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jayesh Choudhary <[email protected]>

[ Upstream commit 43d6508ddbf9fb974fbc359a033154f78c9d4c8b ]

In case if we get errors in cdns_mhdp_link_up() or cdns_mhdp_reg_read() in atomic_enable, we will go to cdns_mhdp_modeset_retry_fn() and will hit NULL pointer while trying to access the mutex. We need the connector to be set before that. Unlike in legacy cases with flag !DRM_BRIDGE_ATTACH_NO_CONNECTOR, we do not have connector initialised in bridge_attach(), so add the mhdp->connector_ptr in device structure to handle both cases with DRM_BRIDGE_ATTACH_NO_CONNECTOR and !DRM_BRIDGE_ATTACH_NO_CONNECTOR, set it in atomic_enable() earlier to avoid possible NULL pointer dereference in recovery paths like modeset_retry_fn() with the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag set.

---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 29 ++++++++++---------
 .../drm/bridge/cadence/cdns-mhdp8546-core.h   |  1 +
 .../drm/bridge/cadence/cdns-mhdp8546-hdcp.c   | 18 +++++++++---
 3 files changed, 30 insertions(+), 18 deletions(-)
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +15 -14
index bdb9fc00c776b..8037a41f9afd2 100644
@@ -810,7 +810,7 @@ static void cdns_mhdp_fw_cb(const struct firmware *fw, void *context)
 	bridge_attached = mhdp->bridge_attached;
 	spin_unlock(&mhdp->start_lock);
 	if (bridge_attached) {
-		if (mhdp->connector.dev)
+		if (mhdp->connector_ptr)
 			drm_kms_helper_hotplug_event(mhdp->bridge.dev);
 		else
 			drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
@@ -1709,6 +1709,7 @@ static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
 		return ret;
 	}
 
+	mhdp->connector_ptr = conn;
 	drm_connector_helper_add(conn, &cdns_mhdp_conn_helper_funcs);
 
 	ret = drm_display_info_set_bus_formats(&conn->display_info,
@@ -1988,17 +1989,25 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
 	struct drm_atomic_state *state = bridge_state->base.state;
 	struct cdns_mhdp_bridge_state *mhdp_state;
 	struct drm_crtc_state *crtc_state;
-	struct drm_connector *connector;
 	struct drm_connector_state *conn_state;
 	struct drm_bridge_state *new_state;
 	const struct drm_display_mode *mode;
 	u32 resp;
-	int ret;
+	int ret = 0;
 
 	dev_dbg(mhdp->dev, "bridge enable\n");
 
 	mutex_lock(&mhdp->link_mutex);
 
+	mhdp->connector_ptr = drm_atomic_get_new_connector_for_encoder(state,
+								       bridge->encoder);
+	if (WARN_ON(!mhdp->connector_ptr))
+		goto out;
+
+	conn_state = drm_atomic_get_new_connector_state(state, mhdp->connector_ptr);
+	if (WARN_ON(!conn_state))
+		goto out;
+
 	if (mhdp->plugged && !mhdp->link_up) {
 		ret = cdns_mhdp_link_up(mhdp);
 		if (ret < 0)
@@ -2018,15 +2027,6 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
 	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
 			    resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
 
-	connector = drm_atomic_get_new_connector_for_encoder(state,
-							     bridge->encoder);
-	if (WARN_ON(!connector))
-		goto out;
-
-	conn_state = drm_atomic_get_new_connector_state(state, connector);
-	if (WARN_ON(!conn_state))
-		goto out;
-
 	if (mhdp->hdcp_supported &&
 	    mhdp->hw_state == MHDP_HW_READY &&
 	    conn_state->content_protection ==
@@ -2103,6 +2103,7 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
 	if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
 		mhdp->info->ops->disable(mhdp);
 
+	mhdp->connector_ptr = NULL;
 	mutex_unlock(&mhdp->link_mutex);
 }
 
@@ -2368,7 +2369,7 @@ static void cdns_mhdp_modeset_retry_fn(struct work_struct *work)
 
 	mhdp = container_of(work, typeof(*mhdp), modeset_retry_work);
 
-	conn = &mhdp->connector;
+	conn = mhdp->connector_ptr;
 
 	/* Grab the locks before changing connector property */
 	mutex_lock(&conn->dev->mode_config.mutex);
@@ -2445,7 +2446,7 @@ static void cdns_mhdp_hpd_work(struct work_struct *work)
 	int ret;
 
 	ret = cdns_mhdp_update_link_status(mhdp);
-	if (mhdp->connector.dev) {
+	if (mhdp->connector_ptr) {
 		if (ret < 0)
 			schedule_work(&mhdp->modeset_retry_work);
 		else
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +1 -0
index bad2fc0c73066..a76775c768956 100644
@@ -376,6 +376,7 @@ struct cdns_mhdp_device {
 	struct mutex link_mutex;
 
 	struct drm_connector connector;
+	struct drm_connector *connector_ptr;
 	struct drm_bridge bridge;
 
 	struct cdns_mhdp_link link;
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c +14 -4
index 5e3b8edcf7948..2866069805524 100644
@@ -394,7 +394,7 @@ static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp)
 	int ret;
 
 	dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n",
-		mhdp->connector.name, mhdp->connector.base.id);
+		mhdp->connector_ptr->name, mhdp->connector_ptr->base.id);
 
 	ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false);
 
@@ -436,6 +436,10 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
 	int ret = 0;
 
 	mutex_lock(&mhdp->hdcp.mutex);
+
+	if (!mhdp->connector_ptr)
+		goto out;
+
 	if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
 		goto out;
 
@@ -445,7 +449,7 @@ static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
 
 	dev_err(mhdp->dev,
 		"[%s:%d] HDCP link failed, retrying authentication\n",
-		mhdp->connector.name, mhdp->connector.base.id);
+		mhdp->connector_ptr->name, mhdp->connector_ptr->base.id);
 
 	ret = _cdns_mhdp_hdcp_disable(mhdp);
 	if (ret) {
@@ -487,13 +491,19 @@ static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
 	struct cdns_mhdp_device *mhdp = container_of(hdcp,
 						     struct cdns_mhdp_device,
 						     hdcp);
-	struct drm_device *dev = mhdp->connector.dev;
+	struct drm_device *dev = NULL;
 	struct drm_connector_state *state;
 
+	if (mhdp->connector_ptr)
+		dev = mhdp->connector_ptr->dev;
+
+	if (!dev)
+		return;
+
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 	mutex_lock(&mhdp->hdcp.mutex);
 	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-		state = mhdp->connector.state;
+		state = mhdp->connector_ptr->state;
 		state->content_protection = mhdp->hdcp.value;
 	}
 	mutex_unlock(&mhdp->hdcp.mutex);
Signature · 1 line
2.53.0
author maintainer
#102 lore raw

PATCH 102/508 drm/bridge: cadence: cdns-mhdp8546-core: Add mode_valid hook to drm_bridge_funcs

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jayesh Choudhary <[email protected]>

[ Upstream commit 6dbff34016052b099558b76632e4983e2df13fed ]

Add cdns_mhdp_bridge_mode_valid() to check if specific mode is valid for this bridge or not. In the legacy usecase with !DRM_BRIDGE_ATTACH_NO_CONNECTOR we were using the hook from drm_connector_helper_funcs but with DRM_BRIDGE_ATTACH_NO_CONNECTOR we need to have mode_valid() in drm_bridge_funcs.

Without this patch, when using DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, the cdns_mhdp_bandwidth_ok() function would not be called during mode validation, potentially allowing modes that exceed the bridge's bandwidth capabilities to be incorrectly marked as valid.

---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +20 -0
index 8037a41f9afd2..34a3348375171 100644
@@ -2234,6 +2234,25 @@ static struct edid *cdns_mhdp_bridge_get_edid(struct drm_bridge *bridge,
 	return cdns_mhdp_get_edid(mhdp, connector);
 }
 
+static enum drm_mode_status
+cdns_mhdp_bridge_mode_valid(struct drm_bridge *bridge,
+			    const struct drm_display_info *info,
+			    const struct drm_display_mode *mode)
+{
+	struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
+
+	mutex_lock(&mhdp->link_mutex);
+
+	if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes,
+				    mhdp->link.rate)) {
+		mutex_unlock(&mhdp->link_mutex);
+		return MODE_CLOCK_HIGH;
+	}
+
+	mutex_unlock(&mhdp->link_mutex);
+	return MODE_OK;
+}
+
 static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
 	.atomic_enable = cdns_mhdp_atomic_enable,
 	.atomic_disable = cdns_mhdp_atomic_disable,
@@ -2248,6 +2267,7 @@ static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
 	.get_edid = cdns_mhdp_bridge_get_edid,
 	.hpd_enable = cdns_mhdp_bridge_hpd_enable,
 	.hpd_disable = cdns_mhdp_bridge_hpd_disable,
+	.mode_valid = cdns_mhdp_bridge_mode_valid,
 };
 
 static bool cdns_mhdp_detect_hpd(struct cdns_mhdp_device *mhdp, bool *hpd_pulse)
Signature · 1 line
2.53.0
author maintainer
#103 lore raw

PATCH 103/508 drm/bridge: cadence: cdns-mhdp8546-core: Handle HDCP state in bridge atomic check

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Harikrishna Shenoy <[email protected]>

[ Upstream commit 4a8edd658489ec2a3d7e20482fa9e8d366153d8d ]

Now that we have DRM_BRIDGE_ATTACH_NO_CONNECTOR framework, handle the HDCP state change in bridge atomic check as well to enable correct functioning for HDCP in both DRM_BRIDGE_ATTACH_NO_CONNECTOR and !DRM_BRIDGE_ATTACH_NO_CONNECTOR case.

Without this patch, when using DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, HDCP state changes would not be properly handled during atomic commits, potentially leading to HDCP authentication failures or incorrect protection status for content requiring HDCP encryption.

---
 .../drm/bridge/cadence/cdns-mhdp8546-core.c   | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +23 -0
index 34a3348375171..44955601a9dfc 100644
@@ -2196,6 +2196,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
 {
 	struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
 	const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+	struct drm_connector_state *old_state, *new_state;
+	struct drm_atomic_state *state = crtc_state->state;
+	struct drm_connector *conn = mhdp->connector_ptr;
+	u64 old_cp, new_cp;
 
 	mutex_lock(&mhdp->link_mutex);
 
@@ -2215,6 +2219,25 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
 	if (mhdp->info)
 		bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
 
+	if (conn && mhdp->hdcp_supported) {
+		old_state = drm_atomic_get_old_connector_state(state, conn);
+		new_state = drm_atomic_get_new_connector_state(state, conn);
+		old_cp = old_state->content_protection;
+		new_cp = new_state->content_protection;
+
+		if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
+		    new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+			new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+			crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
+			crtc_state->mode_changed = true;
+		}
+
+		if (!new_state->crtc) {
+			if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+				new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+		}
+	}
+
 	mutex_unlock(&mhdp->link_mutex);
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#104 lore raw

PATCH 104/508 spi: fsl-qspi: Use reinit_completion() for repeated operations

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felix Gu <[email protected]>

[ Upstream commit 981b080a79724738882b0af1c5bb7ade30d94f24 ]

The driver currently calls init_completion() during every spi_mem_op. Tchnically it may work, but it's not the recommended pattern.

According to the kernel documentation: Calling init_completion() on the same completion object twice is most likely a bug as it re-initializes the queue to an empty queue and enqueued tasks could get "lost" - use reinit_completion() in that case, but be aware of other races.

So moves the initial initialization to probe function and uses reinit_completion() for subsequent operations.

Fixes 84d043185dbe ("spi: Add a driver for the Freescale/NXP QuadSPI controller")
---
 drivers/spi/spi-fsl-qspi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/spi-fsl-qspi.c +2 -1
index 21e357966d2a2..cb2e5413dd32b 100644
@@ -606,7 +606,7 @@ static int fsl_qspi_do_op(struct fsl_qspi *q, const struct spi_mem_op *op)
 	void __iomem *base = q->iobase;
 	int err = 0;
 
-	init_completion(&q->c);
+	reinit_completion(&q->c);
 
 	/*
 	 * Always start the sequence at the same index since we update
@@ -924,6 +924,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_disable_clk;
 
+	init_completion(&q->c);
 	ret = devm_request_irq(dev, ret,
 			fsl_qspi_irq_handler, 0, pdev->name, q);
 	if (ret) {
Signature · 1 line
2.53.0
author maintainer
#105 lore raw

PATCH 105/508 drm/sun4i: Fix resource leaks

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ethan Tidmore <[email protected]>

[ Upstream commit 127367ad2e0f4870de60c6d719ae82ecf68d674c ]

Three clocks are not being released in devm_regmap_init_mmio() error path.

Add proper goto and set ret to the error code.

Fixes 8270249fbeaf0 ("drm/sun4i: backend: Create regmap after access is possible")
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/sun4i/sun4i_backend.c +2 -1
index 6a2ffaa477ab8..4943577ec7fb8 100644
@@ -878,7 +878,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 						     &sun4i_backend_regmap_config);
 	if (IS_ERR(backend->engine.regs)) {
 		dev_err(dev, "Couldn't create the backend regmap\n");
-		return PTR_ERR(backend->engine.regs);
+		ret = PTR_ERR(backend->engine.regs);
+		goto err_disable_ram_clk;
 	}
 
 	list_add_tail(&backend->engine.list, &drv->engine_list);
Signature · 1 line
2.53.0
author maintainer
#106 lore raw

PATCH 106/508 drm/amdgpu: Add default case in DVI mode validation

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Srinivasan Shanmugam <[email protected]>

[ Upstream commit e6020a55b8e364d15eac27f9c788e13114eec6b7 ]

amdgpu_connector_dvi_mode_valid() assigns max_digital_pixel_clock_khz based on connector_object_id using a switch statement that lacks a default case.

In practice this code path should never be hit because the existing cases already cover all digital connector types that this function is used for. This is also legacy display code which is not used for new hardware.

Add a default case returning MODE_BAD to make the switch exhaustive and silence the static analyzer smatch error. The new branch is effectively defensive and should never be reached during normal operation.

Fixes 585b2f685c56 ("drm/amdgpu: Respect max pixel clock for HDMI and DVI-D (v2)")
Cc Dan Carpenter <[email protected]>
Cc Timur Kristóf <[email protected]>
Cc Alex Deucher <[email protected]>
Cc Christian König <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +2 -0
index 52c093e42531b..5f4fef27177b4 100644
@@ -1257,6 +1257,8 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector
 		case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
 			max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock * 2;
 			break;
+		default:
+			return MODE_BAD;
 		}
 
 		/* When the display EDID claims that it's an HDMI display,
Signature · 1 line
2.53.0
author maintainer
#107 lore raw

PATCH 107/508 dm init: ensure device probing has finished in dm-mod.waitfor=

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guillaume Gonnet <[email protected]>

[ Upstream commit 99a2312f69805f4ba92d98a757625e0300a747ab ]

The early_lookup_bdev() function returns successfully when the disk device is present but not necessarily its partitions. In this situation, dm_early_create() fails as the partition block device does not exist yet.

In my case, this phenomenon occurs quite often because the device is an SD card with slow reading times, on which kernel takes time to enumerate available partitions.

Fortunately, the underlying device is back to "probing" state while enumerating partitions. Waiting for all probing to end is enough to fix this issue.

That's also the reason why this problem never occurs with rootwait=
parameter: the while loop inside wait_for_root() explicitly waits for probing to be done and then the function calls async_synchronize_full(). These lines were omitted in 035641b, even though the commit says it's based on the rootwait logic...

Anyway, calling wait_for_device_probe() after our while loop does the job (it both waits for probing and calls async_synchronize_full).

Fixes 035641b01e72 ("dm init: add dm-mod.waitfor to wait for asynchronously probed block devices")
---
 drivers/md/dm-init.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/dm-init.c +3 -1
index b37bbe7625003..423269cbdd2bb 100644
@@ -303,8 +303,10 @@ static int __init dm_init_init(void)
 		}
 	}
 
-	if (waitfor[0])
+	if (waitfor[0]) {
+		wait_for_device_probe();
 		DMINFO("all devices available");
+	}
 
 	list_for_each_entry(dev, &devices, list) {
 		if (dm_early_create(&dev->dmi, dev->table,
Signature · 1 line
2.53.0
author maintainer
#108 lore raw

PATCH 108/508 fbdev: matroxfb: Mark variable with __maybe_unused to avoid W=1 build break

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andy Shevchenko <[email protected]>

[ Upstream commit caf6144053b4e1c815aa56afb54745a176f999df ]

Clang is not happy about set but unused variable:

drivers/video/fbdev/matrox/g450_pll.c:412:18: error: variable 'mnp' set but not used
412 | unsigned int mnp;
| ^
1 error generated.

Since the commit 7b987887f97b ("video: fbdev: matroxfb: remove dead code and set but not used variable") the 'mnp' became unused, but eliminating that code might have side-effects. The question here is what should we do with 'mnp'? The easiest way out is just mark it with __maybe_unused which will shut the compiler up and won't change any possible IO flow. So does this change.

A dive into the history of the driver:

The problem was revealed when the #if 0 guarded code along with unused pixel_vco variable was removed. That code was introduced in the original commit 213d22146d1f ("[PATCH] (1/3) matroxfb for 2.5.3"). And then guarded in the commit 705e41f82988 ("matroxfb DVI updates: Handle DVI output on G450/G550. Powerdown unused portions of G450/G550 DAC. Split G450/G550 DAC from older DAC1064 handling. Modify PLL setting when both CRTCs use same pixel clocks.").

NOTE: The two commits mentioned above pre-date Git era and available in history.git repository for archaeological purposes.

Even without that guard the modern compilers may see that the pixel_vco wasn't ever used and seems a leftover after some debug or review made 25 years ago.

The g450_mnp2vco() doesn't have any IO and as Jason said doesn't seem to have any side effects either than some unneeded CPU processing during runtime. I agree that's unlikely that timeout (or heating up the CPU) has any effect on the HW (GPU/display) functionality.

Fixes 7b987887f97b ("video: fbdev: matroxfb: remove dead code and set but not used variable")
---
 drivers/video/fbdev/matrox/g450_pll.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/fbdev/matrox/g450_pll.c +1 -1
index ff8e321a22cef..b2d3f7328ea83 100644
@@ -407,7 +407,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
 		case M_VIDEO_PLL:
 			{
 				u_int8_t tmp;
-				unsigned int mnp;
+				unsigned int mnp __maybe_unused;
 				unsigned long flags;
 				
 				matroxfb_DAC_lock_irqsave(flags);
Signature · 1 line
2.53.0
author maintainer
#109 lore raw

PATCH 109/508 crypto: atmel - Remove cfb and ofb

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Herbert Xu <[email protected]>

[ Upstream commit a16144bda9c332079b6a1db52725e9c22007114d ]

Remove the unused CFB/OFB implementation.

Stable-dep-of: 57a13941c0bb ("crypto: atmel-aes - guard unregister on error in atmel_aes_register_algs")

---
 drivers/crypto/atmel-aes.c  | 214 +-----------------------------------
 drivers/crypto/atmel-tdes.c | 205 +---------------------------------
 2 files changed, 8 insertions(+), 411 deletions(-)
drivers/crypto/atmel-aes.c +2 -212
index 97fcde0126766..f023f27468c0d 100644
@@ -46,11 +46,6 @@
 #define ATMEL_AES_BUFFER_ORDER	2
 #define ATMEL_AES_BUFFER_SIZE	(PAGE_SIZE << ATMEL_AES_BUFFER_ORDER)
 
-#define CFB8_BLOCK_SIZE		1
-#define CFB16_BLOCK_SIZE	2
-#define CFB32_BLOCK_SIZE	4
-#define CFB64_BLOCK_SIZE	8
-
 #define SIZE_IN_WORDS(x)	((x) >> 2)
 
 /* AES flags */
@@ -60,12 +55,6 @@
 #define AES_FLAGS_OPMODE_MASK	(AES_MR_OPMOD_MASK | AES_MR_CFBS_MASK)
 #define AES_FLAGS_ECB		AES_MR_OPMOD_ECB
 #define AES_FLAGS_CBC		AES_MR_OPMOD_CBC
-#define AES_FLAGS_OFB		AES_MR_OPMOD_OFB
-#define AES_FLAGS_CFB128	(AES_MR_OPMOD_CFB | AES_MR_CFBS_128b)
-#define AES_FLAGS_CFB64		(AES_MR_OPMOD_CFB | AES_MR_CFBS_64b)
-#define AES_FLAGS_CFB32		(AES_MR_OPMOD_CFB | AES_MR_CFBS_32b)
-#define AES_FLAGS_CFB16		(AES_MR_OPMOD_CFB | AES_MR_CFBS_16b)
-#define AES_FLAGS_CFB8		(AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
 #define AES_FLAGS_CTR		AES_MR_OPMOD_CTR
 #define AES_FLAGS_GCM		AES_MR_OPMOD_GCM
 #define AES_FLAGS_XTS		AES_MR_OPMOD_XTS
@@ -87,7 +76,6 @@
 
 struct atmel_aes_caps {
 	bool			has_dualbuff;
-	bool			has_cfb64;
 	bool			has_gcm;
 	bool			has_xts;
 	bool			has_authenc;
@@ -860,22 +848,6 @@ static int atmel_aes_dma_start(struct atmel_aes_dev *dd,
 	int err;
 
 	switch (dd->ctx->block_size) {
-	case CFB8_BLOCK_SIZE:
-		addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		maxburst = 1;
-		break;
-
-	case CFB16_BLOCK_SIZE:
-		addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		maxburst = 1;
-		break;
-
-	case CFB32_BLOCK_SIZE:
-	case CFB64_BLOCK_SIZE:
-		addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		maxburst = 1;
-		break;
-
 	case AES_BLOCK_SIZE:
 		addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		maxburst = dd->caps.max_burst_size;
@@ -1103,7 +1075,7 @@ static int atmel_aes_crypt(struct skcipher_request *req, unsigned long mode)
 	}
 
 	/*
-	 * ECB, CBC, CFB, OFB or CTR mode require the plaintext and ciphertext
+	 * ECB, CBC or CTR mode require the plaintext and ciphertext
 	 * to have a positve integer length.
 	 */
 	if (!req->cryptlen && opmode != AES_FLAGS_XTS)
@@ -1113,27 +1085,7 @@ static int atmel_aes_crypt(struct skcipher_request *req, unsigned long mode)
 	    !IS_ALIGNED(req->cryptlen, crypto_skcipher_blocksize(skcipher)))
 		return -EINVAL;
 
-	switch (mode & AES_FLAGS_OPMODE_MASK) {
-	case AES_FLAGS_CFB8:
-		ctx->block_size = CFB8_BLOCK_SIZE;
-		break;
-
-	case AES_FLAGS_CFB16:
-		ctx->block_size = CFB16_BLOCK_SIZE;
-		break;
-
-	case AES_FLAGS_CFB32:
-		ctx->block_size = CFB32_BLOCK_SIZE;
-		break;
-
-	case AES_FLAGS_CFB64:
-		ctx->block_size = CFB64_BLOCK_SIZE;
-		break;
-
-	default:
-		ctx->block_size = AES_BLOCK_SIZE;
-		break;
-	}
+	ctx->block_size = AES_BLOCK_SIZE;
 	ctx->is_aead = false;
 
 	rctx = skcipher_request_ctx(req);
@@ -1188,66 +1140,6 @@ static int atmel_aes_cbc_decrypt(struct skcipher_request *req)
 	return atmel_aes_crypt(req, AES_FLAGS_CBC);
 }
 
-static int atmel_aes_ofb_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_OFB | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_ofb_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_OFB);
-}
-
-static int atmel_aes_cfb_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB128 | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_cfb_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB128);
-}
-
-static int atmel_aes_cfb64_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB64 | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_cfb64_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB64);
-}
-
-static int atmel_aes_cfb32_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB32 | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_cfb32_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB32);
-}
-
-static int atmel_aes_cfb16_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB16 | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_cfb16_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB16);
-}
-
-static int atmel_aes_cfb8_encrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB8 | AES_FLAGS_ENCRYPT);
-}
-
-static int atmel_aes_cfb8_decrypt(struct skcipher_request *req)
-{
-	return atmel_aes_crypt(req, AES_FLAGS_CFB8);
-}
-
 static int atmel_aes_ctr_encrypt(struct skcipher_request *req)
 {
 	return atmel_aes_crypt(req, AES_FLAGS_CTR | AES_FLAGS_ENCRYPT);
@@ -1318,76 +1210,6 @@ static struct skcipher_alg aes_algs[] = {
 	.decrypt		= atmel_aes_cbc_decrypt,
 	.ivsize			= AES_BLOCK_SIZE,
 },
-{
-	.base.cra_name		= "ofb(aes)",
-	.base.cra_driver_name	= "atmel-ofb-aes",
-	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_ofb_encrypt,
-	.decrypt		= atmel_aes_ofb_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-},
-{
-	.base.cra_name		= "cfb(aes)",
-	.base.cra_driver_name	= "atmel-cfb-aes",
-	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_cfb_encrypt,
-	.decrypt		= atmel_aes_cfb_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-},
-{
-	.base.cra_name		= "cfb32(aes)",
-	.base.cra_driver_name	= "atmel-cfb32-aes",
-	.base.cra_blocksize	= CFB32_BLOCK_SIZE,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_cfb32_encrypt,
-	.decrypt		= atmel_aes_cfb32_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-},
-{
-	.base.cra_name		= "cfb16(aes)",
-	.base.cra_driver_name	= "atmel-cfb16-aes",
-	.base.cra_blocksize	= CFB16_BLOCK_SIZE,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_cfb16_encrypt,
-	.decrypt		= atmel_aes_cfb16_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-},
-{
-	.base.cra_name		= "cfb8(aes)",
-	.base.cra_driver_name	= "atmel-cfb8-aes",
-	.base.cra_blocksize	= CFB8_BLOCK_SIZE,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_cfb8_encrypt,
-	.decrypt		= atmel_aes_cfb8_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-},
 {
 	.base.cra_name		= "ctr(aes)",
 	.base.cra_driver_name	= "atmel-ctr-aes",
@@ -1404,21 +1226,6 @@ static struct skcipher_alg aes_algs[] = {
 },
 };
 
-static struct skcipher_alg aes_cfb64_alg = {
-	.base.cra_name		= "cfb64(aes)",
-	.base.cra_driver_name	= "atmel-cfb64-aes",
-	.base.cra_blocksize	= CFB64_BLOCK_SIZE,
-	.base.cra_ctxsize	= sizeof(struct atmel_aes_ctx),
-
-	.init			= atmel_aes_init_tfm,
-	.min_keysize		= AES_MIN_KEY_SIZE,
-	.max_keysize		= AES_MAX_KEY_SIZE,
-	.setkey			= atmel_aes_setkey,
-	.encrypt		= atmel_aes_cfb64_encrypt,
-	.decrypt		= atmel_aes_cfb64_decrypt,
-	.ivsize			= AES_BLOCK_SIZE,
-};
-
 
 /* gcm aead functions */
 
@@ -2407,9 +2214,6 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 	if (dd->caps.has_gcm)
 		crypto_unregister_aead(&aes_gcm_alg);
 
-	if (dd->caps.has_cfb64)
-		crypto_unregister_skcipher(&aes_cfb64_alg);
-
 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
 		crypto_unregister_skcipher(&aes_algs[i]);
 }
@@ -2434,14 +2238,6 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 			goto err_aes_algs;
 	}
 
-	if (dd->caps.has_cfb64) {
-		atmel_aes_crypto_alg_init(&aes_cfb64_alg.base);
-
-		err = crypto_register_skcipher(&aes_cfb64_alg);
-		if (err)
-			goto err_aes_cfb64_alg;
-	}
-
 	if (dd->caps.has_gcm) {
 		atmel_aes_crypto_alg_init(&aes_gcm_alg.base);
 
@@ -2482,8 +2278,6 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 err_aes_xts_alg:
 	crypto_unregister_aead(&aes_gcm_alg);
 err_aes_gcm_alg:
-	crypto_unregister_skcipher(&aes_cfb64_alg);
-err_aes_cfb64_alg:
 	i = ARRAY_SIZE(aes_algs);
 err_aes_algs:
 	for (j = 0; j < i; j++)
@@ -2495,7 +2289,6 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 {
 	dd->caps.has_dualbuff = 0;
-	dd->caps.has_cfb64 = 0;
 	dd->caps.has_gcm = 0;
 	dd->caps.has_xts = 0;
 	dd->caps.has_authenc = 0;
@@ -2507,7 +2300,6 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 	case 0x600:
 	case 0x500:
 		dd->caps.has_dualbuff = 1;
-		dd->caps.has_cfb64 = 1;
 		dd->caps.has_gcm = 1;
 		dd->caps.has_xts = 1;
 		dd->caps.has_authenc = 1;
@@ -2515,13 +2307,11 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
 		break;
 	case 0x200:
 		dd->caps.has_dualbuff = 1;
-		dd->caps.has_cfb64 = 1;
 		dd->caps.has_gcm = 1;
 		dd->caps.max_burst_size = 4;
 		break;
 	case 0x130:
 		dd->caps.has_dualbuff = 1;
-		dd->caps.has_cfb64 = 1;
 		dd->caps.max_burst_size = 4;
 		break;
 	case 0x120:
drivers/crypto/atmel-tdes.c +6 -199

280 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#110 lore raw

PATCH 110/508 crypto: atmel - Use unregister_{aeads,ahashes,skciphers}

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thorsten Blum <[email protected]>

[ Upstream commit 2ffc1ef4e826f0c3274f9ff5eb42bc70a5571afd ]

Replace multiple for loops with calls to crypto_unregister_aeads(), crypto_unregister_ahashes(), and crypto_unregister_skciphers().

Remove the definition of atmel_tdes_unregister_algs() because it is equivalent to calling crypto_unregister_skciphers() directly, and the function parameter 'struct atmel_tdes_dev *' is unused anyway.

Stable-dep-of: 57a13941c0bb ("crypto: atmel-aes - guard unregister on error in atmel_aes_register_algs")

---
 drivers/crypto/atmel-aes.c  | 17 ++++++-----------
 drivers/crypto/atmel-sha.c  | 27 ++++++++++-----------------
 drivers/crypto/atmel-tdes.c | 25 ++++++-------------------
 3 files changed, 22 insertions(+), 47 deletions(-)
drivers/crypto/atmel-aes.c +6 -11
index f023f27468c0d..9bd18825e1bf2 100644
@@ -2200,12 +2200,10 @@ static irqreturn_t atmel_aes_irq(int irq, void *dev_id)
 
 static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 {
-	int i;
-
 #if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	if (dd->caps.has_authenc)
-		for (i = 0; i < ARRAY_SIZE(aes_authenc_algs); i++)
-			crypto_unregister_aead(&aes_authenc_algs[i]);
+		crypto_unregister_aeads(aes_authenc_algs,
+					ARRAY_SIZE(aes_authenc_algs));
 #endif
 
 	if (dd->caps.has_xts)
@@ -2214,8 +2212,7 @@ static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
 	if (dd->caps.has_gcm)
 		crypto_unregister_aead(&aes_gcm_alg);
 
-	for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
-		crypto_unregister_skcipher(&aes_algs[i]);
+	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
 }
 
 static void atmel_aes_crypto_alg_init(struct crypto_alg *alg)
@@ -2228,7 +2225,7 @@ static void atmel_aes_crypto_alg_init(struct crypto_alg *alg)
 
 static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 {
-	int err, i, j;
+	int err, i;
 
 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
 		atmel_aes_crypto_alg_init(&aes_algs[i].base);
@@ -2271,8 +2268,7 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 #if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	/* i = ARRAY_SIZE(aes_authenc_algs); */
 err_aes_authenc_alg:
-	for (j = 0; j < i; j++)
-		crypto_unregister_aead(&aes_authenc_algs[j]);
+	crypto_unregister_aeads(aes_authenc_algs, i);
 	crypto_unregister_skcipher(&aes_xts_alg);
 #endif
 err_aes_xts_alg:
@@ -2280,8 +2276,7 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 err_aes_gcm_alg:
 	i = ARRAY_SIZE(aes_algs);
 err_aes_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_skcipher(&aes_algs[j]);
+	crypto_unregister_skciphers(aes_algs, i);
 
 	return err;
 }
drivers/crypto/atmel-sha.c +10 -17
index 3622120add625..d32fb4e770119 100644
@@ -2418,27 +2418,23 @@ EXPORT_SYMBOL_GPL(atmel_sha_authenc_abort);
 
 static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
 {
-	int i;
-
 	if (dd->caps.has_hmac)
-		for (i = 0; i < ARRAY_SIZE(sha_hmac_algs); i++)
-			crypto_unregister_ahash(&sha_hmac_algs[i]);
+		crypto_unregister_ahashes(sha_hmac_algs,
+					  ARRAY_SIZE(sha_hmac_algs));
 
-	for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++)
-		crypto_unregister_ahash(&sha_1_256_algs[i]);
+	crypto_unregister_ahashes(sha_1_256_algs, ARRAY_SIZE(sha_1_256_algs));
 
 	if (dd->caps.has_sha224)
 		crypto_unregister_ahash(&sha_224_alg);
 
-	if (dd->caps.has_sha_384_512) {
-		for (i = 0; i < ARRAY_SIZE(sha_384_512_algs); i++)
-			crypto_unregister_ahash(&sha_384_512_algs[i]);
-	}
+	if (dd->caps.has_sha_384_512)
+		crypto_unregister_ahashes(sha_384_512_algs,
+					  ARRAY_SIZE(sha_384_512_algs));
 }
 
 static int atmel_sha_register_algs(struct atmel_sha_dev *dd)
 {
-	int err, i, j;
+	int err, i;
 
 	for (i = 0; i < ARRAY_SIZE(sha_1_256_algs); i++) {
 		atmel_sha_alg_init(&sha_1_256_algs[i]);
@@ -2480,18 +2476,15 @@ static int atmel_sha_register_algs(struct atmel_sha_dev *dd)
 
 	/*i = ARRAY_SIZE(sha_hmac_algs);*/
 err_sha_hmac_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_ahash(&sha_hmac_algs[j]);
+	crypto_unregister_ahashes(sha_hmac_algs, i);
 	i = ARRAY_SIZE(sha_384_512_algs);
 err_sha_384_512_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_ahash(&sha_384_512_algs[j]);
+	crypto_unregister_ahashes(sha_384_512_algs, i);
 	crypto_unregister_ahash(&sha_224_alg);
 err_sha_224_algs:
 	i = ARRAY_SIZE(sha_1_256_algs);
 err_sha_1_256_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_ahash(&sha_1_256_algs[j]);
+	crypto_unregister_ahashes(sha_1_256_algs, i);
 
 	return err;
 }
drivers/crypto/atmel-tdes.c +6 -19
index 48888b2ff7936..0bf485f350c8f 100644
@@ -897,38 +897,25 @@ static irqreturn_t atmel_tdes_irq(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
-static void atmel_tdes_unregister_algs(struct atmel_tdes_dev *dd)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(tdes_algs); i++)
-		crypto_unregister_skcipher(&tdes_algs[i]);
-}
-
 static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd)
 {
-	int err, i, j;
+	int err, i;
 
 	for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) {
 		atmel_tdes_skcipher_alg_init(&tdes_algs[i]);
 
 		err = crypto_register_skcipher(&tdes_algs[i]);
-		if (err)
-			goto err_tdes_algs;
+		if (err) {
+			crypto_unregister_skciphers(tdes_algs, i);
+			return err;
+		}
 	}
 
 	return 0;
-
-err_tdes_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_skcipher(&tdes_algs[j]);
-
-	return err;
 }
 
 static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd)
 {
-
 	dd->caps.has_dma = 0;
 
 	/* keep only major version number */
@@ -1061,7 +1048,7 @@ static int atmel_tdes_remove(struct platform_device *pdev)
 	list_del(&tdes_dd->list);
 	spin_unlock(&atmel_tdes.lock);
 
-	atmel_tdes_unregister_algs(tdes_dd);
+	crypto_unregister_skciphers(tdes_algs, ARRAY_SIZE(tdes_algs));
 
 	tasklet_kill(&tdes_dd->done_task);
 	tasklet_kill(&tdes_dd->queue_task);
Signature · 1 line
2.53.0
author maintainer
#111 lore raw

PATCH 111/508 crypto: atmel-aes - guard unregister on error in atmel_aes_register_algs

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thorsten Blum <[email protected]>

[ Upstream commit 57a13941c0bb06ae24e3b34672d7b6f2172b253f ]

Ensure the device supports XTS and GCM with 'has_xts' and 'has_gcm' before unregistering algorithms when XTS or authenc registration fails, which would trigger a WARN in crypto_unregister_alg().

Currently, with the capabilities defined in atmel_aes_get_cap(), this bug cannot happen because all devices that support XTS and authenc also support GCM, but the error handling should still be correct regardless of hardware capabilities.

Fixes d52db5188a87 ("crypto: atmel-aes - add support to the XTS mode")
---
 drivers/crypto/atmel-aes.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/crypto/atmel-aes.c +4 -2
index 9bd18825e1bf2..3402cf3f017f1 100644
@@ -2269,10 +2269,12 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 	/* i = ARRAY_SIZE(aes_authenc_algs); */
 err_aes_authenc_alg:
 	crypto_unregister_aeads(aes_authenc_algs, i);
-	crypto_unregister_skcipher(&aes_xts_alg);
+	if (dd->caps.has_xts)
+		crypto_unregister_skcipher(&aes_xts_alg);
 #endif
 err_aes_xts_alg:
-	crypto_unregister_aead(&aes_gcm_alg);
+	if (dd->caps.has_gcm)
+		crypto_unregister_aead(&aes_gcm_alg);
 err_aes_gcm_alg:
 	i = ARRAY_SIZE(aes_algs);
 err_aes_algs:
Signature · 1 line
2.53.0