This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.77-rc1... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.15.77-rc1
Kuniyuki Iwashima kuniyu@amazon.com tcp/udp: Fix memory leak in ipv6_renew_options().
Lukas Wunner lukas@wunner.de serial: Deassert Transmit Enable on probe in driver-specific way
Lino Sanfilippo LinoSanfilippo@gmx.de serial: core: move RS485 configuration tasks from drivers into core
Biju Das biju.das.jz@bp.renesas.com can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global FIFO receive
Biju Das biju.das.jz@bp.renesas.com can: rcar_canfd: fix channel specific IRQ handling for RZ/G2L
Yu Kuai yukuai3@huawei.com scsi: sd: Revert "scsi: sd: Remove a local variable"
D Scott Phillips scott@os.amperecomputing.com arm64: Add AMPERE1 to the Spectre-BHB affected list
Vladimir Oltean vladimir.oltean@nxp.com net: enetc: survive memory pressure without crashing
Eric Dumazet edumazet@google.com kcm: do not sense pfmemalloc status in kcm_sendpage()
Eric Dumazet edumazet@google.com net: do not sense pfmemalloc status in skb_append_pagefrags()
Suresh Devarakonda ramad@nvidia.com net/mlx5: Fix crash during sync firmware reset
Roy Novich royno@nvidia.com net/mlx5: Update fw fatal reporter state on PCI handlers successful recover
Saeed Mahameed saeedm@nvidia.com net/mlx5: Print more info on pci error handlers
Tariq Toukan tariqt@nvidia.com net/mlx5: Fix possible use-after-free in async command interface
Aya Levin ayal@nvidia.com net/mlx5e: Extend SKB room check to include PTP-SQ
Hyong Youb Kim hyonkim@cisco.com net/mlx5e: Do not increment ESN when updating IPsec ESN state
Zhengchao Shao shaozhengchao@huawei.com netdevsim: remove dir in nsim_dev_debugfs_init() when creating ports dir failed
Rafał Miłecki rafal@milecki.pl net: broadcom: bcm4908_enet: update TX stats after actual transmission
Colin Ian King colin.i.king@gmail.com net: broadcom: bcm4908enet: remove redundant variable bytes
Nicolas Dichtel nicolas.dichtel@6wind.com nh: fix scope used to find saddr when adding non gw nh
Florian Fainelli f.fainelli@gmail.com net: bcmsysport: Indicate MAC is in charge of PHY PM
Yang Yingliang yangyingliang@huawei.com net: ehea: fix possible memory leak in ehea_register_port()
Aaron Conole aconole@redhat.com openvswitch: switch from WARN to pr_warn
Takashi Iwai tiwai@suse.de ALSA: aoa: Fix I2S device accounting
Yang Yingliang yangyingliang@huawei.com ALSA: aoa: i2sbus: fix possible memory leak in i2sbus_add_dev()
Kunihiko Hayashi hayashi.kunihiko@socionext.com net: ethernet: ave: Fix MAC to be in charge of PHY PM
Juergen Borleis jbe@pengutronix.de net: fec: limit register access on i.MX6UL
Shang XiaoJing shangxiaojing@huawei.com perf vendor events arm64: Fix incorrect Hisi hip08 L3 metrics
Sudeep Holla sudeep.holla@arm.com PM: domains: Fix handling of unavailable/disabled idle states
Yang Yingliang yangyingliang@huawei.com net: ksz884x: fix missing pci_disable_device() on error in pcidev_init()
Slawomir Laba slawomirx.laba@intel.com i40e: Fix flow-type by setting GL_HASH_INSET registers
Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com i40e: Fix VF hang when reset is triggered on another VF
Slawomir Laba slawomirx.laba@intel.com i40e: Fix ethtool rx-flow-hash setting for X722
Eric Dumazet edumazet@google.com ipv6: ensure sane device mtu in tunnels
Kajol Jain kjain@linux.ibm.com perf vendor events power10: Fix hv-24x7 metric events
Hans Verkuil hverkuil-cisco@xs4all.nl media: vivid: set num_in/outputs to 0 if not supported
Hans Verkuil hverkuil-cisco@xs4all.nl media: videodev2.h: V4L2_DV_BT_BLANKING_HEIGHT should check 'interlaced'
Hans Verkuil hverkuil-cisco@xs4all.nl media: v4l2-dv-timings: add sanity checks for blanking values
Hans Verkuil hverkuil-cisco@xs4all.nl media: vivid: dev->bitmap_cap wasn't freed in all cases
Hans Verkuil hverkuil-cisco@xs4all.nl media: vivid: s_fbuf: add more sanity checks
Mario Limonciello mario.limonciello@amd.com PM: hibernate: Allow hybrid sleep to work with s2idle
Dongliang Mu dzm91@hust.edu.cn can: mcp251x: mcp251x_can_probe(): add missing unregister_candev() in error path
Dongliang Mu dzm91@hust.edu.cn can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error path
Rafael Mendonca rafaelmendsr@gmail.com drm/amdkfd: Fix memory leak in kfd_mem_dmamap_userptr()
Jakub Kicinski kuba@kernel.org net-memcg: avoid stalls when under memory pressure
Neal Cardwell ncardwell@google.com tcp: fix indefinite deferral of RTO with SACK reneging
Lu Wei luwei32@huawei.com tcp: fix a signed-integer-overflow bug in tcp_add_backlog()
Eric Dumazet edumazet@google.com tcp: minor optimization in tcp_add_backlog()
Zhang Changzhong zhangchangzhong@huawei.com net: lantiq_etop: don't free skb when returning NETDEV_TX_BUSY
Zhengchao Shao shaozhengchao@huawei.com net: fix UAF issue in nfqnl_nf_hook_drop() when ops_init() failed
Eric Dumazet edumazet@google.com kcm: annotate data-races around kcm->rx_wait
Eric Dumazet edumazet@google.com kcm: annotate data-races around kcm->rx_psock
Íñigo Huguet ihuguet@redhat.com atlantic: fix deadlock at aq_nic_stop
Ankit Nautiyal ankit.k.nautiyal@intel.com drm/i915/dp: Reset frl trained flag before restarting FRL training
Raju Rangoju Raju.Rangoju@amd.com amd-xgbe: add the bit rate quirk for Molex cables
Raju Rangoju Raju.Rangoju@amd.com amd-xgbe: fix the SFP compliance codes check for DAC cables
Chen Zhongjin chenzhongjin@huawei.com x86/unwind/orc: Fix unreliable stack dump with gcov
Shang XiaoJing shangxiaojing@huawei.com nfc: virtual_ncidev: Fix memory leak in virtual_nci_send()
Sergiu Moga sergiu.moga@microchip.com net: macb: Specify PHY PM management done by MAC
Zhengchao Shao shaozhengchao@huawei.com net: hinic: fix the issue of double release MBOX callback of VF
Zhengchao Shao shaozhengchao@huawei.com net: hinic: fix the issue of CMDQ memory leaks
Zhengchao Shao shaozhengchao@huawei.com net: hinic: fix memory leak when reading function table
Zhengchao Shao shaozhengchao@huawei.com net: hinic: fix incorrect assignment issue in hinic_set_interrupt_cfg()
Yang Yingliang yangyingliang@huawei.com net: netsec: fix error handling in netsec_register_mdio()
Xin Long lucien.xin@gmail.com tipc: fix a null-ptr-deref in tipc_topsrv_accept
Maxim Levitsky mlevitsk@redhat.com perf/x86/intel/lbr: Use setup_clear_cpu_cap() instead of clear_cpu_cap()
Yang Yingliang yangyingliang@huawei.com ALSA: ac97: fix possible memory leak in snd_ac97_dev_register()
Srinivasa Rao Mandadapu quic_srivasam@quicinc.com ASoC: qcom: lpass-cpu: Mark HDMI TX parity register as volatile
Yang Yingliang yangyingliang@huawei.com mtd: rawnand: intel: Add missing of_node_put() in ebu_nand_probe()
Randy Dunlap rdunlap@infradead.org arc: iounmap() arg is volatile
Lin Shengwang linshengwang1@huawei.com sched/core: Fix comparison in sched_group_cookie_match()
Peter Zijlstra peterz@infradead.org perf: Fix missing SIGTRAPs
Srinivasa Rao Mandadapu quic_srivasam@quicinc.com ASoC: qcom: lpass-cpu: mark HDMI TX registers as volatile
Gavin Shan gshan@redhat.com KVM: selftests: Fix number of pages for memory slot in memslot_modification_stress_test
Nathan Huckleberry nhuck@google.com drm/msm: Fix return type of mdp4_lvds_connector_mode_valid
Dan Carpenter dan.carpenter@oracle.com media: atomisp: prevent integer overflow in sh_css_set_black_frame()
Alexander Stein alexander.stein@ew.tq-group.com media: v4l2: Fix v4l2_i2c_subdev_set_name function documentation
Wei Yongjun weiyongjun1@huawei.com net: ieee802154: fix error return code in dgram_bind()
Xin Long lucien.xin@gmail.com ethtool: eeprom: fix null-deref on genl_info in dump
Christian Löhle CLoehle@hyperstone.com mmc: block: Remove error check of hw_reset on reset
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: SLI path split: Refactor lpfc_iocbq"
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: SLI path split: Refactor fast and slow paths to native SLI4"
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: SLI path split: Refactor SCSI paths"
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: Fix locking for lpfc_sli_iocbq_lookup()"
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: Fix element offset in __lpfc_sli_release_iocbq_s4()"
James Smart jsmart2021@gmail.com Revert "scsi: lpfc: Resolve some cleanup issues following SLI path refactoring"
Heiko Carstens hca@linux.ibm.com s390/pci: add missing EX_TABLE entries to __pcistg_mio_inuser()/__pcilg_mio_inuser()
Heiko Carstens hca@linux.ibm.com s390/futex: add missing EX_TABLE entry to __futex_atomic_op()
Adrian Hunter adrian.hunter@intel.com perf auxtrace: Fix address filter symbol name match for modules
Pavel Kozlov pavel.kozlov@synopsys.com ARC: mm: fix leakage of memory allocated for PTE
Siarhei Volkau lis8215@gmail.com pinctrl: Ingenic: JZ4755 bug fixes
Christian A. Ehrhardt lk@c--e.de kernfs: fix use-after-free in __kernfs_remove
William Breathitt Gray william.gray@linaro.org counter: microchip-tcb-capture: Handle Signal1 read and Synapse
Sascha Hauer s.hauer@pengutronix.de mmc: sdhci-esdhc-imx: Propagate ESDHC_FLAG_HS400* only on 8bit bus
Patrick Thompson ptf@google.com mmc: sdhci-pci-core: Disable ES for ASUS BIOS on Jasper Lake
Matthew Ma mahongwei@zeku.com mmc: core: Fix kernel panic when remove non-standard SDIO card
Brian Norris briannorris@chromium.org mmc: sdhci_am654: 'select', not 'depends' REGMAP_MMIO
James Clark james.clark@arm.com coresight: cti: Fix hang in cti_disable_hw()
Johan Hovold johan+linaro@kernel.org drm/msm/dp: fix IRQ lifetime
Johan Hovold johan+linaro@kernel.org drm/msm/hdmi: fix memory corruption with too many bridges
Johan Hovold johan+linaro@kernel.org drm/msm/dsi: fix memory corruption with too many bridges
Prike Liang Prike.Liang@amd.com drm/amdgpu: disallow gfxoff until GC IP blocks complete s2idle resume
Manish Rangankar mrangankar@marvell.com scsi: qla2xxx: Use transport-defined speed mask for supported_speeds
Miquel Raynal miquel.raynal@bootlin.com mac802154: Fix LQI recording
Bernd Edlinger bernd.edlinger@hotmail.de exec: Copy oldsighand->action under spin-lock
Li Zetao lizetao1@huawei.com fs/binfmt_elf: Fix memory leak in load_elf_binary()
Rafael J. Wysocki rafael.j.wysocki@intel.com cpufreq: intel_pstate: hybrid: Use known scaling factor for P-cores
Rafael J. Wysocki rafael.j.wysocki@intel.com cpufreq: intel_pstate: Read all MSRs on the target CPU
Hyunwoo Kim imv4bel@gmail.com fbdev: smscufx: Fix several use-after-free bugs
Matti Vaittinen mazziesaccount@gmail.com iio: adxl372: Fix unsafe buffer attributes
Cosmin Tanislav cosmin.tanislav@analog.com iio: temperature: ltc2983: allocate iio channels once
Shreeya Patel shreeya.patel@collabora.com iio: light: tsl2583: Fix module unloading
Matti Vaittinen mazziesaccount@gmail.com tools: iio: iio_utils: fix digit calculation
Mathias Nyman mathias.nyman@linux.intel.com xhci: Remove device endpoints from bandwidth list when freeing the device
Mario Limonciello mario.limonciello@amd.com xhci-pci: Set runtime PM as default policy on all xHC 1.2 or later devices
Mathias Nyman mathias.nyman@linux.intel.com xhci: Add quirk to reset host back to default state at shutdown
Tony O'Brien tony.obrien@alliedtelesis.co.nz mtd: rawnand: marvell: Use correct logic for nand-keep-config
Jens Glathe jens.glathe@oldschoolsolutions.biz usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96 controller
Justin Chen justinpopo6@gmail.com usb: bdc: change state when port disconnected
Thinh Nguyen Thinh.Nguyen@synopsys.com usb: dwc3: gadget: Don't set IMI for no_interrupt
Thinh Nguyen Thinh.Nguyen@synopsys.com usb: dwc3: gadget: Stop processing more requests on IMI
Jeff Vanhoof qjv001@motorola.com usb: gadget: uvc: fix sg handling during video encode
Dan Vacura w36195@motorola.com usb: gadget: uvc: fix sg handling in error case
Hannu Hartikainen hannu@hrtk.in USB: add RESET_RESUME quirk for NVIDIA Jetson devices in RCM
Jason A. Donenfeld Jason@zx2c4.com ALSA: rme9652: use explicitly signed char
Jason A. Donenfeld Jason@zx2c4.com ALSA: au88x0: use explicitly signed char
Takashi Iwai tiwai@suse.de ALSA: usb-audio: Add quirks for M-Audio Fast Track C400/600
Steven Rostedt (Google) rostedt@goodmis.org ALSA: Use del_timer_sync() before freeing timer
Anssi Hannula anssi.hannula@bitwise.fi can: kvaser_usb: Fix possible completions during init_completion
Yang Yingliang yangyingliang@huawei.com can: j1939: transport: j1939_session_skb_drop_old(): spin_unlock_irqrestore() before kfree_skb()
Scott Mayhew smayhew@redhat.com NFSv4: Add an fattr allocation to _nfs4_discover_trunking()
Benjamin Coddington bcodding@redhat.com NFSv4: Fix free of uninitialized nfs4_label on referral lookup.
-------------
Diffstat:
Makefile | 4 +- arch/arc/include/asm/io.h | 2 +- arch/arc/include/asm/pgtable-levels.h | 2 +- arch/arc/mm/ioremap.c | 2 +- arch/arm64/include/asm/cputype.h | 4 + arch/arm64/kernel/proton-pack.c | 6 + arch/s390/include/asm/futex.h | 3 +- arch/s390/pci/pci_mmio.c | 8 +- arch/x86/events/intel/lbr.c | 2 +- arch/x86/kernel/unwind_orc.c | 2 +- drivers/base/power/domain.c | 4 + drivers/counter/microchip-tcb-capture.c | 18 +- drivers/cpufreq/intel_pstate.c | 133 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 + drivers/gpu/drm/i915/display/intel_dp.c | 2 + .../gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c | 5 +- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.c | 6 + drivers/gpu/drm/msm/hdmi/hdmi.c | 5 + drivers/hwtracing/coresight/coresight-cti-core.c | 5 - drivers/iio/accel/adxl372.c | 23 +- drivers/iio/light/tsl2583.c | 2 +- drivers/iio/temperature/ltc2983.c | 13 +- drivers/media/test-drivers/vivid/vivid-core.c | 38 +- drivers/media/test-drivers/vivid/vivid-core.h | 2 + drivers/media/test-drivers/vivid/vivid-vid-cap.c | 27 +- drivers/media/v4l2-core/v4l2-dv-timings.c | 14 + drivers/mmc/core/block.c | 44 +- drivers/mmc/core/sdio_bus.c | 3 +- drivers/mmc/host/Kconfig | 3 +- drivers/mmc/host/sdhci-esdhc-imx.c | 14 +- drivers/mmc/host/sdhci-pci-core.c | 14 +- drivers/mtd/nand/raw/intel-nand-controller.c | 19 +- drivers/mtd/nand/raw/marvell_nand.c | 2 +- drivers/net/can/mscan/mpc5xxx_can.c | 8 +- drivers/net/can/rcar/rcar_canfd.c | 24 +- drivers/net/can/spi/mcp251x.c | 5 +- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 4 +- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 +- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 17 +- drivers/net/ethernet/aquantia/atlantic/aq_macsec.c | 96 ++- drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 2 + drivers/net/ethernet/broadcom/bcm4908_enet.c | 10 +- drivers/net/ethernet/broadcom/bcmsysport.c | 3 + drivers/net/ethernet/cadence/macb_main.c | 1 + drivers/net/ethernet/freescale/enetc/enetc.c | 5 + drivers/net/ethernet/freescale/fec_main.c | 46 +- drivers/net/ethernet/huawei/hinic/hinic_debugfs.c | 18 +- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 2 +- drivers/net/ethernet/huawei/hinic/hinic_sriov.c | 1 - drivers/net/ethernet/ibm/ehea/ehea_main.c | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 100 ++- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 43 +- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 + drivers/net/ethernet/lantiq_etop.c | 1 - drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 10 +- drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 9 + drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 6 + .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 - drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 6 + drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c | 6 +- drivers/net/ethernet/mellanox/mlx5/core/main.c | 55 +- drivers/net/ethernet/micrel/ksz884x.c | 2 +- drivers/net/ethernet/socionext/netsec.c | 2 + drivers/net/ethernet/socionext/sni_ave.c | 6 + drivers/net/netdevsim/dev.c | 11 +- drivers/nfc/virtual_ncidev.c | 3 + drivers/pinctrl/pinctrl-ingenic.c | 4 +- drivers/scsi/lpfc/lpfc.h | 40 - drivers/scsi/lpfc/lpfc_bsg.c | 50 +- drivers/scsi/lpfc/lpfc_crtn.h | 3 +- drivers/scsi/lpfc/lpfc_ct.c | 8 +- drivers/scsi/lpfc/lpfc_els.c | 139 ++-- drivers/scsi/lpfc/lpfc_hw4.h | 7 - drivers/scsi/lpfc/lpfc_init.c | 13 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 4 +- drivers/scsi/lpfc/lpfc_nvme.c | 34 +- drivers/scsi/lpfc/lpfc_nvme.h | 6 +- drivers/scsi/lpfc/lpfc_nvmet.c | 83 +- drivers/scsi/lpfc/lpfc_scsi.c | 441 ++++++----- drivers/scsi/lpfc/lpfc_sli.c | 876 ++++++++++++--------- drivers/scsi/lpfc/lpfc_sli.h | 26 +- drivers/scsi/qla2xxx/qla_attr.c | 28 +- drivers/scsi/sd.c | 3 +- drivers/staging/media/atomisp/pci/sh_css_params.c | 4 +- drivers/tty/serial/8250/8250_omap.c | 3 + drivers/tty/serial/8250/8250_pci.c | 9 +- drivers/tty/serial/8250/8250_port.c | 12 +- drivers/tty/serial/fsl_lpuart.c | 8 +- drivers/tty/serial/imx.c | 8 +- drivers/tty/serial/serial_core.c | 61 +- drivers/usb/core/quirks.c | 9 + drivers/usb/dwc3/gadget.c | 8 +- drivers/usb/gadget/function/uvc_queue.c | 8 +- drivers/usb/gadget/function/uvc_video.c | 22 +- drivers/usb/gadget/udc/bdc/bdc_udc.c | 1 + drivers/usb/host/xhci-mem.c | 20 +- drivers/usb/host/xhci-pci.c | 44 +- drivers/usb/host/xhci.c | 10 +- drivers/usb/host/xhci.h | 1 + drivers/video/fbdev/smscufx.c | 55 +- fs/binfmt_elf.c | 3 +- fs/exec.c | 4 +- fs/kernfs/dir.c | 5 +- fs/nfs/nfs4namespace.c | 9 +- fs/nfs/nfs4proc.c | 34 +- fs/nfs/nfs4state.c | 9 +- fs/nfs/nfs4xdr.c | 4 +- include/linux/mlx5/driver.h | 2 +- include/linux/nfs_xdr.h | 2 +- include/linux/perf_event.h | 19 +- include/media/v4l2-common.h | 3 +- include/net/sock.h | 2 +- include/uapi/linux/videodev2.h | 3 +- kernel/events/core.c | 153 +++- kernel/events/ring_buffer.c | 2 +- kernel/power/hibernate.c | 2 +- kernel/sched/sched.h | 18 +- net/can/j1939/transport.c | 4 +- net/core/net_namespace.c | 7 + net/core/skbuff.c | 2 +- net/ethtool/eeprom.c | 2 +- net/ieee802154/socket.c | 4 +- net/ipv4/nexthop.c | 2 +- net/ipv4/tcp_input.c | 3 +- net/ipv4/tcp_ipv4.c | 7 +- net/ipv6/ip6_gre.c | 12 +- net/ipv6/ip6_tunnel.c | 11 +- net/ipv6/ipv6_sockglue.c | 7 + net/ipv6/sit.c | 8 +- net/kcm/kcmsock.c | 25 +- net/mac802154/rx.c | 5 +- net/openvswitch/datapath.c | 3 +- net/tipc/topsrv.c | 16 +- sound/aoa/soundbus/i2sbus/core.c | 7 +- sound/pci/ac97/ac97_codec.c | 1 + sound/pci/au88x0/au88x0.h | 6 +- sound/pci/au88x0/au88x0_core.c | 2 +- sound/pci/rme9652/hdsp.c | 26 +- sound/pci/rme9652/rme9652.c | 22 +- sound/soc/qcom/lpass-cpu.c | 10 + sound/synth/emux/emux.c | 7 +- sound/usb/implicit.c | 2 + tools/iio/iio_utils.c | 4 + .../arch/arm64/hisilicon/hip08/metrics.json | 6 +- .../arch/powerpc/power10/nest_metrics.json | 72 +- tools/perf/util/auxtrace.c | 10 +- .../kvm/memslot_modification_stress_test.c | 2 +- 151 files changed, 2130 insertions(+), 1459 deletions(-)
From: Benjamin Coddington bcodding@redhat.com
commit c3ed222745d9ad7b69299b349a64ba533c64a34f upstream.
Send along the already-allocated fattr along with nfs4_fs_locations, and drop the memcpy of fattr. We end up growing two more allocations, but this fixes up a crash as:
PID: 790 TASK: ffff88811b43c000 CPU: 0 COMMAND: "ls" #0 [ffffc90000857920] panic at ffffffff81b9bfde #1 [ffffc900008579c0] do_trap at ffffffff81023a9b #2 [ffffc90000857a10] do_error_trap at ffffffff81023b78 #3 [ffffc90000857a58] exc_stack_segment at ffffffff81be1f45 #4 [ffffc90000857a80] asm_exc_stack_segment at ffffffff81c009de #5 [ffffc90000857b08] nfs_lookup at ffffffffa0302322 [nfs] #6 [ffffc90000857b70] __lookup_slow at ffffffff813a4a5f #7 [ffffc90000857c60] walk_component at ffffffff813a86c4 #8 [ffffc90000857cb8] path_lookupat at ffffffff813a9553 #9 [ffffc90000857cf0] filename_lookup at ffffffff813ab86b
Suggested-by: Trond Myklebust trondmy@hammerspace.com Fixes: 9558a007dbc3 ("NFS: Remove the label from the nfs4_lookup_res struct") Signed-off-by: Benjamin Coddington bcodding@redhat.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/nfs/nfs4namespace.c | 9 +++++++-- fs/nfs/nfs4proc.c | 15 +++++++-------- fs/nfs/nfs4state.c | 9 ++++++++- fs/nfs/nfs4xdr.c | 4 ++-- include/linux/nfs_xdr.h | 2 +- 5 files changed, 25 insertions(+), 14 deletions(-)
--- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -417,6 +417,9 @@ static int nfs_do_refmount(struct fs_con fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); if (!fs_locations) goto out_free; + fs_locations->fattr = nfs_alloc_fattr(); + if (!fs_locations->fattr) + goto out_free_2;
/* Get locations */ dentry = ctx->clone_data.dentry; @@ -427,14 +430,16 @@ static int nfs_do_refmount(struct fs_con err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page); dput(parent); if (err != 0) - goto out_free_2; + goto out_free_3;
err = -ENOENT; if (fs_locations->nlocations <= 0 || fs_locations->fs_path.ncomponents <= 0) - goto out_free_2; + goto out_free_3;
err = nfs_follow_referral(fc, fs_locations); +out_free_3: + kfree(fs_locations->fattr); out_free_2: kfree(fs_locations); out_free: --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4213,6 +4213,8 @@ static int nfs4_get_referral(struct rpc_ if (locations == NULL) goto out;
+ locations->fattr = fattr; + status = nfs4_proc_fs_locations(client, dir, name, locations, page); if (status != 0) goto out; @@ -4222,17 +4224,14 @@ static int nfs4_get_referral(struct rpc_ * referral. Cause us to drop into the exception handler, which * will kick off migration recovery. */ - if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { + if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &fattr->fsid)) { dprintk("%s: server did not return a different fsid for" " a referral at %s\n", __func__, name->name); status = -NFS4ERR_MOVED; goto out; } /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ - nfs_fixup_referral_attributes(&locations->fattr); - - /* replace the lookup nfs_fattr with the locations nfs_fattr */ - memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); + nfs_fixup_referral_attributes(fattr); memset(fhandle, 0, sizeof(struct nfs_fh)); out: if (page) @@ -7917,7 +7916,7 @@ static int _nfs4_proc_fs_locations(struc else bitmask[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
- nfs_fattr_init(&fs_locations->fattr); + nfs_fattr_init(fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0); @@ -7982,7 +7981,7 @@ static int _nfs40_proc_get_locations(str unsigned long now = jiffies; int status;
- nfs_fattr_init(&locations->fattr); + nfs_fattr_init(locations->fattr); locations->server = server; locations->nlocations = 0;
@@ -8035,7 +8034,7 @@ static int _nfs41_proc_get_locations(str }; int status;
- nfs_fattr_init(&locations->fattr); + nfs_fattr_init(locations->fattr); locations->server = server; locations->nlocations = 0;
--- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -2096,6 +2096,11 @@ static int nfs4_try_migration(struct nfs dprintk("<-- %s: no memory\n", __func__); goto out; } + locations->fattr = nfs_alloc_fattr(); + if (locations->fattr == NULL) { + dprintk("<-- %s: no memory\n", __func__); + goto out; + }
inode = d_inode(server->super->s_root); result = nfs4_proc_get_locations(server, NFS_FH(inode), locations, @@ -2110,7 +2115,7 @@ static int nfs4_try_migration(struct nfs if (!locations->nlocations) goto out;
- if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { + if (!(locations->fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { dprintk("<-- %s: No fs_locations data, migration skipped\n", __func__); goto out; @@ -2135,6 +2140,8 @@ static int nfs4_try_migration(struct nfs out: if (page != NULL) __free_page(page); + if (locations != NULL) + kfree(locations->fattr); kfree(locations); if (result) { pr_err("NFS: migration recovery failed (server %s)\n", --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -7028,7 +7028,7 @@ static int nfs4_xdr_dec_fs_locations(str if (res->migration) { xdr_enter_page(xdr, PAGE_SIZE); status = decode_getfattr_generic(xdr, - &res->fs_locations->fattr, + res->fs_locations->fattr, NULL, res->fs_locations, NULL, res->fs_locations->server); if (status) @@ -7041,7 +7041,7 @@ static int nfs4_xdr_dec_fs_locations(str goto out; xdr_enter_page(xdr, PAGE_SIZE); status = decode_getfattr_generic(xdr, - &res->fs_locations->fattr, + res->fs_locations->fattr, NULL, res->fs_locations, NULL, res->fs_locations->server); } --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1219,7 +1219,7 @@ struct nfs4_fs_location {
#define NFS4_FS_LOCATIONS_MAXENTRIES 10 struct nfs4_fs_locations { - struct nfs_fattr fattr; + struct nfs_fattr *fattr; const struct nfs_server *server; struct nfs4_pathname fs_path; int nlocations;
From: Scott Mayhew smayhew@redhat.com
commit 4f40a5b5544618b096d1611a18219dd91fd57f80 upstream.
This was missed in c3ed222745d9 ("NFSv4: Fix free of uninitialized nfs4_label on referral lookup.") and causes a panic when mounting with '-o trunkdiscovery':
PID: 1604 TASK: ffff93dac3520000 CPU: 3 COMMAND: "mount.nfs" #0 [ffffb79140f738f8] machine_kexec at ffffffffaec64bee #1 [ffffb79140f73950] __crash_kexec at ffffffffaeda67fd #2 [ffffb79140f73a18] crash_kexec at ffffffffaeda76ed #3 [ffffb79140f73a30] oops_end at ffffffffaec2658d #4 [ffffb79140f73a50] general_protection at ffffffffaf60111e [exception RIP: nfs_fattr_init+0x5] RIP: ffffffffc0c18265 RSP: ffffb79140f73b08 RFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff93dac304a800 RCX: 0000000000000000 RDX: ffffb79140f73bb0 RSI: ffff93dadc8cbb40 RDI: d03ee11cfaf6bd50 RBP: ffffb79140f73be8 R8: ffffffffc0691560 R9: 0000000000000006 R10: ffff93db3ffd3df8 R11: 0000000000000000 R12: ffff93dac4040000 R13: ffff93dac2848e00 R14: ffffb79140f73b60 R15: ffffb79140f73b30 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #5 [ffffb79140f73b08] _nfs41_proc_get_locations at ffffffffc0c73d53 [nfsv4] #6 [ffffb79140f73bf0] nfs4_proc_get_locations at ffffffffc0c83e90 [nfsv4] #7 [ffffb79140f73c60] nfs4_discover_trunking at ffffffffc0c83fb7 [nfsv4] #8 [ffffb79140f73cd8] nfs_probe_fsinfo at ffffffffc0c0f95f [nfs] #9 [ffffb79140f73da0] nfs_probe_server at ffffffffc0c1026a [nfs] RIP: 00007f6254fce26e RSP: 00007ffc69496ac8 RFLAGS: 00000246 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f6254fce26e RDX: 00005600220a82a0 RSI: 00005600220a64d0 RDI: 00005600220a6520 RBP: 00007ffc69496c50 R8: 00005600220a8710 R9: 003035322e323231 R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffc69496c50 R13: 00005600220a8440 R14: 0000000000000010 R15: 0000560020650ef9 ORIG_RAX: 00000000000000a5 CS: 0033 SS: 002b
Fixes: c3ed222745d9 ("NFSv4: Fix free of uninitialized nfs4_label on referral lookup.") Signed-off-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Anna Schumaker Anna.Schumaker@Netapp.com Signed-off-by: Trond Myklebust trond.myklebust@hammerspace.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/nfs/nfs4proc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
--- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3981,18 +3981,23 @@ static int _nfs4_discover_trunking(struc }
page = alloc_page(GFP_KERNEL); + if (!page) + return -ENOMEM; locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); - if (page == NULL || locations == NULL) - goto out; + if (!locations) + goto out_free; + locations->fattr = nfs_alloc_fattr(); + if (!locations->fattr) + goto out_free_2;
status = nfs4_proc_get_locations(server, fhandle, locations, page, cred); - if (status) - goto out; -out: - if (page) - __free_page(page); + + kfree(locations->fattr); +out_free_2: kfree(locations); +out_free: + __free_page(page); return status; }
From: Yang Yingliang yangyingliang@huawei.com
commit c3c06c61890da80494bb196f75d89b791adda87f upstream.
It is not allowed to call kfree_skb() from hardware interrupt context or with interrupts being disabled. The skb is unlinked from the queue, so it can be freed after spin_unlock_irqrestore().
Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Acked-by: Oleksij Rempel o.rempel@pengutronix.de Link: https://lore.kernel.org/all/20221027091237.2290111-1-yangyingliang@huawei.co... Cc: stable@vger.kernel.org [mkl: adjust subject] Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/can/j1939/transport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -342,10 +342,12 @@ static void j1939_session_skb_drop_old(s __skb_unlink(do_skb, &session->skb_queue); /* drop ref taken in j1939_session_skb_queue() */ skb_unref(do_skb); + spin_unlock_irqrestore(&session->skb_queue.lock, flags);
kfree_skb(do_skb); + } else { + spin_unlock_irqrestore(&session->skb_queue.lock, flags); } - spin_unlock_irqrestore(&session->skb_queue.lock, flags); }
void j1939_session_skb_queue(struct j1939_session *session,
From: Anssi Hannula anssi.hannula@bitwise.fi
commit 2871edb32f4622c3a25ce4b3977bad9050b91974 upstream.
kvaser_usb uses completions to signal when a response event is received for outgoing commands.
However, it uses init_completion() to reinitialize the start_comp and stop_comp completions before sending the start/stop commands.
In case the device sends the corresponding response just before the actual command is sent, complete() may be called concurrently with init_completion() which is not safe.
This might be triggerable even with a properly functioning device by stopping the interface (CMD_STOP_CHIP) just after it goes bus-off (which also causes the driver to send CMD_STOP_CHIP when restart-ms is off), but that was not tested.
Fix the issue by using reinit_completion() instead.
Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") Tested-by: Jimmy Assarsson extja@kvaser.com Signed-off-by: Anssi Hannula anssi.hannula@bitwise.fi Signed-off-by: Jimmy Assarsson extja@kvaser.com Link: https://lore.kernel.org/all/20221010185237.319219-2-extja@kvaser.com Cc: stable@vger.kernel.org Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 4 ++-- drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1873,7 +1873,7 @@ static int kvaser_usb_hydra_start_chip(s { int err;
- init_completion(&priv->start_comp); + reinit_completion(&priv->start_comp);
err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_START_CHIP_REQ, priv->channel); @@ -1891,7 +1891,7 @@ static int kvaser_usb_hydra_stop_chip(st { int err;
- init_completion(&priv->stop_comp); + reinit_completion(&priv->stop_comp);
/* Make sure we do not report invalid BUS_OFF from CMD_CHIP_STATE_EVENT * see comment in kvaser_usb_hydra_update_state() --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -1324,7 +1324,7 @@ static int kvaser_usb_leaf_start_chip(st { int err;
- init_completion(&priv->start_comp); + reinit_completion(&priv->start_comp);
err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP, priv->channel); @@ -1342,7 +1342,7 @@ static int kvaser_usb_leaf_stop_chip(str { int err;
- init_completion(&priv->stop_comp); + reinit_completion(&priv->stop_comp);
err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, priv->channel);
From: Steven Rostedt (Google) rostedt@goodmis.org
commit f0a868788fcbf63cdab51f5adcf73b271ede8164 upstream.
The current code for freeing the emux timer is extremely dangerous:
CPU0 CPU1 ---- ---- snd_emux_timer_callback() snd_emux_free() spin_lock(&emu->voice_lock) del_timer(&emu->tlist); <-- returns immediately spin_unlock(&emu->voice_lock); [..] kfree(emu);
spin_lock(&emu->voice_lock);
[BOOM!]
Instead just use del_timer_sync() which will wait for the timer to finish before continuing. No need to check if the timer is active or not when doing so.
This doesn't fix the race of a possible re-arming of the timer, but at least it won't use the data that has just been freed.
[ Fixed unused variable warning by tiwai ]
Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Steven Rostedt (Google) rostedt@goodmis.org Reviewed-by: Guenter Roeck linux@roeck-us.net Link: https://lore.kernel.org/r/20221026231236.6834b551@gandalf.local.home Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/synth/emux/emux.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
--- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -126,15 +126,10 @@ EXPORT_SYMBOL(snd_emux_register); */ int snd_emux_free(struct snd_emux *emu) { - unsigned long flags; - if (! emu) return -EINVAL;
- spin_lock_irqsave(&emu->voice_lock, flags); - if (emu->timer_active) - del_timer(&emu->tlist); - spin_unlock_irqrestore(&emu->voice_lock, flags); + del_timer_sync(&emu->tlist);
snd_emux_proc_free(emu); snd_emux_delete_virmidi(emu);
From: Takashi Iwai tiwai@suse.de
commit 794814529384721ce8f4d34228dc599cc010353d upstream.
M-Audio Fast Track C400 and C600 devices (0763:2030 and 0763:2031, respectively) seem requiring the explicit setup for the implicit feedback mode. This patch adds the quirk entries for those.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214817 Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221021122722.24784-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/usb/implicit.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -47,6 +47,8 @@ struct snd_usb_implicit_fb_match { static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { /* Fixed EP */ /* FIXME: check the availability of generic matching */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */ + IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */ IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */ IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */ IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
From: Jason A. Donenfeld Jason@zx2c4.com
commit ee03c0f200eb0d9f22dd8732d9fb7956d91019c2 upstream.
With char becoming unsigned by default, and with `char` alone being ambiguous and based on architecture, signed chars need to be marked explicitly as such. This fixes warnings like:
sound/pci/au88x0/au88x0_core.c:2029 vortex_adb_checkinout() warn: signedness bug returning '(-22)' sound/pci/au88x0/au88x0_core.c:2046 vortex_adb_checkinout() warn: signedness bug returning '(-12)' sound/pci/au88x0/au88x0_core.c:2125 vortex_adb_allocroute() warn: 'vortex_adb_checkinout(vortex, (0), en, 0)' is unsigned sound/pci/au88x0/au88x0_core.c:2170 vortex_adb_allocroute() warn: 'vortex_adb_checkinout(vortex, stream->resources, en, 4)' is unsigned
As well, since one function returns errnos, return an `int` rather than a `signed char`.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221024162929.536004-1-Jason@zx2c4.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/au88x0/au88x0.h | 6 +++--- sound/pci/au88x0/au88x0_core.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
--- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h @@ -141,7 +141,7 @@ struct snd_vortex { #ifndef CHIP_AU8810 stream_t dma_wt[NR_WT]; wt_voice_t wt_voice[NR_WT]; /* WT register cache. */ - char mixwt[(NR_WT / NR_WTPB) * 6]; /* WT mixin objects */ + s8 mixwt[(NR_WT / NR_WTPB) * 6]; /* WT mixin objects */ #endif
/* Global resources */ @@ -235,8 +235,8 @@ static int vortex_alsafmt_aspfmt(snd_pcm static void vortex_connect_default(vortex_t * vortex, int en); static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type, int subdev); -static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, - int restype); +static int vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, + int restype); #ifndef CHIP_AU8810 static int vortex_wt_allocroute(vortex_t * vortex, int dma, int nr_ch); static void vortex_wt_connect(vortex_t * vortex, int en); --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -1998,7 +1998,7 @@ static const int resnum[VORTEX_RESOURCE_ out: Mean checkout if != 0. Else mean Checkin resource. restype: Indicates type of resource to be checked in or out. */ -static char +static int vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) { int i, qty = resnum[restype], resinuse = 0;
From: Jason A. Donenfeld Jason@zx2c4.com
commit 50895a55bcfde8ac6f22a37c6bc8cff506b3c7c6 upstream.
With char becoming unsigned by default, and with `char` alone being ambiguous and based on architecture, signed chars need to be marked explicitly as such. This fixes warnings like:
sound/pci/rme9652/hdsp.c:3953 hdsp_channel_buffer_location() warn: 'hdsp->channel_map[channel]' is unsigned sound/pci/rme9652/hdsp.c:4153 snd_hdsp_channel_info() warn: impossible condition '(hdsp->channel_map[channel] < 0) => (0-255 < 0)' sound/pci/rme9652/rme9652.c:1833 rme9652_channel_buffer_location() warn: 'rme9652->channel_map[channel]' is unsigned
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221025000313.546261-1-Jason@zx2c4.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- sound/pci/rme9652/hdsp.c | 26 +++++++++++++------------- sound/pci/rme9652/rme9652.c | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-)
--- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -433,7 +433,7 @@ struct hdsp_midi { struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *input; struct snd_rawmidi_substream *output; - char istimer; /* timer in use */ + signed char istimer; /* timer in use */ struct timer_list timer; spinlock_t lock; int pending; @@ -480,7 +480,7 @@ struct hdsp { pid_t playback_pid; int running; int system_sample_rate; - const char *channel_map; + const signed char *channel_map; int dev; int irq; unsigned long port; @@ -502,7 +502,7 @@ struct hdsp { where the data for that channel can be read/written from/to. */
-static const char channel_map_df_ss[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_df_ss[HDSP_MAX_CHANNELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }; @@ -517,7 +517,7 @@ static const char channel_map_mf_ss[HDSP -1, -1, -1, -1, -1, -1, -1, -1 };
-static const char channel_map_ds[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_ds[HDSP_MAX_CHANNELS] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, /* channels 12 and 13 are S/PDIF */ @@ -526,7 +526,7 @@ static const char channel_map_ds[HDSP_MA -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
-static const char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { /* ADAT channels */ 0, 1, 2, 3, 4, 5, 6, 7, /* SPDIF */ @@ -540,7 +540,7 @@ static const char channel_map_H9632_ss[H -1, -1 };
-static const char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { /* ADAT */ 1, 3, 5, 7, /* SPDIF */ @@ -554,7 +554,7 @@ static const char channel_map_H9632_ds[H -1, -1, -1, -1, -1, -1 };
-static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { /* ADAT is disabled in this mode */ /* SPDIF */ 8, 9, @@ -3939,7 +3939,7 @@ static snd_pcm_uframes_t snd_hdsp_hw_poi return hdsp_hw_pointer(hdsp); }
-static char *hdsp_channel_buffer_location(struct hdsp *hdsp, +static signed char *hdsp_channel_buffer_location(struct hdsp *hdsp, int stream, int channel)
@@ -3964,7 +3964,7 @@ static int snd_hdsp_playback_copy(struct void __user *src, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -3982,7 +3982,7 @@ static int snd_hdsp_playback_copy_kernel void *src, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) @@ -3996,7 +3996,7 @@ static int snd_hdsp_capture_copy(struct void __user *dst, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -4014,7 +4014,7 @@ static int snd_hdsp_capture_copy_kernel( void *dst, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) @@ -4028,7 +4028,7 @@ static int snd_hdsp_hw_silence(struct sn unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -230,7 +230,7 @@ struct snd_rme9652 { int last_spdif_sample_rate; /* so that we can catch externally ... */ int last_adat_sample_rate; /* ... induced rate changes */
- const char *channel_map; + const signed char *channel_map;
struct snd_card *card; struct snd_pcm *pcm; @@ -247,12 +247,12 @@ struct snd_rme9652 { where the data for that channel can be read/written from/to. */
-static const char channel_map_9652_ss[26] = { +static const signed char channel_map_9652_ss[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
-static const char channel_map_9636_ss[26] = { +static const signed char channel_map_9636_ss[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* channels 16 and 17 are S/PDIF */ 24, 25, @@ -260,7 +260,7 @@ static const char channel_map_9636_ss[26 -1, -1, -1, -1, -1, -1, -1, -1 };
-static const char channel_map_9652_ds[26] = { +static const signed char channel_map_9652_ds[26] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, /* channels 12 and 13 are S/PDIF */ @@ -269,7 +269,7 @@ static const char channel_map_9652_ds[26 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
-static const char channel_map_9636_ds[26] = { +static const signed char channel_map_9636_ds[26] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, /* channels 8 and 9 are S/PDIF */ @@ -1819,7 +1819,7 @@ static snd_pcm_uframes_t snd_rme9652_hw_ return rme9652_hw_pointer(rme9652); }
-static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, +static signed char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, int stream, int channel)
@@ -1847,7 +1847,7 @@ static int snd_rme9652_playback_copy(str void __user *src, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -1867,7 +1867,7 @@ static int snd_rme9652_playback_copy_ker void *src, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = rme9652_channel_buffer_location(rme9652, substream->pstr->stream, @@ -1883,7 +1883,7 @@ static int snd_rme9652_capture_copy(stru void __user *dst, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -1903,7 +1903,7 @@ static int snd_rme9652_capture_copy_kern void *dst, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = rme9652_channel_buffer_location(rme9652, substream->pstr->stream, @@ -1919,7 +1919,7 @@ static int snd_rme9652_hw_silence(struct unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf;
channel_buf = rme9652_channel_buffer_location (rme9652, substream->pstr->stream,
From: Hannu Hartikainen hannu@hrtk.in
commit fc4ade55c617dc73c7e9756b57f3230b4ff24540 upstream.
NVIDIA Jetson devices in Force Recovery mode (RCM) do not support suspending, ie. flashing fails if the device has been suspended. The devices are still visible in lsusb and seem to work otherwise, making the issue hard to debug. This has been discovered in various forum posts, eg. [1].
The patch has been tested on NVIDIA Jetson AGX Xavier, but I'm adding all the Jetson models listed in [2] on the assumption that they all behave similarly.
[1]: https://forums.developer.nvidia.com/t/flashing-not-working/72365 [2]: https://docs.nvidia.com/jetson/archives/l4t-archived/l4t-3271/index.html#pag...
Signed-off-by: Hannu Hartikainen hannu@hrtk.in Cc: stable stable@kernel.org # after 6.1-rc3 Link: https://lore.kernel.org/r/20220919171610.30484-1-hannu@hrtk.in Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/core/quirks.c | 9 +++++++++ 1 file changed, 9 insertions(+)
--- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -388,6 +388,15 @@ static const struct usb_device_id usb_qu /* Kingston DataTraveler 3.0 */ { USB_DEVICE(0x0951, 0x1666), .driver_info = USB_QUIRK_NO_LPM },
+ /* NVIDIA Jetson devices in Force Recovery mode */ + { USB_DEVICE(0x0955, 0x7018), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7019), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7418), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7721), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7c18), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7e19), .driver_info = USB_QUIRK_RESET_RESUME }, + { USB_DEVICE(0x0955, 0x7f21), .driver_info = USB_QUIRK_RESET_RESUME }, + /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
From: Dan Vacura w36195@motorola.com
commit 0a0a2760b04814428800d48281a447a7522470ad upstream.
If there is a transmission error the buffer will be returned too early, causing a memory fault as subsequent requests for that buffer are still queued up to be sent. Refactor the error handling to wait for the final request to come in before reporting back the buffer to userspace for all transfer types (bulk/isoc/isoc_sg). This ensures userspace knows if the frame was successfully sent.
Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: stable@vger.kernel.org Signed-off-by: Dan Vacura w36195@motorola.com Link: https://lore.kernel.org/r/20221018215044.765044-4-w36195@motorola.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/gadget/function/uvc_queue.c | 8 +++++--- drivers/usb/gadget/function/uvc_video.c | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-)
--- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -313,6 +313,7 @@ int uvcg_queue_enable(struct uvc_video_q
queue->sequence = 0; queue->buf_used = 0; + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) @@ -338,10 +339,11 @@ int uvcg_queue_enable(struct uvc_video_q void uvcg_complete_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { - if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && - buf->length != buf->bytesused) { - buf->state = UVC_BUF_STATE_QUEUED; + if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) { + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + buf->state = UVC_BUF_STATE_ERROR; vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); return; }
--- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -59,6 +59,7 @@ uvc_video_encode_bulk(struct usb_request struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret;
@@ -84,13 +85,14 @@ uvc_video_encode_bulk(struct usb_request video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf;
video->payload_size = 0; }
if (video->payload_size == video->max_payload_size || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE || buf->bytesused == video->queue.buf_used) video->payload_size = 0; } @@ -151,7 +153,8 @@ uvc_video_encode_isoc_sg(struct usb_requ req->length -= len; video->queue.buf_used += req->length - header_len;
- if (buf->bytesused == video->queue.buf_used || !buf->sg) { + if (buf->bytesused == video->queue.buf_used || !buf->sg || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; buf->offset = 0; @@ -166,6 +169,7 @@ uvc_video_encode_isoc(struct usb_request struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret;
@@ -180,12 +184,13 @@ uvc_video_encode_isoc(struct usb_request
req->length = video->req_size - len;
- if (buf->bytesused == video->queue.buf_used) { + if (buf->bytesused == video->queue.buf_used || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; } }
@@ -222,6 +227,11 @@ uvc_video_complete(struct usb_ep *ep, st case 0: break;
+ case -EXDEV: + uvcg_dbg(&video->uvc->func, "VS request missed xfer.\n"); + queue->flags |= UVC_QUEUE_DROP_INCOMPLETE; + break; + case -ESHUTDOWN: /* disconnect from host. */ uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); uvcg_queue_cancel(queue, 1);
From: Jeff Vanhoof qjv001@motorola.com
commit b57b08e6f431348363adffa5b6643fe3ec9dc7fe upstream.
In uvc_video_encode_isoc_sg, the uvc_request's sg list is incorrectly being populated leading to corrupt video being received by the remote end. When building the sg list the usage of buf->sg's 'dma_length' field is not correct and instead its 'length' field should be used.
Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: stable@vger.kernel.org Signed-off-by: Jeff Vanhoof qjv001@motorola.com Signed-off-by: Dan Vacura w36195@motorola.com Link: https://lore.kernel.org/r/20221018215044.765044-5-w36195@motorola.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/gadget/function/uvc_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -128,10 +128,10 @@ uvc_video_encode_isoc_sg(struct usb_requ sg = sg_next(sg);
for_each_sg(sg, iter, ureq->sgt.nents - 1, i) { - if (!len || !buf->sg || !sg_dma_len(buf->sg)) + if (!len || !buf->sg || !buf->sg->length) break;
- sg_left = sg_dma_len(buf->sg) - buf->offset; + sg_left = buf->sg->length - buf->offset; part = min_t(unsigned int, len, sg_left);
sg_set_page(iter, sg_page(buf->sg), part, buf->offset);
From: Thinh Nguyen Thinh.Nguyen@synopsys.com
commit f78961f8380b940e0cfc7e549336c21a2ad44f4d upstream.
When servicing a transfer completion event, the dwc3 driver will reclaim TRBs of started requests up to the request associated with the interrupt event. Currently we don't check for interrupt due to missed isoc, and the driver may attempt to reclaim TRBs beyond the associated event. This causes invalid memory access when the hardware still owns the TRB. If there's a missed isoc TRB with IMI (interrupt on missed isoc), make sure to stop servicing further.
Note that only the last TRB of chained TRBs has its status updated with missed isoc.
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Reported-by: Jeff Vanhoof jdv1029@gmail.com Reported-by: Dan Vacura w36195@motorola.com Signed-off-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Reviewed-by: Jeff Vanhoof jdv1029@gmail.com Tested-by: Jeff Vanhoof jdv1029@gmail.com Link: https://lore.kernel.org/r/b29acbeab531b666095dfdafd8cb5c7654fbb3e1.166673545... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3146,6 +3146,10 @@ static int dwc3_gadget_ep_reclaim_comple if (event->status & DEPEVT_STATUS_SHORT && !chain) return 1;
+ if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) && + DWC3_TRB_SIZE_TRBSTS(trb->size) == DWC3_TRBSTS_MISSED_ISOC) + return 1; + if ((trb->ctrl & DWC3_TRB_CTRL_IOC) || (trb->ctrl & DWC3_TRB_CTRL_LST)) return 1;
From: Thinh Nguyen Thinh.Nguyen@synopsys.com
commit 308c316d16cbad99bb834767382baa693ac42169 upstream.
The gadget driver may have a certain expectation of how the request completion flow should be from to its configuration. Make sure the controller driver respect that. That is, don't set IMI (Interrupt on Missed Isoc) when usb_request->no_interrupt is set. Also, the driver should only set IMI to the last TRB of a chain.
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable@vger.kernel.org Signed-off-by: Thinh Nguyen Thinh.Nguyen@synopsys.com Reviewed-by: Jeff Vanhoof jdv1029@gmail.com Tested-by: Jeff Vanhoof jdv1029@gmail.com Link: https://lore.kernel.org/r/ced336c84434571340c07994e3667a0ee284fefe.166673545... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1263,8 +1263,8 @@ static void dwc3_prepare_one_trb(struct trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS; }
- /* always enable Interrupt on Missed ISOC */ - trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; + if (!no_interrupt && !chain) + trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; break;
case USB_ENDPOINT_XFER_BULK:
From: Justin Chen justinpopo6@gmail.com
commit fb8f60dd1b67520e0e0d7978ef17d015690acfc1 upstream.
When port is connected and then disconnected, the state stays as configured. Which is incorrect as the port is no longer configured, but in a not attached state.
Signed-off-by: Justin Chen justinpopo6@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Fixes: efed421a94e6 ("usb: gadget: Add UDC driver for Broadcom USB3.0 device controller IP BDC") Cc: stable stable@kernel.org Link: https://lore.kernel.org/r/1664997235-18198-1-git-send-email-justinpopo6@gmai... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/gadget/udc/bdc/bdc_udc.c | 1 + 1 file changed, 1 insertion(+)
--- a/drivers/usb/gadget/udc/bdc/bdc_udc.c +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c @@ -151,6 +151,7 @@ static void bdc_uspc_disconnected(struct bdc->delayed_status = false; bdc->reinit = reinit; bdc->test_mode = false; + usb_gadget_set_state(&bdc->gadget, USB_STATE_NOTATTACHED); }
/* TNotify wkaeup timer */
From: Jens Glathe jens.glathe@oldschoolsolutions.biz
commit 4f547472380136718b56064ea5689a61e135f904 upstream.
This appears to fix the error: "xhci_hcd <address>; ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13" that appear spuriously (or pretty often) when using a r8152 USB3 ethernet adapter with integrated hub.
ASM1042 reports as a 0.96 controller, but appears to behave more like 1.0
Inspired by this email thread: https://markmail.org/thread/7vzqbe7t6du6qsw3
Cc: stable@vger.kernel.org Signed-off-by: Jens Glathe jens.glathe@oldschoolsolutions.biz Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20221024142720.4122053-2-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -307,8 +307,14 @@ static void xhci_pci_quirks(struct devic }
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) { + /* + * try to tame the ASMedia 1042 controller which reports 0.96 + * but appears to behave more like 1.0 + */ + xhci->quirks |= XHCI_SPURIOUS_SUCCESS; xhci->quirks |= XHCI_BROKEN_STREAMS; + } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) { xhci->quirks |= XHCI_TRUST_TX_LENGTH;
From: Tony O'Brien tony.obrien@alliedtelesis.co.nz
commit ce107713b722af57c4b7f2477594d445b496420e upstream.
Originally the absence of the marvell,nand-keep-config property caused the setup_data_interface function to be provided. However when setup_data_interface was moved into nand_controller_ops the logic was unintentionally inverted. Update the logic so that only if the marvell,nand-keep-config property is present the bootloader NAND config kept.
Cc: stable@vger.kernel.org Fixes: 7a08dbaedd36 ("mtd: rawnand: Move ->setup_data_interface() to nand_controller_ops") Signed-off-by: Tony O'Brien tony.obrien@alliedtelesis.co.nz Signed-off-by: Chris Packham chris.packham@alliedtelesis.co.nz Reviewed-by: Boris Brezillon boris.brezillon@collabora.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20220927024728.28447-1-chris.packham@allie... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mtd/nand/raw/marvell_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2672,7 +2672,7 @@ static int marvell_nand_chip_init(struct chip->controller = &nfc->controller; nand_set_flash_node(chip, np);
- if (!of_property_read_bool(np, "marvell,nand-keep-config")) + if (of_property_read_bool(np, "marvell,nand-keep-config")) chip->options |= NAND_KEEP_TIMINGS;
mtd = nand_to_mtd(chip);
From: Mathias Nyman mathias.nyman@linux.intel.com
commit 34cd2db408d591bc15771cbcc90939ade0a99a21 upstream.
Systems based on Alder Lake P see significant boot time delay if boot firmware tries to control usb ports in unexpected link states.
This is seen with self-powered usb devices that survive in U3 link suspended state over S5.
A more generic solution to power off ports at shutdown was attempted in commit 83810f84ecf1 ("xhci: turn off port power in shutdown") but it caused regression.
Add host specific XHCI_RESET_TO_DEFAULT quirk which will reset host and ports back to default state in shutdown.
Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20221024142720.4122053-3-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci.c | 4 ++++ drivers/usb/host/xhci.c | 10 ++++++++-- drivers/usb/host/xhci.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -259,6 +259,10 @@ static void xhci_pci_quirks(struct devic xhci->quirks |= XHCI_MISSING_CAS;
if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI) + xhci->quirks |= XHCI_RESET_TO_DEFAULT; + + if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_XHCI || --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -795,9 +795,15 @@ void xhci_shutdown(struct usb_hcd *hcd)
spin_lock_irq(&xhci->lock); xhci_halt(xhci); - /* Workaround for spurious wakeups at shutdown with HSW */ - if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) + + /* + * Workaround for spurious wakeps at shutdown with HSW, and for boot + * firmware delay in ADL-P PCH if port are left in U3 at shutdown + */ + if (xhci->quirks & XHCI_SPURIOUS_WAKEUP || + xhci->quirks & XHCI_RESET_TO_DEFAULT) xhci_reset(xhci, XHCI_RESET_SHORT_USEC); + spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci); --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1904,6 +1904,7 @@ struct xhci_hcd { #define XHCI_BROKEN_D3COLD BIT_ULL(41) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) +#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
unsigned int num_active_eps; unsigned int limit_active_eps;
From: Mario Limonciello mario.limonciello@amd.com
commit a611bf473d1f77b70f7188b5577542cb39b4701b upstream.
For optimal power consumption of USB4 routers the XHCI PCIe endpoint used for tunneling must be in D3. Historically this is accomplished by a long list of PCIe IDs that correspond to these endpoints because the xhci_hcd driver will not default to allowing runtime PM for all devices.
As both AMD and Intel have released new products with new XHCI controllers this list continues to grow. In reviewing the XHCI specification v1.2 on page 607 there is already a requirement that the PCI power management states D3hot and D3cold must be supported.
In the quirk list, use this to indicate that runtime PM should be allowed on XHCI controllers. The following controllers are known to be xHC 1.2 and dropped explicitly: * AMD Yellow Carp * Intel Alder Lake * Intel Meteor Lake * Intel Raptor Lake
[keep PCI ID for Alder Lake PCH for recently added quirk -Mathias]
Cc: stable@vger.kernel.org Suggested-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://www.intel.com/content/dam/www/public/us/en/documents/technical-speci... Signed-off-by: Mario Limonciello mario.limonciello@amd.com Reviewed-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20221024142720.4122053-4-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-pci.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-)
--- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -58,25 +58,13 @@ #define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e -#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed -#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e -#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI 0x7ec0 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 0x161a -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 0x161b -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 0x161d -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6 -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7 -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c -#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f
#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 @@ -273,12 +261,7 @@ static void xhci_pci_quirks(struct devic pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON && @@ -347,15 +330,8 @@ static void xhci_pci_quirks(struct devic pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) xhci->quirks |= XHCI_NO_SOFT_RETRY;
- if (pdev->vendor == PCI_VENDOR_ID_AMD && - (pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 || - pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8)) + /* xHC spec requires PCI devices to support D3hot and D3cold */ + if (xhci->hci_version >= 0x120) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (xhci->quirks & XHCI_RESET_ON_RESUME)
From: Mathias Nyman mathias.nyman@linux.intel.com
commit 5aed5b7c2430ce318a8e62f752f181e66f0d1053 upstream.
Endpoints are normally deleted from the bandwidth list when they are dropped, before the virt device is freed.
If xHC host is dying or being removed then the endpoints aren't dropped cleanly due to functions returning early to avoid interacting with a non-accessible host controller.
So check and delete endpoints that are still on the bandwidth list when freeing the virt device.
Solves a list_del corruption kernel crash when unbinding xhci-pci, caused by xhci_mem_cleanup() when it later tried to delete already freed endpoints from the bandwidth list.
This only affects hosts that use software bandwidth checking, which currenty is only the xHC in intel Panther Point PCH (Ivy Bridge)
Cc: stable@vger.kernel.org Reported-by: Marek Marczykowski-Górecki marmarek@invisiblethingslab.com Tested-by: Marek Marczykowski-Górecki marmarek@invisiblethingslab.com Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com Link: https://lore.kernel.org/r/20221024142720.4122053-5-mathias.nyman@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/usb/host/xhci-mem.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
--- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -898,15 +898,19 @@ void xhci_free_virt_device(struct xhci_h if (dev->eps[i].stream_info) xhci_free_stream_info(xhci, dev->eps[i].stream_info); - /* Endpoints on the TT/root port lists should have been removed - * when usb_disable_device() was called for the device. - * We can't drop them anyway, because the udev might have gone - * away by this point, and we can't tell what speed it was. + /* + * Endpoints are normally deleted from the bandwidth list when + * endpoints are dropped, before device is freed. + * If host is dying or being removed then endpoints aren't + * dropped cleanly, so delete the endpoint from list here. + * Only applicable for hosts with software bandwidth checking. */ - if (!list_empty(&dev->eps[i].bw_endpoint_list)) - xhci_warn(xhci, "Slot %u endpoint %u " - "not removed from BW list!\n", - slot_id, i); + + if (!list_empty(&dev->eps[i].bw_endpoint_list)) { + list_del_init(&dev->eps[i].bw_endpoint_list); + xhci_dbg(xhci, "Slot %u endpoint %u not removed from BW list!\n", + slot_id, i); + } } /* If this is a hub, free the TT(s) from the TT list */ xhci_free_tt_info(xhci, dev, slot_id);
From: Matti Vaittinen mazziesaccount@gmail.com
commit 72b2aa38191bcba28389b0e20bf6b4f15017ff2b upstream.
The iio_utils uses a digit calculation in order to know length of the file name containing a buffer number. The digit calculation does not work for number 0.
This leads to allocation of one character too small buffer for the file-name when file name contains value '0'. (Eg. buffer0).
Fix digit calculation by returning one digit to be present for number '0'.
Fixes: 096f9b862e60 ("tools:iio:iio_utils: implement digit calculation") Signed-off-by: Matti Vaittinen mazziesaccount@gmail.com Link: https://lore.kernel.org/r/Y0f+tKCz+ZAIoroQ@dc75zzyyyyyyyyyyyyycy-3.rev.dnain... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/iio/iio_utils.c | 4 ++++ 1 file changed, 4 insertions(+)
--- a/tools/iio/iio_utils.c +++ b/tools/iio/iio_utils.c @@ -547,6 +547,10 @@ static int calc_digits(int num) { int count = 0;
+ /* It takes a digit to represent zero */ + if (!num) + return 1; + while (num != 0) { num /= 10; count++;
From: Shreeya Patel shreeya.patel@collabora.com
commit 0dec4d2f2636b9e54d9d29f17afc7687c5407f78 upstream.
tsl2583 probe() uses devm_iio_device_register() and calling iio_device_unregister() causes the unregister to occur twice. s Switch to iio_device_register() instead of devm_iio_device_register() in probe to avoid the device managed cleanup.
Fixes: 371894f5d1a0 ("iio: tsl2583: add runtime power management support") Signed-off-by: Shreeya Patel shreeya.patel@collabora.com Link: https://lore.kernel.org/r/20220826122352.288438-1-shreeya.patel@collabora.co... Cc: Stable@vger.kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/light/tsl2583.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -858,7 +858,7 @@ static int tsl2583_probe(struct i2c_clie TSL2583_POWER_OFF_DELAY_MS); pm_runtime_use_autosuspend(&clientp->dev);
- ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); + ret = iio_device_register(indio_dev); if (ret) { dev_err(&clientp->dev, "%s: iio registration failed\n", __func__);
From: Cosmin Tanislav cosmin.tanislav@analog.com
commit 4132f19173211856d35180958d2754f5c56d520a upstream.
Currently, every time the device wakes up from sleep, the iio_chan array is reallocated, leaking the previous one until the device is removed (basically never).
Move the allocation to the probe function to avoid this.
Signed-off-by: Cosmin Tanislav cosmin.tanislav@analog.com Fixes: f110f3188e563 ("iio: temperature: Add support for LTC2983") Cc: Stable@vger.kernel.org Link: https://lore.kernel.org/r/20221014123724.1401011-2-demonsingur@gmail.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/temperature/ltc2983.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
--- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -1376,13 +1376,6 @@ static int ltc2983_setup(struct ltc2983_ return ret; }
- st->iio_chan = devm_kzalloc(&st->spi->dev, - st->iio_channels * sizeof(*st->iio_chan), - GFP_KERNEL); - - if (!st->iio_chan) - return -ENOMEM; - ret = regmap_update_bits(st->regmap, LTC2983_GLOBAL_CONFIG_REG, LTC2983_NOTCH_FREQ_MASK, LTC2983_NOTCH_FREQ(st->filter_notch_freq)); @@ -1494,6 +1487,12 @@ static int ltc2983_probe(struct spi_devi if (ret) return ret;
+ st->iio_chan = devm_kzalloc(&spi->dev, + st->iio_channels * sizeof(*st->iio_chan), + GFP_KERNEL); + if (!st->iio_chan) + return -ENOMEM; + ret = ltc2983_setup(st, true); if (ret) return ret;
From: Matti Vaittinen mazziesaccount@gmail.com
commit ab0ee36e90f611f32c3a53afe9dc743de48138e2 upstream.
The iio_triggered_buffer_setup_ext() was changed by commit 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") to silently expect that all attributes given in buffer_attrs array are device-attributes. This expectation was not forced by the API - and some drivers did register attributes created by IIO_CONST_ATTR().
The added attribute "wrapping" does not copy the pointer to stored string constant and when the sysfs file is read the kernel will access to invalid location.
Change the IIO_CONST_ATTRs from the driver to IIO_DEVICE_ATTR in order to prevent the invalid memory access.
Signed-off-by: Matti Vaittinen mazziesaccount@gmail.com Fixes: 15097c7a1adc ("iio: buffer: wrap all buffer attributes into iio_dev_attr") Cc: Stable@vger.kernel.org Link: https://lore.kernel.org/r/19158499623cdf7f9c5efae1f13c9f1a918ff75f.166478267... Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/iio/accel/adxl372.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index e3ecbaee61f7..bc53af809d5d 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -998,17 +998,30 @@ static ssize_t adxl372_get_fifo_watermark(struct device *dev, return sprintf(buf, "%d\n", st->watermark); }
-static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); -static IIO_CONST_ATTR(hwfifo_watermark_max, - __stringify(ADXL372_FIFO_SIZE)); +static ssize_t hwfifo_watermark_min_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", "1"); +} + +static ssize_t hwfifo_watermark_max_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", __stringify(ADXL372_FIFO_SIZE)); +} + +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0); +static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, adxl372_get_fifo_watermark, NULL, 0); static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, adxl372_get_fifo_enabled, NULL, 0);
static const struct attribute *adxl372_fifo_attributes[] = { - &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, - &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, &iio_dev_attr_hwfifo_watermark.dev_attr.attr, &iio_dev_attr_hwfifo_enabled.dev_attr.attr, NULL,
From: Hyunwoo Kim imv4bel@gmail.com
commit cc67482c9e5f2c80d62f623bcc347c29f9f648e1 upstream.
Several types of UAFs can occur when physically removing a USB device.
Adds ufx_ops_destroy() function to .fb_destroy of fb_ops, and in this function, there is kref_put() that finally calls ufx_free().
This fix prevents multiple UAFs.
Signed-off-by: Hyunwoo Kim imv4bel@gmail.com Link: https://lore.kernel.org/linux-fbdev/20221011153436.GA4446@ubuntu/ Cc: stable@vger.kernel.org Signed-off-by: Helge Deller deller@gmx.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/video/fbdev/smscufx.c | 55 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 25 deletions(-)
--- a/drivers/video/fbdev/smscufx.c +++ b/drivers/video/fbdev/smscufx.c @@ -97,7 +97,6 @@ struct ufx_data { struct kref kref; int fb_count; bool virtualized; /* true when physical usb device not present */ - struct delayed_work free_framebuffer_work; atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ u8 *edid; /* null until we read edid from hw or get from sysfs */ @@ -1116,15 +1115,24 @@ static void ufx_free(struct kref *kref) { struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
- /* this function will wait for all in-flight urbs to complete */ - if (dev->urbs.count > 0) - ufx_free_urb_list(dev); + kfree(dev); +}
- pr_debug("freeing ufx_data %p", dev); +static void ufx_ops_destory(struct fb_info *info) +{ + struct ufx_data *dev = info->par; + int node = info->node;
- kfree(dev); + /* Assume info structure is freed after this point */ + framebuffer_release(info); + + pr_debug("fb_info for /dev/fb%d has been freed", node); + + /* release reference taken by kref_init in probe() */ + kref_put(&dev->kref, ufx_free); }
+ static void ufx_release_urb_work(struct work_struct *work) { struct urb_node *unode = container_of(work, struct urb_node, @@ -1133,14 +1141,9 @@ static void ufx_release_urb_work(struct up(&unode->dev->urbs.limit_sem); }
-static void ufx_free_framebuffer_work(struct work_struct *work) +static void ufx_free_framebuffer(struct ufx_data *dev) { - struct ufx_data *dev = container_of(work, struct ufx_data, - free_framebuffer_work.work); struct fb_info *info = dev->info; - int node = info->node; - - unregister_framebuffer(info);
if (info->cmap.len != 0) fb_dealloc_cmap(&info->cmap); @@ -1152,11 +1155,6 @@ static void ufx_free_framebuffer_work(st
dev->info = NULL;
- /* Assume info structure is freed after this point */ - framebuffer_release(info); - - pr_debug("fb_info for /dev/fb%d has been freed", node); - /* ref taken in probe() as part of registering framebfufer */ kref_put(&dev->kref, ufx_free); } @@ -1168,11 +1166,13 @@ static int ufx_ops_release(struct fb_inf { struct ufx_data *dev = info->par;
+ mutex_lock(&disconnect_mutex); + dev->fb_count--;
/* We can't free fb_info here - fbmem will touch it when we return */ if (dev->virtualized && (dev->fb_count == 0)) - schedule_delayed_work(&dev->free_framebuffer_work, HZ); + ufx_free_framebuffer(dev);
if ((dev->fb_count == 0) && (info->fbdefio)) { fb_deferred_io_cleanup(info); @@ -1185,6 +1185,8 @@ static int ufx_ops_release(struct fb_inf
kref_put(&dev->kref, ufx_free);
+ mutex_unlock(&disconnect_mutex); + return 0; }
@@ -1291,6 +1293,7 @@ static const struct fb_ops ufx_ops = { .fb_blank = ufx_ops_blank, .fb_check_var = ufx_ops_check_var, .fb_set_par = ufx_ops_set_par, + .fb_destroy = ufx_ops_destory, };
/* Assumes &info->lock held by caller @@ -1672,9 +1675,6 @@ static int ufx_usb_probe(struct usb_inte goto destroy_modedb; }
- INIT_DELAYED_WORK(&dev->free_framebuffer_work, - ufx_free_framebuffer_work); - retval = ufx_reg_read(dev, 0x3000, &id_rev); check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval); dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); @@ -1747,10 +1747,12 @@ e_nomem: static void ufx_usb_disconnect(struct usb_interface *interface) { struct ufx_data *dev; + struct fb_info *info;
mutex_lock(&disconnect_mutex);
dev = usb_get_intfdata(interface); + info = dev->info;
pr_debug("USB disconnect starting\n");
@@ -1764,12 +1766,15 @@ static void ufx_usb_disconnect(struct us
/* if clients still have us open, will be freed on last close */ if (dev->fb_count == 0) - schedule_delayed_work(&dev->free_framebuffer_work, 0); + ufx_free_framebuffer(dev);
- /* release reference taken by kref_init in probe() */ - kref_put(&dev->kref, ufx_free); + /* this function will wait for all in-flight urbs to complete */ + if (dev->urbs.count > 0) + ufx_free_urb_list(dev);
- /* consider ufx_data freed */ + pr_debug("freeing ufx_data %p", dev); + + unregister_framebuffer(info);
mutex_unlock(&disconnect_mutex); }
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit 8dbab94d45fb1094cefac7956b7fb987a36e2b12 upstream.
Some of the MSR accesses in intel_pstate are carried out on the CPU that is running the code, but the values coming from them are used for the performance scaling of the other CPUs.
This is problematic, for example, on hybrid platforms where MSR_TURBO_RATIO_LIMIT for P-cores and E-cores is different, so the values read from it on a P-core are generally not applicable to E-cores and the other way around.
For this reason, make the driver access all MSRs on the target CPU on platforms using the "core" pstate_funcs callbacks which is the case for all of the hybrid platforms released to date. For this purpose, pass a CPU argument to the ->get_max(), ->get_max_physical(), ->get_min() and ->get_turbo() pstate_funcs callbacks and from there pass it to rdmsrl_on_cpu() or rdmsrl_safe_on_cpu() to access the MSR on the target CPU.
Fixes: 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") Acked-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Tested-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Cc: 5.15+ stable@vger.kernel.org # 5.15+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/intel_pstate.c | 66 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -277,10 +277,10 @@ static struct cpudata **all_cpu_data; * structure is used to store those callbacks. */ struct pstate_funcs { - int (*get_max)(void); - int (*get_max_physical)(void); - int (*get_min)(void); - int (*get_turbo)(void); + int (*get_max)(int cpu); + int (*get_max_physical)(int cpu); + int (*get_min)(int cpu); + int (*get_turbo)(int cpu); int (*get_scaling)(void); int (*get_cpu_scaling)(int cpu); int (*get_aperf_mperf_shift)(void); @@ -528,12 +528,12 @@ static void intel_pstate_hybrid_hwp_adju { int perf_ctl_max_phys = cpu->pstate.max_pstate_physical; int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling; - int perf_ctl_turbo = pstate_funcs.get_turbo(); + int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu); int turbo_freq = perf_ctl_turbo * perf_ctl_scaling; int scaling = cpu->pstate.scaling;
pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys); - pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max()); + pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max(cpu->cpu)); pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo); pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling); pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate); @@ -1581,7 +1581,7 @@ static void intel_pstate_hwp_enable(stru cpudata->epp_default = intel_pstate_get_epp(cpudata, 0); }
-static int atom_get_min_pstate(void) +static int atom_get_min_pstate(int not_used) { u64 value;
@@ -1589,7 +1589,7 @@ static int atom_get_min_pstate(void) return (value >> 8) & 0x7F; }
-static int atom_get_max_pstate(void) +static int atom_get_max_pstate(int not_used) { u64 value;
@@ -1597,7 +1597,7 @@ static int atom_get_max_pstate(void) return (value >> 16) & 0x7F; }
-static int atom_get_turbo_pstate(void) +static int atom_get_turbo_pstate(int not_used) { u64 value;
@@ -1675,23 +1675,23 @@ static void atom_get_vid(struct cpudata cpudata->vid.turbo = value & 0x7f; }
-static int core_get_min_pstate(void) +static int core_get_min_pstate(int cpu) { u64 value;
- rdmsrl(MSR_PLATFORM_INFO, value); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value); return (value >> 40) & 0xFF; }
-static int core_get_max_pstate_physical(void) +static int core_get_max_pstate_physical(int cpu) { u64 value;
- rdmsrl(MSR_PLATFORM_INFO, value); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value); return (value >> 8) & 0xFF; }
-static int core_get_tdp_ratio(u64 plat_info) +static int core_get_tdp_ratio(int cpu, u64 plat_info) { /* Check how many TDP levels present */ if (plat_info & 0x600000000) { @@ -1701,13 +1701,13 @@ static int core_get_tdp_ratio(u64 plat_i int err;
/* Get the TDP level (0, 1, 2) to get ratios */ - err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl); + err = rdmsrl_safe_on_cpu(cpu, MSR_CONFIG_TDP_CONTROL, &tdp_ctrl); if (err) return err;
/* TDP MSR are continuous starting at 0x648 */ tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x03); - err = rdmsrl_safe(tdp_msr, &tdp_ratio); + err = rdmsrl_safe_on_cpu(cpu, tdp_msr, &tdp_ratio); if (err) return err;
@@ -1724,7 +1724,7 @@ static int core_get_tdp_ratio(u64 plat_i return -ENXIO; }
-static int core_get_max_pstate(void) +static int core_get_max_pstate(int cpu) { u64 tar; u64 plat_info; @@ -1732,10 +1732,10 @@ static int core_get_max_pstate(void) int tdp_ratio; int err;
- rdmsrl(MSR_PLATFORM_INFO, plat_info); + rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &plat_info); max_pstate = (plat_info >> 8) & 0xFF;
- tdp_ratio = core_get_tdp_ratio(plat_info); + tdp_ratio = core_get_tdp_ratio(cpu, plat_info); if (tdp_ratio <= 0) return max_pstate;
@@ -1744,7 +1744,7 @@ static int core_get_max_pstate(void) return tdp_ratio; }
- err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar); + err = rdmsrl_safe_on_cpu(cpu, MSR_TURBO_ACTIVATION_RATIO, &tar); if (!err) { int tar_levels;
@@ -1759,13 +1759,13 @@ static int core_get_max_pstate(void) return max_pstate; }
-static int core_get_turbo_pstate(void) +static int core_get_turbo_pstate(int cpu) { u64 value; int nont, ret;
- rdmsrl(MSR_TURBO_RATIO_LIMIT, value); - nont = core_get_max_pstate(); + rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value); + nont = core_get_max_pstate(cpu); ret = (value) & 255; if (ret <= nont) ret = nont; @@ -1793,13 +1793,13 @@ static int knl_get_aperf_mperf_shift(voi return 10; }
-static int knl_get_turbo_pstate(void) +static int knl_get_turbo_pstate(int cpu) { u64 value; int nont, ret;
- rdmsrl(MSR_TURBO_RATIO_LIMIT, value); - nont = core_get_max_pstate(); + rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value); + nont = core_get_max_pstate(cpu); ret = (((value) >> 8) & 0xFF); if (ret <= nont) ret = nont; @@ -1866,10 +1866,10 @@ static void intel_pstate_max_within_limi
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { - int perf_ctl_max_phys = pstate_funcs.get_max_physical(); + int perf_ctl_max_phys = pstate_funcs.get_max_physical(cpu->cpu); int perf_ctl_scaling = pstate_funcs.get_scaling();
- cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu); cpu->pstate.max_pstate_physical = perf_ctl_max_phys; cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
@@ -1885,8 +1885,8 @@ static void intel_pstate_get_cpu_pstates } } else { cpu->pstate.scaling = perf_ctl_scaling; - cpu->pstate.max_pstate = pstate_funcs.get_max(); - cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); + cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu); }
if (cpu->pstate.scaling == perf_ctl_scaling) { @@ -3063,9 +3063,9 @@ static unsigned int force_load __initdat
static int __init intel_pstate_msrs_not_valid(void) { - if (!pstate_funcs.get_max() || - !pstate_funcs.get_min() || - !pstate_funcs.get_turbo()) + if (!pstate_funcs.get_max(0) || + !pstate_funcs.get_min(0) || + !pstate_funcs.get_turbo(0)) return -ENODEV;
return 0;
From: Rafael J. Wysocki rafael.j.wysocki@intel.com
commit f5c8cf2a4992dd929fa0c2f25c09ee69b8dcbce1 upstream.
Commit 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") attempted to use the information from CPPC (the nominal performance in particular) to obtain the scaling factor allowing the frequency to be computed if the HWP performance level of the given CPU is known or vice versa.
However, it turns out that on some platforms this doesn't work, because the CPPC information on them does not align with the contents of the MSR_HWP_CAPABILITIES registers.
This basically means that the only way to make intel_pstate work on all of the hybrid platforms to date is to use the observation that on all of them the scaling factor between the HWP performance levels and frequency for P-cores is 78741 (approximately 100000/1.27). For E-cores it is 100000, which is the same as for all of the non-hybrid "core" platforms and does not require any changes.
Accordingly, make intel_pstate use 78741 as the scaling factor between HWP performance levels and frequency for P-cores on all hybrid platforms and drop the dependency of the HWP calibration code on CPPC.
Fixes: 46573fd6369f ("cpufreq: intel_pstate: hybrid: Rework HWP calibration") Reported-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Acked-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Tested-by: Srinivas Pandruvada srinivas.pandruvada@linux.intel.com Cc: 5.15+ stable@vger.kernel.org # 5.15+ Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/cpufreq/intel_pstate.c | 69 ++++++++--------------------------------- 1 file changed, 15 insertions(+), 54 deletions(-)
--- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -27,6 +27,7 @@ #include <linux/pm_qos.h> #include <trace/events/power.h>
+#include <asm/cpu.h> #include <asm/div64.h> #include <asm/msr.h> #include <asm/cpu_device_id.h> @@ -395,16 +396,6 @@ static int intel_pstate_get_cppc_guarant
return cppc_perf.nominal_perf; } - -static u32 intel_pstate_cppc_nominal(int cpu) -{ - u64 nominal_perf; - - if (cppc_get_nominal_perf(cpu, &nominal_perf)) - return 0; - - return nominal_perf; -} #else /* CONFIG_ACPI_CPPC_LIB */ static inline void intel_pstate_set_itmt_prio(int cpu) { @@ -529,34 +520,17 @@ static void intel_pstate_hybrid_hwp_adju int perf_ctl_max_phys = cpu->pstate.max_pstate_physical; int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling; int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu); - int turbo_freq = perf_ctl_turbo * perf_ctl_scaling; int scaling = cpu->pstate.scaling;
pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys); - pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max(cpu->cpu)); pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo); pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling); pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate); pr_debug("CPU%d: HWP_CAP highest = %d\n", cpu->cpu, cpu->pstate.turbo_pstate); pr_debug("CPU%d: HWP-to-frequency scaling factor: %d\n", cpu->cpu, scaling);
- /* - * If the product of the HWP performance scaling factor and the HWP_CAP - * highest performance is greater than the maximum turbo frequency - * corresponding to the pstate_funcs.get_turbo() return value, the - * scaling factor is too high, so recompute it to make the HWP_CAP - * highest performance correspond to the maximum turbo frequency. - */ - cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling; - if (turbo_freq < cpu->pstate.turbo_freq) { - cpu->pstate.turbo_freq = turbo_freq; - scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate); - cpu->pstate.scaling = scaling; - - pr_debug("CPU%d: refined HWP-to-frequency scaling factor: %d\n", - cpu->cpu, scaling); - } - + cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_pstate * scaling, + perf_ctl_scaling); cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling, perf_ctl_scaling);
@@ -1806,37 +1780,24 @@ static int knl_get_turbo_pstate(int cpu) return ret; }
-#ifdef CONFIG_ACPI_CPPC_LIB -static u32 hybrid_ref_perf; - -static int hybrid_get_cpu_scaling(int cpu) +static void hybrid_get_type(void *data) { - return DIV_ROUND_UP(core_get_scaling() * hybrid_ref_perf, - intel_pstate_cppc_nominal(cpu)); + u8 *cpu_type = data; + + *cpu_type = get_this_hybrid_cpu_type(); }
-static void intel_pstate_cppc_set_cpu_scaling(void) +static int hybrid_get_cpu_scaling(int cpu) { - u32 min_nominal_perf = U32_MAX; - int cpu; + u8 cpu_type = 0;
- for_each_present_cpu(cpu) { - u32 nominal_perf = intel_pstate_cppc_nominal(cpu); + smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); + /* P-cores have a smaller perf level-to-freqency scaling factor. */ + if (cpu_type == 0x40) + return 78741;
- if (nominal_perf && nominal_perf < min_nominal_perf) - min_nominal_perf = nominal_perf; - } - - if (min_nominal_perf < U32_MAX) { - hybrid_ref_perf = min_nominal_perf; - pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; - } + return core_get_scaling(); } -#else -static inline void intel_pstate_cppc_set_cpu_scaling(void) -{ -} -#endif /* CONFIG_ACPI_CPPC_LIB */
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) { @@ -3281,7 +3242,7 @@ static int __init intel_pstate_init(void default_driver = &intel_pstate;
if (boot_cpu_has(X86_FEATURE_HYBRID_CPU)) - intel_pstate_cppc_set_cpu_scaling(); + pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling;
goto hwp_cpu_matched; }
From: Li Zetao lizetao1@huawei.com
commit 594d2a14f2168c09b13b114c3d457aa939403e52 upstream.
There is a memory leak reported by kmemleak:
unreferenced object 0xffff88817104ef80 (size 224): comm "xfs_admin", pid 47165, jiffies 4298708825 (age 1333.476s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 60 a8 b3 00 81 88 ff ff a8 10 5a 00 81 88 ff ff `.........Z..... backtrace: [<ffffffff819171e1>] __alloc_file+0x21/0x250 [<ffffffff81918061>] alloc_empty_file+0x41/0xf0 [<ffffffff81948cda>] path_openat+0xea/0x3d30 [<ffffffff8194ec89>] do_filp_open+0x1b9/0x290 [<ffffffff8192660e>] do_open_execat+0xce/0x5b0 [<ffffffff81926b17>] open_exec+0x27/0x50 [<ffffffff81a69250>] load_elf_binary+0x510/0x3ed0 [<ffffffff81927759>] bprm_execve+0x599/0x1240 [<ffffffff8192a997>] do_execveat_common.isra.0+0x4c7/0x680 [<ffffffff8192b078>] __x64_sys_execve+0x88/0xb0 [<ffffffff83bbf0a5>] do_syscall_64+0x35/0x80
If "interp_elf_ex" fails to allocate memory in load_elf_binary(), the program will take the "out_free_ph" error handing path, resulting in "interpreter" file resource is not released.
Fix it by adding an error handing path "out_free_file", which will release the file resource when "interp_elf_ex" failed to allocate memory.
Fixes: 0693ffebcfe5 ("fs/binfmt_elf.c: allocate less for static executable") Signed-off-by: Li Zetao lizetao1@huawei.com Reviewed-by: Alexey Dobriyan adobriyan@gmail.com Signed-off-by: Kees Cook keescook@chromium.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221024154421.982230-1-lizetao1@huawei.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/binfmt_elf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -910,7 +910,7 @@ static int load_elf_binary(struct linux_ interp_elf_ex = kmalloc(sizeof(*interp_elf_ex), GFP_KERNEL); if (!interp_elf_ex) { retval = -ENOMEM; - goto out_free_ph; + goto out_free_file; }
/* Get the exec headers */ @@ -1331,6 +1331,7 @@ out: out_free_dentry: kfree(interp_elf_ex); kfree(interp_elf_phdata); +out_free_file: allow_write_access(interpreter); if (interpreter) fput(interpreter);
From: Bernd Edlinger bernd.edlinger@hotmail.de
commit 5bf2fedca8f59379025b0d52f917b9ddb9bfe17e upstream.
unshare_sighand should only access oldsighand->action while holding oldsighand->siglock, to make sure that newsighand->action is in a consistent state.
Signed-off-by: Bernd Edlinger bernd.edlinger@hotmail.de Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Kees Cook keescook@chromium.org Link: https://lore.kernel.org/r/AM8PR10MB470871DEBD1DED081F9CC391E4389@AM8PR10MB47... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/exec.c +++ b/fs/exec.c @@ -1198,11 +1198,11 @@ static int unshare_sighand(struct task_s return -ENOMEM;
refcount_set(&newsighand->count, 1); - memcpy(newsighand->action, oldsighand->action, - sizeof(newsighand->action));
write_lock_irq(&tasklist_lock); spin_lock(&oldsighand->siglock); + memcpy(newsighand->action, oldsighand->action, + sizeof(newsighand->action)); rcu_assign_pointer(me->sighand, newsighand); spin_unlock(&oldsighand->siglock); write_unlock_irq(&tasklist_lock);
From: Miquel Raynal miquel.raynal@bootlin.com
commit 5a5c4e06fd03b595542d5590f2bc05a6b7fc5c2b upstream.
Back in 2014, the LQI was saved in the skb control buffer (skb->cb, or mac_cb(skb)) without any actual reset of this area prior to its use.
As part of a useful rework of the use of this region, 32edc40ae65c ("ieee802154: change _cb handling slightly") introduced mac_cb_init() to basically memset the cb field to 0. In particular, this new function got called at the beginning of mac802154_parse_frame_start(), right before the location where the buffer got actually filled.
What went through unnoticed however, is the fact that the very first helper called by device drivers in the receive path already used this area to save the LQI value for later extraction. Resetting the cb field "so late" led to systematically zeroing the LQI.
If we consider the reset of the cb field needed, we can make it as soon as we get an skb from a device driver, right before storing the LQI, as is the very first time we need to write something there.
Cc: stable@vger.kernel.org Fixes: 32edc40ae65c ("ieee802154: change _cb handling slightly") Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Acked-by: Alexander Aring aahringo@redhat.com Link: https://lore.kernel.org/r/20221020142535.1038885-1-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt stefan@datenfreihafen.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/mac802154/rx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c @@ -132,7 +132,7 @@ static int ieee802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr) { int hlen; - struct ieee802154_mac_cb *cb = mac_cb_init(skb); + struct ieee802154_mac_cb *cb = mac_cb(skb);
skb_reset_mac_header(skb);
@@ -294,8 +294,9 @@ void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi) { struct ieee802154_local *local = hw_to_local(hw); + struct ieee802154_mac_cb *cb = mac_cb_init(skb);
- mac_cb(skb)->lqi = lqi; + cb->lqi = lqi; skb->pkt_type = IEEE802154_RX_MSG; skb_queue_tail(&local->skb_queue, skb); tasklet_schedule(&local->tasklet);
From: Manish Rangankar mrangankar@marvell.com
commit 0b863257c17c5f57a41e0a48de140ed026957a63 upstream.
One of the sysfs values reported for supported_speeds was not valid (20Gb/s reported instead of 64Gb/s). Instead of driver internal speed mask definition, use speed mask defined in transport_fc for reporting host->supported_speeds.
Link: https://lore.kernel.org/r/20220927115946.17559-1-njavali@marvell.com Cc: stable@vger.kernel.org Reviewed-by: Himanshu Madhani himanshu.madhani@oracle.com Signed-off-by: Manish Rangankar mrangankar@marvell.com Signed-off-by: Nilesh Javali njavali@marvell.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/qla2xxx/qla_attr.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
--- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -3318,11 +3318,34 @@ struct fc_function_template qla2xxx_tran .bsg_timeout = qla24xx_bsg_timeout, };
+static uint +qla2x00_get_host_supported_speeds(scsi_qla_host_t *vha, uint speeds) +{ + uint supported_speeds = FC_PORTSPEED_UNKNOWN; + + if (speeds & FDMI_PORT_SPEED_64GB) + supported_speeds |= FC_PORTSPEED_64GBIT; + if (speeds & FDMI_PORT_SPEED_32GB) + supported_speeds |= FC_PORTSPEED_32GBIT; + if (speeds & FDMI_PORT_SPEED_16GB) + supported_speeds |= FC_PORTSPEED_16GBIT; + if (speeds & FDMI_PORT_SPEED_8GB) + supported_speeds |= FC_PORTSPEED_8GBIT; + if (speeds & FDMI_PORT_SPEED_4GB) + supported_speeds |= FC_PORTSPEED_4GBIT; + if (speeds & FDMI_PORT_SPEED_2GB) + supported_speeds |= FC_PORTSPEED_2GBIT; + if (speeds & FDMI_PORT_SPEED_1GB) + supported_speeds |= FC_PORTSPEED_1GBIT; + + return supported_speeds; +} + void qla2x00_init_host_attr(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - u32 speeds = FC_PORTSPEED_UNKNOWN; + u32 speeds = 0, fdmi_speed = 0;
fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); @@ -3332,7 +3355,8 @@ qla2x00_init_host_attr(scsi_qla_host_t * fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
- speeds = qla25xx_fdmi_port_speed_capability(ha); + fdmi_speed = qla25xx_fdmi_port_speed_capability(ha); + speeds = qla2x00_get_host_supported_speeds(vha, fdmi_speed);
fc_host_supported_speeds(vha->host) = speeds; }
From: Prike Liang Prike.Liang@amd.com
commit d61e1d1d5225a9baeb995bcbdb904f66f70ed87e upstream.
In the S2idle suspend/resume phase the gfxoff is keeping functional so some IP blocks will be likely to reinitialize at gfxoff entry and that will result in failing to program GC registers.Therefore, let disallow gfxoff until AMDGPU IPs reinitialized completely.
Signed-off-by: Prike Liang Prike.Liang@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org # 5.15.x Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3185,6 +3185,15 @@ static int amdgpu_device_ip_resume_phase return r; } adev->ip_blocks[i].status.hw = true; + + if (adev->in_s0ix && adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) { + /* disable gfxoff for IP resume. The gfxoff will be re-enabled in + * amdgpu_device_resume() after IP resume. + */ + amdgpu_gfx_off_ctrl(adev, false); + DRM_DEBUG("will disable gfxoff for re-initializing other blocks\n"); + } + }
return 0; @@ -4114,6 +4123,13 @@ int amdgpu_device_resume(struct drm_devi /* Make sure IB tests flushed */ flush_delayed_work(&adev->delayed_init_work);
+ if (adev->in_s0ix) { + /* re-enable gfxoff after IP resume. This re-enables gfxoff after + * it was disabled for IP resume in amdgpu_device_ip_resume_phase2(). + */ + amdgpu_gfx_off_ctrl(adev, true); + DRM_DEBUG("will enable gfxoff for the mission mode\n"); + } if (fbcon) amdgpu_fbdev_set_suspend(adev, 0);
From: Johan Hovold johan+linaro@kernel.org
commit 2e786eb2f9cebb07e317226b60054df510b60c65 upstream.
Add the missing sanity check on the bridge counter to avoid corrupting data beyond the fixed-sized bridge array in case there are ever more than eight bridges.
Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Cc: stable@vger.kernel.org # 4.1 Signed-off-by: Johan Hovold johan+linaro@kernel.org Tested-by: Kuogee Hsieh quic_khsieh@quicinc.com Reviewed-by: Kuogee Hsieh quic_khsieh@quicinc.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Patchwork: https://patchwork.freedesktop.org/patch/502668/ Link: https://lore.kernel.org/r/20220913085320.8577-4-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar quic_abhinavk@quicinc.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/msm/dsi/dsi.c | 6 ++++++ 1 file changed, 6 insertions(+)
--- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -212,6 +212,12 @@ int msm_dsi_modeset_init(struct msm_dsi return -EINVAL;
priv = dev->dev_private; + + if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { + DRM_DEV_ERROR(dev->dev, "too many bridges\n"); + return -ENOSPC; + } + msm_dsi->dev = dev;
ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
From: Johan Hovold johan+linaro@kernel.org
commit 4c1294da6aed1f16d47a417dcfe6602833c3c95c upstream.
Add the missing sanity check on the bridge counter to avoid corrupting data beyond the fixed-sized bridge array in case there are ever more than eight bridges.
Fixes: a3376e3ec81c ("drm/msm: convert to drm_bridge") Cc: stable@vger.kernel.org # 3.12 Signed-off-by: Johan Hovold johan+linaro@kernel.org Tested-by: Kuogee Hsieh quic_khsieh@quicinc.com Reviewed-by: Kuogee Hsieh quic_khsieh@quicinc.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Patchwork: https://patchwork.freedesktop.org/patch/502670/ Link: https://lore.kernel.org/r/20220913085320.8577-5-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar quic_abhinavk@quicinc.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/msm/hdmi/hdmi.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -295,6 +295,11 @@ int msm_hdmi_modeset_init(struct hdmi *h struct platform_device *pdev = hdmi->pdev; int ret;
+ if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) { + DRM_DEV_ERROR(dev->dev, "too many bridges\n"); + return -ENOSPC; + } + hdmi->dev = dev; hdmi->encoder = encoder;
From: Johan Hovold johan+linaro@kernel.org
commit a79343dcaba4b11adb57350e0b6426906a9b658e upstream.
Device-managed resources allocated post component bind must be tied to the lifetime of the aggregate DRM device or they will not necessarily be released when binding of the aggregate device is deferred.
This is specifically true for the DP IRQ, which will otherwise remain requested so that the next bind attempt fails when requesting the IRQ a second time.
Since commit c3bf8e21b38a ("drm/msm/dp: Add eDP support via aux_bus") this can happen when the aux-bus panel driver has not yet been loaded so that probe is deferred.
Fix this by tying the device-managed lifetime of the DP IRQ to the DRM device so that it is released when bind fails.
Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Cc: stable@vger.kernel.org # 5.10 Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Signed-off-by: Johan Hovold johan+linaro@kernel.org Tested-by: Kuogee Hsieh quic_khsieh@quicinc.com Reviewed-by: Kuogee Hsieh quic_khsieh@quicinc.com Patchwork: https://patchwork.freedesktop.org/patch/502679/ Link: https://lore.kernel.org/r/20220913085320.8577-6-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar quic_abhinavk@quicinc.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1229,7 +1229,7 @@ int dp_display_request_irq(struct msm_dp return -EINVAL; }
- rc = devm_request_irq(&dp->pdev->dev, dp->irq, + rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq, dp_display_irq_handler, IRQF_TRIGGER_HIGH, "dp_display_isr", dp); if (rc < 0) {
From: James Clark james.clark@arm.com
commit 6746eae4bbaddcc16b40efb33dab79210828b3ce upstream.
cti_enable_hw() and cti_disable_hw() are called from an atomic context so shouldn't use runtime PM because it can result in a sleep when communicating with firmware.
Since commit 3c6656337852 ("Revert "firmware: arm_scmi: Add clock management to the SCMI power domain""), this causes a hang on Juno when running the Perf Coresight tests or running this command:
perf record -e cs_etm//u -- ls
This was also missed until the revert commit because pm_runtime_put() was called with the wrong device until commit 692c9a499b28 ("coresight: cti: Correct the parameter for pm_runtime_put")
With lock and scheduler debugging enabled the following is output:
coresight cti_sys0: cti_enable_hw -- dev:cti_sys0 parent: 20020000.cti BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1151 in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 330, name: perf-exec preempt_count: 2, expected: 0 RCU nest depth: 0, expected: 0 INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [<0000000000000000>] 0x0 hardirqs last disabled at (0): [<ffff80000822b394>] copy_process+0xa0c/0x1948 softirqs last enabled at (0): [<ffff80000822b394>] copy_process+0xa0c/0x1948 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 3 PID: 330 Comm: perf-exec Not tainted 6.0.0-00053-g042116d99298 #7 Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Sep 13 2022 Call trace: dump_backtrace+0x134/0x140 show_stack+0x20/0x58 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 __might_resched+0x180/0x228 __might_sleep+0x50/0x88 __pm_runtime_resume+0xac/0xb0 cti_enable+0x44/0x120 coresight_control_assoc_ectdev+0xc0/0x150 coresight_enable_path+0xb4/0x288 etm_event_start+0x138/0x170 etm_event_add+0x48/0x70 event_sched_in.isra.122+0xb4/0x280 merge_sched_in+0x1fc/0x3d0 visit_groups_merge.constprop.137+0x16c/0x4b0 ctx_sched_in+0x114/0x1f0 perf_event_sched_in+0x60/0x90 ctx_resched+0x68/0xb0 perf_event_exec+0x138/0x508 begin_new_exec+0x52c/0xd40 load_elf_binary+0x6b8/0x17d0 bprm_execve+0x360/0x7f8 do_execveat_common.isra.47+0x218/0x238 __arm64_sys_execve+0x48/0x60 invoke_syscall+0x4c/0x110 el0_svc_common.constprop.4+0xfc/0x120 do_el0_svc+0x34/0xc0 el0_svc+0x40/0x98 el0t_64_sync_handler+0x98/0xc0 el0t_64_sync+0x170/0x174
Fix the issue by removing the runtime PM calls completely. They are not needed here because it must have already been done when building the path for a trace.
Fixes: 835d722ba10a ("coresight: cti: Initial CoreSight CTI Driver") Cc: stable stable@kernel.org Reported-by: Aishwarya TCV Aishwarya.TCV@arm.com Reported-by: Cristian Marussi Cristian.Marussi@arm.com Suggested-by: Suzuki K Poulose suzuki.poulose@arm.com Signed-off-by: James Clark james.clark@arm.com Reviewed-by: Mike Leach mike.leach@linaro.org Tested-by: Mike Leach mike.leach@linaro.org [ Fix build warnings ] Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Link: https://lore.kernel.org/r/20221025131032.1149459-1-suzuki.poulose@arm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/hwtracing/coresight/coresight-cti-core.c | 5 ----- 1 file changed, 5 deletions(-)
--- a/drivers/hwtracing/coresight/coresight-cti-core.c +++ b/drivers/hwtracing/coresight/coresight-cti-core.c @@ -90,11 +90,9 @@ void cti_write_all_hw_regs(struct cti_dr static int cti_enable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct device *dev = &drvdata->csdev->dev; unsigned long flags; int rc = 0;
- pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags);
/* no need to do anything if enabled or unpowered*/ @@ -119,7 +117,6 @@ cti_state_unchanged: /* cannot enable due to error */ cti_err_not_enabled: spin_unlock_irqrestore(&drvdata->spinlock, flags); - pm_runtime_put(dev->parent); return rc; }
@@ -153,7 +150,6 @@ cti_hp_not_enabled: static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; - struct device *dev = &drvdata->csdev->dev; struct coresight_device *csdev = drvdata->csdev;
spin_lock(&drvdata->spinlock); @@ -175,7 +171,6 @@ static int cti_disable_hw(struct cti_drv coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); - pm_runtime_put(dev->parent); return 0;
/* not disabled this call */
From: Brian Norris briannorris@chromium.org
commit 8d280b1df87e0b3d1355aeac7e62b62214b93f1c upstream.
REGMAP_MMIO is not user-configurable, so we can only satisfy this dependency by enabling some other Kconfig symbol that properly 'select's it. Use select like everybody else.
Noticed when trying to enable this driver for compile testing.
Fixes: 59592cc1f593 ("mmc: sdhci_am654: Add dependency on MMC_SDHCI_AM654") Signed-off-by: Brian Norris briannorris@chromium.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221024180300.2292208-1-briannorris@chromium.org Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1069,9 +1069,10 @@ config MMC_SDHCI_OMAP
config MMC_SDHCI_AM654 tristate "Support for the SDHCI Controller in TI's AM654 SOCs" - depends on MMC_SDHCI_PLTFM && OF && REGMAP_MMIO + depends on MMC_SDHCI_PLTFM && OF select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI + select REGMAP_MMIO help This selects the Secure Digital Host Controller Interface (SDHCI) support present in TI's AM654 SOCs. The controller supports
From: Matthew Ma mahongwei@zeku.com
commit 9972e6b404884adae9eec7463e30d9b3c9a70b18 upstream.
SDIO tuple is only allocated for standard SDIO card, especially it causes memory corruption issues when the non-standard SDIO card has removed, which is because the card device's reference counter does not increase for it at sdio_init_func(), but all SDIO card device reference counter gets decreased at sdio_release_func().
Fixes: 6f51be3d37df ("sdio: allow non-standard SDIO cards") Signed-off-by: Matthew Ma mahongwei@zeku.com Reviewed-by: Weizhao Ouyang ouyangweizhao@zeku.com Reviewed-by: John Wang wangdayu@zeku.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221014034951.2300386-1-ouyangweizhao@zeku.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/core/sdio_bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -290,7 +290,8 @@ static void sdio_release_func(struct dev { struct sdio_func *func = dev_to_sdio_func(dev);
- sdio_free_func_cis(func); + if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO)) + sdio_free_func_cis(func);
kfree(func->info); kfree(func->tmpbuf);
From: Patrick Thompson ptf@google.com
commit 9dc0033e4658d6f9d9952c3c0c6be3ec25bc2985 upstream.
Enhanced Strobe (ES) does not work correctly on the ASUS 1100 series of devices. Jasper Lake eMMCs (pci_id 8086:4dc4) are supposed to support ES. There are also two system families under the series, thus this is being scoped to the ASUS BIOS.
The failing ES prevents the installer from writing to disk. Falling back to HS400 without ES fixes the issue.
Signed-off-by: Patrick Thompson ptf@google.com Fixes: 315e3bd7ac19 ("mmc: sdhci-pci: Add support for Intel JSL") Acked-by: Adrian Hunter adrian.hunter@intel.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221013210017.3751025-1-ptf@google.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-pci-core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
--- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -978,6 +978,12 @@ static bool glk_broken_cqhci(struct sdhc dmi_match(DMI_SYS_VENDOR, "IRBIS")); }
+static bool jsl_broken_hs400es(struct sdhci_pci_slot *slot) +{ + return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_JSL_EMMC && + dmi_match(DMI_BIOS_VENDOR, "ASUSTeK COMPUTER INC."); +} + static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) { int ret = byt_emmc_probe_slot(slot); @@ -986,9 +992,11 @@ static int glk_emmc_probe_slot(struct sd slot->host->mmc->caps2 |= MMC_CAP2_CQE;
if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { - slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; - slot->host->mmc_host_ops.hs400_enhanced_strobe = - intel_hs400_enhanced_strobe; + if (!jsl_broken_hs400es(slot)) { + slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; + slot->host->mmc_host_ops.hs400_enhanced_strobe = + intel_hs400_enhanced_strobe; + } slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; }
From: Sascha Hauer s.hauer@pengutronix.de
commit 1ed5c3b22fc78735c539e4767832aea58db6761c upstream.
The core issues the warning "drop HS400 support since no 8-bit bus" when one of the ESDHC_FLAG_HS400* flags is set on a non 8bit capable host. To avoid this warning set these flags only on hosts that actually can do 8bit, i.e. have bus-width = <8> set in the device tree.
Signed-off-by: Sascha Hauer s.hauer@pengutronix.de Reviewed-by: Haibo Chen haibo.chen@nxp.com Fixes: 029e2476f9e6 ("mmc: sdhci-esdhc-imx: add HS400_ES support for i.MX8QXP") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221013093248.2220802-1-s.hauer@pengutronix.de Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/host/sdhci-esdhc-imx.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
--- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1643,6 +1643,10 @@ static int sdhci_esdhc_imx_probe(struct host->mmc_host_ops.execute_tuning = usdhc_execute_tuning; }
+ err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); + if (err) + goto disable_ahb_clk; + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) sdhci_esdhc_ops.platform_execute_tuning = esdhc_executing_tuning; @@ -1650,13 +1654,15 @@ static int sdhci_esdhc_imx_probe(struct if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
- if (imx_data->socdata->flags & ESDHC_FLAG_HS400) + if (host->caps & MMC_CAP_8_BIT_DATA && + imx_data->socdata->flags & ESDHC_FLAG_HS400) host->mmc->caps2 |= MMC_CAP2_HS400;
if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
- if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { + if (host->caps & MMC_CAP_8_BIT_DATA && + imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { host->mmc->caps2 |= MMC_CAP2_HS400_ES; host->mmc_host_ops.hs400_enhanced_strobe = esdhc_hs400_enhanced_strobe; @@ -1678,10 +1684,6 @@ static int sdhci_esdhc_imx_probe(struct goto disable_ahb_clk; }
- err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); - if (err) - goto disable_ahb_clk; - sdhci_esdhc_imx_hwinit(host);
err = sdhci_add_host(host);
From: William Breathitt Gray william.gray@linaro.org
commit d917a62af81b133f35f627e7936e193c842a7947 upstream.
The signal_read(), action_read(), and action_write() callbacks have been assuming Signal0 is requested without checking. This results in requests for Signal1 returning data for Signal0. This patch fixes these oversights by properly checking for the Signal's id in the respective callbacks and handling accordingly based on the particular Signal requested. The trig_inverted member of the mchp_tc_data is removed as superfluous.
Fixes: 106b104137fd ("counter: Add microchip TCB capture counter") Cc: stable@vger.kernel.org Reviewed-by: Kamel Bouhara kamel.bouhara@bootlin.com Link: https://lore.kernel.org/r/20221018121014.7368-1-william.gray@linaro.org/ Signed-off-by: William Breathitt Gray william.gray@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/counter/microchip-tcb-capture.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
--- a/drivers/counter/microchip-tcb-capture.c +++ b/drivers/counter/microchip-tcb-capture.c @@ -29,7 +29,6 @@ struct mchp_tc_data { int qdec_mode; int num_channels; int channel[2]; - bool trig_inverted; };
enum mchp_tc_count_function { @@ -166,7 +165,7 @@ static int mchp_tc_count_signal_read(str
regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
- if (priv->trig_inverted) + if (signal->id == 1) sigstatus = (sr & ATMEL_TC_MTIOB); else sigstatus = (sr & ATMEL_TC_MTIOA); @@ -184,6 +183,17 @@ static int mchp_tc_count_action_get(stru struct mchp_tc_data *const priv = counter->priv; u32 cmr;
+ if (priv->qdec_mode) { + *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; + return 0; + } + + /* Only TIOA signal is evaluated in non-QDEC mode */ + if (synapse->signal->id != 0) { + *action = COUNTER_SYNAPSE_ACTION_NONE; + return 0; + } + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
switch (cmr & ATMEL_TC_ETRGEDG) { @@ -212,8 +222,8 @@ static int mchp_tc_count_action_set(stru struct mchp_tc_data *const priv = counter->priv; u32 edge = ATMEL_TC_ETRGEDG_NONE;
- /* QDEC mode is rising edge only */ - if (priv->qdec_mode) + /* QDEC mode is rising edge only; only TIOA handled in non-QDEC mode */ + if (priv->qdec_mode || synapse->signal->id != 0) return -EINVAL;
switch (action) {
From: Christian A. Ehrhardt lk@c--e.de
commit 4abc99652812a2ddf932f137515d5c5a04723538 upstream.
Syzkaller managed to trigger concurrent calls to kernfs_remove_by_name_ns() for the same file resulting in a KASAN detected use-after-free. The race occurs when the root node is freed during kernfs_drain().
To prevent this acquire an additional reference for the root of the tree that is removed before calling __kernfs_remove().
Found by syzkaller with the following reproducer (slab_nomerge is required):
syz_mount_image$ext4(0x0, &(0x7f0000000100)='./file0\x00', 0x100000, 0x0, 0x0, 0x0, 0x0) r0 = openat(0xffffffffffffff9c, &(0x7f0000000080)='/proc/self/exe\x00', 0x0, 0x0) close(r0) pipe2(&(0x7f0000000140)={0xffffffffffffffff, <r1=>0xffffffffffffffff}, 0x800) mount$9p_fd(0x0, &(0x7f0000000040)='./file0\x00', &(0x7f00000000c0), 0x408, &(0x7f0000000280)={'trans=fd,', {'rfdno', 0x3d, r0}, 0x2c, {'wfdno', 0x3d, r1}, 0x2c, {[{@cache_loose}, {@mmap}, {@loose}, {@loose}, {@mmap}], [{@mask={'mask', 0x3d, '^MAY_EXEC'}}, {@fsmagic={'fsmagic', 0x3d, 0x10001}}, {@dont_hash}]}})
Sample report:
================================================================== BUG: KASAN: use-after-free in kernfs_type include/linux/kernfs.h:335 [inline] BUG: KASAN: use-after-free in kernfs_leftmost_descendant fs/kernfs/dir.c:1261 [inline] BUG: KASAN: use-after-free in __kernfs_remove.part.0+0x843/0x960 fs/kernfs/dir.c:1369 Read of size 2 at addr ffff8880088807f0 by task syz-executor.2/857
CPU: 0 PID: 857 Comm: syz-executor.2 Not tainted 6.0.0-rc3-00363-g7726d4c3e60b #5 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x6e/0x91 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:317 [inline] print_report.cold+0x5e/0x5e5 mm/kasan/report.c:433 kasan_report+0xa3/0x130 mm/kasan/report.c:495 kernfs_type include/linux/kernfs.h:335 [inline] kernfs_leftmost_descendant fs/kernfs/dir.c:1261 [inline] __kernfs_remove.part.0+0x843/0x960 fs/kernfs/dir.c:1369 __kernfs_remove fs/kernfs/dir.c:1356 [inline] kernfs_remove_by_name_ns+0x108/0x190 fs/kernfs/dir.c:1589 sysfs_slab_add+0x133/0x1e0 mm/slub.c:5943 __kmem_cache_create+0x3e0/0x550 mm/slub.c:4899 create_cache mm/slab_common.c:229 [inline] kmem_cache_create_usercopy+0x167/0x2a0 mm/slab_common.c:335 p9_client_create+0xd4d/0x1190 net/9p/client.c:993 v9fs_session_init+0x1e6/0x13c0 fs/9p/v9fs.c:408 v9fs_mount+0xb9/0xbd0 fs/9p/vfs_super.c:126 legacy_get_tree+0xf1/0x200 fs/fs_context.c:610 vfs_get_tree+0x85/0x2e0 fs/super.c:1530 do_new_mount fs/namespace.c:3040 [inline] path_mount+0x675/0x1d00 fs/namespace.c:3370 do_mount fs/namespace.c:3383 [inline] __do_sys_mount fs/namespace.c:3591 [inline] __se_sys_mount fs/namespace.c:3568 [inline] __x64_sys_mount+0x282/0x300 fs/namespace.c:3568 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7f725f983aed Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f725f0f7028 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 RAX: ffffffffffffffda RBX: 00007f725faa3f80 RCX: 00007f725f983aed RDX: 00000000200000c0 RSI: 0000000020000040 RDI: 0000000000000000 RBP: 00007f725f9f419c R08: 0000000020000280 R09: 0000000000000000 R10: 0000000000000408 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000006 R14: 00007f725faa3f80 R15: 00007f725f0d7000 </TASK>
Allocated by task 855: kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38 kasan_set_track mm/kasan/common.c:45 [inline] set_alloc_info mm/kasan/common.c:437 [inline] __kasan_slab_alloc+0x66/0x80 mm/kasan/common.c:470 kasan_slab_alloc include/linux/kasan.h:224 [inline] slab_post_alloc_hook mm/slab.h:727 [inline] slab_alloc_node mm/slub.c:3243 [inline] slab_alloc mm/slub.c:3251 [inline] __kmem_cache_alloc_lru mm/slub.c:3258 [inline] kmem_cache_alloc+0xbf/0x200 mm/slub.c:3268 kmem_cache_zalloc include/linux/slab.h:723 [inline] __kernfs_new_node+0xd4/0x680 fs/kernfs/dir.c:593 kernfs_new_node fs/kernfs/dir.c:655 [inline] kernfs_create_dir_ns+0x9c/0x220 fs/kernfs/dir.c:1010 sysfs_create_dir_ns+0x127/0x290 fs/sysfs/dir.c:59 create_dir lib/kobject.c:63 [inline] kobject_add_internal+0x24a/0x8d0 lib/kobject.c:223 kobject_add_varg lib/kobject.c:358 [inline] kobject_init_and_add+0x101/0x160 lib/kobject.c:441 sysfs_slab_add+0x156/0x1e0 mm/slub.c:5954 __kmem_cache_create+0x3e0/0x550 mm/slub.c:4899 create_cache mm/slab_common.c:229 [inline] kmem_cache_create_usercopy+0x167/0x2a0 mm/slab_common.c:335 p9_client_create+0xd4d/0x1190 net/9p/client.c:993 v9fs_session_init+0x1e6/0x13c0 fs/9p/v9fs.c:408 v9fs_mount+0xb9/0xbd0 fs/9p/vfs_super.c:126 legacy_get_tree+0xf1/0x200 fs/fs_context.c:610 vfs_get_tree+0x85/0x2e0 fs/super.c:1530 do_new_mount fs/namespace.c:3040 [inline] path_mount+0x675/0x1d00 fs/namespace.c:3370 do_mount fs/namespace.c:3383 [inline] __do_sys_mount fs/namespace.c:3591 [inline] __se_sys_mount fs/namespace.c:3568 [inline] __x64_sys_mount+0x282/0x300 fs/namespace.c:3568 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
Freed by task 857: kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38 kasan_set_track+0x21/0x30 mm/kasan/common.c:45 kasan_set_free_info+0x20/0x40 mm/kasan/generic.c:370 ____kasan_slab_free mm/kasan/common.c:367 [inline] ____kasan_slab_free mm/kasan/common.c:329 [inline] __kasan_slab_free+0x108/0x190 mm/kasan/common.c:375 kasan_slab_free include/linux/kasan.h:200 [inline] slab_free_hook mm/slub.c:1754 [inline] slab_free_freelist_hook mm/slub.c:1780 [inline] slab_free mm/slub.c:3534 [inline] kmem_cache_free+0x9c/0x340 mm/slub.c:3551 kernfs_put.part.0+0x2b2/0x520 fs/kernfs/dir.c:547 kernfs_put+0x42/0x50 fs/kernfs/dir.c:521 __kernfs_remove.part.0+0x72d/0x960 fs/kernfs/dir.c:1407 __kernfs_remove fs/kernfs/dir.c:1356 [inline] kernfs_remove_by_name_ns+0x108/0x190 fs/kernfs/dir.c:1589 sysfs_slab_add+0x133/0x1e0 mm/slub.c:5943 __kmem_cache_create+0x3e0/0x550 mm/slub.c:4899 create_cache mm/slab_common.c:229 [inline] kmem_cache_create_usercopy+0x167/0x2a0 mm/slab_common.c:335 p9_client_create+0xd4d/0x1190 net/9p/client.c:993 v9fs_session_init+0x1e6/0x13c0 fs/9p/v9fs.c:408 v9fs_mount+0xb9/0xbd0 fs/9p/vfs_super.c:126 legacy_get_tree+0xf1/0x200 fs/fs_context.c:610 vfs_get_tree+0x85/0x2e0 fs/super.c:1530 do_new_mount fs/namespace.c:3040 [inline] path_mount+0x675/0x1d00 fs/namespace.c:3370 do_mount fs/namespace.c:3383 [inline] __do_sys_mount fs/namespace.c:3591 [inline] __se_sys_mount fs/namespace.c:3568 [inline] __x64_sys_mount+0x282/0x300 fs/namespace.c:3568 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff888008880780 which belongs to the cache kernfs_node_cache of size 128 The buggy address is located 112 bytes inside of 128-byte region [ffff888008880780, ffff888008880800)
The buggy address belongs to the physical page: page:00000000732833f8 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8880 flags: 0x100000000000200(slab|node=0|zone=1) raw: 0100000000000200 0000000000000000 dead000000000122 ffff888001147280 raw: 0000000000000000 0000000000150015 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected
Memory state around the buggy address: ffff888008880680: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb ffff888008880700: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff888008880780: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^ ffff888008880800: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb ffff888008880880: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ==================================================================
Acked-by: Tejun Heo tj@kernel.org Cc: stable stable@kernel.org # -rc3 Signed-off-by: Christian A. Ehrhardt lk@c--e.de Link: https://lore.kernel.org/r/20220913121723.691454-1-lk@c--e.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/kernfs/dir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
--- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1547,8 +1547,11 @@ int kernfs_remove_by_name_ns(struct kern down_write(&kernfs_rwsem);
kn = kernfs_find_ns(parent, name, ns); - if (kn) + if (kn) { + kernfs_get(kn); __kernfs_remove(kn); + kernfs_put(kn); + }
up_write(&kernfs_rwsem);
From: Siarhei Volkau lis8215@gmail.com
commit 17747577bbcb496e1b1c4096d64c2fc1e7bc0fef upstream.
Fixes UART1 function bits and MMC groups typo.
For pins 0x97,0x99 function 0 is designated to PWM3/PWM5 respectively, function is 1 designated to the UART1.
Diff from v1: - sent separately - added tag Fixes
Cc: stable@vger.kernel.org Fixes: b582b5a434d3 ("pinctrl: Ingenic: Add pinctrl driver for JZ4755.") Tested-by: Siarhei Volkau lis8215@gmail.com Signed-off-by: Siarhei Volkau lis8215@gmail.com Link: https://lore.kernel.org/r/20221016153548.3024209-1-lis8215@gmail.com Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/pinctrl/pinctrl-ingenic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -643,7 +643,7 @@ static u8 jz4755_lcd_24bit_funcs[] = { 1 static const struct group_desc jz4755_groups[] = { INGENIC_PIN_GROUP("uart0-data", jz4755_uart0_data, 0), INGENIC_PIN_GROUP("uart0-hwflow", jz4755_uart0_hwflow, 0), - INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 0), + INGENIC_PIN_GROUP("uart1-data", jz4755_uart1_data, 1), INGENIC_PIN_GROUP("uart2-data", jz4755_uart2_data, 1), INGENIC_PIN_GROUP("ssi-dt-b", jz4755_ssi_dt_b, 0), INGENIC_PIN_GROUP("ssi-dt-f", jz4755_ssi_dt_f, 0), @@ -697,7 +697,7 @@ static const char *jz4755_ssi_groups[] = "ssi-ce1-b", "ssi-ce1-f", }; static const char *jz4755_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", }; -static const char *jz4755_mmc1_groups[] = { "mmc0-1bit", "mmc0-4bit", }; +static const char *jz4755_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", }; static const char *jz4755_i2c_groups[] = { "i2c-data", }; static const char *jz4755_cim_groups[] = { "cim-data", }; static const char *jz4755_lcd_groups[] = {
From: Pavel Kozlov pavel.kozlov@synopsys.com
commit 4fd9df10cb7a9289fbd22d669f9f98164d95a1ce upstream.
Since commit d9820ff ("ARC: mm: switch pgtable_t back to struct page *") a memory leakage problem occurs. Memory allocated for page table entries not released during process termination. This issue can be reproduced by a small program that allocates a large amount of memory. After several runs, you'll see that the amount of free memory has reduced and will continue to reduce after each run. All ARC CPUs are effected by this issue. The issue was introduced since the kernel stable release v5.15-rc1.
As described in commit d9820ff after switch pgtable_t back to struct page *, a pointer to "struct page" and appropriate functions are used to allocate and free a memory page for PTEs, but the pmd_pgtable macro hasn't changed and returns the direct virtual address from the PMD (PGD) entry. Than this address used as a parameter in the __pte_free() and as a result this function couldn't release memory page allocated for PTEs.
Fix this issue by changing the pmd_pgtable macro and returning pointer to struct page.
Fixes: d9820ff76f95 ("ARC: mm: switch pgtable_t back to struct page *") Cc: Mike Rapoport rppt@kernel.org Cc: stable@vger.kernel.org # 5.15.x Signed-off-by: Pavel Kozlov pavel.kozlov@synopsys.com Signed-off-by: Vineet Gupta vgupta@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arc/include/asm/pgtable-levels.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arc/include/asm/pgtable-levels.h +++ b/arch/arc/include/asm/pgtable-levels.h @@ -163,7 +163,7 @@ #define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK) #define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd)) #define set_pmd(pmdp, pmd) (*(pmdp) = pmd) -#define pmd_pgtable(pmd) ((pgtable_t) pmd_page_vaddr(pmd)) +#define pmd_pgtable(pmd) ((pgtable_t) pmd_page(pmd))
/* * 4th level paging: pte
From: Adrian Hunter adrian.hunter@intel.com
commit cba04f3136b658583adb191556f99d087589c1cc upstream.
For modules, names from kallsyms__parse() contain the module name which meant that module symbols did not match exactly by name.
Fix by matching the name string up to the separating tab character.
Fixes: 1b36c03e356936d6 ("perf record: Add support for using symbols in address filters") Signed-off-by: Adrian Hunter adrian.hunter@intel.com Cc: Adrian Hunter adrian.hunter@intel.com Cc: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@kernel.org Cc: Namhyung Kim namhyung@kernel.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20221026072736.2982-1-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- tools/perf/util/auxtrace.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
--- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -2260,11 +2260,19 @@ struct sym_args { bool near; };
+static bool kern_sym_name_match(const char *kname, const char *name) +{ + size_t n = strlen(name); + + return !strcmp(kname, name) || + (!strncmp(kname, name, n) && kname[n] == '\t'); +} + static bool kern_sym_match(struct sym_args *args, const char *name, char type) { /* A function with the same name, and global or the n'th found or any */ return kallsyms__is_function(type) && - !strcmp(name, args->name) && + kern_sym_name_match(name, args->name) && ((args->global && isupper(type)) || (args->selected && ++(args->cnt) == args->idx) || (!args->global && !args->selected));
From: Heiko Carstens hca@linux.ibm.com
commit a262d3ad6a433e4080cecd0a8841104a5906355e upstream.
For some exception types the instruction address points behind the instruction that caused the exception. Take that into account and add the missing exception table entry.
Cc: stable@vger.kernel.org Reviewed-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/s390/include/asm/futex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/s390/include/asm/futex.h +++ b/arch/s390/include/asm/futex.h @@ -16,7 +16,8 @@ "3: jl 1b\n" \ " lhi %0,0\n" \ "4: sacf 768\n" \ - EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b) \ + EX_TABLE(0b,4b) EX_TABLE(1b,4b) \ + EX_TABLE(2b,4b) EX_TABLE(3b,4b) \ : "=d" (ret), "=&d" (oldval), "=&d" (newval), \ "=m" (*uaddr) \ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
From: Heiko Carstens hca@linux.ibm.com
commit 6ec803025cf3173a57222e4411097166bd06fa98 upstream.
For some exception types the instruction address points behind the instruction that caused the exception. Take that into account and add the missing exception table entry.
Cc: stable@vger.kernel.org Fixes: f058599e22d5 ("s390/pci: Fix s390_mmio_read/write with MIO") Reviewed-by: Niklas Schnelle schnelle@linux.ibm.com Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/s390/pci/pci_mmio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
--- a/arch/s390/pci/pci_mmio.c +++ b/arch/s390/pci/pci_mmio.c @@ -63,7 +63,7 @@ static inline int __pcistg_mio_inuser( asm volatile ( " sacf 256\n" "0: llgc %[tmp],0(%[src])\n" - " sllg %[val],%[val],8\n" + "4: sllg %[val],%[val],8\n" " aghi %[src],1\n" " ogr %[val],%[tmp]\n" " brctg %[cnt],0b\n" @@ -71,7 +71,7 @@ static inline int __pcistg_mio_inuser( "2: ipm %[cc]\n" " srl %[cc],28\n" "3: sacf 768\n" - EX_TABLE(0b, 3b) EX_TABLE(1b, 3b) EX_TABLE(2b, 3b) + EX_TABLE(0b, 3b) EX_TABLE(4b, 3b) EX_TABLE(1b, 3b) EX_TABLE(2b, 3b) : [src] "+a" (src), [cnt] "+d" (cnt), [val] "+d" (val), [tmp] "=d" (tmp), @@ -214,10 +214,10 @@ static inline int __pcilg_mio_inuser( "2: ahi %[shift],-8\n" " srlg %[tmp],%[val],0(%[shift])\n" "3: stc %[tmp],0(%[dst])\n" - " aghi %[dst],1\n" + "5: aghi %[dst],1\n" " brctg %[cnt],2b\n" "4: sacf 768\n" - EX_TABLE(0b, 4b) EX_TABLE(1b, 4b) EX_TABLE(3b, 4b) + EX_TABLE(0b, 4b) EX_TABLE(1b, 4b) EX_TABLE(3b, 4b) EX_TABLE(5b, 4b) : [ioaddr_len] "+&d" (ioaddr_len.pair), [cc] "+d" (cc), [val] "=d" (val),
From: James Smart jsmart2021@gmail.com
This reverts commit 17bf429b913b9e7f8d2353782e24ed3a491bb2d8.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its a fix specific to the Path Split patches, which were partially included and now being pulled from 5.15.
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-)
--- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -11968,7 +11968,7 @@ lpfc_sli_enable_msi(struct lpfc_hba *phb rc = pci_enable_msi(phba->pcidev); if (!rc) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "0012 PCI enable MSI mode success.\n"); + "0462 PCI enable MSI mode success.\n"); else { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0471 PCI enable MSI mode failed (%d)\n", rc); --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1939,7 +1939,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba sync_buf = __lpfc_sli_get_iocbq(phba); if (!sync_buf) { lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT, - "6244 No available WQEs for CMF_SYNC_WQE\n"); + "6213 No available WQEs for CMF_SYNC_WQE\n"); ret_val = ENOMEM; goto out_unlock; } @@ -3739,7 +3739,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb set_job_ulpword4(cmdiocbp, IOERR_ABORT_REQUESTED); /* - * For SLI4, irspiocb contains + * For SLI4, irsiocb contains * NO_XRI in sli_xritag, it * shall not affect releasing * sgl (xri) process. @@ -3757,7 +3757,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb } } } - cmdiocbp->cmd_cmpl(phba, cmdiocbp, saveq); + (cmdiocbp->cmd_cmpl) (phba, cmdiocbp, saveq); } else lpfc_sli_release_iocbq(phba, cmdiocbp); } else { @@ -3997,7 +3997,8 @@ lpfc_sli_handle_fast_ring_event(struct l cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; if (cmdiocbq->cmd_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - cmdiocbq->cmd_cmpl(phba, cmdiocbq, &rspiocbq); + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, + &rspiocbq); spin_lock_irqsave(&phba->hbalock, iflag); } break; @@ -10937,7 +10938,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_fcp_io_s3 is wrapper function to invoke lockless func to - * send an iocb command to an HBA with SLI-3 interface spec. + * send an iocb command to an HBA with SLI-4 interface spec. * * This function takes the hbalock before invoking the lockless version. * The function will return success after it successfully submit the wqe to @@ -12990,7 +12991,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl; cmdiocbq->wait_cmd_cmpl = NULL; if (cmdiocbq->cmd_cmpl) - cmdiocbq->cmd_cmpl(phba, cmdiocbq, NULL); + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, NULL); else lpfc_sli_release_iocbq(phba, cmdiocbq); return; @@ -13004,9 +13005,9 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba
/* Set the exchange busy flag for task management commands */ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && - !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { + !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf, - cur_iocbq); + cur_iocbq); if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY)) lpfc_cmd->flags |= LPFC_SBUF_XBUSY; else @@ -14144,7 +14145,7 @@ void lpfc_sli4_els_xri_abort_event_proc( * @irspiocbq: Pointer to work-queue completion queue entry. * * This routine handles an ELS work-queue completion event and construct - * a pseudo response ELS IOCBQ from the SLI4 ELS WCQE for the common + * a pseudo response ELS IODBQ from the SLI4 ELS WCQE for the common * discovery engine to handle. * * Return: Pointer to the receive IOCBQ, NULL otherwise. @@ -14188,7 +14189,7 @@ lpfc_sli4_els_preprocess_rspiocbq(struct
if (bf_get(lpfc_wcqe_c_xb, wcqe)) { spin_lock_irqsave(&phba->hbalock, iflags); - irspiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; + cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore(&phba->hbalock, iflags); }
@@ -15047,7 +15048,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc /* Pass the cmd_iocb and the wcqe to the upper layer */ memcpy(&cmdiocbq->wcqe_cmpl, wcqe, sizeof(struct lpfc_wcqe_complete)); - cmdiocbq->cmd_cmpl(phba, cmdiocbq, cmdiocbq); + (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, cmdiocbq); } else { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0375 FCP cmdiocb not callback function " @@ -19211,7 +19212,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vp
/* Free iocb created in lpfc_prep_seq */ list_for_each_entry_safe(curr_iocb, next_iocb, - &iocbq->list, list) { + &iocbq->list, list) { list_del_init(&curr_iocb->list); lpfc_sli_release_iocbq(phba, curr_iocb); }
From: James Smart jsmart2021@gmail.com
This reverts commit 6e99860de6f4e286c386f533c4d35e7e283803d4.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its a fix specific to the Path Split patches, which were partially included and now being pulled from 5.15.
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc_sli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1384,7 +1384,7 @@ static void __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { struct lpfc_sglq *sglq; - size_t start_clean = offsetof(struct lpfc_iocbq, wqe); + size_t start_clean = offsetof(struct lpfc_iocbq, iocb); unsigned long iflag = 0; struct lpfc_sli_ring *pring;
From: James Smart jsmart2021@gmail.com
This reverts commit 9a570069cdbbc28c4b5b4632d5c9369371ec739c.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its a fix specific to the Path Split patches, which were partially included and now being pulled from 5.15.
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc_sli.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
--- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3644,15 +3644,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb unsigned long iflag; u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag;
- if (phba->sli_rev == LPFC_SLI_REV4) - spin_lock_irqsave(&pring->ring_lock, iflag); - else - spin_lock_irqsave(&phba->hbalock, iflag); cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); - if (phba->sli_rev == LPFC_SLI_REV4) - spin_unlock_irqrestore(&pring->ring_lock, iflag); - else - spin_unlock_irqrestore(&phba->hbalock, iflag);
ulp_command = get_job_cmnd(phba, saveq); ulp_status = get_job_ulpstatus(phba, saveq); @@ -3989,8 +3981,10 @@ lpfc_sli_handle_fast_ring_event(struct l break; }
+ spin_unlock_irqrestore(&phba->hbalock, iflag); cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring, &rspiocbq); + spin_lock_irqsave(&phba->hbalock, iflag); if (unlikely(!cmdiocbq)) break; if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED)
From: James Smart jsmart2021@gmail.com
This reverts commit b4543dbea84c8b64566dd0d626d63f8cbe977f61.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its one of the partial Path Split patches that was included.
NOTE: fixed a git revert error which caused a new line to be inserted: line 5755 of lpfc_scsi.c in lpfc_queuecommand + atomic_inc(&ndlp->cmd_pending); Removed the line
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc.h | 4 drivers/scsi/lpfc/lpfc_scsi.c | 376 +++++++++++++++++++++++------------------- drivers/scsi/lpfc/lpfc_sli.c | 6 3 files changed, 211 insertions(+), 175 deletions(-)
--- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -920,10 +920,6 @@ struct lpfc_hba { (struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, uint8_t tmo); - int (*lpfc_scsi_prep_task_mgmt_cmd) - (struct lpfc_vport *vport, - struct lpfc_io_buf *lpfc_cmd, - u64 lun, u8 task_mgmt_cmd);
/* IOCB interface function jump table entries */ int (*__lpfc_sli_issue_iocb) --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2942,58 +2942,154 @@ out: * -1 - Internal error (bad profile, ...etc) */ static int -lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, - struct lpfc_iocbq *pIocbOut) +lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + struct lpfc_wcqe_complete *wcqe) { struct scsi_cmnd *cmd = lpfc_cmd->pCmd; - struct sli3_bg_fields *bgf; int ret = 0; - struct lpfc_wcqe_complete *wcqe; - u32 status; + u32 status = bf_get(lpfc_wcqe_c_status, wcqe); u32 bghm = 0; u32 bgstat = 0; u64 failing_sector = 0;
- if (phba->sli_rev == LPFC_SLI_REV4) { - wcqe = &pIocbOut->wcqe_cmpl; - status = bf_get(lpfc_wcqe_c_status, wcqe); + if (status == CQE_STATUS_DI_ERROR) { + if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ + bgstat |= BGS_GUARD_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */ + bgstat |= BGS_APPTAG_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */ + bgstat |= BGS_REFTAG_ERR_MASK; + + /* Check to see if there was any good data before the error */ + if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { + bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; + bghm = wcqe->total_data_placed; + }
- if (status == CQE_STATUS_DI_ERROR) { - /* Guard Check failed */ - if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) - bgstat |= BGS_GUARD_ERR_MASK; - - /* AppTag Check failed */ - if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) - bgstat |= BGS_APPTAG_ERR_MASK; - - /* RefTag Check failed */ - if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) - bgstat |= BGS_REFTAG_ERR_MASK; + /* + * Set ALL the error bits to indicate we don't know what + * type of error it is. + */ + if (!bgstat) + bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | + BGS_GUARD_ERR_MASK); + }
- /* Check to see if there was any good data before the - * error - */ - if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { - bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; - bghm = wcqe->total_data_placed; - } + if (lpfc_bgs_get_guard_err(bgstat)) { + ret = 1;
- /* - * Set ALL the error bits to indicate we don't know what - * type of error it is. - */ - if (!bgstat) - bgstat |= (BGS_REFTAG_ERR_MASK | - BGS_APPTAG_ERR_MASK | - BGS_GUARD_ERR_MASK); + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); + set_host_byte(cmd, DID_ABORT); + phba->bg_guard_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9059 BLKGRD: Guard Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + scsi_logical_block_count(cmd), bgstat, bghm); + } + + if (lpfc_bgs_get_reftag_err(bgstat)) { + ret = 1; + + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); + set_host_byte(cmd, DID_ABORT); + + phba->bg_reftag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9060 BLKGRD: Ref Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + scsi_logical_block_count(cmd), bgstat, bghm); + } + + if (lpfc_bgs_get_apptag_err(bgstat)) { + ret = 1; + + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); + set_host_byte(cmd, DID_ABORT); + + phba->bg_apptag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9062 BLKGRD: App Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + scsi_logical_block_count(cmd), bgstat, bghm); + } + + if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { + /* + * setup sense data descriptor 0 per SPC-4 as an information + * field, and put the failing LBA in it. + * This code assumes there was also a guard/app/ref tag error + * indication. + */ + cmd->sense_buffer[7] = 0xc; /* Additional sense length */ + cmd->sense_buffer[8] = 0; /* Information descriptor type */ + cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */ + cmd->sense_buffer[10] = 0x80; /* Validity bit */ + + /* bghm is a "on the wire" FC frame based count */ + switch (scsi_get_prot_op(cmd)) { + case SCSI_PROT_READ_INSERT: + case SCSI_PROT_WRITE_STRIP: + bghm /= cmd->device->sector_size; + break; + case SCSI_PROT_READ_STRIP: + case SCSI_PROT_WRITE_INSERT: + case SCSI_PROT_READ_PASS: + case SCSI_PROT_WRITE_PASS: + bghm /= (cmd->device->sector_size + + sizeof(struct scsi_dif_tuple)); + break; }
- } else { - bgf = &pIocbOut->iocb.unsli3.sli3_bg; - bghm = bgf->bghm; - bgstat = bgf->bgstat; + failing_sector = scsi_get_lba(cmd); + failing_sector += bghm; + + /* Descriptor Information */ + put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]); + } + + if (!ret) { + /* No error was reported - problem in FW? */ + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9068 BLKGRD: Unknown error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + scsi_logical_block_count(cmd), bgstat, bghm); + + /* Calculate what type of error it was */ + lpfc_calc_bg_err(phba, lpfc_cmd); } + return ret; +} + +/* + * This function checks for BlockGuard errors detected by + * the HBA. In case of errors, the ASC/ASCQ fields in the + * sense buffer will be set accordingly, paired with + * ILLEGAL_REQUEST to signal to the kernel that the HBA + * detected corruption. + * + * Returns: + * 0 - No error found + * 1 - BlockGuard error found + * -1 - Internal error (bad profile, ...etc) + */ +static int +lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + struct lpfc_iocbq *pIocbOut) +{ + struct scsi_cmnd *cmd = lpfc_cmd->pCmd; + struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg; + int ret = 0; + uint32_t bghm = bgf->bghm; + uint32_t bgstat = bgf->bgstat; + uint64_t failing_sector = 0;
if (lpfc_bgs_get_invalid_prof(bgstat)) { cmd->result = DID_ERROR << 16; @@ -3021,6 +3117,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba,
if (lpfc_bgs_get_guard_err(bgstat)) { ret = 1; + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1); set_host_byte(cmd, DID_ABORT); phba->bg_guard_err_cnt++; @@ -3034,8 +3131,10 @@ lpfc_parse_bg_err(struct lpfc_hba *phba,
if (lpfc_bgs_get_reftag_err(bgstat)) { ret = 1; + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3); set_host_byte(cmd, DID_ABORT); + phba->bg_reftag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9056 BLKGRD: Ref Tag error in cmd " @@ -3047,8 +3146,10 @@ lpfc_parse_bg_err(struct lpfc_hba *phba,
if (lpfc_bgs_get_apptag_err(bgstat)) { ret = 1; + scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2); set_host_byte(cmd, DID_ABORT); + phba->bg_apptag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9061 BLKGRD: App Tag error in cmd " @@ -4093,6 +4194,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba struct Scsi_Host *shost; u32 logit = LOG_FCP; u32 status, idx; + unsigned long iflags = 0; u32 lat; u8 wait_xb_clr = 0;
@@ -4107,16 +4209,30 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba rdata = lpfc_cmd->rdata; ndlp = rdata->pnode;
+ if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + /* TOREMOVE - currently this flag is checked during + * the release of lpfc_iocbq. Remove once we move + * to lpfc_wqe_job construct. + * + * This needs to be done outside buf_lock + */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore(&phba->hbalock, iflags); + } + + /* Guard against abort handler being called at same time */ + spin_lock(&lpfc_cmd->buf_lock); + /* Sanity check on return of outstanding command */ cmd = lpfc_cmd->pCmd; if (!cmd) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "9042 I/O completion: Not an active IO\n"); + spin_unlock(&lpfc_cmd->buf_lock); lpfc_release_scsi_buf(phba, lpfc_cmd); return; } - /* Guard against abort handler being called at same time */ - spin_lock(&lpfc_cmd->buf_lock); idx = lpfc_cmd->cur_iocbq.hba_wqidx; if (phba->sli4_hba.hdwq) phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; @@ -4290,14 +4406,12 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba * This is a response for a BG enabled * cmd. Parse BG error */ - lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut); + lpfc_sli4_parse_bg_err(phba, lpfc_cmd, + wcqe); break; - } else { - lpfc_printf_vlog(vport, KERN_WARNING, - LOG_BG, - "9040 non-zero BGSTAT " - "on unprotected cmd\n"); } + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 non-zero BGSTAT on unprotected cmd\n"); } lpfc_printf_vlog(vport, KERN_WARNING, logit, "9036 Local Reject FCP cmd x%x failed" @@ -4902,7 +5016,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *v }
/** - * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit + * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit * @vport: The virtual port for which this call is being executed. * @lpfc_cmd: Pointer to lpfc_io_buf data structure. * @lun: Logical unit number. @@ -4916,9 +5030,10 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *v * 1 - Success **/ static int -lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport, - struct lpfc_io_buf *lpfc_cmd, - u64 lun, u8 task_mgmt_cmd) +lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + uint64_t lun, + uint8_t task_mgmt_cmd) { struct lpfc_iocbq *piocbq; IOCB_t *piocb; @@ -4939,10 +5054,15 @@ lpfc_scsi_prep_task_mgmt_cmd_s3(struct l memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); int_to_scsilun(lun, &fcp_cmnd->fcp_lun); fcp_cmnd->fcpCntl2 = task_mgmt_cmd; - if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) + if (vport->phba->sli_rev == 3 && + !(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); piocb->ulpCommand = CMD_FCP_ICMND64_CR; piocb->ulpContext = ndlp->nlp_rpi; + if (vport->phba->sli_rev == LPFC_SLI_REV4) { + piocb->ulpContext = + vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + } piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0; piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f); piocb->ulpPU = 0; @@ -4958,79 +5078,8 @@ lpfc_scsi_prep_task_mgmt_cmd_s3(struct l } else piocb->ulpTimeout = lpfc_cmd->timeout;
- return 1; -} - -/** - * lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit - * @vport: The virtual port for which this call is being executed. - * @lpfc_cmd: Pointer to lpfc_io_buf data structure. - * @lun: Logical unit number. - * @task_mgmt_cmd: SCSI task management command. - * - * This routine creates FCP information unit corresponding to @task_mgmt_cmd - * for device with SLI-4 interface spec. - * - * Return codes: - * 0 - Error - * 1 - Success - **/ -static int -lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport, - struct lpfc_io_buf *lpfc_cmd, - u64 lun, u8 task_mgmt_cmd) -{ - struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; - union lpfc_wqe128 *wqe = &pwqeq->wqe; - struct fcp_cmnd *fcp_cmnd; - struct lpfc_rport_data *rdata = lpfc_cmd->rdata; - struct lpfc_nodelist *ndlp = rdata->pnode; - - if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE) - return 0; - - pwqeq->vport = vport; - /* Initialize 64 bytes only */ - memset(wqe, 0, sizeof(union lpfc_wqe128)); - - /* From the icmnd template, initialize words 4 - 11 */ - memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4], - sizeof(uint32_t) * 8); - - fcp_cmnd = lpfc_cmd->fcp_cmnd; - /* Clear out any old data in the FCP command area */ - memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); - int_to_scsilun(lun, &fcp_cmnd->fcp_lun); - fcp_cmnd->fcpCntl3 = 0; - fcp_cmnd->fcpCntl2 = task_mgmt_cmd; - - bf_set(payload_offset_len, &wqe->fcp_icmd, - sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); - bf_set(cmd_buff_len, &wqe->fcp_icmd, 0); - bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, /* ulpContext */ - vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); - bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, - ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0)); - bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, - (ndlp->nlp_fcp_info & 0x0f)); - - /* ulpTimeout is only one byte */ - if (lpfc_cmd->timeout > 0xff) { - /* - * Do not timeout the command at the firmware level. - * The driver will provide the timeout mechanism. - */ - bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0); - } else { - bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout); - } - - lpfc_prep_embed_io(vport->phba, lpfc_cmd); - bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag); - wqe->generic.wqe_com.abort_tag = pwqeq->iotag; - bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); - - lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd); + if (vport->phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
return 1; } @@ -5057,8 +5106,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hb phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3; - phba->lpfc_scsi_prep_task_mgmt_cmd = - lpfc_scsi_prep_task_mgmt_cmd_s3; break; case LPFC_PCI_DEV_OC: phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; @@ -5066,8 +5113,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hb phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4; - phba->lpfc_scsi_prep_task_mgmt_cmd = - lpfc_scsi_prep_task_mgmt_cmd_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -5546,7 +5591,6 @@ lpfc_queuecommand(struct Scsi_Host *shos { struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - struct lpfc_iocbq *cur_iocbq = NULL; struct lpfc_rport_data *rdata; struct lpfc_nodelist *ndlp; struct lpfc_io_buf *lpfc_cmd; @@ -5640,7 +5684,6 @@ lpfc_queuecommand(struct Scsi_Host *shos } lpfc_cmd->rx_cmd_start = start;
- cur_iocbq = &lpfc_cmd->cur_iocbq; /* * Store the midlayer's command structure for the completion phase * and complete the command initialization. @@ -5648,7 +5691,7 @@ lpfc_queuecommand(struct Scsi_Host *shos lpfc_cmd->pCmd = cmnd; lpfc_cmd->rdata = rdata; lpfc_cmd->ndlp = ndlp; - cur_iocbq->cmd_cmpl = NULL; + lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; cmnd->host_scribble = (unsigned char *)lpfc_cmd;
err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); @@ -5690,6 +5733,7 @@ lpfc_queuecommand(struct Scsi_Host *shos goto out_host_busy_free_buf; }
+ /* check the necessary and sufficient condition to support VMID */ if (lpfc_is_vmid_enabled(phba) && (ndlp->vmid_support || @@ -5702,9 +5746,9 @@ lpfc_queuecommand(struct Scsi_Host *shos if (uuid) { err = lpfc_vmid_get_appid(vport, uuid, cmnd, (union lpfc_vmid_io_tag *) - &cur_iocbq->vmid_tag); + &lpfc_cmd->cur_iocbq.vmid_tag); if (!err) - cur_iocbq->cmd_flag |= LPFC_IO_VMID; + lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID; } }
@@ -5713,7 +5757,8 @@ lpfc_queuecommand(struct Scsi_Host *shos this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); #endif /* Issue I/O to adapter */ - err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq, + err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, + &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS if (start) { @@ -5726,25 +5771,25 @@ lpfc_queuecommand(struct Scsi_Host *shos #endif if (err) { lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "3376 FCP could not issue iocb err %x " - "FCP cmd x%x <%d/%llu> " - "sid: x%x did: x%x oxid: x%x " - "Data: x%x x%x x%x x%x\n", - err, cmnd->cmnd[0], - cmnd->device ? cmnd->device->id : 0xffff, - cmnd->device ? cmnd->device->lun : (u64)-1, - vport->fc_myDID, ndlp->nlp_DID, - phba->sli_rev == LPFC_SLI_REV4 ? - cur_iocbq->sli4_xritag : 0xffff, - phba->sli_rev == LPFC_SLI_REV4 ? - phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : - cur_iocbq->iocb.ulpContext, - cur_iocbq->iotag, - phba->sli_rev == LPFC_SLI_REV4 ? - bf_get(wqe_tmo, - &cur_iocbq->wqe.generic.wqe_com) : - cur_iocbq->iocb.ulpTimeout, - (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000)); + "3376 FCP could not issue IOCB err %x " + "FCP cmd x%x <%d/%llu> " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x x%x\n", + err, cmnd->cmnd[0], + cmnd->device ? cmnd->device->id : 0xffff, + cmnd->device ? cmnd->device->lun : (u64)-1, + vport->fc_myDID, ndlp->nlp_DID, + phba->sli_rev == LPFC_SLI_REV4 ? + lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, + phba->sli_rev == LPFC_SLI_REV4 ? + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : + lpfc_cmd->cur_iocbq.iocb.ulpContext, + lpfc_cmd->cur_iocbq.iotag, + phba->sli_rev == LPFC_SLI_REV4 ? + bf_get(wqe_tmo, + &lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) : + lpfc_cmd->cur_iocbq.iocb.ulpTimeout, + (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
goto out_host_busy_free_buf; } @@ -6121,7 +6166,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp return FAILED; pnode = rdata->pnode;
- lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL); + lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL); if (lpfc_cmd == NULL) return FAILED; lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; @@ -6129,8 +6174,8 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp lpfc_cmd->pCmd = cmnd; lpfc_cmd->ndlp = pnode;
- status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, - task_mgmt_cmd); + status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, + task_mgmt_cmd); if (!status) { lpfc_release_scsi_buf(phba, lpfc_cmd); return FAILED; @@ -6143,7 +6188,6 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp return FAILED; } iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl; - iocbq->vport = vport;
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "0702 Issue %s to TGT %d LUN %llu " @@ -6155,28 +6199,26 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, iocbq, iocbqrsp, lpfc_cmd->timeout); if ((status != IOCB_SUCCESS) || - (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) { + (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { if (status != IOCB_SUCCESS || - get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR) + iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0727 TMF %s to TGT %d LUN %llu " "failed (%d, %d) cmd_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, - get_job_ulpstatus(phba, iocbqrsp), - get_job_word4(phba, iocbqrsp), + iocbqrsp->iocb.ulpStatus, + iocbqrsp->iocb.un.ulpWord[4], iocbq->cmd_flag); /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ if (status == IOCB_SUCCESS) { - if (get_job_ulpstatus(phba, iocbqrsp) == - IOSTAT_FCP_RSP_ERROR) + if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) /* Something in the FCP_RSP was invalid. * Check conditions */ ret = lpfc_check_fcp_rsp(vport, lpfc_cmd); else ret = FAILED; - } else if ((status == IOCB_TIMEDOUT) || - (status == IOCB_ABORTED)) { + } else if (status == IOCB_TIMEDOUT) { ret = TIMEOUT_ERROR; } else { ret = FAILED; @@ -6186,7 +6228,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp
lpfc_sli_release_iocbq(phba, iocbqrsp);
- if (status != IOCB_TIMEDOUT) + if (ret != TIMEOUT_ERROR) lpfc_release_scsi_buf(phba, lpfc_cmd);
return ret; --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -12970,7 +12970,6 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba wait_queue_head_t *pdone_q; unsigned long iflags; struct lpfc_io_buf *lpfc_cmd; - size_t offset = offsetof(struct lpfc_iocbq, wqe);
spin_lock_irqsave(&phba->hbalock, iflags); if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) { @@ -12991,11 +12990,10 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba return; }
- /* Copy the contents of the local rspiocb into the caller's buffer. */ cmdiocbq->cmd_flag |= LPFC_IO_WAKE; if (cmdiocbq->context2 && rspiocbq) - memcpy((char *)cmdiocbq->context2 + offset, - (char *)rspiocbq + offset, sizeof(*rspiocbq) - offset); + memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, + &rspiocbq->iocb, sizeof(IOCB_t));
/* Set the exchange busy flag for task management commands */ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) &&
From: James Smart jsmart2021@gmail.com
This reverts commit c56cc7fefc3159049f94fb1318e48aa60cabf703.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its one of the partial Path Split patches that was included.
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc.h | 36 -- drivers/scsi/lpfc/lpfc_crtn.h | 1 drivers/scsi/lpfc/lpfc_hw4.h | 7 drivers/scsi/lpfc/lpfc_sli.c | 513 ++++++++++++++++++++++++------------------ drivers/scsi/lpfc/lpfc_sli.h | 2 5 files changed, 302 insertions(+), 257 deletions(-)
--- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1803,39 +1803,3 @@ static inline int lpfc_is_vmid_enabled(s { return phba->cfg_vmid_app_header || phba->cfg_vmid_priority_tagging; } - -static inline -u8 get_job_ulpstatus(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) -{ - if (phba->sli_rev == LPFC_SLI_REV4) - return bf_get(lpfc_wcqe_c_status, &iocbq->wcqe_cmpl); - else - return iocbq->iocb.ulpStatus; -} - -static inline -u32 get_job_word4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) -{ - if (phba->sli_rev == LPFC_SLI_REV4) - return iocbq->wcqe_cmpl.parameter; - else - return iocbq->iocb.un.ulpWord[4]; -} - -static inline -u8 get_job_cmnd(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) -{ - if (phba->sli_rev == LPFC_SLI_REV4) - return bf_get(wqe_cmnd, &iocbq->wqe.generic.wqe_com); - else - return iocbq->iocb.ulpCommand; -} - -static inline -u16 get_job_ulpcontext(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) -{ - if (phba->sli_rev == LPFC_SLI_REV4) - return bf_get(wqe_ctxt_tag, &iocbq->wqe.generic.wqe_com); - else - return iocbq->iocb.ulpContext; -} --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -129,7 +129,6 @@ void lpfc_disc_list_loopmap(struct lpfc_ void lpfc_disc_start(struct lpfc_vport *); void lpfc_cleanup_discovery_resources(struct lpfc_vport *); void lpfc_cleanup(struct lpfc_vport *); -void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd); void lpfc_disc_timeout(struct timer_list *);
int lpfc_unregister_fcf_prep(struct lpfc_hba *); --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -60,13 +60,6 @@ ((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \ ((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))
-#define get_wqe_reqtag(x) (((x)->wqe.words[9] >> 0) & 0xFFFF) - -#define get_job_ulpword(x, y) ((x)->iocb.un.ulpWord[y]) - -#define set_job_ulpstatus(x, y) bf_set(lpfc_wcqe_c_status, &(x)->wcqe_cmpl, y) -#define set_job_ulpword4(x, y) ((&(x)->wcqe_cmpl)->parameter = y) - struct dma_address { uint32_t addr_lo; uint32_t addr_hi; --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -70,9 +70,8 @@ static int lpfc_sli_issue_mbox_s4(struct uint32_t); static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, uint8_t *, uint32_t *); -static struct lpfc_iocbq * -lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, - struct lpfc_iocbq *rspiocbq); +static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *, + struct lpfc_iocbq *); static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, struct hbq_dmabuf *); static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, @@ -90,9 +89,6 @@ static struct lpfc_cqe *lpfc_sli4_cq_get static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe); -static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, - struct lpfc_iocbq *pwqeq, - struct lpfc_sglq *sglq);
union lpfc_wqe128 lpfc_iread_cmd_template; union lpfc_wqe128 lpfc_iwrite_cmd_template; @@ -3556,12 +3552,17 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *p struct lpfc_iocbq *prspiocb) { struct lpfc_iocbq *cmd_iocb = NULL; - u16 iotag; + uint16_t iotag; + spinlock_t *temp_lock = NULL; + unsigned long iflag = 0;
if (phba->sli_rev == LPFC_SLI_REV4) - iotag = get_wqe_reqtag(prspiocb); + temp_lock = &pring->ring_lock; else - iotag = prspiocb->iocb.ulpIoTag; + temp_lock = &phba->hbalock; + + spin_lock_irqsave(temp_lock, iflag); + iotag = prspiocb->iocb.ulpIoTag;
if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; @@ -3570,14 +3571,17 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *p list_del_init(&cmd_iocb->list); cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; + spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; } }
+ spin_unlock_irqrestore(temp_lock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0317 iotag x%x is out of " - "range: max iotag x%x\n", - iotag, phba->sli.last_iotag); + "range: max iotag x%x wd0 x%x\n", + iotag, phba->sli.last_iotag, + *(((uint32_t *) &prspiocb->iocb) + 7)); return NULL; }
@@ -3598,7 +3602,15 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc struct lpfc_sli_ring *pring, uint16_t iotag) { struct lpfc_iocbq *cmd_iocb = NULL; + spinlock_t *temp_lock = NULL; + unsigned long iflag = 0;
+ if (phba->sli_rev == LPFC_SLI_REV4) + temp_lock = &pring->ring_lock; + else + temp_lock = &phba->hbalock; + + spin_lock_irqsave(temp_lock, iflag); if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { @@ -3606,10 +3618,12 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc list_del_init(&cmd_iocb->list); cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; + spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; } }
+ spin_unlock_irqrestore(temp_lock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0372 iotag x%x lookup error: max iotag (x%x) " "cmd_flag x%x\n", @@ -3642,29 +3656,18 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb struct lpfc_iocbq *cmdiocbp; int rc = 1; unsigned long iflag; - u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag;
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); - - ulp_command = get_job_cmnd(phba, saveq); - ulp_status = get_job_ulpstatus(phba, saveq); - ulp_word4 = get_job_word4(phba, saveq); - ulp_context = get_job_ulpcontext(phba, saveq); - if (phba->sli_rev == LPFC_SLI_REV4) - iotag = get_wqe_reqtag(saveq); - else - iotag = saveq->iocb.ulpIoTag; - if (cmdiocbp) { - ulp_command = get_job_cmnd(phba, cmdiocbp); if (cmdiocbp->cmd_cmpl) { /* * If an ELS command failed send an event to mgmt * application. */ - if (ulp_status && + if (saveq->iocb.ulpStatus && (pring->ringno == LPFC_ELS_RING) && - (ulp_command == CMD_ELS_REQUEST64_CR)) + (cmdiocbp->iocb.ulpCommand == + CMD_ELS_REQUEST64_CR)) lpfc_send_els_failure_event(phba, cmdiocbp, saveq);
@@ -3726,20 +3729,20 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore( &phba->hbalock, iflag); - set_job_ulpstatus(cmdiocbp, - IOSTAT_LOCAL_REJECT); - set_job_ulpword4(cmdiocbp, - IOERR_ABORT_REQUESTED); + cmdiocbp->iocb.ulpStatus = + IOSTAT_LOCAL_REJECT; + cmdiocbp->iocb.un.ulpWord[4] = + IOERR_ABORT_REQUESTED; /* * For SLI4, irsiocb contains * NO_XRI in sli_xritag, it * shall not affect releasing * sgl (xri) process. */ - set_job_ulpstatus(saveq, - IOSTAT_LOCAL_REJECT); - set_job_ulpword4(saveq, - IOERR_SLI_ABORTED); + saveq->iocb.ulpStatus = + IOSTAT_LOCAL_REJECT; + saveq->iocb.un.ulpWord[4] = + IOERR_SLI_ABORTED; spin_lock_irqsave( &phba->hbalock, iflag); saveq->cmd_flag |= @@ -3767,8 +3770,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb "0322 Ring %d handler: " "unexpected completion IoTag x%x " "Data: x%x x%x x%x x%x\n", - pring->ringno, iotag, ulp_status, - ulp_word4, ulp_command, ulp_context); + pring->ringno, + saveq->iocb.ulpIoTag, + saveq->iocb.ulpStatus, + saveq->iocb.un.ulpWord[4], + saveq->iocb.ulpCommand, + saveq->iocb.ulpContext); } }
@@ -4083,159 +4090,155 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_h struct lpfc_iocbq *rspiocbp) { struct lpfc_iocbq *saveq; - struct lpfc_iocbq *cmdiocb; + struct lpfc_iocbq *cmdiocbp; struct lpfc_iocbq *next_iocb; - IOCB_t *irsp; + IOCB_t *irsp = NULL; uint32_t free_saveq; - u8 cmd_type; + uint8_t iocb_cmd_type; lpfc_iocb_type type; unsigned long iflag; - u32 ulp_status = get_job_ulpstatus(phba, rspiocbp); - u32 ulp_word4 = get_job_word4(phba, rspiocbp); - u32 ulp_command = get_job_cmnd(phba, rspiocbp); int rc;
spin_lock_irqsave(&phba->hbalock, iflag); /* First add the response iocb to the countinueq list */ - list_add_tail(&rspiocbp->list, &pring->iocb_continueq); + list_add_tail(&rspiocbp->list, &(pring->iocb_continueq)); pring->iocb_continueq_cnt++;
- /* - * By default, the driver expects to free all resources - * associated with this iocb completion. - */ - free_saveq = 1; - saveq = list_get_first(&pring->iocb_continueq, - struct lpfc_iocbq, list); - list_del_init(&pring->iocb_continueq); - pring->iocb_continueq_cnt = 0; + /* Now, determine whether the list is completed for processing */ + irsp = &rspiocbp->iocb; + if (irsp->ulpLe) { + /* + * By default, the driver expects to free all resources + * associated with this iocb completion. + */ + free_saveq = 1; + saveq = list_get_first(&pring->iocb_continueq, + struct lpfc_iocbq, list); + irsp = &(saveq->iocb); + list_del_init(&pring->iocb_continueq); + pring->iocb_continueq_cnt = 0;
- pring->stats.iocb_rsp++; + pring->stats.iocb_rsp++;
- /* - * If resource errors reported from HBA, reduce - * queuedepths of the SCSI device. - */ - if (ulp_status == IOSTAT_LOCAL_REJECT && - ((ulp_word4 & IOERR_PARAM_MASK) == - IOERR_NO_RESOURCES)) { - spin_unlock_irqrestore(&phba->hbalock, iflag); - phba->lpfc_rampdown_queue_depth(phba); - spin_lock_irqsave(&phba->hbalock, iflag); - } + /* + * If resource errors reported from HBA, reduce + * queuedepths of the SCSI device. + */ + if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && + ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + IOERR_NO_RESOURCES)) { + spin_unlock_irqrestore(&phba->hbalock, iflag); + phba->lpfc_rampdown_queue_depth(phba); + spin_lock_irqsave(&phba->hbalock, iflag); + }
- if (ulp_status) { - /* Rsp ring <ringno> error: IOCB */ - if (phba->sli_rev < LPFC_SLI_REV4) { - irsp = &rspiocbp->iocb; - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "0328 Rsp Ring %d error: ulp_status x%x " - "IOCB Data: " - "x%08x x%08x x%08x x%08x " - "x%08x x%08x x%08x x%08x " - "x%08x x%08x x%08x x%08x " - "x%08x x%08x x%08x x%08x\n", - pring->ringno, ulp_status, - get_job_ulpword(rspiocbp, 0), - get_job_ulpword(rspiocbp, 1), - get_job_ulpword(rspiocbp, 2), - get_job_ulpword(rspiocbp, 3), - get_job_ulpword(rspiocbp, 4), - get_job_ulpword(rspiocbp, 5), - *(((uint32_t *)irsp) + 6), - *(((uint32_t *)irsp) + 7), - *(((uint32_t *)irsp) + 8), - *(((uint32_t *)irsp) + 9), - *(((uint32_t *)irsp) + 10), - *(((uint32_t *)irsp) + 11), - *(((uint32_t *)irsp) + 12), - *(((uint32_t *)irsp) + 13), - *(((uint32_t *)irsp) + 14), - *(((uint32_t *)irsp) + 15)); - } else { + if (irsp->ulpStatus) { + /* Rsp ring <ringno> error: IOCB */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "0321 Rsp Ring %d error: " + "0328 Rsp Ring %d error: " "IOCB Data: " + "x%x x%x x%x x%x " + "x%x x%x x%x x%x " + "x%x x%x x%x x%x " "x%x x%x x%x x%x\n", pring->ringno, - rspiocbp->wcqe_cmpl.word0, - rspiocbp->wcqe_cmpl.total_data_placed, - rspiocbp->wcqe_cmpl.parameter, - rspiocbp->wcqe_cmpl.word3); + irsp->un.ulpWord[0], + irsp->un.ulpWord[1], + irsp->un.ulpWord[2], + irsp->un.ulpWord[3], + irsp->un.ulpWord[4], + irsp->un.ulpWord[5], + *(((uint32_t *) irsp) + 6), + *(((uint32_t *) irsp) + 7), + *(((uint32_t *) irsp) + 8), + *(((uint32_t *) irsp) + 9), + *(((uint32_t *) irsp) + 10), + *(((uint32_t *) irsp) + 11), + *(((uint32_t *) irsp) + 12), + *(((uint32_t *) irsp) + 13), + *(((uint32_t *) irsp) + 14), + *(((uint32_t *) irsp) + 15)); } - }
+ /* + * Fetch the IOCB command type and call the correct completion + * routine. Solicited and Unsolicited IOCBs on the ELS ring + * get freed back to the lpfc_iocb_list by the discovery + * kernel thread. + */ + iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK; + type = lpfc_sli_iocb_cmd_type(iocb_cmd_type); + switch (type) { + case LPFC_SOL_IOCB: + spin_unlock_irqrestore(&phba->hbalock, iflag); + rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); + spin_lock_irqsave(&phba->hbalock, iflag); + break;
- /* - * Fetch the iocb command type and call the correct completion - * routine. Solicited and Unsolicited IOCBs on the ELS ring - * get freed back to the lpfc_iocb_list by the discovery - * kernel thread. - */ - cmd_type = ulp_command & CMD_IOCB_MASK; - type = lpfc_sli_iocb_cmd_type(cmd_type); - switch (type) { - case LPFC_SOL_IOCB: - spin_unlock_irqrestore(&phba->hbalock, iflag); - rc = lpfc_sli_process_sol_iocb(phba, pring, saveq); - spin_lock_irqsave(&phba->hbalock, iflag); - break; - case LPFC_UNSOL_IOCB: - spin_unlock_irqrestore(&phba->hbalock, iflag); - rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); - spin_lock_irqsave(&phba->hbalock, iflag); - if (!rc) - free_saveq = 0; - break; - case LPFC_ABORT_IOCB: - cmdiocb = NULL; - if (ulp_command != CMD_XRI_ABORTED_CX) - cmdiocb = lpfc_sli_iocbq_lookup(phba, pring, - saveq); - if (cmdiocb) { - /* Call the specified completion routine */ - if (cmdiocb->cmd_cmpl) { + case LPFC_UNSOL_IOCB: + spin_unlock_irqrestore(&phba->hbalock, iflag); + rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq); + spin_lock_irqsave(&phba->hbalock, iflag); + if (!rc) + free_saveq = 0; + break; + + case LPFC_ABORT_IOCB: + cmdiocbp = NULL; + if (irsp->ulpCommand != CMD_XRI_ABORTED_CX) { spin_unlock_irqrestore(&phba->hbalock, iflag); - cmdiocb->cmd_cmpl(phba, cmdiocb, saveq); + cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, + saveq); spin_lock_irqsave(&phba->hbalock, iflag); + } + if (cmdiocbp) { + /* Call the specified completion routine */ + if (cmdiocbp->cmd_cmpl) { + spin_unlock_irqrestore(&phba->hbalock, + iflag); + (cmdiocbp->cmd_cmpl)(phba, cmdiocbp, + saveq); + spin_lock_irqsave(&phba->hbalock, + iflag); + } else + __lpfc_sli_release_iocbq(phba, + cmdiocbp); + } + break; + + case LPFC_UNKNOWN_IOCB: + if (irsp->ulpCommand == CMD_ADAPTER_MSG) { + char adaptermsg[LPFC_MAX_ADPTMSG]; + memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); + memcpy(&adaptermsg[0], (uint8_t *)irsp, + MAX_MSG_DATA); + dev_warn(&((phba->pcidev)->dev), + "lpfc%d: %s\n", + phba->brd_no, adaptermsg); } else { - __lpfc_sli_release_iocbq(phba, cmdiocb); + /* Unknown IOCB command */ + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, + "0335 Unknown IOCB " + "command Data: x%x " + "x%x x%x x%x\n", + irsp->ulpCommand, + irsp->ulpStatus, + irsp->ulpIoTag, + irsp->ulpContext); } + break; } - break; - case LPFC_UNKNOWN_IOCB: - if (ulp_command == CMD_ADAPTER_MSG) { - char adaptermsg[LPFC_MAX_ADPTMSG]; - - memset(adaptermsg, 0, LPFC_MAX_ADPTMSG); - memcpy(&adaptermsg[0], (uint8_t *)&rspiocbp->wqe, - MAX_MSG_DATA); - dev_warn(&((phba->pcidev)->dev), - "lpfc%d: %s\n", - phba->brd_no, adaptermsg); - } else { - /* Unknown command */ - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "0335 Unknown IOCB " - "command Data: x%x " - "x%x x%x x%x\n", - ulp_command, - ulp_status, - get_wqe_reqtag(rspiocbp), - get_job_ulpcontext(phba, rspiocbp)); - } - break; - }
- if (free_saveq) { - list_for_each_entry_safe(rspiocbp, next_iocb, - &saveq->list, list) { - list_del_init(&rspiocbp->list); - __lpfc_sli_release_iocbq(phba, rspiocbp); + if (free_saveq) { + list_for_each_entry_safe(rspiocbp, next_iocb, + &saveq->list, list) { + list_del_init(&rspiocbp->list); + __lpfc_sli_release_iocbq(phba, rspiocbp); + } + __lpfc_sli_release_iocbq(phba, saveq); } - __lpfc_sli_release_iocbq(phba, saveq); + rspiocbp = NULL; } - rspiocbp = NULL; spin_unlock_irqrestore(&phba->hbalock, iflag); return rspiocbp; } @@ -4428,8 +4431,8 @@ lpfc_sli_handle_slow_ring_event_s4(struc irspiocbq = container_of(cq_event, struct lpfc_iocbq, cq_event); /* Translate ELS WCQE to response IOCBQ */ - irspiocbq = lpfc_sli4_els_preprocess_rspiocbq(phba, - irspiocbq); + irspiocbq = lpfc_sli4_els_wcqe_to_rspiocbq(phba, + irspiocbq); if (irspiocbq) lpfc_sli_sp_handle_rspiocb(phba, pring, irspiocbq); @@ -10973,17 +10976,7 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_h int rc; struct lpfc_io_buf *lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; - - lpfc_prep_embed_io(phba, lpfc_cmd); - rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); - return rc; -} - -void -lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) -{ - struct lpfc_iocbq *piocb = &lpfc_cmd->cur_iocbq; - union lpfc_wqe128 *wqe = &lpfc_cmd->cur_iocbq.wqe; + union lpfc_wqe128 *wqe = &piocb->wqe; struct sli4_sge *sgl;
/* 128 byte wqe support here */ @@ -11032,6 +11025,8 @@ lpfc_prep_embed_io(struct lpfc_hba *phba wqe->words[31] = piocb->vmid_tag.app_id; } } + rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); + return rc; }
/** @@ -11053,10 +11048,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba struct lpfc_iocbq *piocb, uint32_t flag) { struct lpfc_sglq *sglq; - union lpfc_wqe128 *wqe; + union lpfc_wqe128 wqe; struct lpfc_queue *wq; struct lpfc_sli_ring *pring; - u32 ulp_command = get_job_cmnd(phba, piocb);
/* Get the WQ */ if ((piocb->cmd_flag & LPFC_IO_FCP) || @@ -11074,9 +11068,10 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba */
lockdep_assert_held(&pring->ring_lock); - wqe = &piocb->wqe; + if (piocb->sli4_xritag == NO_XRI) { - if (ulp_command == CMD_ABORT_XRI_WQE) + if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || + piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) sglq = NULL; else { if (!list_empty(&pring->txq)) { @@ -11117,24 +11112,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba if (sglq) { piocb->sli4_lxritag = sglq->sli4_lxritag; piocb->sli4_xritag = sglq->sli4_xritag; - - /* ABTS sent by initiator to CT exchange, the - * RX_ID field will be filled with the newly - * allocated responder XRI. - */ - if (ulp_command == CMD_XMIT_BLS_RSP64_CX && - piocb->abort_bls == LPFC_ABTS_UNSOL_INT) - bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp, - piocb->sli4_xritag); - - bf_set(wqe_xri_tag, &wqe->generic.wqe_com, - piocb->sli4_xritag); - - if (lpfc_wqe_bpl2sgl(phba, piocb, sglq) == NO_XRI) + if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq)) return IOCB_ERROR; }
- if (lpfc_sli4_wq_put(wq, wqe)) + if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe)) + return IOCB_ERROR; + + if (lpfc_sli4_wq_put(wq, &wqe)) return IOCB_ERROR; lpfc_sli_ringtxcmpl_put(phba, pring, piocb);
@@ -14132,7 +14117,123 @@ void lpfc_sli4_els_xri_abort_event_proc( }
/** - * lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe + * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn + * @phba: pointer to lpfc hba data structure + * @pIocbIn: pointer to the rspiocbq + * @pIocbOut: pointer to the cmdiocbq + * @wcqe: pointer to the complete wcqe + * + * This routine transfers the fields of a command iocbq to a response iocbq + * by copying all the IOCB fields from command iocbq and transferring the + * completion status information from the complete wcqe. + **/ +static void +lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, + struct lpfc_iocbq *pIocbIn, + struct lpfc_iocbq *pIocbOut, + struct lpfc_wcqe_complete *wcqe) +{ + int numBdes, i; + unsigned long iflags; + uint32_t status, max_response; + struct lpfc_dmabuf *dmabuf; + struct ulp_bde64 *bpl, bde; + size_t offset = offsetof(struct lpfc_iocbq, iocb); + + memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, + sizeof(struct lpfc_iocbq) - offset); + /* Map WCQE parameters into irspiocb parameters */ + status = bf_get(lpfc_wcqe_c_status, wcqe); + pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK); + if (pIocbOut->cmd_flag & LPFC_IO_FCP) + if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) + pIocbIn->iocb.un.fcpi.fcpi_parm = + pIocbOut->iocb.un.fcpi.fcpi_parm - + wcqe->total_data_placed; + else + pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; + else { + pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; + switch (pIocbOut->iocb.ulpCommand) { + case CMD_ELS_REQUEST64_CR: + dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; + bpl = (struct ulp_bde64 *)dmabuf->virt; + bde.tus.w = le32_to_cpu(bpl[1].tus.w); + max_response = bde.tus.f.bdeSize; + break; + case CMD_GEN_REQUEST64_CR: + max_response = 0; + if (!pIocbOut->context3) + break; + numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/ + sizeof(struct ulp_bde64); + dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; + bpl = (struct ulp_bde64 *)dmabuf->virt; + for (i = 0; i < numBdes; i++) { + bde.tus.w = le32_to_cpu(bpl[i].tus.w); + if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) + max_response += bde.tus.f.bdeSize; + } + break; + default: + max_response = wcqe->total_data_placed; + break; + } + if (max_response < wcqe->total_data_placed) + pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response; + else + pIocbIn->iocb.un.genreq64.bdl.bdeSize = + wcqe->total_data_placed; + } + + /* Convert BG errors for completion status */ + if (status == CQE_STATUS_DI_ERROR) { + pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; + + if (bf_get(lpfc_wcqe_c_bg_edir, wcqe)) + pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED; + else + pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED; + + pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0; + if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ + pIocbIn->iocb.unsli3.sli3_bg.bgstat |= + BGS_GUARD_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */ + pIocbIn->iocb.unsli3.sli3_bg.bgstat |= + BGS_APPTAG_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */ + pIocbIn->iocb.unsli3.sli3_bg.bgstat |= + BGS_REFTAG_ERR_MASK; + + /* Check to see if there was any good data before the error */ + if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { + pIocbIn->iocb.unsli3.sli3_bg.bgstat |= + BGS_HI_WATER_MARK_PRESENT_MASK; + pIocbIn->iocb.unsli3.sli3_bg.bghm = + wcqe->total_data_placed; + } + + /* + * Set ALL the error bits to indicate we don't know what + * type of error it is. + */ + if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat) + pIocbIn->iocb.unsli3.sli3_bg.bgstat |= + (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | + BGS_GUARD_ERR_MASK); + } + + /* Pick up HBA exchange busy condition */ + if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + spin_lock_irqsave(&phba->hbalock, iflags); + pIocbIn->cmd_flag |= LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore(&phba->hbalock, iflags); + } +} + +/** + * lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe * @phba: Pointer to HBA context object. * @irspiocbq: Pointer to work-queue completion queue entry. * @@ -14143,8 +14244,8 @@ void lpfc_sli4_els_xri_abort_event_proc( * Return: Pointer to the receive IOCBQ, NULL otherwise. **/ static struct lpfc_iocbq * -lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, - struct lpfc_iocbq *irspiocbq) +lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba, + struct lpfc_iocbq *irspiocbq) { struct lpfc_sli_ring *pring; struct lpfc_iocbq *cmdiocbq; @@ -14156,13 +14257,11 @@ lpfc_sli4_els_preprocess_rspiocbq(struct return NULL;
wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl; - spin_lock_irqsave(&pring->ring_lock, iflags); pring->stats.iocb_event++; /* Look up the ELS command IOCB and create pseudo response IOCB */ cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, bf_get(lpfc_wcqe_c_request_tag, wcqe)); if (unlikely(!cmdiocbq)) { - spin_unlock_irqrestore(&pring->ring_lock, iflags); lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0386 ELS complete with no corresponding " "cmdiocb: 0x%x 0x%x 0x%x 0x%x\n", @@ -14172,18 +14271,13 @@ lpfc_sli4_els_preprocess_rspiocbq(struct return NULL; }
- memcpy(&irspiocbq->wqe, &cmdiocbq->wqe, sizeof(union lpfc_wqe128)); - memcpy(&irspiocbq->wcqe_cmpl, wcqe, sizeof(*wcqe)); - + spin_lock_irqsave(&pring->ring_lock, iflags); /* Put the iocb back on the txcmplq */ lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq); spin_unlock_irqrestore(&pring->ring_lock, iflags);
- if (bf_get(lpfc_wcqe_c_xb, wcqe)) { - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } + /* Fake the irspiocbq and copy necessary response information */ + lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
return irspiocbq; } @@ -15009,9 +15103,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc /* Look up the FCP command IOCB and create pseudo response IOCB */ spin_lock_irqsave(&pring->ring_lock, iflags); pring->stats.iocb_event++; + spin_unlock_irqrestore(&pring->ring_lock, iflags); cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring, bf_get(lpfc_wcqe_c_request_tag, wcqe)); - spin_unlock_irqrestore(&pring->ring_lock, iflags); if (unlikely(!cmdiocbq)) { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0374 FCP complete with no corresponding " @@ -18872,16 +18966,13 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vpor ctiocb->sli4_lxritag = NO_XRI; ctiocb->sli4_xritag = NO_XRI;
- if (fctl & FC_FC_EX_CTX) { + if (fctl & FC_FC_EX_CTX) /* Exchange responder sent the abort so we * own the oxid. */ - ctiocb->abort_bls = LPFC_ABTS_UNSOL_RSP; xri = oxid; - } else { - ctiocb->abort_bls = LPFC_ABTS_UNSOL_INT; + else xri = rxid; - } lxri = lpfc_sli4_xri_inrange(phba, xri); if (lxri != NO_XRI) lpfc_set_rrq_active(phba, ndlp, lxri, --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -76,8 +76,6 @@ struct lpfc_iocbq { struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
uint8_t num_bdes; - uint8_t abort_bls; /* ABTS by initiator or responder */ - uint8_t priority; /* OAS priority */ uint8_t retry; /* retry counter for IOCB cmd - if needed */ u32 cmd_flag;
From: James Smart jsmart2021@gmail.com
This reverts commit 1c5e670d6a5a8e7e99b51f45e79879f7828bd2ec.
LTS 5.15 pulled in several lpfc "SLI Path split" patches. The Path Split mods were a 14-patch set, which refactors the driver from to split the sli-3 hw (now eol) from the sli-4 hw and use sli4 structures natively. The patches are highly inter-related.
Given only some of the patches were included, it created a situation where FLOGI's fail, thus SLI Ports can't start communication.
Reverting this patch as its one of the partial Path Split patches that was included.
Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/lpfc/lpfc_bsg.c | 50 ++--- drivers/scsi/lpfc/lpfc_crtn.h | 2 drivers/scsi/lpfc/lpfc_ct.c | 8 drivers/scsi/lpfc/lpfc_els.c | 139 +++++++-------- drivers/scsi/lpfc/lpfc_init.c | 11 - drivers/scsi/lpfc/lpfc_nportdisc.c | 4 drivers/scsi/lpfc/lpfc_nvme.c | 34 +-- drivers/scsi/lpfc/lpfc_nvme.h | 6 drivers/scsi/lpfc/lpfc_nvmet.c | 83 ++++----- drivers/scsi/lpfc/lpfc_scsi.c | 75 ++++---- drivers/scsi/lpfc/lpfc_sli.c | 340 +++++++++++++++++++------------------ drivers/scsi/lpfc/lpfc_sli.h | 24 +- 12 files changed, 391 insertions(+), 385 deletions(-)
--- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -325,7 +325,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_h
/* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags);
iocb = &dd_data->context_un.iocb; @@ -481,11 +481,11 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *j cmd->ulpOwner = OWN_CHIP; cmdiocbq->vport = phba->pport; cmdiocbq->context3 = bmp; - cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; timeout = phba->fc_ratov * 2; cmd->ulpTimeout = timeout;
- cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; + cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; cmdiocbq->context1 = dd_data; cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; @@ -516,9 +516,9 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *j if (iocb_stat == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed yet */ - if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { + if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -600,7 +600,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *
/* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags);
rsp = &rspiocbq->iocb; @@ -726,10 +726,10 @@ lpfc_bsg_rport_els(struct bsg_job *job) cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi]; else cmdiocbq->iocb.ulpContext = rpi; - cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; cmdiocbq->context1 = dd_data; cmdiocbq->context_un.ndlp = ndlp; - cmdiocbq->cmd_cmpl = lpfc_bsg_rport_els_cmp; + cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp; dd_data->type = TYPE_IOCB; dd_data->set_job = job; dd_data->context_un.iocb.cmdiocbq = cmdiocbq; @@ -757,9 +757,9 @@ lpfc_bsg_rport_els(struct bsg_job *job) if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ - if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) { + if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -1053,7 +1053,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba lpfc_in_buf_free(phba, dmabuf); } else { - lpfc_sli3_post_buffer(phba, + lpfc_post_buffer(phba, pring, 1); } @@ -1061,7 +1061,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba default: if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_sli3_post_buffer(phba, + lpfc_post_buffer(phba, pring, 1); break; @@ -1395,7 +1395,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *p
/* Close the timeout handler abort window */ spin_lock_irqsave(&phba->hbalock, flags); - cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING; + cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; spin_unlock_irqrestore(&phba->hbalock, flags);
ndlp = dd_data->context_un.iocb.ndlp; @@ -1549,13 +1549,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n", icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
- ctiocb->cmd_flag |= LPFC_IO_LIBDFC; + ctiocb->iocb_flag |= LPFC_IO_LIBDFC; ctiocb->vport = phba->pport; ctiocb->context1 = dd_data; ctiocb->context2 = cmp; ctiocb->context3 = bmp; ctiocb->context_un.ndlp = ndlp; - ctiocb->cmd_cmpl = lpfc_issue_ct_rsp_cmp; + ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
dd_data->type = TYPE_IOCB; dd_data->set_job = job; @@ -1582,9 +1582,9 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ - if (ctiocb->cmd_flag & LPFC_IO_LIBDFC) { + if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) { /* open up abort window to timeout handler */ - ctiocb->cmd_flag |= LPFC_IO_CMD_OUTSTANDING; + ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; } spin_unlock_irqrestore(&phba->hbalock, flags); return 0; /* done for now */ @@ -2713,9 +2713,9 @@ static int lpfcdiag_loop_get_xri(struct cmd->ulpClass = CLASS3; cmd->ulpContext = rpi;
- cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; cmdiocbq->vport = phba->pport; - cmdiocbq->cmd_cmpl = NULL; + cmdiocbq->iocb_cmpl = NULL;
iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq, @@ -3286,10 +3286,10 @@ lpfc_bsg_diag_loopback_run(struct bsg_jo cmdiocbq->sli4_xritag = NO_XRI; cmd->unsli3.rcvsli3.ox_id = 0xffff; } - cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; - cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK; + cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; + cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK; cmdiocbq->vport = phba->pport; - cmdiocbq->cmd_cmpl = NULL; + cmdiocbq->iocb_cmpl = NULL; iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq, (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT); @@ -5273,11 +5273,11 @@ lpfc_menlo_cmd(struct bsg_job *job) cmd->ulpClass = CLASS3; cmd->ulpOwner = OWN_CHIP; cmd->ulpLe = 1; /* Limited Edition */ - cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; + cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; cmdiocbq->vport = phba->pport; /* We want the firmware to timeout before we do */ cmd->ulpTimeout = MENLO_TIMEOUT - 5; - cmdiocbq->cmd_cmpl = lpfc_bsg_menlo_cmd_cmp; + cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp; cmdiocbq->context1 = dd_data; cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; @@ -6001,7 +6001,7 @@ lpfc_bsg_timeout(struct bsg_job *job)
spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O abort window is still open */ - if (!(cmdiocb->cmd_flag & LPFC_IO_CMD_OUTSTANDING)) { + if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) { spin_unlock_irqrestore(&phba->hbalock, flags); return -EAGAIN; } --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -210,7 +210,7 @@ int lpfc_config_port_post(struct lpfc_hb int lpfc_hba_down_prep(struct lpfc_hba *); int lpfc_hba_down_post(struct lpfc_hba *); void lpfc_hba_init(struct lpfc_hba *, uint32_t *); -int lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt); +int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int); void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); int lpfc_online(struct lpfc_hba *); void lpfc_unblock_mgmt_io(struct lpfc_hba *); --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -239,7 +239,7 @@ lpfc_ct_reject_event(struct lpfc_nodelis cmdiocbq->context1 = lpfc_nlp_get(ndlp); cmdiocbq->context2 = (uint8_t *)mp; cmdiocbq->context3 = (uint8_t *)bmp; - cmdiocbq->cmd_cmpl = lpfc_ct_unsol_cmpl; + cmdiocbq->iocb_cmpl = lpfc_ct_unsol_cmpl; icmd->ulpContext = rx_id; /* Xri / rx_id */ icmd->unsli3.rcvsli3.ox_id = ox_id; icmd->un.ulpWord[3] = @@ -370,7 +370,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phb /* Not enough posted buffers; Try posting more buffers */ phba->fc_stat.NoRcvBuf++; if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_sli3_post_buffer(phba, pring, 2); + lpfc_post_buffer(phba, pring, 2); return; }
@@ -447,7 +447,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phb lpfc_ct_unsol_buffer(phba, iocbq, mp, size); lpfc_in_buf_free(phba, mp); } - lpfc_sli3_post_buffer(phba, pring, i); + lpfc_post_buffer(phba, pring, i); } list_del(&head); } @@ -652,7 +652,7 @@ lpfc_gen_req(struct lpfc_vport *vport, s "Data: x%x x%x\n", ndlp->nlp_DID, icmd->ulpIoTag, vport->port_state); - geniocb->cmd_cmpl = cmpl; + geniocb->iocb_cmpl = cmpl; geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; geniocb->vport = vport; geniocb->retry = retry; --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -192,23 +192,23 @@ lpfc_prep_els_iocb(struct lpfc_vport *vp (elscmd == ELS_CMD_LOGO))) switch (elscmd) { case ELS_CMD_FLOGI: - elsiocb->cmd_flag |= + elsiocb->iocb_flag |= ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_FDISC: - elsiocb->cmd_flag |= + elsiocb->iocb_flag |= ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; case ELS_CMD_LOGO: - elsiocb->cmd_flag |= + elsiocb->iocb_flag |= ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT) & LPFC_FIP_ELS_ID_MASK); break; } else - elsiocb->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; + elsiocb->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
icmd = &elsiocb->iocb;
@@ -1252,10 +1252,10 @@ lpfc_cmpl_els_link_down(struct lpfc_hba "6445 ELS completes after LINK_DOWN: " " Status %x/%x cmd x%x flg x%x\n", irsp->ulpStatus, irsp->un.ulpWord[4], cmd, - cmdiocb->cmd_flag); + cmdiocb->iocb_flag);
- if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) { - cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) { + cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; atomic_dec(&phba->fabric_iocb_count); } lpfc_els_free_iocb(phba, cmdiocb); @@ -1370,7 +1370,7 @@ lpfc_issue_els_flogi(struct lpfc_vport * phba->fc_ratov = tmo;
phba->fc_stat.elsXmitFLOGI++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_flogi; + elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue FLOGI: opt:x%x", @@ -1463,7 +1463,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *ph if (ndlp && ndlp->nlp_DID == Fabric_DID) { if ((phba->pport->fc_flag & FC_PT2PT) && !(phba->pport->fc_flag & FC_PT2PT_PLOGI)) - iocb->fabric_cmd_cmpl = + iocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); @@ -2226,7 +2226,7 @@ lpfc_issue_els_plogi(struct lpfc_vport * }
phba->fc_stat.elsXmitPLOGI++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_plogi; + elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue PLOGI: did:x%x refcnt %d", @@ -2478,7 +2478,7 @@ lpfc_issue_els_prli(struct lpfc_vport *v /* For FCP support */ npr->prliType = PRLI_FCP_TYPE; npr->initiatorFunc = 1; - elsiocb->cmd_flag |= LPFC_PRLI_FCP_REQ; + elsiocb->iocb_flag |= LPFC_PRLI_FCP_REQ;
/* Remove FCP type - processed. */ local_nlp_type &= ~NLP_FC4_FCP; @@ -2512,14 +2512,14 @@ lpfc_issue_els_prli(struct lpfc_vport *v
npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); - elsiocb->cmd_flag |= LPFC_PRLI_NVME_REQ; + elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ;
/* Remove NVME type - processed. */ local_nlp_type &= ~NLP_FC4_NVME; }
phba->fc_stat.elsXmitPRLI++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_prli; + elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_PRLI_SND;
@@ -2842,7 +2842,7 @@ lpfc_issue_els_adisc(struct lpfc_vport * ap->DID = be32_to_cpu(vport->fc_myDID);
phba->fc_stat.elsXmitADISC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_adisc; + elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_ADISC_SND; spin_unlock_irq(&ndlp->lock); @@ -3065,7 +3065,7 @@ lpfc_issue_els_logo(struct lpfc_vport *v memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
phba->fc_stat.elsXmitLOGO++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_logo; + elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; @@ -3417,7 +3417,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vp ndlp->nlp_DID, 0, 0);
phba->fc_stat.elsXmitSCR++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3514,7 +3514,7 @@ lpfc_issue_els_rscn(struct lpfc_vport *v event->portid.rscn_fid[2] = nportid & 0x000000FF;
phba->fc_stat.elsXmitRSCN++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3613,7 +3613,7 @@ lpfc_issue_els_farpr(struct lpfc_vport * ndlp->nlp_DID, 0, 0);
phba->fc_stat.elsXmitFARPR++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -3704,7 +3704,7 @@ lpfc_issue_els_rdf(struct lpfc_vport *vp phba->cgn_reg_fpin);
phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ; - elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -4154,7 +4154,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vp ndlp->nlp_DID, phba->cgn_reg_signal, phba->cgn_reg_fpin);
- elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd; + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -4968,12 +4968,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba
/* context2 = cmd, context2->next = rsp, context3 = bpl */ if (elsiocb->context2) { - if (elsiocb->cmd_flag & LPFC_DELAY_MEM_FREE) { + if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) { /* Firmware could still be in progress of DMAing * payload, so don't free data buffer till after * a hbeat. */ - elsiocb->cmd_flag &= ~LPFC_DELAY_MEM_FREE; + elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE; buf_ptr = elsiocb->context2; elsiocb->context2 = NULL; if (buf_ptr) { @@ -5480,9 +5480,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vpor ndlp->nlp_flag & NLP_REG_LOGIN_SEND)) ndlp->nlp_flag &= ~NLP_LOGO_ACC; spin_unlock_irq(&ndlp->lock); - elsiocb->cmd_cmpl = lpfc_cmpl_els_logo_acc; + elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; } else { - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; }
phba->fc_stat.elsXmitACC++; @@ -5577,7 +5577,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *v ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
phba->fc_stat.elsXmitLSRJT++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -5657,7 +5657,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport "Issue EDC ACC: did:x%x flg:x%x refcnt %d", ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); @@ -5750,7 +5750,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
phba->fc_stat.elsXmitACC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -5924,7 +5924,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
phba->fc_stat.elsXmitACC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6025,7 +6025,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
phba->fc_stat.elsXmitACC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6139,7 +6139,7 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
phba->fc_stat.elsXmitACC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -6803,7 +6803,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, rdp_context->page_a0, vport);
rdp_res->length = cpu_to_be32(len - 8); - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
/* Now that we know the true size of the payload, update the BPL */ bpl = (struct ulp_bde64 *) @@ -6844,7 +6844,7 @@ error: stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
phba->fc_stat.elsXmitLSRJT++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { lpfc_els_free_iocb(phba, elsiocb); @@ -7066,7 +7066,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, lcb_res->capability = lcb_context->capability; lcb_res->lcb_frequency = lcb_context->frequency; lcb_res->lcb_duration = lcb_context->duration; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++;
elsiocb->context1 = lpfc_nlp_get(ndlp); @@ -7105,7 +7105,7 @@ error: if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE) stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
- elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitLSRJT++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8172,7 +8172,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *ph elsiocb->iotag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8324,7 +8324,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vpor ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi, rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov); - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8401,7 +8401,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vp "Issue RRQ: did:x%x", did, rrq->xritag, rrq->rxid); elsiocb->context_un.rrq = rrq; - elsiocb->cmd_cmpl = lpfc_cmpl_els_rrq; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq;
lpfc_nlp_get(ndlp); elsiocb->context1 = ndlp; @@ -8507,7 +8507,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport * elsiocb->iotag, elsiocb->iocb.ulpContext, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -8947,7 +8947,7 @@ lpfc_els_timeout_handler(struct lpfc_vpo list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { cmd = &piocb->iocb;
- if ((piocb->cmd_flag & LPFC_IO_LIBDFC) != 0 || + if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) continue; @@ -9060,13 +9060,13 @@ lpfc_els_flush_cmd(struct lpfc_vport *vp
/* First we need to issue aborts to outstanding cmds on txcmpl */ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { - if (piocb->cmd_flag & LPFC_IO_LIBDFC) + if (piocb->iocb_flag & LPFC_IO_LIBDFC) continue;
if (piocb->vport != vport) continue;
- if (piocb->cmd_flag & LPFC_DRIVER_ABORTED) + if (piocb->iocb_flag & LPFC_DRIVER_ABORTED) continue;
/* On the ELS ring we can have ELS_REQUESTs or @@ -9084,7 +9084,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vp * and avoid any retry logic. */ if (phba->link_state == LPFC_LINK_DOWN) - piocb->cmd_cmpl = lpfc_cmpl_els_link_down; + piocb->iocb_cmpl = lpfc_cmpl_els_link_down; } if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) list_add_tail(&piocb->dlist, &abort_list); @@ -9119,8 +9119,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vp list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { cmd = &piocb->iocb;
- if (piocb->cmd_flag & LPFC_IO_LIBDFC) + if (piocb->iocb_flag & LPFC_IO_LIBDFC) { continue; + }
/* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || @@ -9765,7 +9766,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; cmd = *payload; if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) - lpfc_sli3_post_buffer(phba, pring, 1); + lpfc_post_buffer(phba, pring, 1);
did = icmd->un.rcvels.remoteID; if (icmd->ulpStatus) { @@ -10238,7 +10239,7 @@ lpfc_els_unsol_event(struct lpfc_hba *ph phba->fc_stat.NoRcvBuf++; /* Not enough posted buffers; Try posting more buffers */ if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_sli3_post_buffer(phba, pring, 0); + lpfc_post_buffer(phba, pring, 0); return; }
@@ -10874,7 +10875,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport * lpfc_set_disctmo(vport);
phba->fc_stat.elsXmitFDISC++; - elsiocb->cmd_cmpl = lpfc_cmpl_els_fdisc; + elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue FDISC: did:x%x", @@ -10998,7 +10999,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vpo "Issue LOGO npiv did:x%x flg:x%x", ndlp->nlp_DID, ndlp->nlp_flag, 0);
- elsiocb->cmd_cmpl = lpfc_cmpl_els_npiv_logo; + elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; spin_unlock_irq(&ndlp->lock); @@ -11083,9 +11084,9 @@ repeat: } spin_unlock_irqrestore(&phba->hbalock, iflags); if (iocb) { - iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; - iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; - iocb->cmd_flag |= LPFC_IO_FABRIC; + iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; + iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; + iocb->iocb_flag |= LPFC_IO_FABRIC;
lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, "Fabric sched1: ste:x%x", @@ -11094,13 +11095,13 @@ repeat: ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0);
if (ret == IOCB_ERROR) { - iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; - iocb->fabric_cmd_cmpl = NULL; - iocb->cmd_flag &= ~LPFC_IO_FABRIC; + iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; + iocb->fabric_iocb_cmpl = NULL; + iocb->iocb_flag &= ~LPFC_IO_FABRIC; cmd = &iocb->iocb; cmd->ulpStatus = IOSTAT_LOCAL_REJECT; cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - iocb->cmd_cmpl(phba, iocb, iocb); + iocb->iocb_cmpl(phba, iocb, iocb);
atomic_dec(&phba->fabric_iocb_count); goto repeat; @@ -11156,8 +11157,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba * @rspiocb: pointer to lpfc response iocb data structure. * * This routine is the callback function that is put to the fabric iocb's - * callback function pointer (iocb->cmd_cmpl). The original iocb's callback - * function pointer has been stored in iocb->fabric_cmd_cmpl. This callback + * callback function pointer (iocb->iocb_cmpl). The original iocb's callback + * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback * function first restores and invokes the original iocb's callback function * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next * fabric bound iocb from the driver internal fabric iocb list onto the wire. @@ -11168,7 +11169,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *p { struct ls_rjt stat;
- WARN_ON((cmdiocb->cmd_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC); + BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC);
switch (rspiocb->iocb.ulpStatus) { case IOSTAT_NPORT_RJT: @@ -11194,10 +11195,10 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *p
BUG_ON(atomic_read(&phba->fabric_iocb_count) == 0);
- cmdiocb->cmd_cmpl = cmdiocb->fabric_cmd_cmpl; - cmdiocb->fabric_cmd_cmpl = NULL; - cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC; - cmdiocb->cmd_cmpl(phba, cmdiocb, rspiocb); + cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl; + cmdiocb->fabric_iocb_cmpl = NULL; + cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; + cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
atomic_dec(&phba->fabric_iocb_count); if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) { @@ -11248,9 +11249,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba * atomic_inc(&phba->fabric_iocb_count); spin_unlock_irqrestore(&phba->hbalock, iflags); if (ready) { - iocb->fabric_cmd_cmpl = iocb->cmd_cmpl; - iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb; - iocb->cmd_flag |= LPFC_IO_FABRIC; + iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; + iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; + iocb->iocb_flag |= LPFC_IO_FABRIC;
lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, "Fabric sched2: ste:x%x", @@ -11259,9 +11260,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba * ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0);
if (ret == IOCB_ERROR) { - iocb->cmd_cmpl = iocb->fabric_cmd_cmpl; - iocb->fabric_cmd_cmpl = NULL; - iocb->cmd_flag &= ~LPFC_IO_FABRIC; + iocb->iocb_cmpl = iocb->fabric_iocb_cmpl; + iocb->fabric_iocb_cmpl = NULL; + iocb->iocb_flag &= ~LPFC_IO_FABRIC; atomic_dec(&phba->fabric_iocb_count); } } else { @@ -11654,7 +11655,7 @@ int lpfc_issue_els_qfpa(struct lpfc_vpor *((u32 *)(pcmd)) = ELS_CMD_QFPA; pcmd += 4;
- elsiocb->cmd_cmpl = lpfc_cmpl_els_qfpa; + elsiocb->iocb_cmpl = lpfc_cmpl_els_qfpa;
elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { @@ -11737,7 +11738,7 @@ lpfc_vmid_uvem(struct lpfc_vport *vport, } inst_desc->word6 = cpu_to_be32(inst_desc->word6);
- elsiocb->cmd_cmpl = lpfc_cmpl_els_uvem; + elsiocb->iocb_cmpl = lpfc_cmpl_els_uvem;
elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) { --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -982,7 +982,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba * spin_lock_irq(&pring->ring_lock); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; list_splice_init(&pring->txcmplq, &completions); pring->txcmplq_cnt = 0; spin_unlock_irq(&pring->ring_lock); @@ -2643,7 +2643,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba }
/** - * lpfc_sli3_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring + * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring * @phba: pointer to lpfc hba data structure. * @pring: pointer to a IOCB ring. * @cnt: the number of IOCBs to be posted to the IOCB ring. @@ -2655,7 +2655,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba * The number of IOCBs NOT able to be posted to the IOCB ring. **/ int -lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) +lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) { IOCB_t *icmd; struct lpfc_iocbq *iocb; @@ -2761,7 +2761,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli;
/* Ring 0, ELS / CT buffers */ - lpfc_sli3_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); + lpfc_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0); /* Ring 2 - FCP no buffers needed */
return 0; @@ -4215,7 +4215,8 @@ lpfc_io_buf_replenish(struct lpfc_hba *p qp = &phba->sli4_hba.hdwq[idx]; lpfc_cmd->hdwq_no = idx; lpfc_cmd->hdwq = qp; - lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; + lpfc_cmd->cur_iocbq.wqe_cmpl = NULL; + lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; spin_lock(&qp->io_buf_list_put_lock); list_add_tail(&lpfc_cmd->list, &qp->lpfc_io_buf_list_put); --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -2139,9 +2139,9 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vp npr = NULL; nvpr = NULL; temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); - if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ) + if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ) npr = (PRLI *) temp_ptr; - else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ) + else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ) nvpr = (struct lpfc_nvme_prli *) temp_ptr;
irsp = &rspiocb->iocb; --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -352,12 +352,11 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *
static void lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_vport *vport = cmdwqe->vport; struct lpfc_nvme_lport *lport; uint32_t status; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
@@ -381,7 +380,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vpo struct lpfc_dmabuf *inp, struct nvmefc_ls_req *pnvme_lsreq, void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_iocbq *), + struct lpfc_wcqe_complete *), struct lpfc_nodelist *ndlp, uint32_t num_entry, uint32_t tmo, uint8_t retry) { @@ -402,7 +401,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vpo memset(wqe, 0, sizeof(union lpfc_wqe));
genwqe->context3 = (uint8_t *)bmp; - genwqe->cmd_flag |= LPFC_IO_NVME_LS; + genwqe->iocb_flag |= LPFC_IO_NVME_LS;
/* Save for completion so we can release these resources */ genwqe->context1 = lpfc_nlp_get(ndlp); @@ -433,7 +432,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vpo first_len = xmit_len; }
- genwqe->num_bdes = num_entry; + genwqe->rsvd2 = num_entry; genwqe->hba_wqidx = 0;
/* Words 0 - 2 */ @@ -484,7 +483,8 @@ lpfc_nvme_gen_req(struct lpfc_vport *vpo
/* Issue GEN REQ WQE for NPORT <did> */ - genwqe->cmd_cmpl = cmpl; + genwqe->wqe_cmpl = cmpl; + genwqe->iocb_cmpl = NULL; genwqe->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT; genwqe->vport = vport; genwqe->retry = retry; @@ -534,7 +534,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vp struct nvmefc_ls_req *pnvme_lsreq, void (*gen_req_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe)) + struct lpfc_wcqe_complete *wcqe)) { struct lpfc_dmabuf *bmp; struct ulp_bde64 *bpl; @@ -722,7 +722,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport * spin_lock(&pring->ring_lock); list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) { if (wqe->context2 == pnvme_lsreq) { - wqe->cmd_flag |= LPFC_DRIVER_ABORTED; + wqe->iocb_flag |= LPFC_DRIVER_ABORTED; foundit = true; break; } @@ -906,7 +906,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport
/* - * lpfc_nvme_io_cmd_cmpl - Complete an NVME-over-FCP IO + * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -917,12 +917,11 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport * TODO: What are the failure codes. **/ static void -lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, - struct lpfc_iocbq *pwqeOut) +lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + struct lpfc_wcqe_complete *wcqe) { struct lpfc_io_buf *lpfc_ncmd = (struct lpfc_io_buf *)pwqeIn->context1; - struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; struct lpfc_vport *vport = pwqeIn->vport; struct nvmefc_fcp_req *nCmd; struct nvme_fc_ersp_iu *ep; @@ -1874,7 +1873,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local }
/* Don't abort IOs no longer on the pending queue. */ - if (!(nvmereq_wqe->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6142 NVME IO req x%px not queued - skipping " "abort req xri x%x\n", @@ -1888,7 +1887,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local nvmereq_wqe->hba_wqidx, pnvme_rport->port_id);
/* Outstanding abort is in progress */ - if (nvmereq_wqe->cmd_flag & LPFC_DRIVER_ABORTED) { + if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6144 Outstanding NVME I/O Abort Request " "still pending on nvme_fcreq x%px, " @@ -1983,8 +1982,8 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, /* Setup key fields in buffer that may have been changed * if other protocols used this buffer. */ - pwqeq->cmd_flag = LPFC_IO_NVME; - pwqeq->cmd_cmpl = lpfc_nvme_io_cmd_cmpl; + pwqeq->iocb_flag = LPFC_IO_NVME; + pwqeq->wqe_cmpl = lpfc_nvme_io_cmd_wqe_cmpl; lpfc_ncmd->start_time = jiffies; lpfc_ncmd->flags = 0;
@@ -2750,7 +2749,6 @@ lpfc_nvme_cancel_iocb(struct lpfc_hba *p if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) bf_set(lpfc_wcqe_c_xb, wcqep, 1);
- memcpy(&pwqeIn->wcqe_cmpl, wcqep, sizeof(*wcqep)); - (pwqeIn->cmd_cmpl)(phba, pwqeIn, pwqeIn); + (pwqeIn->wqe_cmpl)(phba, pwqeIn, wcqep); #endif } --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -234,7 +234,7 @@ int __lpfc_nvme_ls_req(struct lpfc_vport struct nvmefc_ls_req *pnvme_lsreq, void (*gen_req_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe)); + struct lpfc_wcqe_complete *wcqe)); void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); int __lpfc_nvme_ls_abort(struct lpfc_vport *vport, @@ -248,6 +248,6 @@ int __lpfc_nvme_xmt_ls_rsp(struct lpfc_a struct nvmefc_ls_rsp *ls_rsp, void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe)); + struct lpfc_wcqe_complete *wcqe)); void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, - struct lpfc_iocbq *cmdwqe, struct lpfc_iocbq *rspwqe); + struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe); --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -285,7 +285,7 @@ lpfc_nvmet_defer_release(struct lpfc_hba * transmission of an NVME LS response. * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. The function frees memory resources used for the command @@ -293,10 +293,9 @@ lpfc_nvmet_defer_release(struct lpfc_hba **/ void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_async_xchg_ctx *axchg = cmdwqe->context2; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp; uint32_t status, result;
@@ -332,7 +331,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_h * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME LS commands @@ -341,11 +340,10 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_h **/ static void lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_nvmet_tgtport *tgtp; uint32_t status, result; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
if (!phba->targetport) goto finish; @@ -367,7 +365,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hb }
finish: - __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, rspwqe); + __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, wcqe); }
/** @@ -709,7 +707,7 @@ out: * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME FCP commands @@ -717,13 +715,12 @@ out: **/ static void lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_nvmet_tgtport *tgtp; struct nvmefc_tgt_fcp_req *rsp; struct lpfc_async_xchg_ctx *ctxp; uint32_t status, result, op, start_clean, logerr; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; #ifdef CONFIG_SCSI_LPFC_DEBUG_FS int id; #endif @@ -820,7 +817,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hb /* lpfc_nvmet_xmt_fcp_release() will recycle the context */ } else { ctxp->entry_cnt++; - start_clean = offsetof(struct lpfc_iocbq, cmd_flag); + start_clean = offsetof(struct lpfc_iocbq, iocb_flag); memset(((char *)cmdwqe) + start_clean, 0, (sizeof(struct lpfc_iocbq) - start_clean)); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS @@ -865,7 +862,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async struct nvmefc_ls_rsp *ls_rsp, void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe)) + struct lpfc_wcqe_complete *wcqe)) { struct lpfc_hba *phba = axchg->phba; struct hbq_dmabuf *nvmebuf = (struct hbq_dmabuf *)axchg->rqb_buffer; @@ -901,7 +898,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async }
/* Save numBdes for bpl2sgl */ - nvmewqeq->num_bdes = 1; + nvmewqeq->rsvd2 = 1; nvmewqeq->hba_wqidx = 0; nvmewqeq->context3 = &dmabuf; dmabuf.virt = &bpl; @@ -916,7 +913,8 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async * be referenced after it returns back to this routine. */
- nvmewqeq->cmd_cmpl = xmt_ls_rsp_cmp; + nvmewqeq->wqe_cmpl = xmt_ls_rsp_cmp; + nvmewqeq->iocb_cmpl = NULL; nvmewqeq->context2 = axchg;
lpfc_nvmeio_data(phba, "NVMEx LS RSP: xri x%x wqidx x%x len x%x\n", @@ -1074,9 +1072,10 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_ta goto aerr; }
- nvmewqeq->cmd_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; + nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_fcp_op_cmp; + nvmewqeq->iocb_cmpl = NULL; nvmewqeq->context2 = ctxp; - nvmewqeq->cmd_flag |= LPFC_IO_NVMET; + nvmewqeq->iocb_flag |= LPFC_IO_NVMET; ctxp->wqeq->hba_wqidx = rsp->hwqid;
lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n", @@ -1276,7 +1275,7 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_tar * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request * @phba: Pointer to HBA context object * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * This function is the completion handler for NVME LS requests. * The function updates any states and statistics, then calls the @@ -1284,9 +1283,8 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_tar **/ static void lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl; __lpfc_nvme_ls_req_cmp(phba, cmdwqe->vport, cmdwqe, wcqe); }
@@ -1583,7 +1581,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_ "6406 Ran out of NVMET iocb/WQEs\n"); return -ENOMEM; } - ctx_buf->iocbq->cmd_flag = LPFC_IO_NVMET; + ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET; nvmewqe = ctx_buf->iocbq; wqe = &nvmewqe->wqe;
@@ -2029,10 +2027,8 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba list_del(&nvmewqeq->list); spin_unlock_irqrestore(&pring->ring_lock, iflags); - memcpy(&nvmewqeq->wcqe_cmpl, wcqep, - sizeof(*wcqep)); lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, - nvmewqeq); + wcqep); return; } continue; @@ -2040,8 +2036,7 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba /* Flush all IOs */ list_del(&nvmewqeq->list); spin_unlock_irqrestore(&pring->ring_lock, iflags); - memcpy(&nvmewqeq->wcqe_cmpl, wcqep, sizeof(*wcqep)); - lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, nvmewqeq); + lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep); spin_lock_irqsave(&pring->ring_lock, iflags); } } @@ -2681,7 +2676,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba * nvmewqe->retry = 1; nvmewqe->vport = phba->pport; nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT; - nvmewqe->cmd_flag |= LPFC_IO_NVME_LS; + nvmewqe->iocb_flag |= LPFC_IO_NVME_LS;
/* Xmit NVMET response to remote NPORT <did> */ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC, @@ -3038,7 +3033,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for FCP cmds @@ -3046,14 +3041,13 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba **/ static void lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; uint32_t result; unsigned long flags; bool released = false; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3108,7 +3102,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for FCP cmds @@ -3116,14 +3110,13 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc **/ static void lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; unsigned long flags; uint32_t result; bool released = false; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3190,7 +3183,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lp * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS * @phba: Pointer to HBA context object. * @cmdwqe: Pointer to driver command WQE object. - * @rspwqe: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for NVME ABTS for LS cmds @@ -3198,12 +3191,11 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lp **/ static void lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, - struct lpfc_iocbq *rspwqe) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_async_xchg_ctx *ctxp; struct lpfc_nvmet_tgtport *tgtp; uint32_t result; - struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
ctxp = cmdwqe->context2; result = wcqe->parameter; @@ -3327,7 +3319,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc abts_wqeq->context1 = ndlp; abts_wqeq->context2 = ctxp; abts_wqeq->context3 = NULL; - abts_wqeq->num_bdes = 0; + abts_wqeq->rsvd2 = 0; /* hba_wqidx should already be setup from command we are aborting */ abts_wqeq->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CR; abts_wqeq->iocb.ulpLe = 1; @@ -3456,7 +3448,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lp }
/* Outstanding abort is in progress */ - if (abts_wqeq->cmd_flag & LPFC_DRIVER_ABORTED) { + if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) { spin_unlock_irqrestore(&phba->hbalock, flags); atomic_inc(&tgtp->xmt_abort_rsp_error); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -3471,14 +3463,15 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lp }
/* Ready - mark outstanding as aborted by driver. */ - abts_wqeq->cmd_flag |= LPFC_DRIVER_ABORTED; + abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED;
lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt);
/* ABTS WQE must go to the same WQ as the WQE to be aborted */ abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx; - abts_wqeq->cmd_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; - abts_wqeq->cmd_flag |= LPFC_IO_NVME; + abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp; + abts_wqeq->iocb_cmpl = NULL; + abts_wqeq->iocb_flag |= LPFC_IO_NVME; abts_wqeq->context2 = ctxp; abts_wqeq->vport = phba->pport; if (!ctxp->hdwq) @@ -3535,8 +3528,9 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct
spin_lock_irqsave(&phba->hbalock, flags); abts_wqeq = ctxp->wqeq; - abts_wqeq->cmd_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; - abts_wqeq->cmd_flag |= LPFC_IO_NVMET; + abts_wqeq->wqe_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp; + abts_wqeq->iocb_cmpl = NULL; + abts_wqeq->iocb_flag |= LPFC_IO_NVMET; if (!ctxp->hdwq) ctxp->hdwq = &phba->sli4_hba.hdwq[abts_wqeq->hba_wqidx];
@@ -3620,8 +3614,9 @@ lpfc_nvme_unsol_ls_issue_abort(struct lp }
spin_lock_irqsave(&phba->hbalock, flags); - abts_wqeq->cmd_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; - abts_wqeq->cmd_flag |= LPFC_IO_NVME_LS; + abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp; + abts_wqeq->iocb_cmpl = NULL; + abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS; rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq); spin_unlock_irqrestore(&phba->hbalock, flags); if (rc == WQE_SUCCESS) { --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -362,7 +362,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport * kfree(psb); break; } - psb->cur_iocbq.cmd_flag |= LPFC_IO_FCP; + psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
psb->fcp_cmnd = psb->data; psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd); @@ -468,7 +468,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(s spin_lock(&qp->abts_io_buf_list_lock); list_for_each_entry_safe(psb, next_psb, &qp->lpfc_abts_io_buf_list, list) { - if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) + if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) continue;
if (psb->rdata && psb->rdata->pnode && @@ -524,7 +524,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba list_del_init(&psb->list); psb->flags &= ~LPFC_SBUF_XBUSY; psb->status = IOSTAT_SUCCESS; - if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) { + if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) { qp->abts_nvme_io_bufs--; spin_unlock(&qp->abts_io_buf_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -571,7 +571,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba * for command completion wake up the thread. */ spin_lock_irqsave(&psb->buf_lock, iflag); - psb->cur_iocbq.cmd_flag &= + psb->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; if (psb->waitq) wake_up(psb->waitq); @@ -593,8 +593,8 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba for (i = 1; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i];
- if (!(iocbq->cmd_flag & LPFC_IO_FCP) || - (iocbq->cmd_flag & LPFC_IO_LIBDFC)) + if (!(iocbq->iocb_flag & LPFC_IO_FCP) || + (iocbq->iocb_flag & LPFC_IO_LIBDFC)) continue; if (iocbq->sli4_xritag != xri) continue; @@ -695,7 +695,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *ph /* Setup key fields in buffer that may have been changed * if other protocols used this buffer. */ - lpfc_cmd->cur_iocbq.cmd_flag = LPFC_IO_FCP; + lpfc_cmd->cur_iocbq.iocb_flag = LPFC_IO_FCP; lpfc_cmd->prot_seg_cnt = 0; lpfc_cmd->seg_cnt = 0; lpfc_cmd->timeout = 0; @@ -783,7 +783,7 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba
spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); psb->pCmd = NULL; - psb->cur_iocbq.cmd_flag = LPFC_IO_FCP; + psb->cur_iocbq.iocb_flag = LPFC_IO_FCP; list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put); spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); } @@ -931,7 +931,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hb physaddr = sg_dma_address(sgel); if (phba->sli_rev == 3 && !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - !(iocbq->cmd_flag & DSS_SECURITY_OP) && + !(iocbq->iocb_flag & DSS_SECURITY_OP) && nseg <= LPFC_EXT_DATA_BDE_COUNT) { data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; data_bde->tus.f.bdeSize = sg_dma_len(sgel); @@ -959,7 +959,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hb */ if (phba->sli_rev == 3 && !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && - !(iocbq->cmd_flag & DSS_SECURITY_OP)) { + !(iocbq->iocb_flag & DSS_SECURITY_OP)) { if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { /* * The extended IOCB format can only fit 3 BDE or a BPL. @@ -3434,7 +3434,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hb */ if ((phba->cfg_fof) && ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->oas_enabled) { - lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->priority;
@@ -3591,15 +3591,15 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc switch (scsi_get_prot_op(scsi_cmnd)) { case SCSI_PROT_WRITE_STRIP: case SCSI_PROT_READ_STRIP: - lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_STRIP; + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP; break; case SCSI_PROT_WRITE_INSERT: case SCSI_PROT_READ_INSERT: - lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_INSERT; + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT; break; case SCSI_PROT_WRITE_PASS: case SCSI_PROT_READ_PASS: - lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_PASS; + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS; break; }
@@ -3630,7 +3630,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc */ if ((phba->cfg_fof) && ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->oas_enabled) { - lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
/* Word 10 */ bf_set(wqe_oas, &wqe->generic.wqe_com, 1); @@ -3640,14 +3640,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc }
/* Word 7. DIF Flags */ - if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_PASS) + if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_PASS) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); - else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_STRIP) + else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_STRIP) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); - else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_INSERT) + else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_INSERT) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
- lpfc_cmd->cur_iocbq.cmd_flag &= ~(LPFC_IO_DIF_PASS | + lpfc_cmd->cur_iocbq.iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT);
return 0; @@ -4172,7 +4172,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *v * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO * @phba: The hba for which this call is being executed. * @pwqeIn: The command WQE for the scsi cmnd. - * @pwqeOut: Pointer to driver response WQE object. + * @wcqe: Pointer to driver response CQE object. * * This routine assigns scsi command result by looking into response WQE * status field appropriately. This routine handles QUEUE FULL condition as @@ -4180,11 +4180,10 @@ lpfc_handle_fcp_err(struct lpfc_vport *v **/ static void lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, - struct lpfc_iocbq *pwqeOut) + struct lpfc_wcqe_complete *wcqe) { struct lpfc_io_buf *lpfc_cmd = (struct lpfc_io_buf *)pwqeIn->context1; - struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl; struct lpfc_vport *vport = pwqeIn->vport; struct lpfc_rport_data *rdata; struct lpfc_nodelist *ndlp; @@ -4217,7 +4216,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba * This needs to be done outside buf_lock */ spin_lock_irqsave(&phba->hbalock, iflags); - lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_EXCHANGE_BUSY; + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore(&phba->hbalock, iflags); }
@@ -4508,7 +4507,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba * wake up the thread. */ spin_lock(&lpfc_cmd->buf_lock); - lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); spin_unlock(&lpfc_cmd->buf_lock); @@ -4568,7 +4567,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba lpfc_cmd->status = pIocbOut->iocb.ulpStatus; /* pick up SLI4 exchange busy status from HBA */ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; - if (pIocbOut->cmd_flag & LPFC_EXCHANGE_BUSY) + if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY) lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS @@ -4777,7 +4776,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba * wake up the thread. */ spin_lock(&lpfc_cmd->buf_lock); - lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); spin_unlock(&lpfc_cmd->buf_lock); @@ -4855,8 +4854,8 @@ static int lpfc_scsi_prep_cmnd_buf_s3(st
piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f); piocbq->context1 = lpfc_cmd; - if (!piocbq->cmd_cmpl) - piocbq->cmd_cmpl = lpfc_scsi_cmd_iocb_cmpl; + if (!piocbq->iocb_cmpl) + piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; piocbq->iocb.ulpTimeout = tmo; piocbq->vport = vport; return 0; @@ -4969,7 +4968,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(st pwqeq->vport = vport; pwqeq->context1 = lpfc_cmd; pwqeq->hba_wqidx = lpfc_cmd->hdwq_no; - pwqeq->cmd_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; + pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl;
return 0; } @@ -5691,7 +5690,7 @@ lpfc_queuecommand(struct Scsi_Host *shos lpfc_cmd->pCmd = cmnd; lpfc_cmd->rdata = rdata; lpfc_cmd->ndlp = ndlp; - lpfc_cmd->cur_iocbq.cmd_cmpl = NULL; + lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; cmnd->host_scribble = (unsigned char *)lpfc_cmd;
err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); @@ -5748,7 +5747,7 @@ lpfc_queuecommand(struct Scsi_Host *shos (union lpfc_vmid_io_tag *) &lpfc_cmd->cur_iocbq.vmid_tag); if (!err) - lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID; + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_VMID; } }
@@ -5935,7 +5934,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmn spin_lock(&pring_s4->ring_lock); } /* the command is in process of being cancelled */ - if (!(iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3169 SCSI Layer abort requested I/O has been " "cancelled by LLD.\n"); @@ -5958,7 +5957,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmn BUG_ON(iocb->context1 != lpfc_cmd);
/* abort issued in recovery is still in progress */ - if (iocb->cmd_flag & LPFC_DRIVER_ABORTED) { + if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3389 SCSI Layer I/O Abort Request is pending\n"); if (phba->sli_rev == LPFC_SLI_REV4) @@ -5999,7 +5998,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmn
wait_for_cmpl: /* - * cmd_flag is set to LPFC_DRIVER_ABORTED before we wait + * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait * for abort to complete. */ wait_event_timeout(waitq, @@ -6187,14 +6186,14 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp lpfc_release_scsi_buf(phba, lpfc_cmd); return FAILED; } - iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl; + iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "0702 Issue %s to TGT %d LUN %llu " "rpi x%x nlp_flag x%x Data: x%x x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, - iocbq->cmd_flag); + iocbq->iocb_flag);
status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING, iocbq, iocbqrsp, lpfc_cmd->timeout); @@ -6204,12 +6203,12 @@ lpfc_send_taskmgmt(struct lpfc_vport *vp iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0727 TMF %s to TGT %d LUN %llu " - "failed (%d, %d) cmd_flag x%x\n", + "failed (%d, %d) iocb_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, iocbqrsp->iocb.un.ulpWord[4], - iocbq->cmd_flag); + iocbq->iocb_flag); /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */ if (status == IOCB_SUCCESS) { if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1254,21 +1254,21 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba struct lpfc_sli_ring *pring = NULL; int found = 0;
- if (piocbq->cmd_flag & LPFC_IO_NVME_LS) + if (piocbq->iocb_flag & LPFC_IO_NVME_LS) pring = phba->sli4_hba.nvmels_wq->pring; else pring = lpfc_phba_elsring(phba);
lockdep_assert_held(&pring->ring_lock);
- if (piocbq->cmd_flag & LPFC_IO_FCP) { + if (piocbq->iocb_flag & LPFC_IO_FCP) { lpfc_cmd = (struct lpfc_io_buf *) piocbq->context1; ndlp = lpfc_cmd->rdata->pnode; } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && - !(piocbq->cmd_flag & LPFC_IO_LIBDFC)) { + !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) { ndlp = piocbq->context_un.ndlp; - } else if (piocbq->cmd_flag & LPFC_IO_LIBDFC) { - if (piocbq->cmd_flag & LPFC_IO_LOOPBACK) + } else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) { + if (piocbq->iocb_flag & LPFC_IO_LOOPBACK) ndlp = NULL; else ndlp = piocbq->context_un.ndlp; @@ -1391,7 +1391,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_
if (sglq) { - if (iocbq->cmd_flag & LPFC_IO_NVMET) { + if (iocbq->iocb_flag & LPFC_IO_NVMET) { spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, iflag); sglq->state = SGL_FREED; @@ -1403,7 +1403,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_ goto out; }
- if ((iocbq->cmd_flag & LPFC_EXCHANGE_BUSY) && + if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && (!(unlikely(pci_channel_offline(phba->pcidev)))) && sglq->state != SGL_XRI_ABORTED) { spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, @@ -1440,7 +1440,7 @@ out: memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); iocbq->sli4_lxritag = NO_XRI; iocbq->sli4_xritag = NO_XRI; - iocbq->cmd_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | + iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF | LPFC_IO_NVME_LS); list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); } @@ -1530,17 +1530,17 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *p
while (!list_empty(iocblist)) { list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); - if (piocb->cmd_cmpl) { - if (piocb->cmd_flag & LPFC_IO_NVME) + if (piocb->wqe_cmpl) { + if (piocb->iocb_flag & LPFC_IO_NVME) lpfc_nvme_cancel_iocb(phba, piocb, ulpstatus, ulpWord4); else lpfc_sli_release_iocbq(phba, piocb);
- } else if (piocb->cmd_cmpl) { + } else if (piocb->iocb_cmpl) { piocb->iocb.ulpStatus = ulpstatus; piocb->iocb.un.ulpWord[4] = ulpWord4; - (piocb->cmd_cmpl) (phba, piocb, piocb); + (piocb->iocb_cmpl) (phba, piocb, piocb); } else { lpfc_sli_release_iocbq(phba, piocb); } @@ -1732,7 +1732,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba BUG_ON(!piocb);
list_add_tail(&piocb->list, &pring->txcmplq); - piocb->cmd_flag |= LPFC_IO_ON_TXCMPLQ; + piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt++;
if ((unlikely(pring->ringno == LPFC_ELS_RING)) && @@ -1773,7 +1773,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phb * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. - * @rspiocb: Pointer to driver response iocb object. + * @cmf_cmpl: Pointer to completed WCQE. * * This routine will inform the driver of any BW adjustments we need * to make. These changes will be picked up during the next CMF @@ -1782,11 +1782,10 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phb **/ static void lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb) + struct lpfc_wcqe_complete *cmf_cmpl) { union lpfc_wqe128 *wqe; uint32_t status, info; - struct lpfc_wcqe_complete *wcqe = &rspiocb->wcqe_cmpl; uint64_t bw, bwdif, slop; uint64_t pcent, bwpcent; int asig, afpin, sigcnt, fpincnt; @@ -1794,22 +1793,22 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba char *s;
/* First check for error */ - status = bf_get(lpfc_wcqe_c_status, wcqe); + status = bf_get(lpfc_wcqe_c_status, cmf_cmpl); if (status) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "6211 CMF_SYNC_WQE Error " "req_tag x%x status x%x hwstatus x%x " "tdatap x%x parm x%x\n", - bf_get(lpfc_wcqe_c_request_tag, wcqe), - bf_get(lpfc_wcqe_c_status, wcqe), - bf_get(lpfc_wcqe_c_hw_status, wcqe), - wcqe->total_data_placed, - wcqe->parameter); + bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl), + bf_get(lpfc_wcqe_c_status, cmf_cmpl), + bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl), + cmf_cmpl->total_data_placed, + cmf_cmpl->parameter); goto out; }
/* Gather congestion information on a successful cmpl */ - info = wcqe->parameter; + info = cmf_cmpl->parameter; phba->cmf_active_info = info;
/* See if firmware info count is valid or has changed */ @@ -1818,15 +1817,15 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba else phba->cmf_info_per_interval = info;
- tdp = bf_get(lpfc_wcqe_c_cmf_bw, wcqe); - cg = bf_get(lpfc_wcqe_c_cmf_cg, wcqe); + tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl); + cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl);
/* Get BW requirement from firmware */ bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE; if (!bw) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, "6212 CMF_SYNC_WQE x%x: NULL bw\n", - bf_get(lpfc_wcqe_c_request_tag, wcqe)); + bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl)); goto out; }
@@ -2000,13 +1999,14 @@ initpath: bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT);
sync_buf->vport = phba->pport; - sync_buf->cmd_cmpl = lpfc_cmf_sync_cmpl; + sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl; + sync_buf->iocb_cmpl = NULL; sync_buf->context1 = NULL; sync_buf->context2 = NULL; sync_buf->context3 = NULL; sync_buf->sli4_xritag = NO_XRI;
- sync_buf->cmd_flag |= LPFC_IO_CMF; + sync_buf->iocb_flag |= LPFC_IO_CMF; ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf); if (ret_val) { lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, @@ -2175,7 +2175,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *ph /* * Set up an iotag */ - nextiocb->iocb.ulpIoTag = (nextiocb->cmd_cmpl) ? nextiocb->iotag : 0; + nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0;
if (pring->ringno == LPFC_ELS_RING) { @@ -2196,9 +2196,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *ph /* * If there is no completion routine to call, we can release the * IOCB buffer back right now. For IOCBs, like QUE_RING_BUF, - * that have no rsp ring completion, cmd_cmpl MUST be NULL. + * that have no rsp ring completion, iocb_cmpl MUST be NULL. */ - if (nextiocb->cmd_cmpl) + if (nextiocb->iocb_cmpl) lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb); else __lpfc_sli_release_iocbq(phba, nextiocb); @@ -3566,10 +3566,10 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *p
if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; - if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { + if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { /* remove from txcmpl queue list */ list_del_init(&cmd_iocb->list); - cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; @@ -3613,10 +3613,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc spin_lock_irqsave(temp_lock, iflag); if (iotag != 0 && iotag <= phba->sli.last_iotag) { cmd_iocb = phba->sli.iocbq_lookup[iotag]; - if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) { + if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { /* remove from txcmpl queue list */ list_del_init(&cmd_iocb->list); - cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; pring->txcmplq_cnt--; spin_unlock_irqrestore(temp_lock, iflag); return cmd_iocb; @@ -3626,9 +3626,9 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc spin_unlock_irqrestore(temp_lock, iflag); lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0372 iotag x%x lookup error: max iotag (x%x) " - "cmd_flag x%x\n", + "iocb_flag x%x\n", iotag, phba->sli.last_iotag, - cmd_iocb ? cmd_iocb->cmd_flag : 0xffff); + cmd_iocb ? cmd_iocb->iocb_flag : 0xffff); return NULL; }
@@ -3659,7 +3659,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb
cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq); if (cmdiocbp) { - if (cmdiocbp->cmd_cmpl) { + if (cmdiocbp->iocb_cmpl) { /* * If an ELS command failed send an event to mgmt * application. @@ -3677,11 +3677,11 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb */ if (pring->ringno == LPFC_ELS_RING) { if ((phba->sli_rev < LPFC_SLI_REV4) && - (cmdiocbp->cmd_flag & + (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED)) { spin_lock_irqsave(&phba->hbalock, iflag); - cmdiocbp->cmd_flag &= + cmdiocbp->iocb_flag &= ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -3696,12 +3696,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb */ spin_lock_irqsave(&phba->hbalock, iflag); - saveq->cmd_flag |= LPFC_DELAY_MEM_FREE; + saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; spin_unlock_irqrestore(&phba->hbalock, iflag); } if (phba->sli_rev == LPFC_SLI_REV4) { - if (saveq->cmd_flag & + if (saveq->iocb_flag & LPFC_EXCHANGE_BUSY) { /* Set cmdiocb flag for the * exchange busy so sgl (xri) @@ -3711,12 +3711,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb */ spin_lock_irqsave( &phba->hbalock, iflag); - cmdiocbp->cmd_flag |= + cmdiocbp->iocb_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore( &phba->hbalock, iflag); } - if (cmdiocbp->cmd_flag & + if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) { /* * Clear LPFC_DRIVER_ABORTED @@ -3725,7 +3725,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb */ spin_lock_irqsave( &phba->hbalock, iflag); - cmdiocbp->cmd_flag &= + cmdiocbp->iocb_flag &= ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore( &phba->hbalock, iflag); @@ -3745,14 +3745,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hb IOERR_SLI_ABORTED; spin_lock_irqsave( &phba->hbalock, iflag); - saveq->cmd_flag |= + saveq->iocb_flag |= LPFC_DELAY_MEM_FREE; spin_unlock_irqrestore( &phba->hbalock, iflag); } } } - (cmdiocbp->cmd_cmpl) (phba, cmdiocbp, saveq); + (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq); } else lpfc_sli_release_iocbq(phba, cmdiocbp); } else { @@ -3994,11 +3994,11 @@ lpfc_sli_handle_fast_ring_event(struct l spin_lock_irqsave(&phba->hbalock, iflag); if (unlikely(!cmdiocbq)) break; - if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) - cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; - if (cmdiocbq->cmd_cmpl) { + if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) + cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; + if (cmdiocbq->iocb_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, + (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &rspiocbq); spin_lock_irqsave(&phba->hbalock, iflag); } @@ -4193,10 +4193,10 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_h } if (cmdiocbp) { /* Call the specified completion routine */ - if (cmdiocbp->cmd_cmpl) { + if (cmdiocbp->iocb_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - (cmdiocbp->cmd_cmpl)(phba, cmdiocbp, + (cmdiocbp->iocb_cmpl)(phba, cmdiocbp, saveq); spin_lock_irqsave(&phba->hbalock, iflag); @@ -4575,7 +4575,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba list_splice_init(&pring->txq, &txq); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -4601,7 +4601,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba list_splice_init(&pring->txq, &txq); list_for_each_entry_safe(piocb, next_iocb, &pring->txcmplq, list) - piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ; + piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); pring->txq_cnt = 0; @@ -10117,7 +10117,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba
lockdep_assert_held(&phba->hbalock);
- if (piocb->cmd_cmpl && (!piocb->vport) && + if (piocb->iocb_cmpl && (!piocb->vport) && (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -10169,10 +10169,10 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba case CMD_QUE_RING_BUF64_CN: /* * For IOCBs, like QUE_RING_BUF, that have no rsp ring - * completion, cmd_cmpl MUST be 0. + * completion, iocb_cmpl MUST be 0. */ - if (piocb->cmd_cmpl) - piocb->cmd_cmpl = NULL; + if (piocb->iocb_cmpl) + piocb->iocb_cmpl = NULL; fallthrough; case CMD_CREATE_XRI_CR: case CMD_CLOSE_XRI_CN: @@ -10363,9 +10363,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba
fip = phba->hba_flag & HBA_FIP_SUPPORT; /* The fcp commands will set command type */ - if (iocbq->cmd_flag & LPFC_IO_FCP) + if (iocbq->iocb_flag & LPFC_IO_FCP) command_type = FCP_COMMAND; - else if (fip && (iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK)) + else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)) command_type = ELS_COMMAND_FIP; else command_type = ELS_COMMAND_NON_FIP; @@ -10410,7 +10410,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba
switch (iocbq->iocb.ulpCommand) { case CMD_ELS_REQUEST64_CR: - if (iocbq->cmd_flag & LPFC_IO_LIBDFC) + if (iocbq->iocb_flag & LPFC_IO_LIBDFC) ndlp = iocbq->context_un.ndlp; else ndlp = (struct lpfc_nodelist *)iocbq->context1; @@ -10437,7 +10437,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); /* CCP CCPE PV PRI in word10 were set in the memcpy */ if (command_type == ELS_COMMAND_FIP) - els_id = ((iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK) + els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) >> LPFC_FIP_ELS_ID_SHIFT); pcmd = (uint32_t *) (((struct lpfc_dmabuf *) iocbq->context2)->virt); @@ -10539,7 +10539,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba LPFC_WQE_LENLOC_WORD4); bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); - if (iocbq->cmd_flag & LPFC_IO_OAS) { + if (iocbq->iocb_flag & LPFC_IO_OAS) { bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1); bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); if (iocbq->priority) { @@ -10603,7 +10603,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba LPFC_WQE_LENLOC_WORD4); bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); - if (iocbq->cmd_flag & LPFC_IO_OAS) { + if (iocbq->iocb_flag & LPFC_IO_OAS) { bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1); bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1); if (iocbq->priority) { @@ -10666,7 +10666,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba LPFC_WQE_LENLOC_NONE); bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com, iocbq->iocb.ulpFCP2Rcvy); - if (iocbq->cmd_flag & LPFC_IO_OAS) { + if (iocbq->iocb_flag & LPFC_IO_OAS) { bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1); bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1); if (iocbq->priority) { @@ -10800,7 +10800,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba abrt_iotag = iocbq->iocb.un.acxri.abortContextTag; if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) { abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag]; - fip = abrtiocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK; + fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK; } else fip = 0;
@@ -10909,13 +10909,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba return IOCB_ERROR; }
- if (iocbq->cmd_flag & LPFC_IO_DIF_PASS) + if (iocbq->iocb_flag & LPFC_IO_DIF_PASS) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); - else if (iocbq->cmd_flag & LPFC_IO_DIF_STRIP) + else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); - else if (iocbq->cmd_flag & LPFC_IO_DIF_INSERT) + else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT) bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); - iocbq->cmd_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | + iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT); bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); @@ -11014,7 +11014,7 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_h }
/* add the VMID tags as per switch response */ - if (unlikely(piocb->cmd_flag & LPFC_IO_VMID)) { + if (unlikely(piocb->iocb_flag & LPFC_IO_VMID)) { if (phba->pport->vmid_priority_tagging) { bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1); bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com, @@ -11053,8 +11053,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba struct lpfc_sli_ring *pring;
/* Get the WQ */ - if ((piocb->cmd_flag & LPFC_IO_FCP) || - (piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { + if ((piocb->iocb_flag & LPFC_IO_FCP) || + (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq; } else { wq = phba->sli4_hba.els_wq; @@ -11095,7 +11095,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba } } } - } else if (piocb->cmd_flag & LPFC_IO_FCP) { + } else if (piocb->iocb_flag & LPFC_IO_FCP) { /* These IO's already have an XRI and a mapped sgl. */ sglq = NULL; } @@ -11212,14 +11212,14 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phb { struct lpfc_io_buf *lpfc_cmd;
- if (piocb->cmd_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { + if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { if (unlikely(!phba->sli4_hba.hdwq)) return NULL; /* * for abort iocb hba_wqidx should already * be setup based on what work queue we used. */ - if (!(piocb->cmd_flag & LPFC_USE_FCPWQIDX)) { + if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { lpfc_cmd = (struct lpfc_io_buf *)piocb->context1; piocb->hba_wqidx = lpfc_cmd->hdwq_no; } @@ -12361,14 +12361,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_h icmd = &cmdiocb->iocb; if (icmd->ulpCommand == CMD_ABORT_XRI_CN || icmd->ulpCommand == CMD_CLOSE_XRI_CN || - cmdiocb->cmd_flag & LPFC_DRIVER_ABORTED) + cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) return IOCB_ABORTING;
if (!pring) { - if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; else - cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; return retval; }
@@ -12378,10 +12378,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_h */ if ((vport->load_flag & FC_UNLOADING) && pring->ringno == LPFC_ELS_RING) { - if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl; + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; else - cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl; + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; return retval; }
@@ -12393,7 +12393,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_h /* This signals the response to set the correct status * before calling the completion handler */ - cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; + cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
iabt = &abtsiocbp->iocb; iabt->un.acxri.abortType = ABORT_TYPE_ABTS; @@ -12414,10 +12414,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_h
/* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; - if (cmdiocb->cmd_flag & LPFC_IO_FCP) - abtsiocbp->cmd_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); - if (cmdiocb->cmd_flag & LPFC_IO_FOF) - abtsiocbp->cmd_flag |= LPFC_IO_FOF; + if (cmdiocb->iocb_flag & LPFC_IO_FCP) + abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); + if (cmdiocb->iocb_flag & LPFC_IO_FOF) + abtsiocbp->iocb_flag |= LPFC_IO_FOF;
if (phba->link_state < LPFC_LINK_UP || (phba->sli_rev == LPFC_SLI_REV4 && @@ -12427,9 +12427,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_h iabt->ulpCommand = CMD_ABORT_XRI_CN;
if (cmpl) - abtsiocbp->cmd_cmpl = cmpl; + abtsiocbp->iocb_cmpl = cmpl; else - abtsiocbp->cmd_cmpl = lpfc_sli_abort_els_cmpl; + abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; abtsiocbp->vport = vport;
if (phba->sli_rev == LPFC_SLI_REV4) { @@ -12456,7 +12456,7 @@ abort_iotag_exit: abtsiocbp->iotag, retval);
if (retval) { - cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; + cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; __lpfc_sli_release_iocbq(phba, abtsiocbp); }
@@ -12524,9 +12524,9 @@ lpfc_sli_validate_fcp_iocb_for_abort(str * can't be premarked as driver aborted, nor be an ABORT iocb itself */ icmd = &iocbq->iocb; - if (!(iocbq->cmd_flag & LPFC_IO_FCP) || - !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ) || - (iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || + if (!(iocbq->iocb_flag & LPFC_IO_FCP) || + !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || + (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || (icmd->ulpCommand == CMD_ABORT_XRI_CN || icmd->ulpCommand == CMD_CLOSE_XRI_CN)) return -EINVAL; @@ -12630,8 +12630,8 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vpo
if (!iocbq || iocbq->vport != vport) continue; - if (!(iocbq->cmd_flag & LPFC_IO_FCP) || - !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) + if (!(iocbq->iocb_flag & LPFC_IO_FCP) || + !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) continue;
/* Include counting outstanding aborts */ @@ -12857,8 +12857,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vpor * If the iocbq is already being aborted, don't take a second * action, but do count it. */ - if ((iocbq->cmd_flag & LPFC_DRIVER_ABORTED) || - !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) { + if ((iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || + !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { if (phba->sli_rev == LPFC_SLI_REV4) spin_unlock(&pring_s4->ring_lock); spin_unlock(&lpfc_cmd->buf_lock); @@ -12888,10 +12888,10 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vpor
/* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocbq->hba_wqidx = iocbq->hba_wqidx; - if (iocbq->cmd_flag & LPFC_IO_FCP) - abtsiocbq->cmd_flag |= LPFC_USE_FCPWQIDX; - if (iocbq->cmd_flag & LPFC_IO_FOF) - abtsiocbq->cmd_flag |= LPFC_IO_FOF; + if (iocbq->iocb_flag & LPFC_IO_FCP) + abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; + if (iocbq->iocb_flag & LPFC_IO_FOF) + abtsiocbq->iocb_flag |= LPFC_IO_FOF;
ndlp = lpfc_cmd->rdata->pnode;
@@ -12902,13 +12902,13 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vpor abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
/* Setup callback routine and issue the command. */ - abtsiocbq->cmd_cmpl = lpfc_sli_abort_fcp_cmpl; + abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
/* * Indicate the IO is being aborted by the driver and set * the caller's flag into the aborted IO. */ - iocbq->cmd_flag |= LPFC_DRIVER_ABORTED; + iocbq->iocb_flag |= LPFC_DRIVER_ABORTED;
if (phba->sli_rev == LPFC_SLI_REV4) { ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, @@ -12957,7 +12957,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba struct lpfc_io_buf *lpfc_cmd;
spin_lock_irqsave(&phba->hbalock, iflags); - if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) { + if (cmdiocbq->iocb_flag & LPFC_IO_WAKE_TMO) {
/* * A time out has occurred for the iocb. If a time out @@ -12966,26 +12966,26 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba */
spin_unlock_irqrestore(&phba->hbalock, iflags); - cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl; - cmdiocbq->wait_cmd_cmpl = NULL; - if (cmdiocbq->cmd_cmpl) - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, NULL); + cmdiocbq->iocb_cmpl = cmdiocbq->wait_iocb_cmpl; + cmdiocbq->wait_iocb_cmpl = NULL; + if (cmdiocbq->iocb_cmpl) + (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, NULL); else lpfc_sli_release_iocbq(phba, cmdiocbq); return; }
- cmdiocbq->cmd_flag |= LPFC_IO_WAKE; + cmdiocbq->iocb_flag |= LPFC_IO_WAKE; if (cmdiocbq->context2 && rspiocbq) memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, &rspiocbq->iocb, sizeof(IOCB_t));
/* Set the exchange busy flag for task management commands */ - if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && - !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { + if ((cmdiocbq->iocb_flag & LPFC_IO_FCP) && + !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) { lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf, cur_iocbq); - if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY)) + if (rspiocbq && (rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY)) lpfc_cmd->flags |= LPFC_SBUF_XBUSY; else lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; @@ -13004,7 +13004,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba * @piocbq: Pointer to command iocb. * @flag: Flag to test. * - * This routine grabs the hbalock and then test the cmd_flag to + * This routine grabs the hbalock and then test the iocb_flag to * see if the passed in flag is set. * Returns: * 1 if flag is set. @@ -13018,7 +13018,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, int ret;
spin_lock_irqsave(&phba->hbalock, iflags); - ret = piocbq->cmd_flag & flag; + ret = piocbq->iocb_flag & flag; spin_unlock_irqrestore(&phba->hbalock, iflags); return ret;
@@ -13033,14 +13033,14 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, * @timeout: Timeout in number of seconds. * * This function issues the iocb to firmware and waits for the - * iocb to complete. The cmd_cmpl field of the shall be used + * iocb to complete. The iocb_cmpl field of the shall be used * to handle iocbs which time out. If the field is NULL, the * function shall free the iocbq structure. If more clean up is * needed, the caller is expected to provide a completion function * that will provide the needed clean up. If the iocb command is * not completed within timeout seconds, the function will either - * free the iocbq structure (if cmd_cmpl == NULL) or execute the - * completion function set in the cmd_cmpl field and then return + * free the iocbq structure (if iocb_cmpl == NULL) or execute the + * completion function set in the iocb_cmpl field and then return * a status of IOCB_TIMEDOUT. The caller should not free the iocb * resources if this function returns IOCB_TIMEDOUT. * The function waits for the iocb completion using an @@ -13052,7 +13052,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba, * This function assumes that the iocb completions occur while * this function sleep. So, this function cannot be called from * the thread which process iocb completion for this ring. - * This function clears the cmd_flag of the iocb object before + * This function clears the iocb_flag of the iocb object before * issuing the iocb and the iocb completion handler sets this * flag and wakes this thread when the iocb completes. * The contents of the response iocb will be copied to prspiocbq @@ -13092,10 +13092,10 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba piocb->context2 = prspiocbq; }
- piocb->wait_cmd_cmpl = piocb->cmd_cmpl; - piocb->cmd_cmpl = lpfc_sli_wake_iocb_wait; + piocb->wait_iocb_cmpl = piocb->iocb_cmpl; + piocb->iocb_cmpl = lpfc_sli_wake_iocb_wait; piocb->context_un.wait_queue = &done_q; - piocb->cmd_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO); + piocb->iocb_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO);
if (phba->cfg_poll & DISABLE_FCP_RING_INT) { if (lpfc_readl(phba->HCregaddr, &creg_val)) @@ -13113,7 +13113,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), timeout_req); spin_lock_irqsave(&phba->hbalock, iflags); - if (!(piocb->cmd_flag & LPFC_IO_WAKE)) { + if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
/* * IOCB timed out. Inform the wake iocb wait @@ -13121,7 +13121,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba */
iocb_completed = false; - piocb->cmd_flag |= LPFC_IO_WAKE_TMO; + piocb->iocb_flag |= LPFC_IO_WAKE_TMO; } spin_unlock_irqrestore(&phba->hbalock, iflags); if (iocb_completed) { @@ -13176,7 +13176,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba piocb->context2 = NULL;
piocb->context_un.wait_queue = NULL; - piocb->cmd_cmpl = NULL; + piocb->iocb_cmpl = NULL; return retval; }
@@ -14145,7 +14145,7 @@ lpfc_sli4_iocb_param_transfer(struct lpf /* Map WCQE parameters into irspiocb parameters */ status = bf_get(lpfc_wcqe_c_status, wcqe); pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK); - if (pIocbOut->cmd_flag & LPFC_IO_FCP) + if (pIocbOut->iocb_flag & LPFC_IO_FCP) if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR) pIocbIn->iocb.un.fcpi.fcpi_parm = pIocbOut->iocb.un.fcpi.fcpi_parm - @@ -14227,7 +14227,7 @@ lpfc_sli4_iocb_param_transfer(struct lpf /* Pick up HBA exchange busy condition */ if (bf_get(lpfc_wcqe_c_xb, wcqe)) { spin_lock_irqsave(&phba->hbalock, iflags); - pIocbIn->cmd_flag |= LPFC_EXCHANGE_BUSY; + pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore(&phba->hbalock, iflags); } } @@ -15078,6 +15078,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc { struct lpfc_sli_ring *pring = cq->pring; struct lpfc_iocbq *cmdiocbq; + struct lpfc_iocbq irspiocbq; unsigned long iflags;
/* Check for response status */ @@ -15116,31 +15117,39 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc #ifdef CONFIG_SCSI_LPFC_DEBUG_FS cmdiocbq->isr_timestamp = cq->isr_timestamp; #endif - if (bf_get(lpfc_wcqe_c_xb, wcqe)) { - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; - spin_unlock_irqrestore(&phba->hbalock, iflags); - } + if (cmdiocbq->iocb_cmpl == NULL) { + if (cmdiocbq->wqe_cmpl) { + /* For FCP the flag is cleared in wqe_cmpl */ + if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) && + cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { + spin_lock_irqsave(&phba->hbalock, iflags); + cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; + spin_unlock_irqrestore(&phba->hbalock, iflags); + }
- if (cmdiocbq->cmd_cmpl) { - /* For FCP the flag is cleared in cmd_cmpl */ - if (!(cmdiocbq->cmd_flag & LPFC_IO_FCP) && - cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) { - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; - spin_unlock_irqrestore(&phba->hbalock, iflags); + /* Pass the cmd_iocb and the wcqe to the upper layer */ + (cmdiocbq->wqe_cmpl)(phba, cmdiocbq, wcqe); + return; } - - /* Pass the cmd_iocb and the wcqe to the upper layer */ - memcpy(&cmdiocbq->wcqe_cmpl, wcqe, - sizeof(struct lpfc_wcqe_complete)); - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, cmdiocbq); - } else { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0375 FCP cmdiocb not callback function " "iotag: (%d)\n", bf_get(lpfc_wcqe_c_request_tag, wcqe)); + return; + } + + /* Only SLI4 non-IO commands stil use IOCB */ + /* Fake the irspiocb and copy necessary response information */ + lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); + + if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { + spin_lock_irqsave(&phba->hbalock, iflags); + cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; + spin_unlock_irqrestore(&phba->hbalock, iflags); } + + /* Pass the cmd_iocb and the rsp state to the upper layer */ + (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq); }
/** @@ -18962,7 +18971,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vpor }
ctiocb->vport = phba->pport; - ctiocb->cmd_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; + ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; ctiocb->sli4_lxritag = NO_XRI; ctiocb->sli4_xritag = NO_XRI;
@@ -19365,8 +19374,8 @@ lpfc_sli4_handle_mds_loopback(struct lpf
iocbq->context2 = pcmd; iocbq->vport = vport; - iocbq->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK; - iocbq->cmd_flag |= LPFC_USE_FCPWQIDX; + iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK; + iocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
/* * Setup rest of the iocb as though it were a WQE @@ -19384,7 +19393,7 @@ lpfc_sli4_handle_mds_loopback(struct lpf
iocbq->iocb.ulpCommand = CMD_SEND_FRAME; iocbq->iocb.ulpLe = 1; - iocbq->cmd_cmpl = lpfc_sli4_mds_loopback_cmpl; + iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0); if (rc == IOCB_ERROR) goto exit; @@ -21226,7 +21235,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, cmd = bf_get(wqe_cmnd, &wqe->generic.wqe_com); if (cmd == CMD_XMIT_BLS_RSP64_WQE) return sglq->sli4_xritag; - numBdes = pwqeq->num_bdes; + numBdes = pwqeq->rsvd2; if (numBdes) { /* The addrHigh and addrLow fields within the WQE * have not been byteswapped yet so there is no @@ -21327,7 +21336,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phb uint32_t ret = 0;
/* NVME_LS and NVME_LS ABTS requests. */ - if (pwqe->cmd_flag & LPFC_IO_NVME_LS) { + if (pwqe->iocb_flag & LPFC_IO_NVME_LS) { pring = phba->sli4_hba.nvmels_wq->pring; lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags, qp, wq_access); @@ -21358,7 +21367,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phb }
/* NVME_FCREQ and NVME_ABTS requests */ - if (pwqe->cmd_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { + if (pwqe->iocb_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ wq = qp->io_wq; pring = wq->pring; @@ -21380,7 +21389,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phb }
/* NVMET requests */ - if (pwqe->cmd_flag & LPFC_IO_NVMET) { + if (pwqe->iocb_flag & LPFC_IO_NVMET) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ wq = qp->io_wq; pring = wq->pring; @@ -21446,7 +21455,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_ return WQE_NORESOURCE;
/* Indicate the IO is being aborted by the driver. */ - cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED; + cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
abtswqe = &abtsiocb->wqe; memset(abtswqe, 0, sizeof(*abtswqe)); @@ -21465,15 +21474,15 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_
/* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocb->hba_wqidx = cmdiocb->hba_wqidx; - abtsiocb->cmd_flag |= LPFC_USE_FCPWQIDX; - if (cmdiocb->cmd_flag & LPFC_IO_FCP) - abtsiocb->cmd_flag |= LPFC_IO_FCP; - if (cmdiocb->cmd_flag & LPFC_IO_NVME) - abtsiocb->cmd_flag |= LPFC_IO_NVME; - if (cmdiocb->cmd_flag & LPFC_IO_FOF) - abtsiocb->cmd_flag |= LPFC_IO_FOF; + abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; + if (cmdiocb->iocb_flag & LPFC_IO_FCP) + abtsiocb->iocb_flag |= LPFC_IO_FCP; + if (cmdiocb->iocb_flag & LPFC_IO_NVME) + abtsiocb->iocb_flag |= LPFC_IO_NVME; + if (cmdiocb->iocb_flag & LPFC_IO_FOF) + abtsiocb->iocb_flag |= LPFC_IO_FOF; abtsiocb->vport = vport; - abtsiocb->cmd_cmpl = cmpl; + abtsiocb->wqe_cmpl = cmpl;
lpfc_cmd = container_of(cmdiocb, struct lpfc_io_buf, cur_iocbq); retval = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, abtsiocb); @@ -21484,7 +21493,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_ xritag, cmdiocb->iotag, abtsiocb->iotag, retval);
if (retval) { - cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED; + cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; __lpfc_sli_release_iocbq(phba, abtsiocb); }
@@ -21846,7 +21855,8 @@ void lpfc_release_io_buf(struct lpfc_hba
/* MUST zero fields if buffer is reused by another protocol */ lpfc_ncmd->nvmeCmd = NULL; - lpfc_ncmd->cur_iocbq.cmd_cmpl = NULL; + lpfc_ncmd->cur_iocbq.wqe_cmpl = NULL; + lpfc_ncmd->cur_iocbq.iocb_cmpl = NULL;
if (phba->cfg_xpsgl && !phba->nvmet_support && !list_empty(&lpfc_ncmd->dma_sgl_xtra_list)) --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -35,7 +35,7 @@ typedef enum _lpfc_ctx_cmd { LPFC_CTX_HOST } lpfc_ctx_cmd;
-union lpfc_vmid_tag { +union lpfc_vmid_iocb_tag { uint32_t app_id; uint8_t cs_ctl_vmid; struct lpfc_vmid_context *vmid_context; /* UVEM context information */ @@ -69,16 +69,16 @@ struct lpfc_iocbq { uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ uint16_t hba_wqidx; /* index to HBA work queue */ struct lpfc_cq_event cq_event; + struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */ uint64_t isr_timestamp;
union lpfc_wqe128 wqe; /* SLI-4 */ IOCB_t iocb; /* SLI-3 */ - struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
- uint8_t num_bdes; + uint8_t rsvd2; uint8_t priority; /* OAS priority */ uint8_t retry; /* retry counter for IOCB cmd - if needed */ - u32 cmd_flag; + uint32_t iocb_flag; #define LPFC_IO_LIBDFC 1 /* libdfc iocb */ #define LPFC_IO_WAKE 2 /* Synchronous I/O completed */ #define LPFC_IO_WAKE_TMO LPFC_IO_WAKE /* Synchronous I/O timed out */ @@ -123,13 +123,15 @@ struct lpfc_iocbq { struct lpfc_node_rrq *rrq; } context_un;
- union lpfc_vmid_tag vmid_tag; - void (*fabric_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, - struct lpfc_iocbq *rsp); - void (*wait_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, - struct lpfc_iocbq *rsp); - void (*cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd, - struct lpfc_iocbq *rsp); + union lpfc_vmid_iocb_tag vmid_tag; + void (*fabric_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_iocbq *); + void (*wait_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_iocbq *); + void (*iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_iocbq *); + void (*wqe_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_wcqe_complete *); };
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
From: Christian Löhle CLoehle@hyperstone.com
commit 406e14808ee695cbae1eafa5fd3ac563c29470ab upstream.
Before switching back to the right partition in mmc_blk_reset there used to be a check if hw_reset was even supported. This return value was removed, so there is no reason to check. Furthermore ensure part_curr is not falsely set to a valid value on reset or partition switch error.
As part of this change the code paths of mmc_blk_reset calls were checked to ensure no commands are issued after a failed mmc_blk_reset directly without going through the block layer.
Fixes: fefdd3c91e0a ("mmc: core: Drop superfluous validations in mmc_hw|sw_reset()") Cc: stable@vger.kernel.org Signed-off-by: Christian Loehle cloehle@hyperstone.com Reviewed-by: Adrian Hunter adrian.hunter@intel.com Link: https://lore.kernel.org/r/e91be6199d04414a91e20611c81bfe1d@hyperstone.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/mmc/core/block.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-)
--- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -133,6 +133,7 @@ struct mmc_blk_data { * track of the current selected device partition. */ unsigned int part_curr; +#define MMC_BLK_PART_INVALID UINT_MAX /* Unknown partition active */ int area_type;
/* debugfs files (only in main mmc_blk_data) */ @@ -984,9 +985,16 @@ static unsigned int mmc_blk_data_timeout return ms; }
+/* + * Attempts to reset the card and get back to the requested partition. + * Therefore any error here must result in cancelling the block layer + * request, it must not be reattempted without going through the mmc_blk + * partition sanity checks. + */ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, int type) { + struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev); int err;
if (md->reset_done & type) @@ -994,23 +1002,22 @@ static int mmc_blk_reset(struct mmc_blk_
md->reset_done |= type; err = mmc_hw_reset(host); + /* + * A successful reset will leave the card in the main partition, but + * upon failure it might not be, so set it to MMC_BLK_PART_INVALID + * in that case. + */ + main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type; + if (err) + return err; /* Ensure we switch back to the correct partition */ - if (err) { - struct mmc_blk_data *main_md = - dev_get_drvdata(&host->card->dev); - int part_err; - - main_md->part_curr = main_md->part_type; - part_err = mmc_blk_part_switch(host->card, md->part_type); - if (part_err) { - /* - * We have failed to get back into the correct - * partition, so we need to abort the whole request. - */ - return -ENODEV; - } - } - return err; + if (mmc_blk_part_switch(host->card, md->part_type)) + /* + * We have failed to get back into the correct + * partition, so we need to abort the whole request. + */ + return -ENODEV; + return 0; }
static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) @@ -1855,8 +1862,9 @@ static void mmc_blk_mq_rw_recovery(struc return;
/* Reset before last retry */ - if (mqrq->retries + 1 == MMC_MAX_RETRIES) - mmc_blk_reset(md, card->host, type); + if (mqrq->retries + 1 == MMC_MAX_RETRIES && + mmc_blk_reset(md, card->host, type)) + return;
/* Command errors fail fast, so use all MMC_MAX_RETRIES */ if (brq->sbc.error || brq->cmd.error)
From: Xin Long lucien.xin@gmail.com
commit 9d9effca9d7d7cf6341182a7c5cabcbd6fa28063 upstream.
The similar fix as commit 46cdedf2a0fa ("ethtool: pse-pd: fix null-deref on genl_info in dump") is also needed for ethtool eeprom.
Fixes: c781ff12a2f3 ("ethtool: Allow network drivers to dump arbitrary EEPROM data") Signed-off-by: Xin Long lucien.xin@gmail.com Link: https://lore.kernel.org/r/5575919a2efc74cd9ad64021880afc3805c54166.166636216... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ethtool/eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c index 1c94bb8ea03f..49c0a2a77f02 100644 --- a/net/ethtool/eeprom.c +++ b/net/ethtool/eeprom.c @@ -124,7 +124,7 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base, if (ret) goto err_free;
- ret = get_module_eeprom_by_page(dev, &page_data, info->extack); + ret = get_module_eeprom_by_page(dev, &page_data, info ? info->extack : NULL); if (ret < 0) goto err_ops;
From: Wei Yongjun weiyongjun1@huawei.com
commit 444d8ad4916edec8a9fc684e841287db9b1e999f upstream.
Fix to return error code -EINVAL from the error handling case instead of 0, as done elsewhere in this function.
Fixes: 94160108a70c ("net/ieee802154: fix uninit value bug in dgram_sendmsg") Signed-off-by: Wei Yongjun weiyongjun1@huawei.com Link: https://lore.kernel.org/r/20220919160830.1436109-1-weiyongjun@huaweicloud.co... Signed-off-by: Stefan Schmidt stefan@datenfreihafen.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ieee802154/socket.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c @@ -502,8 +502,10 @@ static int dgram_bind(struct sock *sk, s if (err < 0) goto out;
- if (addr->family != AF_IEEE802154) + if (addr->family != AF_IEEE802154) { + err = -EINVAL; goto out; + }
ieee802154_addr_from_sa(&haddr, &addr->addr); dev = ieee802154_get_dev(sock_net(sk), &haddr);
From: Alexander Stein alexander.stein@ew.tq-group.com
[ Upstream commit bb9ea2c31fa11b789ade4c3abcdda3c5370a76ab ]
The doc says the I²C device's name is used if devname is NULL, but actually the I²C device driver's name is used.
Fixes: 0658293012af ("media: v4l: subdev: Add a function to set an I²C sub-device's name") Signed-off-by: Alexander Stein alexander.stein@ew.tq-group.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/media/v4l2-common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 3eb202259e8c..5e25a098e8ce 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -175,7 +175,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, * * @sd: pointer to &struct v4l2_subdev * @client: pointer to struct i2c_client - * @devname: the name of the device; if NULL, the I²C device's name will be used + * @devname: the name of the device; if NULL, the I²C device drivers's name + * will be used * @postfix: sub-device specific string to put right after the I²C device name; * may be NULL */
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit 3ad290194bb06979367622e47357462836c1d3b4 ]
The "height" and "width" values come from the user so the "height * width" multiplication can overflow.
Link: https://lore.kernel.org/r/YxBBCRnm3mmvaiuR@kili
Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Reviewed-by: Andy Shevchenko andriy.shevchenko@intel.com Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/staging/media/atomisp/pci/sh_css_params.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index ccc007879564..deecffd438ae 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -962,8 +962,8 @@ sh_css_set_black_frame(struct ia_css_stream *stream, params->fpn_config.data = NULL; } if (!params->fpn_config.data) { - params->fpn_config.data = kvmalloc(height * width * - sizeof(short), GFP_KERNEL); + params->fpn_config.data = kvmalloc(array3_size(height, width, sizeof(short)), + GFP_KERNEL); if (!params->fpn_config.data) { IA_CSS_ERROR("out of memory"); IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
From: Nathan Huckleberry nhuck@google.com
[ Upstream commit 0b33a33bd15d5bab73b87152b220a8d0153a4587 ]
The mode_valid field in drm_connector_helper_funcs is expected to be of type: enum drm_mode_status (* mode_valid) (struct drm_connector *connector, struct drm_display_mode *mode);
The mismatched return type breaks forward edge kCFI since the underlying function definition does not match the function hook definition.
The return type of mdp4_lvds_connector_mode_valid should be changed from int to enum drm_mode_status.
Reported-by: Dan Carpenter error27@gmail.com Link: https://github.com/ClangBuiltLinux/linux/issues/1703 Cc: llvm@lists.linux.dev Signed-off-by: Nathan Huckleberry nhuck@google.com Fixes: 3e87599b68e7 ("drm/msm/mdp4: add LVDS panel support") Reviewed-by: Abhinav Kumar quic_abhinavk@quicinc.com Reviewed-by: Nathan Chancellor nathan@kernel.org Patchwork: https://patchwork.freedesktop.org/patch/502878/ Link: https://lore.kernel.org/r/20220913205551.155128-1-nhuck@google.com Signed-off-by: Abhinav Kumar quic_abhinavk@quicinc.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index 7288041dd86a..7444b75c4215 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -56,8 +56,9 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) return ret; }
-static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static enum drm_mode_status +mdp4_lvds_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { struct mdp4_lvds_connector *mdp4_lvds_connector = to_mdp4_lvds_connector(connector);
From: Gavin Shan gshan@redhat.com
[ Upstream commit 05c2224d4b049406b0545a10be05280ff4b8ba0a ]
It's required by vm_userspace_mem_region_add() that memory size should be aligned to host page size. However, one guest page is provided by memslot_modification_stress_test. It triggers failure in the scenario of 64KB-page-size-host and 4KB-page-size-guest, as the following messages indicate.
# ./memslot_modification_stress_test Testing guest mode: PA-bits:40, VA-bits:48, 4K pages guest physical test memory: [0xffbfff0000, 0xffffff0000) Finished creating vCPUs Started all vCPUs ==== Test Assertion Failure ==== lib/kvm_util.c:824: vm_adjust_num_guest_pages(vm->mode, npages) == npages pid=5712 tid=5712 errno=0 - Success 1 0x0000000000404eeb: vm_userspace_mem_region_add at kvm_util.c:822 2 0x0000000000401a5b: add_remove_memslot at memslot_modification_stress_test.c:82 3 (inlined by) run_test at memslot_modification_stress_test.c:110 4 0x0000000000402417: for_each_guest_mode at guest_modes.c:100 5 0x00000000004016a7: main at memslot_modification_stress_test.c:187 6 0x0000ffffb8cd4383: ?? ??:0 7 0x0000000000401827: _start at :? Number of guest pages is not compatible with the host. Try npages=16
Fix the issue by providing 16 guest pages to the memory slot for this particular combination of 64KB-page-size-host and 4KB-page-size-guest on aarch64.
Fixes: ef4c9f4f65462 ("KVM: selftests: Fix 32-bit truncation of vm_get_max_gfn()") Signed-off-by: Gavin Shan gshan@redhat.com Signed-off-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/r/20221013063020.201856-1-gshan@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/kvm/memslot_modification_stress_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/memslot_modification_stress_test.c b/tools/testing/selftests/kvm/memslot_modification_stress_test.c index 4cfcafea9f5a..1d806b8ffee2 100644 --- a/tools/testing/selftests/kvm/memslot_modification_stress_test.c +++ b/tools/testing/selftests/kvm/memslot_modification_stress_test.c @@ -72,7 +72,7 @@ struct memslot_antagonist_args { static void add_remove_memslot(struct kvm_vm *vm, useconds_t delay, uint64_t nr_modifications) { - const uint64_t pages = 1; + uint64_t pages = max_t(int, vm->page_size, getpagesize()) / vm->page_size; uint64_t gpa; int i;
From: Srinivasa Rao Mandadapu quic_srivasam@quicinc.com
[ Upstream commit c9a3545b1d771fb7b06a487796c40288c02c41c5 ]
Update HDMI volatile registers list as DMA, Channel Selection registers, vbit control registers are being reflected by hardware DP port disconnection.
This update is required to fix no display and no sound issue observed after reconnecting TAMA/SANWA DP cables. Once DP cable is unplugged, DMA control registers are being reset by hardware, however at second plugin, new dma control values does not updated to the dma hardware registers since new register value and cached values at the time of first plugin are same.
Fixes: 7cb37b7bd0d3 ("ASoC: qcom: Add support for lpass hdmi driver")
Signed-off-by: Srinivasa Rao Mandadapu quic_srivasam@quicinc.com Reported-by: Kuogee Hsieh quic_khsieh@quicinc.com Link: https://lore.kernel.org/r/1665637711-13300-1-git-send-email-quic_srivasam@qu... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/lpass-cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 5e89d280e355..b37f4736ee10 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -779,10 +779,18 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg) return true; if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v)) return true; + if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v)) + return true;
for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACURR_REG(v, i)) return true; + if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i)) + return true; + if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i)) + return true; + if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i)) + return true; } return false; }
From: Peter Zijlstra peterz@infradead.org
[ Upstream commit ca6c21327c6af02b7eec31ce4b9a740a18c6c13f ]
Marco reported:
Due to the implementation of how SIGTRAP are delivered if perf_event_attr::sigtrap is set, we've noticed 3 issues:
1. Missing SIGTRAP due to a race with event_sched_out() (more details below).
2. Hardware PMU events being disabled due to returning 1 from perf_event_overflow(). The only way to re-enable the event is for user space to first "properly" disable the event and then re-enable it.
3. The inability to automatically disable an event after a specified number of overflows via PERF_EVENT_IOC_REFRESH.
The worst of the 3 issues is problem (1), which occurs when a pending_disable is "consumed" by a racing event_sched_out(), observed as follows:
CPU0 | CPU1 --------------------------------+--------------------------- __perf_event_overflow() | perf_event_disable_inatomic() | pending_disable = CPU0 | ... | _perf_event_enable() | event_function_call() | task_function_call() | /* sends IPI to CPU0 */ <IPI> | ... __perf_event_enable() +--------------------------- ctx_resched() task_ctx_sched_out() ctx_sched_out() group_sched_out() event_sched_out() pending_disable = -1 </IPI> <IRQ-work> perf_pending_event() perf_pending_event_disable() /* Fails to send SIGTRAP because no pending_disable! */ </IRQ-work>
In the above case, not only is that particular SIGTRAP missed, but also all future SIGTRAPs because 'event_limit' is not reset back to 1.
To fix, rework pending delivery of SIGTRAP via IRQ-work by introduction of a separate 'pending_sigtrap', no longer using 'event_limit' and 'pending_disable' for its delivery.
Additionally; and different to Marco's proposed patch:
- recognise that pending_disable effectively duplicates oncpu for the case where it is set. As such, change the irq_work handler to use ->oncpu to target the event and use pending_* as boolean toggles.
- observe that SIGTRAP targets the ctx->task, so the context switch optimization that carries contexts between tasks is invalid. If the irq_work were delayed enough to hit after a context switch the SIGTRAP would be delivered to the wrong task.
- observe that if the event gets scheduled out (rotation/migration/context-switch/...) the irq-work would be insufficient to deliver the SIGTRAP when the event gets scheduled back in (the irq-work might still be pending on the old CPU).
Therefore have event_sched_out() convert the pending sigtrap into a task_work which will deliver the signal at return_to_user.
Fixes: 97ba62b27867 ("perf: Add support for SIGTRAP on perf events") Reported-by: Dmitry Vyukov dvyukov@google.com Debugged-by: Dmitry Vyukov dvyukov@google.com Reported-by: Marco Elver elver@google.com Debugged-by: Marco Elver elver@google.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Marco Elver elver@google.com Tested-by: Marco Elver elver@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/perf_event.h | 19 ++++- kernel/events/core.c | 153 +++++++++++++++++++++++++++--------- kernel/events/ring_buffer.c | 2 +- 3 files changed, 130 insertions(+), 44 deletions(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 6cce33e7e7ac..014eb0a963fc 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -723,11 +723,14 @@ struct perf_event { struct fasync_struct *fasync;
/* delayed work for NMIs and such */ - int pending_wakeup; - int pending_kill; - int pending_disable; + unsigned int pending_wakeup; + unsigned int pending_kill; + unsigned int pending_disable; + unsigned int pending_sigtrap; unsigned long pending_addr; /* SIGTRAP */ - struct irq_work pending; + struct irq_work pending_irq; + struct callback_head pending_task; + unsigned int pending_work;
atomic_t event_limit;
@@ -841,6 +844,14 @@ struct perf_event_context { #endif void *task_ctx_data; /* pmu specific data */ struct rcu_head rcu_head; + + /* + * Sum (event->pending_sigtrap + event->pending_work) + * + * The SIGTRAP is targeted at ctx->task, as such it won't do changing + * that until the signal is delivered. + */ + local_t nr_pending; };
/* diff --git a/kernel/events/core.c b/kernel/events/core.c index c6c7a4d80573..59654c737168 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -54,6 +54,7 @@ #include <linux/highmem.h> #include <linux/pgtable.h> #include <linux/buildid.h> +#include <linux/task_work.h>
#include "internal.h"
@@ -2352,11 +2353,26 @@ event_sched_out(struct perf_event *event, event->pmu->del(event, 0); event->oncpu = -1;
- if (READ_ONCE(event->pending_disable) >= 0) { - WRITE_ONCE(event->pending_disable, -1); + if (event->pending_disable) { + event->pending_disable = 0; perf_cgroup_event_disable(event, ctx); state = PERF_EVENT_STATE_OFF; } + + if (event->pending_sigtrap) { + bool dec = true; + + event->pending_sigtrap = 0; + if (state != PERF_EVENT_STATE_OFF && + !event->pending_work) { + event->pending_work = 1; + dec = false; + task_work_add(current, &event->pending_task, TWA_RESUME); + } + if (dec) + local_dec(&event->ctx->nr_pending); + } + perf_event_set_state(event, state);
if (!is_software_event(event)) @@ -2508,7 +2524,7 @@ static void __perf_event_disable(struct perf_event *event, * hold the top-level event's child_mutex, so any descendant that * goes to exit will block in perf_event_exit_event(). * - * When called from perf_pending_event it's OK because event->ctx + * When called from perf_pending_irq it's OK because event->ctx * is the current context on this CPU and preemption is disabled, * hence we can't get into perf_event_task_sched_out for this context. */ @@ -2547,9 +2563,8 @@ EXPORT_SYMBOL_GPL(perf_event_disable);
void perf_event_disable_inatomic(struct perf_event *event) { - WRITE_ONCE(event->pending_disable, smp_processor_id()); - /* can fail, see perf_pending_event_disable() */ - irq_work_queue(&event->pending); + event->pending_disable = 1; + irq_work_queue(&event->pending_irq); }
#define MAX_INTERRUPTS (~0ULL) @@ -3506,11 +3521,23 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn, raw_spin_lock_nested(&next_ctx->lock, SINGLE_DEPTH_NESTING); if (context_equiv(ctx, next_ctx)) {
+ perf_pmu_disable(pmu); + + /* PMIs are disabled; ctx->nr_pending is stable. */ + if (local_read(&ctx->nr_pending) || + local_read(&next_ctx->nr_pending)) { + /* + * Must not swap out ctx when there's pending + * events that rely on the ctx->task relation. + */ + raw_spin_unlock(&next_ctx->lock); + rcu_read_unlock(); + goto inside_switch; + } + WRITE_ONCE(ctx->task, next); WRITE_ONCE(next_ctx->task, task);
- perf_pmu_disable(pmu); - if (cpuctx->sched_cb_usage && pmu->sched_task) pmu->sched_task(ctx, false);
@@ -3551,6 +3578,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn, raw_spin_lock(&ctx->lock); perf_pmu_disable(pmu);
+inside_switch: if (cpuctx->sched_cb_usage && pmu->sched_task) pmu->sched_task(ctx, false); task_ctx_sched_out(cpuctx, ctx, EVENT_ALL); @@ -5030,7 +5058,7 @@ static void perf_addr_filters_splice(struct perf_event *event,
static void _free_event(struct perf_event *event) { - irq_work_sync(&event->pending); + irq_work_sync(&event->pending_irq);
unaccount_event(event);
@@ -6524,7 +6552,8 @@ static void perf_sigtrap(struct perf_event *event) return;
/* - * perf_pending_event() can race with the task exiting. + * Both perf_pending_task() and perf_pending_irq() can race with the + * task exiting. */ if (current->flags & PF_EXITING) return; @@ -6533,23 +6562,33 @@ static void perf_sigtrap(struct perf_event *event) event->attr.type, event->attr.sig_data); }
-static void perf_pending_event_disable(struct perf_event *event) +/* + * Deliver the pending work in-event-context or follow the context. + */ +static void __perf_pending_irq(struct perf_event *event) { - int cpu = READ_ONCE(event->pending_disable); + int cpu = READ_ONCE(event->oncpu);
+ /* + * If the event isn't running; we done. event_sched_out() will have + * taken care of things. + */ if (cpu < 0) return;
+ /* + * Yay, we hit home and are in the context of the event. + */ if (cpu == smp_processor_id()) { - WRITE_ONCE(event->pending_disable, -1); - - if (event->attr.sigtrap) { + if (event->pending_sigtrap) { + event->pending_sigtrap = 0; perf_sigtrap(event); - atomic_set_release(&event->event_limit, 1); /* rearm event */ - return; + local_dec(&event->ctx->nr_pending); + } + if (event->pending_disable) { + event->pending_disable = 0; + perf_event_disable_local(event); } - - perf_event_disable_local(event); return; }
@@ -6569,36 +6608,63 @@ static void perf_pending_event_disable(struct perf_event *event) * irq_work_queue(); // FAILS * * irq_work_run() - * perf_pending_event() + * perf_pending_irq() * * But the event runs on CPU-B and wants disabling there. */ - irq_work_queue_on(&event->pending, cpu); + irq_work_queue_on(&event->pending_irq, cpu); }
-static void perf_pending_event(struct irq_work *entry) +static void perf_pending_irq(struct irq_work *entry) { - struct perf_event *event = container_of(entry, struct perf_event, pending); + struct perf_event *event = container_of(entry, struct perf_event, pending_irq); int rctx;
- rctx = perf_swevent_get_recursion_context(); /* * If we 'fail' here, that's OK, it means recursion is already disabled * and we won't recurse 'further'. */ + rctx = perf_swevent_get_recursion_context();
- perf_pending_event_disable(event); - + /* + * The wakeup isn't bound to the context of the event -- it can happen + * irrespective of where the event is. + */ if (event->pending_wakeup) { event->pending_wakeup = 0; perf_event_wakeup(event); }
+ __perf_pending_irq(event); + if (rctx >= 0) perf_swevent_put_recursion_context(rctx); }
-/* +static void perf_pending_task(struct callback_head *head) +{ + struct perf_event *event = container_of(head, struct perf_event, pending_task); + int rctx; + + /* + * If we 'fail' here, that's OK, it means recursion is already disabled + * and we won't recurse 'further'. + */ + preempt_disable_notrace(); + rctx = perf_swevent_get_recursion_context(); + + if (event->pending_work) { + event->pending_work = 0; + perf_sigtrap(event); + local_dec(&event->ctx->nr_pending); + } + + if (rctx >= 0) + perf_swevent_put_recursion_context(rctx); + preempt_enable_notrace(); +} + +/* * We assume there is only KVM supporting the callbacks. * Later on, we might change it to a list if there is * another virtualization implementation supporting the callbacks. @@ -9229,8 +9295,8 @@ int perf_event_account_interrupt(struct perf_event *event) */
static int __perf_event_overflow(struct perf_event *event, - int throttle, struct perf_sample_data *data, - struct pt_regs *regs) + int throttle, struct perf_sample_data *data, + struct pt_regs *regs) { int events = atomic_read(&event->event_limit); int ret = 0; @@ -9253,24 +9319,36 @@ static int __perf_event_overflow(struct perf_event *event, if (events && atomic_dec_and_test(&event->event_limit)) { ret = 1; event->pending_kill = POLL_HUP; - event->pending_addr = data->addr; - perf_event_disable_inatomic(event); }
+ if (event->attr.sigtrap) { + /* + * Should not be able to return to user space without processing + * pending_sigtrap (kernel events can overflow multiple times). + */ + WARN_ON_ONCE(event->pending_sigtrap && event->attr.exclude_kernel); + if (!event->pending_sigtrap) { + event->pending_sigtrap = 1; + local_inc(&event->ctx->nr_pending); + } + event->pending_addr = data->addr; + irq_work_queue(&event->pending_irq); + } + READ_ONCE(event->overflow_handler)(event, data, regs);
if (*perf_event_fasync(event) && event->pending_kill) { event->pending_wakeup = 1; - irq_work_queue(&event->pending); + irq_work_queue(&event->pending_irq); }
return ret; }
int perf_event_overflow(struct perf_event *event, - struct perf_sample_data *data, - struct pt_regs *regs) + struct perf_sample_data *data, + struct pt_regs *regs) { return __perf_event_overflow(event, 1, data, regs); } @@ -11576,8 +11654,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
init_waitqueue_head(&event->waitq); - event->pending_disable = -1; - init_irq_work(&event->pending, perf_pending_event); + init_irq_work(&event->pending_irq, perf_pending_irq); + init_task_work(&event->pending_task, perf_pending_task);
mutex_init(&event->mmap_mutex); raw_spin_lock_init(&event->addr_filters.lock); @@ -11599,9 +11677,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (parent_event) event->event_caps = parent_event->event_caps;
- if (event->attr.sigtrap) - atomic_set(&event->event_limit, 1); - if (task) { event->attach_state = PERF_ATTACH_TASK; /* diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index fb35b926024c..f40da32f5e75 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -22,7 +22,7 @@ static void perf_output_wakeup(struct perf_output_handle *handle) atomic_set(&handle->rb->poll, EPOLLIN);
handle->event->pending_wakeup = 1; - irq_work_queue(&handle->event->pending); + irq_work_queue(&handle->event->pending_irq); }
/*
From: Lin Shengwang linshengwang1@huawei.com
[ Upstream commit e705968dd687574b6ca3ebe772683d5642759132 ]
In commit 97886d9dcd86 ("sched: Migration changes for core scheduling"), sched_group_cookie_match() was added to help determine if a cookie matches the core state.
However, while it iterates the SMT group, it fails to actually use the RQ for each of the CPUs iterated, use cpu_rq(cpu) instead of rq to fix things.
Fixes: 97886d9dcd86 ("sched: Migration changes for core scheduling") Signed-off-by: Lin Shengwang linshengwang1@huawei.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Link: https://lkml.kernel.org/r/20221008022709.642-1-linshengwang1@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/sched.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index e49902898253..7a3fcd70aa86 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1148,6 +1148,14 @@ static inline bool is_migration_disabled(struct task_struct *p) #endif }
+DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); + +#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) +#define this_rq() this_cpu_ptr(&runqueues) +#define task_rq(p) cpu_rq(task_cpu(p)) +#define cpu_curr(cpu) (cpu_rq(cpu)->curr) +#define raw_rq() raw_cpu_ptr(&runqueues) + struct sched_group; #ifdef CONFIG_SCHED_CORE static inline struct cpumask *sched_group_span(struct sched_group *sg); @@ -1235,7 +1243,7 @@ static inline bool sched_group_cookie_match(struct rq *rq, return true;
for_each_cpu_and(cpu, sched_group_span(group), p->cpus_ptr) { - if (sched_core_cookie_match(rq, p)) + if (sched_core_cookie_match(cpu_rq(cpu), p)) return true; } return false; @@ -1361,14 +1369,6 @@ static inline void update_idle_core(struct rq *rq) static inline void update_idle_core(struct rq *rq) { } #endif
-DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); - -#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) -#define this_rq() this_cpu_ptr(&runqueues) -#define task_rq(p) cpu_rq(task_cpu(p)) -#define cpu_curr(cpu) (cpu_rq(cpu)->curr) -#define raw_rq() raw_cpu_ptr(&runqueues) - #ifdef CONFIG_FAIR_GROUP_SCHED static inline struct task_struct *task_of(struct sched_entity *se) {
From: Randy Dunlap rdunlap@infradead.org
[ Upstream commit c44f15c1c09481d50fd33478ebb5b8284f8f5edb ]
Add 'volatile' to iounmap()'s argument to prevent build warnings. This make it the same as other major architectures.
Placates these warnings: (12 such warnings)
../drivers/video/fbdev/riva/fbdev.c: In function 'rivafb_probe': ../drivers/video/fbdev/riva/fbdev.c:2067:42: error: passing argument 1 of 'iounmap' discards 'volatile' qualifier from pointer target type [-Werror=discarded-qualifiers] 2067 | iounmap(default_par->riva.PRAMIN);
Fixes: 1162b0701b14b ("ARC: I/O and DMA Mappings") Signed-off-by: Randy Dunlap rdunlap@infradead.org Cc: Vineet Gupta vgupta@kernel.org Cc: linux-snps-arc@lists.infradead.org Cc: Arnd Bergmann arnd@arndb.de Signed-off-by: Vineet Gupta vgupta@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arc/include/asm/io.h | 2 +- arch/arc/mm/ioremap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index 8f777d6441a5..80347382a380 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -32,7 +32,7 @@ static inline void ioport_unmap(void __iomem *addr) { }
-extern void iounmap(const void __iomem *addr); +extern void iounmap(const volatile void __iomem *addr);
/* * io{read,write}{16,32}be() macros diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c index 0ee75aca6e10..712c2311daef 100644 --- a/arch/arc/mm/ioremap.c +++ b/arch/arc/mm/ioremap.c @@ -94,7 +94,7 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size, EXPORT_SYMBOL(ioremap_prot);
-void iounmap(const void __iomem *addr) +void iounmap(const volatile void __iomem *addr) { /* weird double cast to handle phys_addr_t > 32 bits */ if (arc_uncached_addr_space((phys_addr_t)(u32)addr))
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 1f3b494d1fc18ebb37aaa47107e9b84bf5b54ff7 ]
The 'chip_np' returned by of_get_next_child() with refcount decremented, of_node_put() need be called in error path to decrease the refcount.
Fixes: bfc618fcc3f1 ("mtd: rawnand: intel: Read the chip-select line from the correct OF node") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Martin Blumenstingl martin.blumenstingl@googlemail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20220924131010.957117-1-yangyingliang@huaw... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mtd/nand/raw/intel-nand-controller.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c index 056835fd4562..53071e791e17 100644 --- a/drivers/mtd/nand/raw/intel-nand-controller.c +++ b/drivers/mtd/nand/raw/intel-nand-controller.c @@ -614,11 +614,12 @@ static int ebu_nand_probe(struct platform_device *pdev) ret = of_property_read_u32(chip_np, "reg", &cs); if (ret) { dev_err(dev, "failed to get chip select: %d\n", ret); - return ret; + goto err_of_node_put; } if (cs >= MAX_CS) { dev_err(dev, "got invalid chip select: %d\n", cs); - return -EINVAL; + ret = -EINVAL; + goto err_of_node_put; }
ebu_host->cs_num = cs; @@ -627,18 +628,20 @@ static int ebu_nand_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname); ebu_host->cs[cs].chipaddr = devm_ioremap_resource(dev, res); if (IS_ERR(ebu_host->cs[cs].chipaddr)) - return PTR_ERR(ebu_host->cs[cs].chipaddr); + goto err_of_node_put; ebu_host->cs[cs].nand_pa = res->start;
ebu_host->clk = devm_clk_get(dev, NULL); - if (IS_ERR(ebu_host->clk)) - return dev_err_probe(dev, PTR_ERR(ebu_host->clk), - "failed to get clock\n"); + if (IS_ERR(ebu_host->clk)) { + ret = dev_err_probe(dev, PTR_ERR(ebu_host->clk), + "failed to get clock\n"); + goto err_of_node_put; + }
ret = clk_prepare_enable(ebu_host->clk); if (ret) { dev_err(dev, "failed to enable clock: %d\n", ret); - return ret; + goto err_of_node_put; } ebu_host->clk_rate = clk_get_rate(ebu_host->clk);
@@ -703,6 +706,8 @@ static int ebu_nand_probe(struct platform_device *pdev) ebu_dma_cleanup(ebu_host); err_disable_unprepare_clk: clk_disable_unprepare(ebu_host->clk); +err_of_node_put: + of_node_put(chip_np);
return ret; }
From: Srinivasa Rao Mandadapu quic_srivasam@quicinc.com
[ Upstream commit 1dd5166102e7ca91e8c5d833110333835e147ddb ]
Update LPASS_HDMI_TX_PARITY_ADDR register as volatile, to fix dp audio failures observed with some of external monitors.
Fixes: 7cb37b7bd0d3 ("ASoC: qcom: Add support for lpass hdmi driver")
Signed-off-by: Srinivasa Rao Mandadapu quic_srivasam@quicinc.com Reviewed-by: Stephen Boyd swboyd@chromium.org Link: https://lore.kernel.org/r/1665825530-7593-1-git-send-email-quic_srivasam@qui... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/qcom/lpass-cpu.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index b37f4736ee10..5e8d045c1a06 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -781,6 +781,8 @@ static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg) return true; if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v)) return true; + if (reg == LPASS_HDMI_TX_PARITY_ADDR(v)) + return true;
for (i = 0; i < v->hdmi_rdma_channels; ++i) { if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 4881bda5ea05c8c240fc8afeaa928e2bc43f61fa ]
If device_register() fails in snd_ac97_dev_register(), it should call put_device() to give up reference, or the name allocated in dev_set_name() is leaked.
Fixes: 0ca06a00e206 ("[ALSA] AC97 bus interface for ad-hoc drivers") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20221019093025.1179475-1-yangyingliang@huawei.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/pci/ac97/ac97_codec.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index cb60a07d39a8..ceead55f13ab 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2009,6 +2009,7 @@ static int snd_ac97_dev_register(struct snd_device *device) err = device_register(&ac97->dev); if (err < 0) { ac97_err(ac97, "Can't register ac97 bus\n"); + put_device(&ac97->dev); ac97->dev.bus = NULL; return err; }
From: Maxim Levitsky mlevitsk@redhat.com
[ Upstream commit b329f5ddc9ce4b622d9c7aaf5c6df4de52caf91a ]
clear_cpu_cap(&boot_cpu_data) is very similar to setup_clear_cpu_cap() except that the latter also sets a bit in 'cpu_caps_cleared' which later clears the same cap in secondary cpus, which is likely what is meant here.
Fixes: 47125db27e47 ("perf/x86/intel/lbr: Support Architectural LBR") Signed-off-by: Maxim Levitsky mlevitsk@redhat.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Kan Liang kan.liang@linux.intel.com Link: https://lkml.kernel.org/r/20220718141123.136106-2-mlevitsk@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/events/intel/lbr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 673721387391..b3f92255cbd2 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1847,7 +1847,7 @@ void __init intel_pmu_arch_lbr_init(void) return;
clear_arch_lbr: - clear_cpu_cap(&boot_cpu_data, X86_FEATURE_ARCH_LBR); + setup_clear_cpu_cap(X86_FEATURE_ARCH_LBR); }
/**
From: Xin Long lucien.xin@gmail.com
[ Upstream commit 82cb4e4612c633a9ce320e1773114875604a3cce ]
syzbot found a crash in tipc_topsrv_accept:
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] Workqueue: tipc_rcv tipc_topsrv_accept RIP: 0010:kernel_accept+0x22d/0x350 net/socket.c:3487 Call Trace: <TASK> tipc_topsrv_accept+0x197/0x280 net/tipc/topsrv.c:460 process_one_work+0x991/0x1610 kernel/workqueue.c:2289 worker_thread+0x665/0x1080 kernel/workqueue.c:2436 kthread+0x2e4/0x3a0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
It was caused by srv->listener that might be set to null by tipc_topsrv_stop() in net .exit whereas it's still used in tipc_topsrv_accept() worker.
srv->listener is protected by srv->idr_lock in tipc_topsrv_stop(), so add a check for srv->listener under srv->idr_lock in tipc_topsrv_accept() to avoid the null-ptr-deref. To ensure the lsock is not released during the tipc_topsrv_accept(), move sock_release() after tipc_topsrv_work_stop() where it's waiting until the tipc_topsrv_accept worker to be done.
Note that sk_callback_lock is used to protect sk->sk_user_data instead of srv->listener, and it should check srv in tipc_topsrv_listener_data_ready() instead. This also ensures that no more tipc_topsrv_accept worker will be started after tipc_conn_close() is called in tipc_topsrv_stop() where it sets sk->sk_user_data to null.
Fixes: 0ef897be12b8 ("tipc: separate topology server listener socket from subcsriber sockets") Reported-by: syzbot+c5ce866a8d30f4be0651@syzkaller.appspotmail.com Signed-off-by: Xin Long lucien.xin@gmail.com Acked-by: Jon Maloy jmaloy@redhat.com Link: https://lore.kernel.org/r/4eee264380c409c61c6451af1059b7fb271a7e7b.166612079... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/tipc/topsrv.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index 14fd05fd6107..d92ec92f0b71 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -450,12 +450,19 @@ static void tipc_conn_data_ready(struct sock *sk) static void tipc_topsrv_accept(struct work_struct *work) { struct tipc_topsrv *srv = container_of(work, struct tipc_topsrv, awork); - struct socket *lsock = srv->listener; - struct socket *newsock; + struct socket *newsock, *lsock; struct tipc_conn *con; struct sock *newsk; int ret;
+ spin_lock_bh(&srv->idr_lock); + if (!srv->listener) { + spin_unlock_bh(&srv->idr_lock); + return; + } + lsock = srv->listener; + spin_unlock_bh(&srv->idr_lock); + while (1) { ret = kernel_accept(lsock, &newsock, O_NONBLOCK); if (ret < 0) @@ -489,7 +496,7 @@ static void tipc_topsrv_listener_data_ready(struct sock *sk)
read_lock_bh(&sk->sk_callback_lock); srv = sk->sk_user_data; - if (srv->listener) + if (srv) queue_work(srv->rcv_wq, &srv->awork); read_unlock_bh(&sk->sk_callback_lock); } @@ -699,8 +706,9 @@ static void tipc_topsrv_stop(struct net *net) __module_get(lsock->sk->sk_prot_creator->owner); srv->listener = NULL; spin_unlock_bh(&srv->idr_lock); - sock_release(lsock); + tipc_topsrv_work_stop(srv); + sock_release(lsock); idr_destroy(&srv->conn_idr); kfree(srv); }
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 94423589689124e8cd145b38a1034be7f25835b2 ]
If phy_device_register() fails, phy_device_free() need be called to put refcount, so memory of phy device and device name can be freed in callback function.
If get_phy_device() fails, mdiobus_unregister() need be called, or it will cause warning in mdiobus_free() and kobject is leaked.
Fixes: 533dd11a12f6 ("net: socionext: Add Synquacer NetSec driver") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20221019064104.3228892-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/socionext/netsec.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 1f46af136aa8..f0451911ab8f 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -1964,11 +1964,13 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr) ret = PTR_ERR(priv->phydev); dev_err(priv->dev, "get_phy_device err(%d)\n", ret); priv->phydev = NULL; + mdiobus_unregister(bus); return -ENODEV; }
ret = phy_device_register(priv->phydev); if (ret) { + phy_device_free(priv->phydev); mdiobus_unregister(bus); dev_err(priv->dev, "phy_device_register err(%d)\n", ret);
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit c0605cd6750f2db9890c43a91ea4d77be8fb4908 ]
The value of lli_credit_cnt is incorrectly assigned, fix it.
Fixes: a0337c0dee68 ("hinic: add support to set and get irq coalesce") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index ca76896d9f1c..8b04d133b3c4 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -892,7 +892,7 @@ int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev, if (err) return -EINVAL;
- interrupt_info->lli_credit_cnt = temp_info.lli_timer_cnt; + interrupt_info->lli_credit_cnt = temp_info.lli_credit_cnt; interrupt_info->lli_timer_cnt = temp_info.lli_timer_cnt;
err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 4c1f602df8956bc0decdafd7e4fc7eef50c550b1 ]
When the input parameter idx meets the expected case option in hinic_dbg_get_func_table(), read_data is not released. Fix it.
Fixes: 5215e16244ee ("hinic: add support to query function table") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/huawei/hinic/hinic_debugfs.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c b/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c index 19eb839177ec..061952c6c21a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c @@ -85,6 +85,7 @@ static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx) struct tag_sml_funcfg_tbl *funcfg_table_elem; struct hinic_cmd_lt_rd *read_data; u16 out_size = sizeof(*read_data); + int ret = ~0; int err;
read_data = kzalloc(sizeof(*read_data), GFP_KERNEL); @@ -111,20 +112,25 @@ static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx)
switch (idx) { case VALID: - return funcfg_table_elem->dw0.bs.valid; + ret = funcfg_table_elem->dw0.bs.valid; + break; case RX_MODE: - return funcfg_table_elem->dw0.bs.nic_rx_mode; + ret = funcfg_table_elem->dw0.bs.nic_rx_mode; + break; case MTU: - return funcfg_table_elem->dw1.bs.mtu; + ret = funcfg_table_elem->dw1.bs.mtu; + break; case RQ_DEPTH: - return funcfg_table_elem->dw13.bs.cfg_rq_depth; + ret = funcfg_table_elem->dw13.bs.cfg_rq_depth; + break; case QUEUE_NUM: - return funcfg_table_elem->dw13.bs.cfg_q_num; + ret = funcfg_table_elem->dw13.bs.cfg_q_num; + break; }
kfree(read_data);
- return ~0; + return ret; }
static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count,
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 363cc87767f6ddcfb9158ad2e2afa2f8d5c4b94e ]
When hinic_set_cmdq_depth() fails in hinic_init_cmdqs(), the cmdq memory is not released correctly. Fix it.
Fixes: 72ef908bb3ff ("hinic: add three net_device_ops of vf") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c index a627237f694b..afa816cfcdf4 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c @@ -929,7 +929,7 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
err_set_cmdq_depth: hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ); - + free_cmdq(&cmdqs->cmdq[HINIC_CMDQ_SYNC]); err_cmdq_ctxt: hinic_wqs_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs, HINIC_MAX_CMDQ_TYPES);
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit 8ec2f4c6b2e11a4249bba77460f0cfe6d95a82f8 ]
In hinic_vf_func_init(), if VF fails to register information with PF through the MBOX, the MBOX callback function of VF is released once. But it is released again in hinic_init_hwdev(). Remove one.
Fixes: 7dd29ee12865 ("hinic: add sriov feature support") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/huawei/hinic/hinic_sriov.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c index a78c398bf5b2..e81a7b28209b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c @@ -1180,7 +1180,6 @@ int hinic_vf_func_init(struct hinic_hwdev *hwdev) dev_err(&hwdev->hwif->pdev->dev, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n", err, register_info.status, out_size); - hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC); return -EIO; } } else {
From: Sergiu Moga sergiu.moga@microchip.com
[ Upstream commit 15a9dbec631cd69dfbbfc4e2cbf90c9dd8432a8f ]
The `macb_resume`/`macb_suspend` methods already call the `phylink_start`/`phylink_stop` methods during their execution so explicitly say that the PM of the PHY is done by MAC by using the `mac_managed_pm` flag of the `struct phylink_config`.
This also fixes the warning message issued during resume: WARNING: CPU: 0 PID: 237 at drivers/net/phy/phy_device.c:323 mdio_bus_phy_resume+0x144/0x148
Depends-on: 96de900ae78e ("net: phylink: add mac_managed_pm in phylink_config structure") Fixes: 744d23c71af3 ("net: phy: Warn about incorrect mdio_bus_phy_resume() state") Signed-off-by: Sergiu Moga sergiu.moga@microchip.com Reviewed-by: Florian Fainelli f.fainelli@gmail.com Reviewed-by: Claudiu Beznea claudiu.beznea@microchip.com Link: https://lore.kernel.org/r/20221019120929.63098-1-sergiu.moga@microchip.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/cadence/macb_main.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 3ca3f9d0fd9b..61efb2350412 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -880,6 +880,7 @@ static int macb_mii_probe(struct net_device *dev)
bp->phylink_config.dev = &dev->dev; bp->phylink_config.type = PHYLINK_NETDEV; + bp->phylink_config.mac_managed_pm = true;
if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { bp->phylink_config.poll_fixed_state = true;
From: Shang XiaoJing shangxiaojing@huawei.com
[ Upstream commit e840d8f4a1b323973052a1af5ad4edafcde8ae3d ]
skb should be free in virtual_nci_send(), otherwise kmemleak will report memleak.
Steps for reproduction (simulated in qemu): cd tools/testing/selftests/nci make ./nci_dev
BUG: memory leak unreferenced object 0xffff888107588000 (size 208): comm "nci_dev", pid 206, jiffies 4294945376 (age 368.248s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<000000008d94c8fd>] __alloc_skb+0x1da/0x290 [<00000000278bc7f8>] nci_send_cmd+0xa3/0x350 [<0000000081256a22>] nci_reset_req+0x6b/0xa0 [<000000009e721112>] __nci_request+0x90/0x250 [<000000005d556e59>] nci_dev_up+0x217/0x5b0 [<00000000e618ce62>] nfc_dev_up+0x114/0x220 [<00000000981e226b>] nfc_genl_dev_up+0x94/0xe0 [<000000009bb03517>] genl_family_rcv_msg_doit.isra.14+0x228/0x2d0 [<00000000b7f8c101>] genl_rcv_msg+0x35c/0x640 [<00000000c94075ff>] netlink_rcv_skb+0x11e/0x350 [<00000000440cfb1e>] genl_rcv+0x24/0x40 [<0000000062593b40>] netlink_unicast+0x43f/0x640 [<000000001d0b13cc>] netlink_sendmsg+0x73a/0xbf0 [<000000003272487f>] __sys_sendto+0x324/0x370 [<00000000ef9f1747>] __x64_sys_sendto+0xdd/0x1b0 [<000000001e437841>] do_syscall_64+0x3f/0x90
Fixes: e624e6c3e777 ("nfc: Add a virtual nci device driver") Signed-off-by: Shang XiaoJing shangxiaojing@huawei.com Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Link: https://lore.kernel.org/r/20221020030505.15572-1-shangxiaojing@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nfc/virtual_ncidev.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c index 221fa3bb8705..6317e8505aaa 100644 --- a/drivers/nfc/virtual_ncidev.c +++ b/drivers/nfc/virtual_ncidev.c @@ -54,16 +54,19 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb) mutex_lock(&nci_mutex); if (state != virtual_ncidev_enabled) { mutex_unlock(&nci_mutex); + kfree_skb(skb); return 0; }
if (send_buff) { mutex_unlock(&nci_mutex); + kfree_skb(skb); return -1; } send_buff = skb_copy(skb, GFP_KERNEL); mutex_unlock(&nci_mutex); wake_up_interruptible(&wq); + consume_skb(skb);
return 0; }
From: Chen Zhongjin chenzhongjin@huawei.com
[ Upstream commit 230db82413c091bc16acee72650f48d419cebe49 ]
When a console stack dump is initiated with CONFIG_GCOV_PROFILE_ALL enabled, show_trace_log_lvl() gets out of sync with the ORC unwinder, causing the stack trace to show all text addresses as unreliable:
# echo l > /proc/sysrq-trigger [ 477.521031] sysrq: Show backtrace of all active CPUs [ 477.523813] NMI backtrace for cpu 0 [ 477.524492] CPU: 0 PID: 1021 Comm: bash Not tainted 6.0.0 #65 [ 477.525295] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.0-1.fc36 04/01/2014 [ 477.526439] Call Trace: [ 477.526854] <TASK> [ 477.527216] ? dump_stack_lvl+0xc7/0x114 [ 477.527801] ? dump_stack+0x13/0x1f [ 477.528331] ? nmi_cpu_backtrace.cold+0xb5/0x10d [ 477.528998] ? lapic_can_unplug_cpu+0xa0/0xa0 [ 477.529641] ? nmi_trigger_cpumask_backtrace+0x16a/0x1f0 [ 477.530393] ? arch_trigger_cpumask_backtrace+0x1d/0x30 [ 477.531136] ? sysrq_handle_showallcpus+0x1b/0x30 [ 477.531818] ? __handle_sysrq.cold+0x4e/0x1ae [ 477.532451] ? write_sysrq_trigger+0x63/0x80 [ 477.533080] ? proc_reg_write+0x92/0x110 [ 477.533663] ? vfs_write+0x174/0x530 [ 477.534265] ? handle_mm_fault+0x16f/0x500 [ 477.534940] ? ksys_write+0x7b/0x170 [ 477.535543] ? __x64_sys_write+0x1d/0x30 [ 477.536191] ? do_syscall_64+0x6b/0x100 [ 477.536809] ? entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 477.537609] </TASK>
This happens when the compiled code for show_stack() has a single word on the stack, and doesn't use a tail call to show_stack_log_lvl(). (CONFIG_GCOV_PROFILE_ALL=y is the only known case of this.) Then the __unwind_start() skip logic hits an off-by-one bug and fails to unwind all the way to the intended starting frame.
Fix it by reverting the following commit:
f1d9a2abff66 ("x86/unwind/orc: Don't skip the first frame for inactive tasks")
The original justification for that commit no longer exists. That original issue was later fixed in a different way, with the following commit:
f2ac57a4c49d ("x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10 compiled kernels")
Fixes: f1d9a2abff66 ("x86/unwind/orc: Don't skip the first frame for inactive tasks") Signed-off-by: Chen Zhongjin chenzhongjin@huawei.com [jpoimboe: rewrite commit log] Signed-off-by: Josh Poimboeuf jpoimboe@kernel.org Signed-off-by: Peter Zijlstra peterz@infradead.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kernel/unwind_orc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 3423aaea4ad8..8488966da5f1 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -700,7 +700,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, /* Otherwise, skip ahead to the user-specified starting frame: */ while (!unwind_done(state) && (!on_stack(&state->stack_info, first_frame, sizeof(long)) || - state->sp < (unsigned long)first_frame)) + state->sp <= (unsigned long)first_frame)) unwind_next_frame(state);
return;
From: Raju Rangoju Raju.Rangoju@amd.com
[ Upstream commit 09c5f6bf11ac98874339e55f4f5f79a9dbc9b375 ]
The current XGBE code assumes that offset 6 of EEPROM SFP DAC (passive) cables is NULL. However, some cables (the 5 meter and 7 meter Molex passive cables) have non-zero data at offset 6. Fix the logic by moving the passive cable check above the active checks, so as not to be improperly identified as an active cable. This will fix the issue for any passive cable that advertises 1000Base-CX in offset 6.
Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") Signed-off-by: Raju Rangoju Raju.Rangoju@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 213769054391..21e38b720d87 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -1151,7 +1151,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) }
/* Determine the type of SFP */ - if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) + if (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE && + xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) + phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; + else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) phy_data->sfp_base = XGBE_SFP_BASE_10000_SR; else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR) phy_data->sfp_base = XGBE_SFP_BASE_10000_LR; @@ -1167,9 +1170,6 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) phy_data->sfp_base = XGBE_SFP_BASE_1000_CX; else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T) phy_data->sfp_base = XGBE_SFP_BASE_1000_T; - else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) && - xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) - phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
switch (phy_data->sfp_base) { case XGBE_SFP_BASE_1000_T:
From: Raju Rangoju Raju.Rangoju@amd.com
[ Upstream commit 170a9e341a3b02c0b2ea0df16ef14a33a4f41de8 ]
The offset 12 (bit-rate) of EEPROM SFP DAC (passive) cables is expected to be in the range 0x64 to 0x68. However, the 5 meter and 7 meter Molex passive cables have the rate ceiling 0x78 at offset 12.
Add a quirk for Molex passive cables to extend the rate ceiling to 0x78.
Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") Signed-off-by: Raju Rangoju Raju.Rangoju@amd.com Acked-by: Tom Lendacky thomas.lendacky@amd.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 21e38b720d87..a7166cd1179f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -239,6 +239,7 @@ enum xgbe_sfp_speed { #define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 #define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +#define XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX 0x78
#define XGBE_SFP_BASE_CU_CABLE_LEN 18
@@ -284,6 +285,8 @@ struct xgbe_sfp_eeprom { #define XGBE_BEL_FUSE_VENDOR "BEL-FUSE " #define XGBE_BEL_FUSE_PARTNO "1GBT-SFP06 "
+#define XGBE_MOLEX_VENDOR "Molex Inc. " + struct xgbe_sfp_ascii { union { char vendor[XGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; @@ -834,7 +837,11 @@ static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, break; case XGBE_SFP_SPEED_10000: min = XGBE_SFP_BASE_BR_10GBE_MIN; - max = XGBE_SFP_BASE_BR_10GBE_MAX; + if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], + XGBE_MOLEX_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN) == 0) + max = XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX; + else + max = XGBE_SFP_BASE_BR_10GBE_MAX; break; default: return false;
From: Ankit Nautiyal ankit.k.nautiyal@intel.com
[ Upstream commit 63720a561b3c98199adf0c73e152807f15cc3b7f ]
For cases where DP has HDMI2.1 sink and FRL Link issues are detected, reset the flag to state FRL trained status before restarting FRL training.
Fixes: 9488a030ac91 ("drm/i915: Add support for enabling link status and recovery") Cc: Swati Sharma swati2.sharma@intel.com Cc: Ankit Nautiyal ankit.k.nautiyal@intel.com Cc: Uma Shankar uma.shankar@intel.com (v2) Cc: Jani Nikula jani.nikula@intel.com Signed-off-by: Ankit Nautiyal ankit.k.nautiyal@intel.com Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20221011063447.904649-2-ankit.... (cherry picked from commit 47e1a59e60c688c5f95b67277202f05b7e84c189) Signed-off-by: Tvrtko Ursulin tvrtko.ursulin@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/i915/display/intel_dp.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f87e4d510ea5..1ccdf2da042b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3497,6 +3497,8 @@ intel_dp_handle_hdmi_link_status_change(struct intel_dp *intel_dp)
drm_dp_pcon_hdmi_frl_link_error_count(&intel_dp->aux, &intel_dp->attached_connector->base);
+ intel_dp->frl.is_trained = false; + /* Restart FRL training or fall back to TMDS mode */ intel_dp_check_frl_training(intel_dp); }
From: Íñigo Huguet ihuguet@redhat.com
[ Upstream commit 6960d133f66ecddcd3af2b1cbd0c7dcd104268b8 ]
NIC is stopped with rtnl_lock held, and during the stop it cancels the 'service_task' work and free irqs.
However, if CONFIG_MACSEC is set, rtnl_lock is acquired both from aq_nic_service_task and aq_linkstate_threaded_isr. Then a deadlock happens if aq_nic_stop tries to cancel/disable them when they've already started their execution.
As the deadlock is caused by rtnl_lock, it causes many other processes to stall, not only atlantic related stuff.
Fix it by introducing a mutex that protects each NIC's macsec related data, and locking it instead of the rtnl_lock from the service task and the threaded IRQ.
Before this patch, all macsec data was protected with rtnl_lock, but maybe not all of it needs to be protected. With this new mutex, further efforts can be made to limit the protected data only to that which requires it. However, probably it doesn't worth it because all macsec's data accesses are infrequent, and almost all are done from macsec_ops or ethtool callbacks, called holding rtnl_lock, so macsec_mutex won't never be much contended.
The issue appeared repeteadly attaching and deattaching the NIC to a bond interface. Doing that after this patch I cannot reproduce the bug.
Fixes: 62c1c2e606f6 ("net: atlantic: MACSec offload skeleton") Reported-by: Li Liang liali@redhat.com Suggested-by: Andrew Lunn andrew@lunn.ch Signed-off-by: Íñigo Huguet ihuguet@redhat.com Reviewed-by: Igor Russkikh irusskikh@marvell.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/aquantia/atlantic/aq_macsec.c | 96 ++++++++++++++----- .../net/ethernet/aquantia/atlantic/aq_nic.h | 2 + 2 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c index 4a6dfac857ca..7c6e0811f2e6 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c @@ -1451,26 +1451,57 @@ static void aq_check_txsa_expiration(struct aq_nic_s *nic) egress_sa_threshold_expired); }
+#define AQ_LOCKED_MDO_DEF(mdo) \ +static int aq_locked_mdo_##mdo(struct macsec_context *ctx) \ +{ \ + struct aq_nic_s *nic = netdev_priv(ctx->netdev); \ + int ret; \ + mutex_lock(&nic->macsec_mutex); \ + ret = aq_mdo_##mdo(ctx); \ + mutex_unlock(&nic->macsec_mutex); \ + return ret; \ +} + +AQ_LOCKED_MDO_DEF(dev_open) +AQ_LOCKED_MDO_DEF(dev_stop) +AQ_LOCKED_MDO_DEF(add_secy) +AQ_LOCKED_MDO_DEF(upd_secy) +AQ_LOCKED_MDO_DEF(del_secy) +AQ_LOCKED_MDO_DEF(add_rxsc) +AQ_LOCKED_MDO_DEF(upd_rxsc) +AQ_LOCKED_MDO_DEF(del_rxsc) +AQ_LOCKED_MDO_DEF(add_rxsa) +AQ_LOCKED_MDO_DEF(upd_rxsa) +AQ_LOCKED_MDO_DEF(del_rxsa) +AQ_LOCKED_MDO_DEF(add_txsa) +AQ_LOCKED_MDO_DEF(upd_txsa) +AQ_LOCKED_MDO_DEF(del_txsa) +AQ_LOCKED_MDO_DEF(get_dev_stats) +AQ_LOCKED_MDO_DEF(get_tx_sc_stats) +AQ_LOCKED_MDO_DEF(get_tx_sa_stats) +AQ_LOCKED_MDO_DEF(get_rx_sc_stats) +AQ_LOCKED_MDO_DEF(get_rx_sa_stats) + const struct macsec_ops aq_macsec_ops = { - .mdo_dev_open = aq_mdo_dev_open, - .mdo_dev_stop = aq_mdo_dev_stop, - .mdo_add_secy = aq_mdo_add_secy, - .mdo_upd_secy = aq_mdo_upd_secy, - .mdo_del_secy = aq_mdo_del_secy, - .mdo_add_rxsc = aq_mdo_add_rxsc, - .mdo_upd_rxsc = aq_mdo_upd_rxsc, - .mdo_del_rxsc = aq_mdo_del_rxsc, - .mdo_add_rxsa = aq_mdo_add_rxsa, - .mdo_upd_rxsa = aq_mdo_upd_rxsa, - .mdo_del_rxsa = aq_mdo_del_rxsa, - .mdo_add_txsa = aq_mdo_add_txsa, - .mdo_upd_txsa = aq_mdo_upd_txsa, - .mdo_del_txsa = aq_mdo_del_txsa, - .mdo_get_dev_stats = aq_mdo_get_dev_stats, - .mdo_get_tx_sc_stats = aq_mdo_get_tx_sc_stats, - .mdo_get_tx_sa_stats = aq_mdo_get_tx_sa_stats, - .mdo_get_rx_sc_stats = aq_mdo_get_rx_sc_stats, - .mdo_get_rx_sa_stats = aq_mdo_get_rx_sa_stats, + .mdo_dev_open = aq_locked_mdo_dev_open, + .mdo_dev_stop = aq_locked_mdo_dev_stop, + .mdo_add_secy = aq_locked_mdo_add_secy, + .mdo_upd_secy = aq_locked_mdo_upd_secy, + .mdo_del_secy = aq_locked_mdo_del_secy, + .mdo_add_rxsc = aq_locked_mdo_add_rxsc, + .mdo_upd_rxsc = aq_locked_mdo_upd_rxsc, + .mdo_del_rxsc = aq_locked_mdo_del_rxsc, + .mdo_add_rxsa = aq_locked_mdo_add_rxsa, + .mdo_upd_rxsa = aq_locked_mdo_upd_rxsa, + .mdo_del_rxsa = aq_locked_mdo_del_rxsa, + .mdo_add_txsa = aq_locked_mdo_add_txsa, + .mdo_upd_txsa = aq_locked_mdo_upd_txsa, + .mdo_del_txsa = aq_locked_mdo_del_txsa, + .mdo_get_dev_stats = aq_locked_mdo_get_dev_stats, + .mdo_get_tx_sc_stats = aq_locked_mdo_get_tx_sc_stats, + .mdo_get_tx_sa_stats = aq_locked_mdo_get_tx_sa_stats, + .mdo_get_rx_sc_stats = aq_locked_mdo_get_rx_sc_stats, + .mdo_get_rx_sa_stats = aq_locked_mdo_get_rx_sa_stats, };
int aq_macsec_init(struct aq_nic_s *nic) @@ -1492,6 +1523,7 @@ int aq_macsec_init(struct aq_nic_s *nic)
nic->ndev->features |= NETIF_F_HW_MACSEC; nic->ndev->macsec_ops = &aq_macsec_ops; + mutex_init(&nic->macsec_mutex);
return 0; } @@ -1515,7 +1547,7 @@ int aq_macsec_enable(struct aq_nic_s *nic) if (!nic->macsec_cfg) return 0;
- rtnl_lock(); + mutex_lock(&nic->macsec_mutex);
if (nic->aq_fw_ops->send_macsec_req) { struct macsec_cfg_request cfg = { 0 }; @@ -1564,7 +1596,7 @@ int aq_macsec_enable(struct aq_nic_s *nic) ret = aq_apply_macsec_cfg(nic);
unlock: - rtnl_unlock(); + mutex_unlock(&nic->macsec_mutex); return ret; }
@@ -1576,9 +1608,9 @@ void aq_macsec_work(struct aq_nic_s *nic) if (!netif_carrier_ok(nic->ndev)) return;
- rtnl_lock(); + mutex_lock(&nic->macsec_mutex); aq_check_txsa_expiration(nic); - rtnl_unlock(); + mutex_unlock(&nic->macsec_mutex); }
int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic) @@ -1589,21 +1621,30 @@ int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic) if (!cfg) return 0;
+ mutex_lock(&nic->macsec_mutex); + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { if (!test_bit(i, &cfg->rxsc_idx_busy)) continue; cnt += hweight_long(cfg->aq_rxsc[i].rx_sa_idx_busy); }
+ mutex_unlock(&nic->macsec_mutex); return cnt; }
int aq_macsec_tx_sc_cnt(struct aq_nic_s *nic) { + int cnt; + if (!nic->macsec_cfg) return 0;
- return hweight_long(nic->macsec_cfg->txsc_idx_busy); + mutex_lock(&nic->macsec_mutex); + cnt = hweight_long(nic->macsec_cfg->txsc_idx_busy); + mutex_unlock(&nic->macsec_mutex); + + return cnt; }
int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic) @@ -1614,12 +1655,15 @@ int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic) if (!cfg) return 0;
+ mutex_lock(&nic->macsec_mutex); + for (i = 0; i < AQ_MACSEC_MAX_SC; i++) { if (!test_bit(i, &cfg->txsc_idx_busy)) continue; cnt += hweight_long(cfg->aq_txsc[i].tx_sa_idx_busy); }
+ mutex_unlock(&nic->macsec_mutex); return cnt; }
@@ -1691,6 +1735,8 @@ u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data) if (!cfg) return data;
+ mutex_lock(&nic->macsec_mutex); + aq_macsec_update_stats(nic);
common_stats = &cfg->stats; @@ -1773,5 +1819,7 @@ u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data)
data += i;
+ mutex_unlock(&nic->macsec_mutex); + return data; } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 1a7148041e3d..b7f7d6f66633 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -154,6 +154,8 @@ struct aq_nic_s { struct mutex fwreq_mutex; #if IS_ENABLED(CONFIG_MACSEC) struct aq_macsec_cfg *macsec_cfg; + /* mutex to protect data in macsec_cfg */ + struct mutex macsec_mutex; #endif /* PTP support */ struct aq_ptp_s *aq_ptp;
From: Eric Dumazet edumazet@google.com
[ Upstream commit 15e4dabda11b0fa31d510a915d1a580f47dfc92e ]
kcm->rx_psock can be read locklessly in kcm_rfree(). Annotate the read and writes accordingly.
We do the same for kcm->rx_wait in the following patch.
syzbot reported: BUG: KCSAN: data-race in kcm_rfree / unreserve_rx_kcm
write to 0xffff888123d827b8 of 8 bytes by task 2758 on cpu 1: unreserve_rx_kcm+0x72/0x1f0 net/kcm/kcmsock.c:313 kcm_rcv_strparser+0x2b5/0x3a0 net/kcm/kcmsock.c:373 __strp_recv+0x64c/0xd20 net/strparser/strparser.c:301 strp_recv+0x6d/0x80 net/strparser/strparser.c:335 tcp_read_sock+0x13e/0x5a0 net/ipv4/tcp.c:1703 strp_read_sock net/strparser/strparser.c:358 [inline] do_strp_work net/strparser/strparser.c:406 [inline] strp_work+0xe8/0x180 net/strparser/strparser.c:415 process_one_work+0x3d3/0x720 kernel/workqueue.c:2289 worker_thread+0x618/0xa70 kernel/workqueue.c:2436 kthread+0x1a9/0x1e0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
read to 0xffff888123d827b8 of 8 bytes by task 5859 on cpu 0: kcm_rfree+0x14c/0x220 net/kcm/kcmsock.c:181 skb_release_head_state+0x8e/0x160 net/core/skbuff.c:841 skb_release_all net/core/skbuff.c:852 [inline] __kfree_skb net/core/skbuff.c:868 [inline] kfree_skb_reason+0x5c/0x260 net/core/skbuff.c:891 kfree_skb include/linux/skbuff.h:1216 [inline] kcm_recvmsg+0x226/0x2b0 net/kcm/kcmsock.c:1161 ____sys_recvmsg+0x16c/0x2e0 ___sys_recvmsg net/socket.c:2743 [inline] do_recvmmsg+0x2f1/0x710 net/socket.c:2837 __sys_recvmmsg net/socket.c:2916 [inline] __do_sys_recvmmsg net/socket.c:2939 [inline] __se_sys_recvmmsg net/socket.c:2932 [inline] __x64_sys_recvmmsg+0xde/0x160 net/socket.c:2932 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
value changed: 0xffff88812971ce00 -> 0x0000000000000000
Reported by Kernel Concurrency Sanitizer on: CPU: 0 PID: 5859 Comm: syz-executor.3 Not tainted 6.0.0-syzkaller-12189-g19d17ab7c68b-dirty #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/22/2022
Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/kcm/kcmsock.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index f780fbe82e7d..2e8990036ec4 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -177,7 +177,7 @@ static void kcm_rfree(struct sk_buff *skb) /* For reading rx_wait and rx_psock without holding lock */ smp_mb__after_atomic();
- if (!kcm->rx_wait && !kcm->rx_psock && + if (!kcm->rx_wait && !READ_ONCE(kcm->rx_psock) && sk_rmem_alloc_get(sk) < sk->sk_rcvlowat) { spin_lock_bh(&mux->rx_lock); kcm_rcv_ready(kcm); @@ -282,7 +282,8 @@ static struct kcm_sock *reserve_rx_kcm(struct kcm_psock *psock, kcm->rx_wait = false;
psock->rx_kcm = kcm; - kcm->rx_psock = psock; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_psock, psock);
spin_unlock_bh(&mux->rx_lock);
@@ -309,7 +310,8 @@ static void unreserve_rx_kcm(struct kcm_psock *psock, spin_lock_bh(&mux->rx_lock);
psock->rx_kcm = NULL; - kcm->rx_psock = NULL; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_psock, NULL);
/* Commit kcm->rx_psock before sk_rmem_alloc_get to sync with * kcm_rfree
From: Eric Dumazet edumazet@google.com
[ Upstream commit 0c745b5141a45a076f1cb9772a399f7ebcb0948a ]
kcm->rx_psock can be read locklessly in kcm_rfree(). Annotate the read and writes accordingly.
syzbot reported:
BUG: KCSAN: data-race in kcm_rcv_strparser / kcm_rfree
write to 0xffff88810784e3d0 of 1 bytes by task 1823 on cpu 1: reserve_rx_kcm net/kcm/kcmsock.c:283 [inline] kcm_rcv_strparser+0x250/0x3a0 net/kcm/kcmsock.c:363 __strp_recv+0x64c/0xd20 net/strparser/strparser.c:301 strp_recv+0x6d/0x80 net/strparser/strparser.c:335 tcp_read_sock+0x13e/0x5a0 net/ipv4/tcp.c:1703 strp_read_sock net/strparser/strparser.c:358 [inline] do_strp_work net/strparser/strparser.c:406 [inline] strp_work+0xe8/0x180 net/strparser/strparser.c:415 process_one_work+0x3d3/0x720 kernel/workqueue.c:2289 worker_thread+0x618/0xa70 kernel/workqueue.c:2436 kthread+0x1a9/0x1e0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
read to 0xffff88810784e3d0 of 1 bytes by task 17869 on cpu 0: kcm_rfree+0x121/0x220 net/kcm/kcmsock.c:181 skb_release_head_state+0x8e/0x160 net/core/skbuff.c:841 skb_release_all net/core/skbuff.c:852 [inline] __kfree_skb net/core/skbuff.c:868 [inline] kfree_skb_reason+0x5c/0x260 net/core/skbuff.c:891 kfree_skb include/linux/skbuff.h:1216 [inline] kcm_recvmsg+0x226/0x2b0 net/kcm/kcmsock.c:1161 ____sys_recvmsg+0x16c/0x2e0 ___sys_recvmsg net/socket.c:2743 [inline] do_recvmmsg+0x2f1/0x710 net/socket.c:2837 __sys_recvmmsg net/socket.c:2916 [inline] __do_sys_recvmmsg net/socket.c:2939 [inline] __se_sys_recvmmsg net/socket.c:2932 [inline] __x64_sys_recvmmsg+0xde/0x160 net/socket.c:2932 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
value changed: 0x01 -> 0x00
Reported by Kernel Concurrency Sanitizer on: CPU: 0 PID: 17869 Comm: syz-executor.2 Not tainted 6.1.0-rc1-syzkaller-00010-gbb1a1146467a-dirty #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/22/2022
Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/kcm/kcmsock.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index 2e8990036ec4..ff6dd2619f22 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -161,7 +161,8 @@ static void kcm_rcv_ready(struct kcm_sock *kcm) /* Buffer limit is okay now, add to ready list */ list_add_tail(&kcm->wait_rx_list, &kcm->mux->kcm_rx_waiters); - kcm->rx_wait = true; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_wait, true); }
static void kcm_rfree(struct sk_buff *skb) @@ -177,7 +178,7 @@ static void kcm_rfree(struct sk_buff *skb) /* For reading rx_wait and rx_psock without holding lock */ smp_mb__after_atomic();
- if (!kcm->rx_wait && !READ_ONCE(kcm->rx_psock) && + if (!READ_ONCE(kcm->rx_wait) && !READ_ONCE(kcm->rx_psock) && sk_rmem_alloc_get(sk) < sk->sk_rcvlowat) { spin_lock_bh(&mux->rx_lock); kcm_rcv_ready(kcm); @@ -236,7 +237,8 @@ static void requeue_rx_msgs(struct kcm_mux *mux, struct sk_buff_head *head) if (kcm_queue_rcv_skb(&kcm->sk, skb)) { /* Should mean socket buffer full */ list_del(&kcm->wait_rx_list); - kcm->rx_wait = false; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_wait, false);
/* Commit rx_wait to read in kcm_free */ smp_wmb(); @@ -279,7 +281,8 @@ static struct kcm_sock *reserve_rx_kcm(struct kcm_psock *psock, kcm = list_first_entry(&mux->kcm_rx_waiters, struct kcm_sock, wait_rx_list); list_del(&kcm->wait_rx_list); - kcm->rx_wait = false; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_wait, false);
psock->rx_kcm = kcm; /* paired with lockless reads in kcm_rfree() */ @@ -1241,7 +1244,8 @@ static void kcm_recv_disable(struct kcm_sock *kcm) if (!kcm->rx_psock) { if (kcm->rx_wait) { list_del(&kcm->wait_rx_list); - kcm->rx_wait = false; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_wait, false); }
requeue_rx_msgs(mux, &kcm->sk.sk_receive_queue); @@ -1794,7 +1798,8 @@ static void kcm_done(struct kcm_sock *kcm)
if (kcm->rx_wait) { list_del(&kcm->wait_rx_list); - kcm->rx_wait = false; + /* paired with lockless reads in kcm_rfree() */ + WRITE_ONCE(kcm->rx_wait, false); } /* Move any pending receive messages to other kcm sockets */ requeue_rx_msgs(mux, &sk->sk_receive_queue);
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit d266935ac43d57586e311a087510fe6a084af742 ]
When the ops_init() interface is invoked to initialize the net, but ops->init() fails, data is released. However, the ptr pointer in net->gen is invalid. In this case, when nfqnl_nf_hook_drop() is invoked to release the net, invalid address access occurs.
The process is as follows: setup_net() ops_init() data = kzalloc(...) ---> alloc "data" net_assign_generic() ---> assign "date" to ptr in net->gen ... ops->init() ---> failed ... kfree(data); ---> ptr in net->gen is invalid ... ops_exit_list() ... nfqnl_nf_hook_drop() *q = nfnl_queue_pernet(net) ---> q is invalid
The following is the Call Trace information: BUG: KASAN: use-after-free in nfqnl_nf_hook_drop+0x264/0x280 Read of size 8 at addr ffff88810396b240 by task ip/15855 Call Trace: <TASK> dump_stack_lvl+0x8e/0xd1 print_report+0x155/0x454 kasan_report+0xba/0x1f0 nfqnl_nf_hook_drop+0x264/0x280 nf_queue_nf_hook_drop+0x8b/0x1b0 __nf_unregister_net_hook+0x1ae/0x5a0 nf_unregister_net_hooks+0xde/0x130 ops_exit_list+0xb0/0x170 setup_net+0x7ac/0xbd0 copy_net_ns+0x2e6/0x6b0 create_new_namespaces+0x382/0xa50 unshare_nsproxy_namespaces+0xa6/0x1c0 ksys_unshare+0x3a4/0x7e0 __x64_sys_unshare+0x2d/0x40 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 </TASK>
Allocated by task 15855: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 __kasan_kmalloc+0xa1/0xb0 __kmalloc+0x49/0xb0 ops_init+0xe7/0x410 setup_net+0x5aa/0xbd0 copy_net_ns+0x2e6/0x6b0 create_new_namespaces+0x382/0xa50 unshare_nsproxy_namespaces+0xa6/0x1c0 ksys_unshare+0x3a4/0x7e0 __x64_sys_unshare+0x2d/0x40 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
Freed by task 15855: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_save_free_info+0x2a/0x40 ____kasan_slab_free+0x155/0x1b0 slab_free_freelist_hook+0x11b/0x220 __kmem_cache_free+0xa4/0x360 ops_init+0xb9/0x410 setup_net+0x5aa/0xbd0 copy_net_ns+0x2e6/0x6b0 create_new_namespaces+0x382/0xa50 unshare_nsproxy_namespaces+0xa6/0x1c0 ksys_unshare+0x3a4/0x7e0 __x64_sys_unshare+0x2d/0x40 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
Fixes: f875bae06533 ("net: Automatically allocate per namespace data.") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/net_namespace.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 9745cb6fdf51..982d06332007 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -117,6 +117,7 @@ static int net_assign_generic(struct net *net, unsigned int id, void *data)
static int ops_init(const struct pernet_operations *ops, struct net *net) { + struct net_generic *ng; int err = -ENOMEM; void *data = NULL;
@@ -135,7 +136,13 @@ static int ops_init(const struct pernet_operations *ops, struct net *net) if (!err) return 0;
+ if (ops->id && ops->size) { cleanup: + ng = rcu_dereference_protected(net->gen, + lockdep_is_held(&pernet_ops_rwsem)); + ng->ptr[*ops->id] = NULL; + } + kfree(data);
out:
From: Zhang Changzhong zhangchangzhong@huawei.com
[ Upstream commit 9c1eaa27ec599fcc25ed4970c0b73c247d147a2b ]
The ndo_start_xmit() method must not free skb when returning NETDEV_TX_BUSY, since caller is going to requeue freed skb.
Fixes: 504d4721ee8e ("MIPS: Lantiq: Add ethernet driver") Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/lantiq_etop.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 62f8c5212182..057d655d1769 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -466,7 +466,6 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { - dev_kfree_skb_any(skb); netdev_err(dev, "tx ring full\n"); netif_tx_stop_queue(txq); return NETDEV_TX_BUSY;
From: Eric Dumazet edumazet@google.com
[ Upstream commit d519f350967a60b85a574ad8aeac43f2b4384746 ]
If packet is going to be coalesced, sk_sndbuf/sk_rcvbuf values are not used. Defer their access to the point we need them.
Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Stable-dep-of: ec791d8149ff ("tcp: fix a signed-integer-overflow bug in tcp_add_backlog()") Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/tcp_ipv4.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 88a45d5650da..bae5c4ec5786 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1808,8 +1808,7 @@ int tcp_v4_early_demux(struct sk_buff *skb)
bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) { - u32 limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf); - u32 tail_gso_size, tail_gso_segs; + u32 limit, tail_gso_size, tail_gso_segs; struct skb_shared_info *shinfo; const struct tcphdr *th; struct tcphdr *thtail; @@ -1917,7 +1916,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) * to reduce memory overhead, so add a little headroom here. * Few sockets backlog are possibly concurrently non empty. */ - limit += 64*1024; + limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf) + 64*1024;
if (unlikely(sk_add_backlog(sk, skb, limit))) { bh_unlock_sock(sk);
From: Lu Wei luwei32@huawei.com
[ Upstream commit ec791d8149ff60c40ad2074af3b92a39c916a03f ]
The type of sk_rcvbuf and sk_sndbuf in struct sock is int, and in tcp_add_backlog(), the variable limit is caculated by adding sk_rcvbuf, sk_sndbuf and 64 * 1024, it may exceed the max value of int and overflow. This patch reduces the limit budget by halving the sndbuf to solve this issue since ACK packets are much smaller than the payload.
Fixes: c9c3321257e1 ("tcp: add tcp_add_backlog()") Signed-off-by: Lu Wei luwei32@huawei.com Reviewed-by: Eric Dumazet edumazet@google.com Acked-by: Kuniyuki Iwashima kuniyu@amazon.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/tcp_ipv4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bae5c4ec5786..42d4af632495 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1912,11 +1912,13 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) __skb_push(skb, hdrlen);
no_coalesce: + limit = (u32)READ_ONCE(sk->sk_rcvbuf) + (u32)(READ_ONCE(sk->sk_sndbuf) >> 1); + /* Only socket owner can try to collapse/prune rx queues * to reduce memory overhead, so add a little headroom here. * Few sockets backlog are possibly concurrently non empty. */ - limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf) + 64*1024; + limit += 64 * 1024;
if (unlikely(sk_add_backlog(sk, skb, limit))) { bh_unlock_sock(sk);
From: Neal Cardwell ncardwell@google.com
[ Upstream commit 3d2af9cce3133b3bc596a9d065c6f9d93419ccfb ]
This commit fixes a bug that can cause a TCP data sender to repeatedly defer RTOs when encountering SACK reneging.
The bug is that when we're in fast recovery in a scenario with SACK reneging, every time we get an ACK we call tcp_check_sack_reneging() and it can note the apparent SACK reneging and rearm the RTO timer for srtt/2 into the future. In some SACK reneging scenarios that can happen repeatedly until the receive window fills up, at which point the sender can't send any more, the ACKs stop arriving, and the RTO fires at srtt/2 after the last ACK. But that can take far too long (O(10 secs)), since the connection is stuck in fast recovery with a low cwnd that cannot grow beyond ssthresh, even if more bandwidth is available.
This fix changes the logic in tcp_check_sack_reneging() to only rearm the RTO timer if data is cumulatively ACKed, indicating forward progress. This avoids this kind of nearly infinite loop of RTO timer re-arming. In addition, this meets the goals of tcp_check_sack_reneging() in handling Windows TCP behavior that looks temporarily like SACK reneging but is not really.
Many thanks to Jakub Kicinski and Neil Spring, who reported this issue and provided critical packet traces that enabled root-causing this issue. Also, many thanks to Jakub Kicinski for testing this fix.
Fixes: 5ae344c949e7 ("tcp: reduce spurious retransmits due to transient SACK reneging") Reported-by: Jakub Kicinski kuba@kernel.org Reported-by: Neil Spring ntspring@fb.com Signed-off-by: Neal Cardwell ncardwell@google.com Reviewed-by: Eric Dumazet edumazet@google.com Cc: Yuchung Cheng ycheng@google.com Tested-by: Jakub Kicinski kuba@kernel.org Link: https://lore.kernel.org/r/20221021170821.1093930-1-ncardwell.kernel@gmail.co... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/tcp_input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 686e210d89c2..102a0436eb29 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2185,7 +2185,8 @@ void tcp_enter_loss(struct sock *sk) */ static bool tcp_check_sack_reneging(struct sock *sk, int flag) { - if (flag & FLAG_SACK_RENEGING) { + if (flag & FLAG_SACK_RENEGING && + flag & FLAG_SND_UNA_ADVANCED) { struct tcp_sock *tp = tcp_sk(sk); unsigned long delay = max(usecs_to_jiffies(tp->srtt_us >> 4), msecs_to_jiffies(10));
From: Jakub Kicinski kuba@kernel.org
[ Upstream commit 720ca52bcef225b967a339e0fffb6d0c7e962240 ]
As Shakeel explains the commit under Fixes had the unintended side-effect of no longer pre-loading the cached memory allowance. Even tho we previously dropped the first packet received when over memory limit - the consecutive ones would get thru by using the cache. The charging was happening in batches of 128kB, so we'd let in 128kB (truesize) worth of packets per one drop.
After the change we no longer force charge, there will be no cache filling side effects. This causes significant drops and connection stalls for workloads which use a lot of page cache, since we can't reclaim page cache under GFP_NOWAIT.
Some of the latency can be recovered by improving SACK reneg handling but nowhere near enough to get back to the pre-5.15 performance (the application I'm experimenting with still sees 5-10x worst latency).
Apply the suggested workaround of using GFP_ATOMIC. We will now be more permissive than previously as we'll drop _no_ packets in softirq when under pressure. But I can't think of any good and simple way to address that within networking.
Link: https://lore.kernel.org/all/20221012163300.795e7b86@kernel.org/ Suggested-by: Shakeel Butt shakeelb@google.com Fixes: 4b1327be9fe5 ("net-memcg: pass in gfp_t mask to mem_cgroup_charge_skmem()") Acked-by: Shakeel Butt shakeelb@google.com Acked-by: Roman Gushchin roman.gushchin@linux.dev Link: https://lore.kernel.org/r/20221021160304.1362511-1-kuba@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/sock.h b/include/net/sock.h index cb1a1bb64ed8..e1a303e4f0f7 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2472,7 +2472,7 @@ static inline gfp_t gfp_any(void)
static inline gfp_t gfp_memcg_charge(void) { - return in_softirq() ? GFP_NOWAIT : GFP_KERNEL; + return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; }
static inline long sock_rcvtimeo(const struct sock *sk, bool noblock)
From: Rafael Mendonca rafaelmendsr@gmail.com
[ Upstream commit 90bfee142af0f0e9d3bec80e7acd5f49b230acf7 ]
If the number of pages from the userptr BO differs from the SG BO then the allocated memory for the SG table doesn't get freed before returning -EINVAL, which may lead to a memory leak in some error paths. Fix this by checking the number of pages before allocating memory for the SG table.
Fixes: 264fb4d332f5 ("drm/amdgpu: Add multi-GPU DMA mapping helpers") Signed-off-by: Rafael Mendonca rafaelmendsr@gmail.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index c904269b3e14..477ab3551177 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -476,13 +476,13 @@ kfd_mem_dmamap_userptr(struct kgd_mem *mem, struct ttm_tt *ttm = bo->tbo.ttm; int ret;
+ if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) + return -EINVAL; + ttm->sg = kmalloc(sizeof(*ttm->sg), GFP_KERNEL); if (unlikely(!ttm->sg)) return -ENOMEM;
- if (WARN_ON(ttm->num_pages != src_ttm->num_pages)) - return -EINVAL; - /* Same sequence as in amdgpu_ttm_tt_pin_userptr */ ret = sg_alloc_table_from_pages(ttm->sg, src_ttm->pages, ttm->num_pages, 0,
From: Dongliang Mu dzm91@hust.edu.cn
[ Upstream commit 3e5b3418827cefb5e1cc658806f02965791b8f07 ]
The commit 1149108e2fbf ("can: mscan: improve clock API use") only adds put_clock() in mpc5xxx_can_remove() function, forgetting to add put_clock() in the error handling code.
Fix this bug by adding put_clock() in the error handling code.
Fixes: 1149108e2fbf ("can: mscan: improve clock API use") Signed-off-by: Dongliang Mu dzm91@hust.edu.cn Link: https://lore.kernel.org/all/20221024133828.35881-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/mscan/mpc5xxx_can.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 35892c1efef0..7d868b6eb579 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -322,14 +322,14 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) &mscan_clksrc); if (!priv->can.clock.freq) { dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n"); - goto exit_free_mscan; + goto exit_put_clock; }
err = register_mscandev(dev, mscan_clksrc); if (err) { dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", DRV_NAME, err); - goto exit_free_mscan; + goto exit_put_clock; }
dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", @@ -337,7 +337,9 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
return 0;
-exit_free_mscan: +exit_put_clock: + if (data->put_clock) + data->put_clock(ofdev); free_candev(dev); exit_dispose_irq: irq_dispose_mapping(irq);
From: Dongliang Mu dzm91@hust.edu.cn
[ Upstream commit b1a09b63684cea56774786ca14c13b7041ffee63 ]
In mcp251x_can_probe(), if mcp251x_gpio_setup() fails, it forgets to unregister the CAN device.
Fix this by unregistering can device in mcp251x_can_probe().
Fixes: 2d52dabbef60 ("can: mcp251x: add GPIO support") Signed-off-by: Dongliang Mu dzm91@hust.edu.cn Link: https://lore.kernel.org/all/20221024090256.717236-1-dzm91@hust.edu.cn [mkl: adjust label] Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/spi/mcp251x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index baab3adc34bc..f02275f71e4d 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1419,11 +1419,14 @@ static int mcp251x_can_probe(struct spi_device *spi)
ret = mcp251x_gpio_setup(priv); if (ret) - goto error_probe; + goto out_unregister_candev;
netdev_info(net, "MCP%x successfully initialized.\n", priv->model); return 0;
+out_unregister_candev: + unregister_candev(net); + error_probe: destroy_workqueue(priv->wq); priv->wq = NULL;
From: Mario Limonciello mario.limonciello@amd.com
[ Upstream commit 85850af4fc47132f3f2f0dd698b90f67906600b4 ]
Hybrid sleep is currently hardcoded to only operate with S3 even on systems that might not support it.
Instead of assuming this mode is what the user wants to use, for hybrid sleep follow the setting of `mem_sleep_current` which will respect mem_sleep_default kernel command line and policy decisions made by the presence of the FADT low power idle bit.
Fixes: 81d45bdf8913 ("PM / hibernate: Untangle power_down()") Reported-and-tested-by: kolAflash kolAflash@kolahilft.de Link: https://bugzilla.kernel.org/show_bug.cgi?id=216574 Signed-off-by: Mario Limonciello mario.limonciello@amd.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/power/hibernate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index d926852f8119..9abc73d500fb 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -640,7 +640,7 @@ static void power_down(void) int error;
if (hibernation_mode == HIBERNATION_SUSPEND) { - error = suspend_devices_and_enter(PM_SUSPEND_MEM); + error = suspend_devices_and_enter(mem_sleep_current); if (error) { hibernation_mode = hibernation_ops ? HIBERNATION_PLATFORM :
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit f8bcaf714abfc94818dff8c0db84d750433984f4 ]
VIDIOC_S_FBUF is by definition a scary ioctl, which is why only root can use it. But at least check if the framebuffer parameters match that of one of the framebuffer created by vivid, and reject anything else.
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Fixes: ef834f7836ec ([media] vivid: add the video capture and output parts) Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/test-drivers/vivid/vivid-core.c | 22 +++++++++++++++++++ drivers/media/test-drivers/vivid/vivid-core.h | 2 ++ .../media/test-drivers/vivid/vivid-vid-cap.c | 9 +++++++- 3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c index d2bd2653cf54..e7cc70a92683 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.c +++ b/drivers/media/test-drivers/vivid/vivid-core.c @@ -330,6 +330,28 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a return vivid_vid_out_g_fbuf(file, fh, a); }
+/* + * Only support the framebuffer of one of the vivid instances. + * Anything else is rejected. + */ +bool vivid_validate_fb(const struct v4l2_framebuffer *a) +{ + struct vivid_dev *dev; + int i; + + for (i = 0; i < n_devs; i++) { + dev = vivid_devs[i]; + if (!dev || !dev->video_pbase) + continue; + if ((unsigned long)a->base == dev->video_pbase && + a->fmt.width <= dev->display_width && + a->fmt.height <= dev->display_height && + a->fmt.bytesperline <= dev->display_byte_stride) + return true; + } + return false; +} + static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a) { struct video_device *vdev = video_devdata(file); diff --git a/drivers/media/test-drivers/vivid/vivid-core.h b/drivers/media/test-drivers/vivid/vivid-core.h index 1e3c4f5a9413..7ceaf9bac2f0 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.h +++ b/drivers/media/test-drivers/vivid/vivid-core.h @@ -610,4 +610,6 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev) return dev->output_type[dev->output] == HDMI; }
+bool vivid_validate_fb(const struct v4l2_framebuffer *a); + #endif diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index b9caa4b26209..c9eb28b3a03d 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -1272,7 +1272,14 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh, return -EINVAL; if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8) return -EINVAL; - if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage) + if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height) + return -EINVAL; + + /* + * Only support the framebuffer of one of the vivid instances. + * Anything else is rejected. + */ + if (!vivid_validate_fb(a)) return -EINVAL;
dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 1f65ea411cc7b6ff128d82a3493d7b5648054e6f ]
Whenever the compose width/height values change, the dev->bitmap_cap vmalloc'ed array must be freed and dev->bitmap_cap set to NULL.
This was done in some places, but not all. This is only an issue if overlay support is enabled and the bitmap clipping is used.
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Fixes: ef834f7836ec ([media] vivid: add the video capture and output parts) Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../media/test-drivers/vivid/vivid-vid-cap.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index c9eb28b3a03d..99139a8cd4c4 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -452,6 +452,12 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls) tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap); dev->crop_cap = dev->src_rect; dev->crop_bounds_cap = dev->src_rect; + if (dev->bitmap_cap && + (dev->compose_cap.width != dev->crop_cap.width || + dev->compose_cap.height != dev->crop_cap.height)) { + vfree(dev->bitmap_cap); + dev->bitmap_cap = NULL; + } dev->compose_cap = dev->crop_cap; if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap)) dev->compose_cap.height /= 2; @@ -909,6 +915,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection struct vivid_dev *dev = video_drvdata(file); struct v4l2_rect *crop = &dev->crop_cap; struct v4l2_rect *compose = &dev->compose_cap; + unsigned orig_compose_w = compose->width; + unsigned orig_compose_h = compose->height; unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1; int ret;
@@ -1025,17 +1033,17 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection s->r.height /= factor; } v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect); - if (dev->bitmap_cap && (compose->width != s->r.width || - compose->height != s->r.height)) { - vfree(dev->bitmap_cap); - dev->bitmap_cap = NULL; - } *compose = s->r; break; default: return -EINVAL; }
+ if (dev->bitmap_cap && (compose->width != orig_compose_w || + compose->height != orig_compose_h)) { + vfree(dev->bitmap_cap); + dev->bitmap_cap = NULL; + } tpg_s_crop_compose(&dev->tpg, crop, compose); return 0; }
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 4b6d66a45ed34a15721cb9e11492fa1a24bc83df ]
Add sanity checks to v4l2_valid_dv_timings() to ensure that the provided blanking values are reasonable.
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Fixes: b18787ed1ce3 ([media] v4l2-dv-timings: add new helper module) Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/v4l2-core/v4l2-dv-timings.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index af48705c704f..003c32fed3f7 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -161,6 +161,20 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) return false; + + /* sanity checks for the blanking timings */ + if (!bt->interlaced && + (bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch)) + return false; + if (bt->hfrontporch > 2 * bt->width || + bt->hsync > 1024 || bt->hbackporch > 1024) + return false; + if (bt->vfrontporch > 4096 || + bt->vsync > 128 || bt->vbackporch > 4096) + return false; + if (bt->interlaced && (bt->il_vfrontporch > 4096 || + bt->il_vsync > 128 || bt->il_vbackporch > 4096)) + return false; return fnc == NULL || fnc(t, fnc_handle); } EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 8da7f0976b9071b528c545008de9d10cc81883b1 ]
If it is a progressive (non-interlaced) format, then ignore the interlaced timing values.
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Fixes: 7f68127fa11f ([media] videodev2.h: defines to calculate blanking and frame sizes) Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/uapi/linux/videodev2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 9260791b8438..61c5011dfc13 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1560,7 +1560,8 @@ struct v4l2_bt_timings { ((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt)) #define V4L2_DV_BT_BLANKING_HEIGHT(bt) \ ((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \ - (bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch) + ((bt)->interlaced ? \ + ((bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch) : 0)) #define V4L2_DV_BT_FRAME_HEIGHT(bt) \ ((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 69d78a80da4ef12faf2a6f9cfa2097ab4ac43983 ]
If node_types does not have video/vbi/meta inputs or outputs, then set num_inputs/num_outputs to 0 instead of 1.
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Fixes: 0c90f649d2f5 (media: vivid: add vivid_create_queue() helper) Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/test-drivers/vivid/vivid-core.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/media/test-drivers/vivid/vivid-core.c b/drivers/media/test-drivers/vivid/vivid-core.c index e7cc70a92683..065bdc33f049 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.c +++ b/drivers/media/test-drivers/vivid/vivid-core.c @@ -932,8 +932,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,
/* how many inputs do we have and of what type? */ dev->num_inputs = num_inputs[inst]; - if (dev->num_inputs < 1) - dev->num_inputs = 1; + if (node_type & 0x20007) { + if (dev->num_inputs < 1) + dev->num_inputs = 1; + } else { + dev->num_inputs = 0; + } if (dev->num_inputs >= MAX_INPUTS) dev->num_inputs = MAX_INPUTS; for (i = 0; i < dev->num_inputs; i++) { @@ -950,8 +954,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,
/* how many outputs do we have and of what type? */ dev->num_outputs = num_outputs[inst]; - if (dev->num_outputs < 1) - dev->num_outputs = 1; + if (node_type & 0x40300) { + if (dev->num_outputs < 1) + dev->num_outputs = 1; + } else { + dev->num_outputs = 0; + } if (dev->num_outputs >= MAX_OUTPUTS) dev->num_outputs = MAX_OUTPUTS; for (i = 0; i < dev->num_outputs; i++) {
From: Kajol Jain kjain@linux.ibm.com
[ Upstream commit b92dd11725a7c57f55e148c7d3ce58a86f480575 ]
Testcase stat_all_metrics.sh fails in powerpc:
90: perf all metrics test : FAILED!
The testcase "stat_all_metrics.sh" verifies perf stat result for all the metric events present in perf list. It runs perf metric events with various commands and expects non-empty metric result.
Incase of powerpc:hv-24x7 events, some of the event count can be 0 based on system configuration. And if that event used as denominator in divide equation, it can cause divide by 0 error. The current nest_metric.json file creating divide by 0 issue for some of the metric events, which results in failure of the "stat_all_metrics.sh" test case.
Most of the metrics events have cycles or an event which expect to have a larger value as denominator, so adding 1 to the denominator of the metric expression as a fix.
Result in powerpc box after this patch changes:
90: perf all metrics test : Ok
Fixes: a3cbcadfdfc330c2 ("perf vendor events power10: Adds 24x7 nest metric events for power10 platform") Signed-off-by: Kajol Jain kjain@linux.ibm.com Reviewed-by: Madhavan Srinivasan maddy@linux.vnet.ibm.com Cc: Athira Jajeev atrajeev@linux.vnet.ibm.com Cc: Disha Goel disgoel@linux.vnet.ibm.com Cc: Jiri Olsa jolsa@kernel.org Cc: Kajol Jain kjain@linux.ibm.com Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman mpe@ellerman.id.au Cc: Nageswara R Sastry rnsastry@linux.ibm.com Link: https://lore.kernel.org/r/20221014140220.122251-1-kjain@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../arch/powerpc/power10/nest_metrics.json | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-)
diff --git a/tools/perf/pmu-events/arch/powerpc/power10/nest_metrics.json b/tools/perf/pmu-events/arch/powerpc/power10/nest_metrics.json index 8ba3e81c9808..fe050d44374b 100644 --- a/tools/perf/pmu-events/arch/powerpc/power10/nest_metrics.json +++ b/tools/perf/pmu-events/arch/powerpc/power10/nest_metrics.json @@ -1,13 +1,13 @@ [ { "MetricName": "VEC_GROUP_PUMP_RETRY_RATIO_P01", - "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP01\,chip\=?@ / hv_24x7@PM_PB_VG_PUMP01\,chip\=?@) * 100", + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP01\,chip\=?@ / (1 + hv_24x7@PM_PB_VG_PUMP01\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "VEC_GROUP_PUMP_RETRY_RATIO_P23", - "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP23\,chip\=?@ / hv_24x7@PM_PB_VG_PUMP23\,chip\=?@) * 100", + "MetricExpr": "(hv_24x7@PM_PB_RTY_VG_PUMP23\,chip\=?@ / (1 + hv_24x7@PM_PB_VG_PUMP23\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, @@ -61,13 +61,13 @@ }, { "MetricName": "REMOTE_NODE_PUMPS_RETRIES_RATIO_P01", - "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP01\,chip\=?@ / hv_24x7@PM_PB_RNS_PUMP01\,chip\=?@) * 100", + "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP01\,chip\=?@ / (1 + hv_24x7@PM_PB_RNS_PUMP01\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "REMOTE_NODE_PUMPS_RETRIES_RATIO_P23", - "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP23\,chip\=?@ / hv_24x7@PM_PB_RNS_PUMP23\,chip\=?@) * 100", + "MetricExpr": "(hv_24x7@PM_PB_RTY_RNS_PUMP23\,chip\=?@ / (1 + hv_24x7@PM_PB_RNS_PUMP23\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, @@ -151,193 +151,193 @@ }, { "MetricName": "XLINK0_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK1_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK2_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK3_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK4_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK5_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK6_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK7_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK0_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK0_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK1_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK1_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK2_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK2_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK3_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK3_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK4_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK4_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK5_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK5_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK6_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK6_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "XLINK7_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_XLINK7_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_XLINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_XLINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK0_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK1_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK2_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK3_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK4_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK5_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK6_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK7_OUT_TOTAL_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_TOTAL_UTIL\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_TOTAL_UTIL\,chip\=?@) / (1 + hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK0_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK0_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK0_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK0_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK1_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK1_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK1_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK1_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK2_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK2_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK2_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK2_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK3_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK3_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK3_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK3_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK4_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK4_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK4_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK4_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK5_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK5_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK5_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK5_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK6_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK6_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK6_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK6_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" }, { "MetricName": "ALINK7_OUT_DATA_UTILIZATION", - "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_DATA\,chip\=?@) / (hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", + "MetricExpr": "((hv_24x7@PM_ALINK7_OUT_ODD_DATA\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_DATA\,chip\=?@) / (1 + hv_24x7@PM_ALINK7_OUT_ODD_AVLBL_CYCLES\,chip\=?@ + hv_24x7@PM_ALINK7_OUT_EVEN_AVLBL_CYCLES\,chip\=?@)) * 100", "ScaleUnit": "1.063%", "AggregationMode": "PerChip" },
From: Eric Dumazet edumazet@google.com
[ Upstream commit d89d7ff01235f218dad37de84457717f699dee79 ]
Another syzbot report [1] with no reproducer hints at a bug in ip6_gre tunnel (dev:ip6gretap0)
Since ipv6 mcast code makes sure to read dev->mtu once and applies a sanity check on it (see commit b9b312a7a451 "ipv6: mcast: better catch silly mtu values"), a remaining possibility is that a layer is able to set dev->mtu to an underflowed value (high order bit set).
This could happen indeed in ip6gre_tnl_link_config_route(), ip6_tnl_link_config() and ipip6_tunnel_bind_dev()
Make sure to sanitize mtu value in a local variable before it is written once on dev->mtu, as lockless readers could catch wrong temporary value.
[1] skbuff: skb_over_panic: text:ffff80000b7a2f38 len:40 put:40 head:ffff000149dcf200 data:ffff000149dcf2b0 tail:0xd8 end:0xc0 dev:ip6gretap0 ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:120 Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 10241 Comm: kworker/1:1 Not tainted 6.0.0-rc7-syzkaller-18095-gbbed346d5a96 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/30/2022 Workqueue: mld mld_ifc_work pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : skb_panic+0x4c/0x50 net/core/skbuff.c:116 lr : skb_panic+0x4c/0x50 net/core/skbuff.c:116 sp : ffff800020dd3b60 x29: ffff800020dd3b70 x28: 0000000000000000 x27: ffff00010df2a800 x26: 00000000000000c0 x25: 00000000000000b0 x24: ffff000149dcf200 x23: 00000000000000c0 x22: 00000000000000d8 x21: ffff80000b7a2f38 x20: ffff00014c2f7800 x19: 0000000000000028 x18: 00000000000001a9 x17: 0000000000000000 x16: ffff80000db49158 x15: ffff000113bf1a80 x14: 0000000000000000 x13: 00000000ffffffff x12: ffff000113bf1a80 x11: ff808000081c0d5c x10: 0000000000000000 x9 : 73f125dc5c63ba00 x8 : 73f125dc5c63ba00 x7 : ffff800008161d1c x6 : 0000000000000000 x5 : 0000000000000080 x4 : 0000000000000001 x3 : 0000000000000000 x2 : ffff0001fefddcd0 x1 : 0000000100000000 x0 : 0000000000000089 Call trace: skb_panic+0x4c/0x50 net/core/skbuff.c:116 skb_over_panic net/core/skbuff.c:125 [inline] skb_put+0xd4/0xdc net/core/skbuff.c:2049 ip6_mc_hdr net/ipv6/mcast.c:1714 [inline] mld_newpack+0x14c/0x270 net/ipv6/mcast.c:1765 add_grhead net/ipv6/mcast.c:1851 [inline] add_grec+0xa20/0xae0 net/ipv6/mcast.c:1989 mld_send_cr+0x438/0x5a8 net/ipv6/mcast.c:2115 mld_ifc_work+0x38/0x290 net/ipv6/mcast.c:2653 process_one_work+0x2d8/0x504 kernel/workqueue.c:2289 worker_thread+0x340/0x610 kernel/workqueue.c:2436 kthread+0x12c/0x158 kernel/kthread.c:376 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:860 Code: 91011400 aa0803e1 a90027ea 94373093 (d4210000)
Fixes: c12b395a4664 ("gre: Support GRE over IPv6") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Link: https://lore.kernel.org/r/20221024020124.3756833-1-eric.dumazet@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/ip6_gre.c | 12 +++++++----- net/ipv6/ip6_tunnel.c | 11 ++++++----- net/ipv6/sit.c | 8 +++++--- 3 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 70ef4d4ebff4..13b1748b8b46 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1153,14 +1153,16 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu, dev->needed_headroom = dst_len;
if (set_mtu) { - dev->mtu = rt->dst.dev->mtu - t_hlen; + int mtu = rt->dst.dev->mtu - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) - dev->mtu -= 8; + mtu -= 8; if (dev->type == ARPHRD_ETHER) - dev->mtu -= ETH_HLEN; + mtu -= ETH_HLEN;
- if (dev->mtu < IPV6_MIN_MTU) - dev->mtu = IPV6_MIN_MTU; + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + WRITE_ONCE(dev->mtu, mtu); } } ip6_rt_put(rt); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fa8da8ff35b4..ea5077942871 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1446,8 +1446,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) struct net_device *tdev = NULL; struct __ip6_tnl_parm *p = &t->parms; struct flowi6 *fl6 = &t->fl.u.ip6; - unsigned int mtu; int t_hlen; + int mtu;
memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); @@ -1494,12 +1494,13 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) dev->hard_header_len = tdev->hard_header_len + t_hlen; mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU);
- dev->mtu = mtu - t_hlen; + mtu = mtu - t_hlen; if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) - dev->mtu -= 8; + mtu -= 8;
- if (dev->mtu < IPV6_MIN_MTU) - dev->mtu = IPV6_MIN_MTU; + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + WRITE_ONCE(dev->mtu, mtu); } } } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 637cd99bd7a6..946871741f12 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1130,10 +1130,12 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
if (tdev && !netif_is_l3_master(tdev)) { int t_hlen = tunnel->hlen + sizeof(struct iphdr); + int mtu;
- dev->mtu = tdev->mtu - t_hlen; - if (dev->mtu < IPV6_MIN_MTU) - dev->mtu = IPV6_MIN_MTU; + mtu = tdev->mtu - t_hlen; + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + WRITE_ONCE(dev->mtu, mtu); } }
From: Slawomir Laba slawomirx.laba@intel.com
[ Upstream commit 54b5af5a438076082d482cab105b1bd484ab5074 ]
When enabling flow type for RSS hash via ethtool:
ethtool -N $pf rx-flow-hash tcp4|tcp6|udp4|udp6 s|d
the driver would fail to setup this setting on X722 device since it was using the mask on the register dedicated for X710 devices.
Apply a different mask on the register when setting the RSS hash for the X722 device.
When displaying the flow types enabled via ethtool:
ethtool -n $pf rx-flow-hash tcp4|tcp6|udp4|udp6
the driver would print wrong values for X722 device.
Fix this issue by testing masks for X722 device in i40e_get_rss_hash_opts function.
Fixes: eb0dd6e4a3b3 ("i40e: Allow RSS Hash set with less than four parameters") Signed-off-by: Slawomir Laba slawomirx.laba@intel.com Signed-off-by: Michal Jaron michalx.jaron@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Tested-by: Gurucharan gurucharanx.g@intel.com (A Contingent worker at Intel) Signed-off-by: Jacob Keller jacob.e.keller@intel.com Link: https://lore.kernel.org/r/20221024100526.1874914-1-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 31 ++++++++++++++----- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 +++ 2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 11a17ebfceef..6d94255bea5f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -3085,10 +3085,17 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
if (cmd->flow_type == TCP_V4_FLOW || cmd->flow_type == UDP_V4_FLOW) { - if (i_set & I40E_L3_SRC_MASK) - cmd->data |= RXH_IP_SRC; - if (i_set & I40E_L3_DST_MASK) - cmd->data |= RXH_IP_DST; + if (hw->mac.type == I40E_MAC_X722) { + if (i_set & I40E_X722_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_X722_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } else { + if (i_set & I40E_L3_SRC_MASK) + cmd->data |= RXH_IP_SRC; + if (i_set & I40E_L3_DST_MASK) + cmd->data |= RXH_IP_DST; + } } else if (cmd->flow_type == TCP_V6_FLOW || cmd->flow_type == UDP_V6_FLOW) { if (i_set & I40E_L3_V6_SRC_MASK) @@ -3446,12 +3453,15 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
/** * i40e_get_rss_hash_bits - Read RSS Hash bits from register + * @hw: hw structure * @nfc: pointer to user request * @i_setc: bits currently set * * Returns value of bits to be set per user request **/ -static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) +static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, + struct ethtool_rxnfc *nfc, + u64 i_setc) { u64 i_set = i_setc; u64 src_l3 = 0, dst_l3 = 0; @@ -3470,8 +3480,13 @@ static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc) dst_l3 = I40E_L3_V6_DST_MASK; } else if (nfc->flow_type == TCP_V4_FLOW || nfc->flow_type == UDP_V4_FLOW) { - src_l3 = I40E_L3_SRC_MASK; - dst_l3 = I40E_L3_DST_MASK; + if (hw->mac.type == I40E_MAC_X722) { + src_l3 = I40E_X722_L3_SRC_MASK; + dst_l3 = I40E_X722_L3_DST_MASK; + } else { + src_l3 = I40E_L3_SRC_MASK; + dst_l3 = I40E_L3_DST_MASK; + } } else { /* Any other flow type are not supported here */ return i_set; @@ -3586,7 +3601,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) flow_pctype)) | ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype)) << 32); - i_set = i40e_get_rss_hash_bits(nfc, i_setc); + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), (u32)i_set); i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 7b3f30beb757..388c3d36d96a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1404,6 +1404,10 @@ struct i40e_lldp_variables { #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000
/* INPUT SET MASK for RSS, flow director, and flexible payload */ +#define I40E_X722_L3_SRC_SHIFT 49 +#define I40E_X722_L3_SRC_MASK (0x3ULL << I40E_X722_L3_SRC_SHIFT) +#define I40E_X722_L3_DST_SHIFT 41 +#define I40E_X722_L3_DST_MASK (0x3ULL << I40E_X722_L3_DST_SHIFT) #define I40E_L3_SRC_SHIFT 47 #define I40E_L3_SRC_MASK (0x3ULL << I40E_L3_SRC_SHIFT) #define I40E_L3_V6_SRC_SHIFT 43
From: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com
[ Upstream commit 52424f974bc53c26ba3f00300a00e9de9afcd972 ]
When a reset was triggered on one VF with i40e_reset_vf global PF state __I40E_VF_DISABLE was set on a PF until the reset finished. If immediately after triggering reset on one VF there is a request to reset on another it will cause a hang on VF side because VF will be notified of incoming reset but the reset will never happen because of this global state, we will get such error message:
[ +4.890195] iavf 0000:86:02.1: Never saw reset
and VF will hang waiting for the reset to be triggered.
Fix this by introducing new VF state I40E_VF_STATE_RESETTING that will be set on a VF if it is currently resetting instead of the global __I40E_VF_DISABLE PF state.
Fixes: 3ba9bcb4b68f ("i40e: add locking around VF reset") Signed-off-by: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Tested-by: Konrad Jankowski konrad0.jankowski@intel.com Signed-off-by: Jacob Keller jacob.e.keller@intel.com Link: https://lore.kernel.org/r/20221024100526.1874914-2-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 43 ++++++++++++++----- .../ethernet/intel/i40e/i40e_virtchnl_pf.h | 1 + 2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index c078fbaf19fd..8f350792e823 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1536,10 +1536,12 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) return true;
- /* If the VFs have been disabled, this means something else is - * resetting the VF, so we shouldn't continue. - */ - if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) + /* Bail out if VFs are disabled. */ + if (test_bit(__I40E_VF_DISABLE, pf->state)) + return true; + + /* If VF is being reset already we don't need to continue. */ + if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) return true;
i40e_trigger_vf_reset(vf, flr); @@ -1576,7 +1578,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) i40e_cleanup_reset_vf(vf);
i40e_flush(hw); - clear_bit(__I40E_VF_DISABLE, pf->state); + clear_bit(I40E_VF_STATE_RESETTING, &vf->vf_states);
return true; } @@ -1609,8 +1611,12 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) return false;
/* Begin reset on all VFs at once */ - for (v = 0; v < pf->num_alloc_vfs; v++) - i40e_trigger_vf_reset(&pf->vf[v], flr); + for (v = 0; v < pf->num_alloc_vfs; v++) { + vf = &pf->vf[v]; + /* If VF is being reset no need to trigger reset again */ + if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + i40e_trigger_vf_reset(&pf->vf[v], flr); + }
/* HW requires some time to make sure it can flush the FIFO for a VF * when it resets it. Poll the VPGEN_VFRSTAT register for each VF in @@ -1626,9 +1632,11 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) */ while (v < pf->num_alloc_vfs) { vf = &pf->vf[v]; - reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id)); - if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK)) - break; + if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) { + reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id)); + if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK)) + break; + }
/* If the current VF has finished resetting, move on * to the next VF in sequence. @@ -1656,6 +1664,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) if (pf->vf[v].lan_vsi_idx == 0) continue;
+ /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]); }
@@ -1667,6 +1679,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) if (pf->vf[v].lan_vsi_idx == 0) continue;
+ /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]); }
@@ -1676,8 +1692,13 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr) mdelay(50);
/* Finish the reset on each VF */ - for (v = 0; v < pf->num_alloc_vfs; v++) + for (v = 0; v < pf->num_alloc_vfs; v++) { + /* If VF is reset in another thread just continue */ + if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) + continue; + i40e_cleanup_reset_vf(&pf->vf[v]); + }
i40e_flush(hw); clear_bit(__I40E_VF_DISABLE, pf->state); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index a554d0a0b09b..358bbdb58795 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -39,6 +39,7 @@ enum i40e_vf_states { I40E_VF_STATE_MC_PROMISC, I40E_VF_STATE_UC_PROMISC, I40E_VF_STATE_PRE_ENABLE, + I40E_VF_STATE_RESETTING };
/* VF capabilities */
From: Slawomir Laba slawomirx.laba@intel.com
[ Upstream commit 3b32c9932853e11d71f9db012d69e92e4669ba23 ]
Fix setting bits for specific flow_type for GLQF_HASH_INSET register. In previous version all of the bits were set only in hena register, while in inset only one bit was set. In order for this working correctly on all types of cards these bits needs to be set correctly for both hena and inset registers.
Fixes: eb0dd6e4a3b3 ("i40e: Allow RSS Hash set with less than four parameters") Signed-off-by: Slawomir Laba slawomirx.laba@intel.com Signed-off-by: Michal Jaron michalx.jaron@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Signed-off-by: Jacob Keller jacob.e.keller@intel.com Link: https://lore.kernel.org/r/20221024100526.1874914-3-jacob.e.keller@intel.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 6d94255bea5f..4e3243287805 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -3504,6 +3504,7 @@ static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, return i_set; }
+#define FLOW_PCTYPES_SIZE 64 /** * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash * @pf: pointer to the physical function struct @@ -3516,9 +3517,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) struct i40e_hw *hw = &pf->hw; u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) | ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32); - u8 flow_pctype = 0; + DECLARE_BITMAP(flow_pctypes, FLOW_PCTYPES_SIZE); u64 i_set, i_setc;
+ bitmap_zero(flow_pctypes, FLOW_PCTYPES_SIZE); + if (pf->flags & I40E_FLAG_MFP_ENABLED) { dev_err(&pf->pdev->dev, "Change of RSS hash input set is not supported when MFP mode is enabled\n"); @@ -3534,36 +3537,35 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
switch (nfc->flow_type) { case TCP_V4_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP; + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, flow_pctypes); if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK, + flow_pctypes); break; case TCP_V6_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, flow_pctypes); if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK, + flow_pctypes); break; case UDP_V4_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP); - + set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, flow_pctypes); + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP, + flow_pctypes); + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP, + flow_pctypes); + } hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4); break; case UDP_V6_FLOW: - flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP; - if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) - hena |= - BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP); - + set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, flow_pctypes); + if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP, + flow_pctypes); + set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP, + flow_pctypes); + } hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6); break; case AH_ESP_V4_FLOW: @@ -3596,17 +3598,20 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) return -EINVAL; }
- if (flow_pctype) { - i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, - flow_pctype)) | - ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, - flow_pctype)) << 32); - i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype), - (u32)i_set); - i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype), - (u32)(i_set >> 32)); - hena |= BIT_ULL(flow_pctype); + if (bitmap_weight(flow_pctypes, FLOW_PCTYPES_SIZE)) { + u8 flow_id; + + for_each_set_bit(flow_id, flow_pctypes, FLOW_PCTYPES_SIZE) { + i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id)) | + ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id)) << 32); + i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc); + + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id), + (u32)i_set); + i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id), + (u32)(i_set >> 32)); + hena |= BIT_ULL(flow_id); + } }
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 5da6d65590a0698199df44d095e54b0ed1708178 ]
pci_disable_device() need be called while module exiting, switch to use pcim_enable(), pci_disable_device() will be called in pcim_release() while unbinding device.
Fixes: 8ca86fd83eae ("net: Micrel KSZ8841/2 PCI Ethernet driver") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20221024131338.2848959-1-yangyingliang@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/micrel/ksz884x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index a0ee155f9f51..f56bcd3e36d2 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -6848,7 +6848,7 @@ static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id) char banner[sizeof(version)]; struct ksz_switch *sw = NULL;
- result = pci_enable_device(pdev); + result = pcim_enable_device(pdev); if (result) return result;
From: Sudeep Holla sudeep.holla@arm.com
[ Upstream commit e0c57a5c70c13317238cb19a7ded0eab4a5f7de5 ]
Platforms can provide the information about the availability of each idle states via status flag. Platforms may have to disable one or more idle states for various reasons like broken firmware or other unmet dependencies.
Fix handling of such unavailable/disabled idle states by ignoring them while parsing the states.
Fixes: a3381e3a65cb ("PM / domains: Fix up domain-idle-states OF parsing") Signed-off-by: Sudeep Holla sudeep.holla@arm.com Reviewed-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/base/power/domain.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7f3d21e6fdfb..94fe30c187ad 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2889,6 +2889,10 @@ static int genpd_iterate_idle_states(struct device_node *dn, np = it.node; if (!of_match_node(idle_state_match, np)) continue; + + if (!of_device_is_available(np)) + continue; + if (states) { ret = genpd_parse_state(&states[i], np); if (ret) {
From: Shang XiaoJing shangxiaojing@huawei.com
[ Upstream commit e9229d5b6254a75291536f582652c599957344d2 ]
Commit 0cc177cfc95d565e ("perf vendor events arm64: Add Hisi hip08 L3 metrics") add L3 metrics of hip08, but some metrics (IF_BP_MISP_BR_RET, IF_BP_MISP_BR_RET, IF_BP_MISP_BR_BL) have incorrect event number due to the mistakes in document, which caused incorrect result. Fix the incorrect metrics.
Before:
65,811,214,308 armv8_pmuv3_0/event=0x1014/ # 18.87 push_branch # -40.19 other_branch 3,564,316,780 BR_MIS_PRED # 0.51 indirect_branch # 21.81 pop_branch
After:
6,537,146,245 BR_MIS_PRED # 0.48 indirect_branch # 0.47 pop_branch # 0.00 push_branch # 0.05 other_branch
Fixes: 0cc177cfc95d565e ("perf vendor events arm64: Add Hisi hip08 L3 metrics") Reviewed-by: John Garry john.garry@huawei.com Signed-off-by: Shang XiaoJing shangxiaojing@huawei.com Acked-by: James Clark james.clark@arm.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Ingo Molnar mingo@redhat.com Cc: Jiri Olsa jolsa@kernel.org Cc: John Garry john.garry@huawei.com Cc: Kajol Jain kjain@linux.ibm.com Cc: Leo Yan leo.yan@linaro.org Cc: linux-arm-kernel@lists.infradead.org Cc: Mark Rutland mark.rutland@arm.com Cc: Mike Leach mike.leach@linaro.org Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Will Deacon will@kernel.org Link: https://lore.kernel.org/r/20221021105035.10000-2-shangxiaojing@huawei.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json index dda8e59149d2..be23d3c89a79 100644 --- a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json +++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json @@ -112,21 +112,21 @@ "MetricName": "indirect_branch" }, { - "MetricExpr": "(armv8_pmuv3_0@event\=0x1014@ + armv8_pmuv3_0@event\=0x1018@) / BR_MIS_PRED", + "MetricExpr": "(armv8_pmuv3_0@event\=0x1013@ + armv8_pmuv3_0@event\=0x1016@) / BR_MIS_PRED", "PublicDescription": "Push branch L3 topdown metric", "BriefDescription": "Push branch L3 topdown metric", "MetricGroup": "TopDownL3", "MetricName": "push_branch" }, { - "MetricExpr": "armv8_pmuv3_0@event\=0x100c@ / BR_MIS_PRED", + "MetricExpr": "armv8_pmuv3_0@event\=0x100d@ / BR_MIS_PRED", "PublicDescription": "Pop branch L3 topdown metric", "BriefDescription": "Pop branch L3 topdown metric", "MetricGroup": "TopDownL3", "MetricName": "pop_branch" }, { - "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\=0x1010@ - armv8_pmuv3_0@event\=0x1014@ - armv8_pmuv3_0@event\=0x1018@ - armv8_pmuv3_0@event\=0x100c@) / BR_MIS_PRED", + "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\=0x1010@ - armv8_pmuv3_0@event\=0x1013@ - armv8_pmuv3_0@event\=0x1016@ - armv8_pmuv3_0@event\=0x100d@) / BR_MIS_PRED", "PublicDescription": "Other branch L3 topdown metric", "BriefDescription": "Other branch L3 topdown metric", "MetricGroup": "TopDownL3",
From: Juergen Borleis jbe@pengutronix.de
[ Upstream commit 0a8b43b12dd78daa77a7dc007b92770d262a2714 ]
Using 'ethtool -d […]' on an i.MX6UL leads to a kernel crash:
Unhandled fault: external abort on non-linefetch (0x1008) at […]
due to this SoC has less registers in its FEC implementation compared to other i.MX6 variants. Thus, a run-time decision is required to avoid access to non-existing registers.
Fixes: a51d3ab50702 ("net: fec: use a more proper compatible string for i.MX6UL type device") Signed-off-by: Juergen Borleis jbe@pengutronix.de Reviewed-by: Andrew Lunn andrew@lunn.ch Link: https://lore.kernel.org/r/20221024080552.21004-1-jbe@pengutronix.de Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/fec_main.c | 46 ++++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 67eb9b671244..313ae8112067 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2336,6 +2336,31 @@ static u32 fec_enet_register_offset[] = { IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, IEEE_R_FDXFC, IEEE_R_OCTETS_OK }; +/* for i.MX6ul */ +static u32 fec_enet_register_offset_6ul[] = { + FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, + FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, + FEC_X_CNTRL, FEC_ADDR_LOW, FEC_ADDR_HIGH, FEC_OPD, FEC_TXIC0, FEC_RXIC0, + FEC_HASH_TABLE_HIGH, FEC_HASH_TABLE_LOW, FEC_GRP_HASH_TABLE_HIGH, + FEC_GRP_HASH_TABLE_LOW, FEC_X_WMRK, FEC_R_DES_START_0, + FEC_X_DES_START_0, FEC_R_BUFF_SIZE_0, FEC_R_FIFO_RSFL, FEC_R_FIFO_RSEM, + FEC_R_FIFO_RAEM, FEC_R_FIFO_RAFL, FEC_RACC, + RMON_T_DROP, RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT, + RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG, + RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255, + RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2047, + RMON_T_P_GTE2048, RMON_T_OCTETS, + IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL, IEEE_T_DEF, + IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR, IEEE_T_SQE, + IEEE_T_FDXFC, IEEE_T_OCTETS_OK, + RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, + RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, + RMON_R_RESVD_O, RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255, + RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, + RMON_R_P_GTE2048, RMON_R_OCTETS, + IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, + IEEE_R_FDXFC, IEEE_R_OCTETS_OK +}; #else static __u32 fec_enet_register_version = 1; static u32 fec_enet_register_offset[] = { @@ -2360,7 +2385,24 @@ static void fec_enet_get_regs(struct net_device *ndev, u32 *buf = (u32 *)regbuf; u32 i, off; int ret; +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ + defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST) + u32 *reg_list; + u32 reg_cnt;
+ if (!of_machine_is_compatible("fsl,imx6ul")) { + reg_list = fec_enet_register_offset; + reg_cnt = ARRAY_SIZE(fec_enet_register_offset); + } else { + reg_list = fec_enet_register_offset_6ul; + reg_cnt = ARRAY_SIZE(fec_enet_register_offset_6ul); + } +#else + /* coldfire */ + static u32 *reg_list = fec_enet_register_offset; + static const u32 reg_cnt = ARRAY_SIZE(fec_enet_register_offset); +#endif ret = pm_runtime_resume_and_get(dev); if (ret < 0) return; @@ -2369,8 +2411,8 @@ static void fec_enet_get_regs(struct net_device *ndev,
memset(buf, 0, regs->len);
- for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) { - off = fec_enet_register_offset[i]; + for (i = 0; i < reg_cnt; i++) { + off = reg_list[i];
if ((off == FEC_R_BOUND || off == FEC_R_FSTART) && !(fep->quirks & FEC_QUIRK_HAS_FRREG))
From: Kunihiko Hayashi hayashi.kunihiko@socionext.com
[ Upstream commit e2badb4bd33abe13ddc35975bd7f7f8693955a4b ]
The phylib callback is called after MAC driver's own resume callback is called. For AVE driver, after resuming immediately, PHY state machine is in PHY_NOLINK because there is a time lag from link-down to link-up due to autoneg. The result is WARN_ON() dump in mdio_bus_phy_resume().
Since ave_resume() itself calls phy_resume(), AVE driver should manage PHY PM. To indicate that MAC driver manages PHY PM, set phydev->mac_managed_pm to true to avoid the unnecessary phylib call and add missing phy_init_hw() to ave_resume().
Suggested-by: Heiner Kallweit hkallweit1@gmail.com Fixes: fba863b81604 ("net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM") Signed-off-by: Kunihiko Hayashi hayashi.kunihiko@socionext.com Link: https://lore.kernel.org/r/20221024072227.24769-1-hayashi.kunihiko@socionext.... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/socionext/sni_ave.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index ae31ed93aaf0..57dc9680ad50 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1229,6 +1229,8 @@ static int ave_init(struct net_device *ndev)
phy_support_asym_pause(phydev);
+ phydev->mac_managed_pm = true; + phy_attached_info(phydev);
return 0; @@ -1758,6 +1760,10 @@ static int ave_resume(struct device *dev)
ave_global_reset(ndev);
+ ret = phy_init_hw(ndev->phydev); + if (ret) + return ret; + ave_ethtool_get_wol(ndev, &wol); wol.wolopts = priv->wolopts; __ave_ethtool_set_wol(ndev, &wol);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 4a4c8482e370d697738a78dcd7bf2780832cb712 ]
dev_set_name() in soundbus_add_one() allocates memory for name, it need be freed when of_device_register() fails, call soundbus_dev_put() to give up the reference that hold in device_initialize(), so that it can be freed in kobject_cleanup() when the refcount hit to 0. And other resources are also freed in i2sbus_release_dev(), so it can return 0 directly.
Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20221027013438.991920-1-yangyingliang@huawei.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/aoa/soundbus/i2sbus/core.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index faf6b03131ee..f6841daf9e3b 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -302,6 +302,10 @@ static int i2sbus_add_dev(struct macio_dev *macio,
if (soundbus_add_one(&dev->sound)) { printk(KERN_DEBUG "i2sbus: device registration error!\n"); + if (dev->sound.ofdev.dev.kobj.state_initialized) { + soundbus_dev_put(&dev->sound); + return 0; + } goto err; }
From: Takashi Iwai tiwai@suse.de
[ Upstream commit f1fae475f10a26b7e34da4ff2e2f19b7feb3548e ]
i2sbus_add_dev() is supposed to return the number of probed devices, i.e. either 1 or 0. However, i2sbus_add_dev() has one error handling that returns -ENODEV; this will screw up the accumulation number counted in the caller, i2sbus_probe().
Fix the return value to 0 and add the comment for better understanding for readers.
Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") Link: https://lore.kernel.org/r/20221027065233.13292-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/aoa/soundbus/i2sbus/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index f6841daf9e3b..51ed2f34b276 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -147,6 +147,7 @@ static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index, return rc; }
+/* Returns 1 if added, 0 for otherwise; don't return a negative value! */ /* FIXME: look at device node refcounting */ static int i2sbus_add_dev(struct macio_dev *macio, struct i2sbus_control *control, @@ -213,7 +214,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, * either as the second one in that case is just a modem. */ if (!ok) { kfree(dev); - return -ENODEV; + return 0; }
mutex_init(&dev->lock);
From: Aaron Conole aconole@redhat.com
[ Upstream commit fd954cc1919e35cb92f78671cab6e42d661945a3 ]
As noted by Paolo Abeni, pr_warn doesn't generate any splat and can still preserve the warning to the user that feature downgrade occurred. We likely cannot introduce other kinds of checks / enforcement here because syzbot can generate different genl versions to the datapath.
Reported-by: syzbot+31cde0bef4bbf8ba2d86@syzkaller.appspotmail.com Fixes: 44da5ae5fbea ("openvswitch: Drop user features if old user space attempted to create datapath") Cc: Thomas Graf tgraf@suug.ch Signed-off-by: Aaron Conole aconole@redhat.com Acked-by: Ilya Maximets i.maximets@ovn.org Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/openvswitch/datapath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 46ef1525b2e5..94c48122fdc3 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1605,7 +1605,8 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, if (IS_ERR(dp)) return;
- WARN(dp->user_features, "Dropping previously announced user features\n"); + pr_warn("%s: Dropping previously announced user features\n", + ovs_dp_name(dp)); dp->user_features = 0; }
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 0e7ce23a917a9cc83ca3c779fbba836bca3bcf1e ]
If of_device_register() returns error, the of node and the name allocated in dev_set_name() is leaked, call put_device() to give up the reference that was set in device_initialize(), so that of node is put in logical_port_release() and the name is freed in kobject_cleanup().
Fixes: 1acf2318dd13 ("ehea: dynamic add / remove port") Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20221025130011.1071357-1-yangyingliang@huawei.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ehea/ehea_main.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index d5df131b183c..6c534b92aeed 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -2898,6 +2898,7 @@ static struct device *ehea_register_port(struct ehea_port *port, ret = of_device_register(&port->ofdev); if (ret) { pr_err("failed to register device. ret=%d\n", ret); + put_device(&port->ofdev.dev); goto out; }
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit 9f172134dde7e4f5bf4b9139f23a1e741ec1c36e ]
Avoid the PHY library call unnecessarily into the suspend/resume functions by setting phydev->mac_managed_pm to true. The SYSTEMPORT driver essentially does exactly what mdio_bus_phy_resume() does by calling phy_resume().
Fixes: fba863b81604 ("net: phy: make PHY PM ops a no-op if MAC driver manages PHY PM") Signed-off-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/20221025234201.2549360-1-f.fainelli@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bcmsysport.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index ae541a9d1eee..4c7f828c69c6 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1991,6 +1991,9 @@ static int bcm_sysport_open(struct net_device *dev) goto out_clk_disable; }
+ /* Indicate that the MAC is responsible for PHY PM */ + phydev->mac_managed_pm = true; + /* Reset house keeping link status */ priv->old_duplex = -1; priv->old_link = -1;
From: Nicolas Dichtel nicolas.dichtel@6wind.com
[ Upstream commit bac0f937c343d651874f83b265ca8f5070ed4f06 ]
As explained by Julian, fib_nh_scope is related to fib_nh_gw4, but fib_info_update_nhc_saddr() needs the scope of the route, which is the scope "before" fib_nh_scope, ie fib_nh_scope - 1.
This patch fixes the problem described in commit 747c14307214 ("ip: fix dflt addr selection for connected nexthop").
Fixes: 597cfe4fc339 ("nexthop: Add support for IPv4 nexthops") Link: https://lore.kernel.org/netdev/6c8a44ba-c2d5-cdf-c5c7-5baf97cba38@ssi.bg/ Signed-off-by: Nicolas Dichtel nicolas.dichtel@6wind.com Reviewed-by: Julian Anastasov ja@ssi.bg Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/nexthop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index cc8f120149f6..6cc7d347ec0a 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -2535,7 +2535,7 @@ static int nh_create_ipv4(struct net *net, struct nexthop *nh, if (!err) { nh->nh_flags = fib_nh->fib_nh_flags; fib_info_update_nhc_saddr(net, &fib_nh->nh_common, - fib_nh->fib_nh_scope); + !fib_nh->fib_nh_scope ? 0 : fib_nh->fib_nh_scope - 1); } else { fib_nh_release(net, fib_nh); }
From: Colin Ian King colin.i.king@gmail.com
[ Upstream commit 62a3106697f3c6f9af64a2cd0f9ff58552010dc8 ]
The variable bytes is being used to summate slot lengths, however the value is never used afterwards. The summation is redundant so remove variable bytes.
Signed-off-by: Colin Ian King colin.i.king@gmail.com Link: https://lore.kernel.org/r/20211222003937.727325-1-colin.i.king@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Stable-dep-of: ef3556ee16c6 ("net: broadcom: bcm4908_enet: update TX stats after actual transmission") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bcm4908_enet.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c index 376f81796a29..994731a33e18 100644 --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c @@ -635,7 +635,6 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight) struct bcm4908_enet_dma_ring_bd *buf_desc; struct bcm4908_enet_dma_ring_slot *slot; struct device *dev = enet->dev; - unsigned int bytes = 0; int handled = 0;
while (handled < weight && tx_ring->read_idx != tx_ring->write_idx) { @@ -646,7 +645,6 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight)
dma_unmap_single(dev, slot->dma_addr, slot->len, DMA_TO_DEVICE); dev_kfree_skb(slot->skb); - bytes += slot->len; if (++tx_ring->read_idx == tx_ring->length) tx_ring->read_idx = 0;
From: Rafał Miłecki rafal@milecki.pl
[ Upstream commit ef3556ee16c68735ec69bd08df41d1cd83b14ad3 ]
Queueing packets doesn't guarantee their transmission. Update TX stats after hardware confirms consuming submitted data.
This also fixes a possible race and NULL dereference. bcm4908_enet_start_xmit() could try to access skb after freeing it in the bcm4908_enet_poll_tx().
Reported-by: Florian Fainelli f.fainelli@gmail.com Fixes: 4feffeadbcb2e ("net: broadcom: bcm4908enet: add BCM4908 controller driver") Signed-off-by: Rafał Miłecki rafal@milecki.pl Reviewed-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/20221027112430.8696-1-zajec5@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/bcm4908_enet.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c index 994731a33e18..7e89664943ce 100644 --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c @@ -561,8 +561,6 @@ static int bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netde
if (++ring->write_idx == ring->length - 1) ring->write_idx = 0; - enet->netdev->stats.tx_bytes += skb->len; - enet->netdev->stats.tx_packets++;
return NETDEV_TX_OK; } @@ -635,6 +633,7 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight) struct bcm4908_enet_dma_ring_bd *buf_desc; struct bcm4908_enet_dma_ring_slot *slot; struct device *dev = enet->dev; + unsigned int bytes = 0; int handled = 0;
while (handled < weight && tx_ring->read_idx != tx_ring->write_idx) { @@ -645,12 +644,17 @@ static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight)
dma_unmap_single(dev, slot->dma_addr, slot->len, DMA_TO_DEVICE); dev_kfree_skb(slot->skb); - if (++tx_ring->read_idx == tx_ring->length) - tx_ring->read_idx = 0;
handled++; + bytes += slot->len; + + if (++tx_ring->read_idx == tx_ring->length) + tx_ring->read_idx = 0; }
+ enet->netdev->stats.tx_packets += handled; + enet->netdev->stats.tx_bytes += bytes; + if (handled < weight) { napi_complete_done(napi, handled); bcm4908_enet_dma_ring_intrs_on(enet, tx_ring);
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit a6aa8d0ce2cfba57ac0f23293fcb3be0b9f53fba ]
Remove dir in nsim_dev_debugfs_init() when creating ports dir failed. Otherwise, the netdevsim device will not be created next time. Kernel reports an error: debugfs: Directory 'netdevsim1' with parent 'netdevsim' already present!
Fixes: ab1d0cc004d7 ("netdevsim: change debugfs tree topology") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/netdevsim/dev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 54313bd57797..94490dfae656 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -229,8 +229,10 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) if (IS_ERR(nsim_dev->ddir)) return PTR_ERR(nsim_dev->ddir); nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir); - if (IS_ERR(nsim_dev->ports_ddir)) - return PTR_ERR(nsim_dev->ports_ddir); + if (IS_ERR(nsim_dev->ports_ddir)) { + err = PTR_ERR(nsim_dev->ports_ddir); + goto err_ddir; + } debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir, &nsim_dev->fw_update_status); debugfs_create_u32("fw_update_overwrite_mask", 0600, nsim_dev->ddir, @@ -267,7 +269,7 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) nsim_dev->nodes_ddir = debugfs_create_dir("rate_nodes", nsim_dev->ddir); if (IS_ERR(nsim_dev->nodes_ddir)) { err = PTR_ERR(nsim_dev->nodes_ddir); - goto err_out; + goto err_ports_ddir; } debugfs_create_bool("fail_trap_drop_counter_get", 0600, nsim_dev->ddir, @@ -275,8 +277,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) nsim_udp_tunnels_debugfs_create(nsim_dev); return 0;
-err_out: +err_ports_ddir: debugfs_remove_recursive(nsim_dev->ports_ddir); +err_ddir: debugfs_remove_recursive(nsim_dev->ddir); return err; }
From: Hyong Youb Kim hyonkim@cisco.com
[ Upstream commit 888be6b279b7257b5f6e4c9527675bff0a335596 ]
An offloaded SA stops receiving after about 2^32 + replay_window packets. For example, when SA reaches <seq-hi 0x1, seq 0x2c>, all subsequent packets get dropped with SA-icv-failure (integrity_failed).
To reproduce the bug: - ConnectX-6 Dx with crypto enabled (FW 22.30.1004) - ipsec.conf: nic-offload = yes replay-window = 32 esn = yes salifetime=24h - Run netperf for a long time to send more than 2^32 packets netperf -H <device-under-test> -t TCP_STREAM -l 20000
When 2^32 + replay_window packets are received, the replay window moves from the 2nd half of subspace (overlap=1) to the 1st half (overlap=0). The driver then updates the 'esn' value in NIC (i.e. seq_hi) as follows.
seq_hi = xfrm_replay_seqhi(seq_bottom) new esn in NIC = seq_hi + 1
The +1 increment is wrong, as seq_hi already contains the correct seq_hi. For example, when seq_hi=1, the driver actually tells NIC to use seq_hi=2 (esn). This incorrect esn value causes all subsequent packets to fail integrity checks (SA-icv-failure). So, do not increment.
Fixes: cb01008390bb ("net/mlx5: IPSec, Add support for ESN") Signed-off-by: Hyong Youb Kim hyonkim@cisco.com Acked-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Link: https://lore.kernel.org/r/20221026135153.154807-2-saeed@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 7cab08a2f715..05882d1a4407 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -113,7 +113,6 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry) struct xfrm_replay_state_esn *replay_esn; u32 seq_bottom = 0; u8 overlap; - u32 *esn;
if (!(sa_entry->x->props.flags & XFRM_STATE_ESN)) { sa_entry->esn_state.trigger = 0; @@ -128,11 +127,9 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
sa_entry->esn_state.esn = xfrm_replay_seqhi(sa_entry->x, htonl(seq_bottom)); - esn = &sa_entry->esn_state.esn;
sa_entry->esn_state.trigger = 1; if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) { - ++(*esn); sa_entry->esn_state.overlap = 0; return true; } else if (unlikely(!overlap &&
From: Aya Levin ayal@nvidia.com
[ Upstream commit 19b43a432e3e47db656a8269a74b50aef826950c ]
When tx_port_ts is set, the driver diverts all UPD traffic over PTP port to a dedicated PTP-SQ. The SKBs are cached until the wire-CQE arrives. When the packet size is greater then MTU, the firmware might drop it and the packet won't be transmitted to the wire, hence the wire-CQE won't reach the driver. In this case the SKBs are accumulated in the SKB fifo. Add room check to consider the PTP-SQ SKB fifo, when the SKB fifo is full, driver stops the queue resulting in a TX timeout. Devlink TX-reporter can recover from it.
Fixes: 1880bc4e4a96 ("net/mlx5e: Add TX port timestamp support") Signed-off-by: Aya Levin ayal@nvidia.com Reviewed-by: Tariq Toukan tariqt@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Link: https://lore.kernel.org/r/20221026135153.154807-5-saeed@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 9 +++++++++ drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 6 ++++++ drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 6 ++++++ 3 files changed, 21 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index a71a32e00ebb..dc7c57e6de77 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -6,6 +6,7 @@
#include "en.h" #include "en_stats.h" +#include "en/txrx.h" #include <linux/ptp_classify.h>
#define MLX5E_PTP_CHANNEL_IX 0 @@ -67,6 +68,14 @@ static inline bool mlx5e_use_ptpsq(struct sk_buff *skb) fk.ports.dst == htons(PTP_EV_PORT)); }
+static inline bool mlx5e_ptpsq_fifo_has_room(struct mlx5e_txqsq *sq) +{ + if (!sq->ptpsq) + return true; + + return mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo); +} + int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, u8 lag_port, struct mlx5e_ptp **cp); void mlx5e_ptp_close(struct mlx5e_ptp *c); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 055c3bc23733..f5c872043bcb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -73,6 +73,12 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev); bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget); void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq);
+static inline bool +mlx5e_skb_fifo_has_room(struct mlx5e_skb_fifo *fifo) +{ + return (*fifo->pc - *fifo->cc) < fifo->mask; +} + static inline bool mlx5e_wqc_has_room_for(struct mlx5_wq_cyc *wq, u16 cc, u16 pc, u16 n) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 1544d4c2c636..e18fa5ae0fd8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -479,6 +479,11 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, if (unlikely(sq->ptpsq)) { mlx5e_skb_cb_hwtstamp_init(skb); mlx5e_skb_fifo_push(&sq->ptpsq->skb_fifo, skb); + if (!netif_tx_queue_stopped(sq->txq) && + !mlx5e_skb_fifo_has_room(&sq->ptpsq->skb_fifo)) { + netif_tx_stop_queue(sq->txq); + sq->stats->stopped++; + } skb_get(skb); }
@@ -906,6 +911,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
if (netif_tx_queue_stopped(sq->txq) && mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) && + mlx5e_ptpsq_fifo_has_room(sq) && !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) { netif_tx_wake_queue(sq->txq); stats->wake++;
From: Tariq Toukan tariqt@nvidia.com
[ Upstream commit bacd22df95147ed673bec4692ab2d4d585935241 ]
mlx5_cmd_cleanup_async_ctx should return only after all its callback handlers were completed. Before this patch, the below race between mlx5_cmd_cleanup_async_ctx and mlx5_cmd_exec_cb_handler was possible and lead to a use-after-free:
1. mlx5_cmd_cleanup_async_ctx is called while num_inflight is 2 (i.e. elevated by 1, a single inflight callback). 2. mlx5_cmd_cleanup_async_ctx decreases num_inflight to 1. 3. mlx5_cmd_exec_cb_handler is called, decreases num_inflight to 0 and is about to call wake_up(). 4. mlx5_cmd_cleanup_async_ctx calls wait_event, which returns immediately as the condition (num_inflight == 0) holds. 5. mlx5_cmd_cleanup_async_ctx returns. 6. The caller of mlx5_cmd_cleanup_async_ctx frees the mlx5_async_ctx object. 7. mlx5_cmd_exec_cb_handler goes on and calls wake_up() on the freed object.
Fix it by syncing using a completion object. Mark it completed when num_inflight reaches 0.
Trace:
BUG: KASAN: use-after-free in do_raw_spin_lock+0x23d/0x270 Read of size 4 at addr ffff888139cd12f4 by task swapper/5/0
CPU: 5 PID: 0 Comm: swapper/5 Not tainted 6.0.0-rc3_for_upstream_debug_2022_08_30_13_10 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: <IRQ> dump_stack_lvl+0x57/0x7d print_report.cold+0x2d5/0x684 ? do_raw_spin_lock+0x23d/0x270 kasan_report+0xb1/0x1a0 ? do_raw_spin_lock+0x23d/0x270 do_raw_spin_lock+0x23d/0x270 ? rwlock_bug.part.0+0x90/0x90 ? __delete_object+0xb8/0x100 ? lock_downgrade+0x6e0/0x6e0 _raw_spin_lock_irqsave+0x43/0x60 ? __wake_up_common_lock+0xb9/0x140 __wake_up_common_lock+0xb9/0x140 ? __wake_up_common+0x650/0x650 ? destroy_tis_callback+0x53/0x70 [mlx5_core] ? kasan_set_track+0x21/0x30 ? destroy_tis_callback+0x53/0x70 [mlx5_core] ? kfree+0x1ba/0x520 ? do_raw_spin_unlock+0x54/0x220 mlx5_cmd_exec_cb_handler+0x136/0x1a0 [mlx5_core] ? mlx5_cmd_cleanup_async_ctx+0x220/0x220 [mlx5_core] ? mlx5_cmd_cleanup_async_ctx+0x220/0x220 [mlx5_core] mlx5_cmd_comp_handler+0x65a/0x12b0 [mlx5_core] ? dump_command+0xcc0/0xcc0 [mlx5_core] ? lockdep_hardirqs_on_prepare+0x400/0x400 ? cmd_comp_notifier+0x7e/0xb0 [mlx5_core] cmd_comp_notifier+0x7e/0xb0 [mlx5_core] atomic_notifier_call_chain+0xd7/0x1d0 mlx5_eq_async_int+0x3ce/0xa20 [mlx5_core] atomic_notifier_call_chain+0xd7/0x1d0 ? irq_release+0x140/0x140 [mlx5_core] irq_int_handler+0x19/0x30 [mlx5_core] __handle_irq_event_percpu+0x1f2/0x620 handle_irq_event+0xb2/0x1d0 handle_edge_irq+0x21e/0xb00 __common_interrupt+0x79/0x1a0 common_interrupt+0x78/0xa0 </IRQ> <TASK> asm_common_interrupt+0x22/0x40 RIP: 0010:default_idle+0x42/0x60 Code: c1 83 e0 07 48 c1 e9 03 83 c0 03 0f b6 14 11 38 d0 7c 04 84 d2 75 14 8b 05 eb 47 22 02 85 c0 7e 07 0f 00 2d e0 9f 48 00 fb f4 <c3> 48 c7 c7 80 08 7f 85 e8 d1 d3 3e fe eb de 66 66 2e 0f 1f 84 00 RSP: 0018:ffff888100dbfdf0 EFLAGS: 00000242 RAX: 0000000000000001 RBX: ffffffff84ecbd48 RCX: 1ffffffff0afe110 RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffffffff835cc9bc RBP: 0000000000000005 R08: 0000000000000001 R09: ffff88881dec4ac3 R10: ffffed1103bd8958 R11: 0000017d0ca571c9 R12: 0000000000000005 R13: ffffffff84f024e0 R14: 0000000000000000 R15: dffffc0000000000 ? default_idle_call+0xcc/0x450 default_idle_call+0xec/0x450 do_idle+0x394/0x450 ? arch_cpu_idle_exit+0x40/0x40 ? do_idle+0x17/0x450 cpu_startup_entry+0x19/0x20 start_secondary+0x221/0x2b0 ? set_cpu_sibling_map+0x2070/0x2070 secondary_startup_64_no_verify+0xcd/0xdb </TASK>
Allocated by task 49502: kasan_save_stack+0x1e/0x40 __kasan_kmalloc+0x81/0xa0 kvmalloc_node+0x48/0xe0 mlx5e_bulk_async_init+0x35/0x110 [mlx5_core] mlx5e_tls_priv_tx_list_cleanup+0x84/0x3e0 [mlx5_core] mlx5e_ktls_cleanup_tx+0x38f/0x760 [mlx5_core] mlx5e_cleanup_nic_tx+0xa7/0x100 [mlx5_core] mlx5e_detach_netdev+0x1ca/0x2b0 [mlx5_core] mlx5e_suspend+0xdb/0x140 [mlx5_core] mlx5e_remove+0x89/0x190 [mlx5_core] auxiliary_bus_remove+0x52/0x70 device_release_driver_internal+0x40f/0x650 driver_detach+0xc1/0x180 bus_remove_driver+0x125/0x2f0 auxiliary_driver_unregister+0x16/0x50 mlx5e_cleanup+0x26/0x30 [mlx5_core] cleanup+0xc/0x4e [mlx5_core] __x64_sys_delete_module+0x2b5/0x450 do_syscall_64+0x3d/0x90 entry_SYSCALL_64_after_hwframe+0x46/0xb0
Freed by task 49502: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_set_free_info+0x20/0x30 ____kasan_slab_free+0x11d/0x1b0 kfree+0x1ba/0x520 mlx5e_tls_priv_tx_list_cleanup+0x2e7/0x3e0 [mlx5_core] mlx5e_ktls_cleanup_tx+0x38f/0x760 [mlx5_core] mlx5e_cleanup_nic_tx+0xa7/0x100 [mlx5_core] mlx5e_detach_netdev+0x1ca/0x2b0 [mlx5_core] mlx5e_suspend+0xdb/0x140 [mlx5_core] mlx5e_remove+0x89/0x190 [mlx5_core] auxiliary_bus_remove+0x52/0x70 device_release_driver_internal+0x40f/0x650 driver_detach+0xc1/0x180 bus_remove_driver+0x125/0x2f0 auxiliary_driver_unregister+0x16/0x50 mlx5e_cleanup+0x26/0x30 [mlx5_core] cleanup+0xc/0x4e [mlx5_core] __x64_sys_delete_module+0x2b5/0x450 do_syscall_64+0x3d/0x90 entry_SYSCALL_64_after_hwframe+0x46/0xb0
Fixes: e355477ed9e4 ("net/mlx5: Make mlx5_cmd_exec_cb() a safe API") Signed-off-by: Tariq Toukan tariqt@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Link: https://lore.kernel.org/r/20221026135153.154807-8-saeed@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 10 +++++----- include/linux/mlx5/driver.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index e06a6104e91f..8a3100f32d3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1865,7 +1865,7 @@ void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, ctx->dev = dev; /* Starts at 1 to avoid doing wake_up if we are not cleaning up */ atomic_set(&ctx->num_inflight, 1); - init_waitqueue_head(&ctx->wait); + init_completion(&ctx->inflight_done); } EXPORT_SYMBOL(mlx5_cmd_init_async_ctx);
@@ -1879,8 +1879,8 @@ EXPORT_SYMBOL(mlx5_cmd_init_async_ctx); */ void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx) { - atomic_dec(&ctx->num_inflight); - wait_event(ctx->wait, atomic_read(&ctx->num_inflight) == 0); + if (!atomic_dec_and_test(&ctx->num_inflight)) + wait_for_completion(&ctx->inflight_done); } EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx);
@@ -1891,7 +1891,7 @@ static void mlx5_cmd_exec_cb_handler(int status, void *_work)
work->user_callback(status, work); if (atomic_dec_and_test(&ctx->num_inflight)) - wake_up(&ctx->wait); + complete(&ctx->inflight_done); }
int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, @@ -1907,7 +1907,7 @@ int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, ret = cmd_exec(ctx->dev, in, in_size, out, out_size, mlx5_cmd_exec_cb_handler, work, false); if (ret && atomic_dec_and_test(&ctx->num_inflight)) - wake_up(&ctx->wait); + complete(&ctx->inflight_done);
return ret; } diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 4c678de4608d..26095c0fd781 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -966,7 +966,7 @@ void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode); struct mlx5_async_ctx { struct mlx5_core_dev *dev; atomic_t num_inflight; - struct wait_queue_head wait; + struct completion inflight_done; };
struct mlx5_async_work;
From: Saeed Mahameed saeedm@nvidia.com
[ Upstream commit fad1783a6d669ac82b6ea4f2f32b4ba2b5484920 ]
In case mlx5_pci_err_detected was called with state equals to pci_channel_io_perm_failure, the driver will never come back up.
It is nice to know why the driver went to zombie land, so print some useful information on pci err handlers.
Signed-off-by: Saeed Mahameed saeedm@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Stable-dep-of: 416ef7136319 ("net/mlx5: Update fw fatal reporter state on PCI handlers successful recover") Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/mellanox/mlx5/core/main.c | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 740065e21181..1f0156efe255 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1576,12 +1576,28 @@ static void remove_one(struct pci_dev *pdev) mlx5_devlink_free(devlink); }
+#define mlx5_pci_trace(dev, fmt, ...) ({ \ + struct mlx5_core_dev *__dev = (dev); \ + mlx5_core_info(__dev, "%s Device state = %d health sensors: %d pci_status: %d. " fmt, \ + __func__, __dev->state, mlx5_health_check_fatal_sensors(__dev), \ + __dev->pci_status, ##__VA_ARGS__); \ +}) + +static const char *result2str(enum pci_ers_result result) +{ + return result == PCI_ERS_RESULT_NEED_RESET ? "need reset" : + result == PCI_ERS_RESULT_DISCONNECT ? "disconnect" : + result == PCI_ERS_RESULT_RECOVERED ? "recovered" : + "unknown"; +} + static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, pci_channel_state_t state) { struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + enum pci_ers_result res;
- mlx5_core_info(dev, "%s was called\n", __func__); + mlx5_pci_trace(dev, "Enter, pci channel state = %d\n", state);
mlx5_enter_error_state(dev, false); mlx5_error_sw_reset(dev); @@ -1589,8 +1605,11 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, mlx5_drain_health_wq(dev); mlx5_pci_disable_device(dev);
- return state == pci_channel_io_perm_failure ? + res = state == pci_channel_io_perm_failure ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; + + mlx5_pci_trace(dev, "Exit, result = %d, %s\n", res, result2str(res)); + return res; }
/* wait for the device to show vital signs by waiting @@ -1624,28 +1643,34 @@ static int wait_vital(struct pci_dev *pdev)
static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) { + enum pci_ers_result res = PCI_ERS_RESULT_DISCONNECT; struct mlx5_core_dev *dev = pci_get_drvdata(pdev); int err;
- mlx5_core_info(dev, "%s was called\n", __func__); + mlx5_pci_trace(dev, "Enter\n");
err = mlx5_pci_enable_device(dev); if (err) { mlx5_core_err(dev, "%s: mlx5_pci_enable_device failed with error code: %d\n", __func__, err); - return PCI_ERS_RESULT_DISCONNECT; + goto out; }
pci_set_master(pdev); pci_restore_state(pdev); pci_save_state(pdev);
- if (wait_vital(pdev)) { - mlx5_core_err(dev, "%s: wait_vital timed out\n", __func__); - return PCI_ERS_RESULT_DISCONNECT; + err = wait_vital(pdev); + if (err) { + mlx5_core_err(dev, "%s: wait vital failed with error code: %d\n", + __func__, err); + goto out; }
- return PCI_ERS_RESULT_RECOVERED; + res = PCI_ERS_RESULT_RECOVERED; +out: + mlx5_pci_trace(dev, "Exit, err = %d, result = %d, %s\n", err, res, result2str(res)); + return res; }
static void mlx5_pci_resume(struct pci_dev *pdev) @@ -1653,14 +1678,12 @@ static void mlx5_pci_resume(struct pci_dev *pdev) struct mlx5_core_dev *dev = pci_get_drvdata(pdev); int err;
- mlx5_core_info(dev, "%s was called\n", __func__); + mlx5_pci_trace(dev, "Enter, loading driver..\n");
err = mlx5_load_one(dev); - if (err) - mlx5_core_err(dev, "%s: mlx5_load_one failed with error code: %d\n", - __func__, err); - else - mlx5_core_info(dev, "%s: device recovered\n", __func__); + + mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err, + !err ? "recovered" : "Failed"); }
static const struct pci_error_handlers mlx5_err_handler = {
From: Roy Novich royno@nvidia.com
[ Upstream commit 416ef713631937cf5452476a7f1041a3ae7b06c6 ]
Update devlink health fw fatal reporter state to "healthy" is needed by strictly calling devlink_health_reporter_state_update() after recovery was done by PCI error handler. This is needed when fw_fatal reporter was triggered due to PCI error. Poll health is called and set reporter state to error. Health recovery failed (since EEH didn't re-enable the PCI). PCI handlers keep on recover flow and succeed later without devlink acknowledgment. Fix this by adding devlink state update at the end of the PCI handler recovery process.
Fixes: 6181e5cb752e ("devlink: add support for reporter recovery completion") Signed-off-by: Roy Novich royno@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Reviewed-by: Aya Levin ayal@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Link: https://lore.kernel.org/r/20221026135153.154807-11-saeed@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 1f0156efe255..d092261e96c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1682,6 +1682,10 @@ static void mlx5_pci_resume(struct pci_dev *pdev)
err = mlx5_load_one(dev);
+ if (!err) + devlink_health_reporter_state_update(dev->priv.health.fw_fatal_reporter, + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); + mlx5_pci_trace(dev, "Done, err = %d, device %s\n", err, !err ? "recovered" : "Failed"); }
From: Suresh Devarakonda ramad@nvidia.com
[ Upstream commit aefb62a9988749703435e941704624949a80a2a9 ]
When setting Bluefield to DPU NIC mode using mlxconfig tool + sync firmware reset flow, we run into scenario where the host was not eswitch manager at the time of mlx5 driver load but becomes eswitch manager after the sync firmware reset flow. This results in null pointer access of mpfs structure during mac filter add. This change prevents null pointer access but mpfs table entries will not be added.
Fixes: 5ec697446f46 ("net/mlx5: Add support for devlink reload action fw activate") Signed-off-by: Suresh Devarakonda ramad@nvidia.com Reviewed-by: Moshe Shemesh moshe@nvidia.com Reviewed-by: Bodong Wang bodong@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Link: https://lore.kernel.org/r/20221026135153.154807-12-saeed@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c index 839a01da110f..8ff16318e32d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -122,7 +122,7 @@ void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) { struct mlx5_mpfs *mpfs = dev->priv.mpfs;
- if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return;
WARN_ON(!hlist_empty(mpfs->hash)); @@ -137,7 +137,7 @@ int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) int err = 0; u32 index;
- if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return 0;
mutex_lock(&mpfs->lock); @@ -185,7 +185,7 @@ int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) int err = 0; u32 index;
- if (!MLX5_ESWITCH_MANAGER(dev)) + if (!mpfs) return 0;
mutex_lock(&mpfs->lock);
From: Eric Dumazet edumazet@google.com
[ Upstream commit 228ebc41dfab5b5d34cd76835ddb0ca8ee12f513 ]
skb_append_pagefrags() is used by af_unix and udp sendpage() implementation so far.
In commit 326140063946 ("tcp: TX zerocopy should not sense pfmemalloc status") we explained why we should not sense pfmemalloc status for pages owned by user space.
We should also use skb_fill_page_desc_noacc() in skb_append_pagefrags() to avoid following KCSAN report:
BUG: KCSAN: data-race in lru_add_fn / skb_append_pagefrags
write to 0xffffea00058fc1c8 of 8 bytes by task 17319 on cpu 0: __list_add include/linux/list.h:73 [inline] list_add include/linux/list.h:88 [inline] lruvec_add_folio include/linux/mm_inline.h:323 [inline] lru_add_fn+0x327/0x410 mm/swap.c:228 folio_batch_move_lru+0x1e1/0x2a0 mm/swap.c:246 lru_add_drain_cpu+0x73/0x250 mm/swap.c:669 lru_add_drain+0x21/0x60 mm/swap.c:773 free_pages_and_swap_cache+0x16/0x70 mm/swap_state.c:311 tlb_batch_pages_flush mm/mmu_gather.c:59 [inline] tlb_flush_mmu_free mm/mmu_gather.c:256 [inline] tlb_flush_mmu+0x5b2/0x640 mm/mmu_gather.c:263 tlb_finish_mmu+0x86/0x100 mm/mmu_gather.c:363 exit_mmap+0x190/0x4d0 mm/mmap.c:3098 __mmput+0x27/0x1b0 kernel/fork.c:1185 mmput+0x3d/0x50 kernel/fork.c:1207 copy_process+0x19fc/0x2100 kernel/fork.c:2518 kernel_clone+0x166/0x550 kernel/fork.c:2671 __do_sys_clone kernel/fork.c:2812 [inline] __se_sys_clone kernel/fork.c:2796 [inline] __x64_sys_clone+0xc3/0xf0 kernel/fork.c:2796 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
read to 0xffffea00058fc1c8 of 8 bytes by task 17325 on cpu 1: page_is_pfmemalloc include/linux/mm.h:1817 [inline] __skb_fill_page_desc include/linux/skbuff.h:2432 [inline] skb_fill_page_desc include/linux/skbuff.h:2453 [inline] skb_append_pagefrags+0x210/0x600 net/core/skbuff.c:3974 unix_stream_sendpage+0x45e/0x990 net/unix/af_unix.c:2338 kernel_sendpage+0x184/0x300 net/socket.c:3561 sock_sendpage+0x5a/0x70 net/socket.c:1054 pipe_to_sendpage+0x128/0x160 fs/splice.c:361 splice_from_pipe_feed fs/splice.c:415 [inline] __splice_from_pipe+0x222/0x4d0 fs/splice.c:559 splice_from_pipe fs/splice.c:594 [inline] generic_splice_sendpage+0x89/0xc0 fs/splice.c:743 do_splice_from fs/splice.c:764 [inline] direct_splice_actor+0x80/0xa0 fs/splice.c:931 splice_direct_to_actor+0x305/0x620 fs/splice.c:886 do_splice_direct+0xfb/0x180 fs/splice.c:974 do_sendfile+0x3bf/0x910 fs/read_write.c:1255 __do_sys_sendfile64 fs/read_write.c:1323 [inline] __se_sys_sendfile64 fs/read_write.c:1309 [inline] __x64_sys_sendfile64+0x10c/0x150 fs/read_write.c:1309 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
value changed: 0x0000000000000000 -> 0xffffea00058fc188
Reported by Kernel Concurrency Sanitizer on: CPU: 1 PID: 17325 Comm: syz-executor.0 Not tainted 6.1.0-rc1-syzkaller-00158-g440b7895c990-dirty #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/11/2022
Fixes: 326140063946 ("tcp: TX zerocopy should not sense pfmemalloc status") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Eric Dumazet edumazet@google.com Link: https://lore.kernel.org/r/20221027040346.1104204-1-edumazet@google.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/skbuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3c193e7d4bc6..9cc607b2d3d2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3821,7 +3821,7 @@ int skb_append_pagefrags(struct sk_buff *skb, struct page *page, skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size); } else if (i < MAX_SKB_FRAGS) { get_page(page); - skb_fill_page_desc(skb, i, page, offset, size); + skb_fill_page_desc_noacc(skb, i, page, offset, size); } else { return -EMSGSIZE; }
From: Eric Dumazet edumazet@google.com
[ Upstream commit ee15e1f38dc201fa7d63c13aa258b728dce27f4d ]
Similar to changes done in TCP in blamed commit. We should not sense pfmemalloc status in sendpage() methods.
Fixes: 326140063946 ("tcp: TX zerocopy should not sense pfmemalloc status") Signed-off-by: Eric Dumazet edumazet@google.com Link: https://lore.kernel.org/r/20221027040637.1107703-1-edumazet@google.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/kcm/kcmsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index ff6dd2619f22..a1478ad393f9 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c @@ -838,7 +838,7 @@ static ssize_t kcm_sendpage(struct socket *sock, struct page *page, }
get_page(page); - skb_fill_page_desc(skb, i, page, offset, size); + skb_fill_page_desc_noacc(skb, i, page, offset, size); skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
coalesced:
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 84ce1ca3fe9e1249bf21176ff162200f1c4e5ed1 ]
Under memory pressure, enetc_refill_rx_ring() may fail, and when called during the enetc_open() -> enetc_setup_rxbdr() procedure, this is not checked for.
An extreme case of memory pressure will result in exactly zero buffers being allocated for the RX ring, and in such a case it is expected that hardware drops all RX packets due to lack of buffers.
This does not happen, because the reset-default value of the consumer and produces index is 0, and this makes the ENETC think that all buffers have been initialized and that it owns them (when in reality none were).
The hardware guide explains this best:
| Configure the receive ring producer index register RBaPIR with a value | of 0. The producer index is initially configured by software but owned | by hardware after the ring has been enabled. Hardware increments the | index when a frame is received which may consume one or more BDs. | Hardware is not allowed to increment the producer index to match the | consumer index since it is used to indicate an empty condition. The ring | can hold at most RBLENR[LENGTH]-1 received BDs. | | Configure the receive ring consumer index register RBaCIR. The | consumer index is owned by software and updated during operation of the | of the BD ring by software, to indicate that any receive data occupied | in the BD has been processed and it has been prepared for new data. | - If consumer index and producer index are initialized to the same | value, it indicates that all BDs in the ring have been prepared and | hardware owns all of the entries. | - If consumer index is initialized to producer index plus N, it would | indicate N BDs have been prepared. Note that hardware cannot start if | only a single buffer is prepared due to the restrictions described in | (2). | - Software may write consumer index to match producer index anytime | while the ring is operational to indicate all received BDs prior have | been processed and new BDs prepared for hardware.
Normally, the value of rx_ring->rcir (consumer index) is brought in sync with the rx_ring->next_to_use software index, but this only happens if page allocation ever succeeded.
When PI==CI==0, the hardware appears to receive frames and write them to DMA address 0x0 (?!), then set the READY bit in the BD.
The enetc_clean_rx_ring() function (and its XDP derivative) is naturally not prepared to handle such a condition. It will attempt to process those frames using the rx_swbd structure associated with index i of the RX ring, but that structure is not fully initialized (enetc_new_page() does all of that). So what happens next is undefined behavior.
To operate using no buffer, we must initialize the CI to PI + 1, which will block the hardware from advancing the CI any further, and drop everything.
The issue was seen while adding support for zero-copy AF_XDP sockets, where buffer memory comes from user space, which can even decide to supply no buffers at all (example: "xdpsock --txonly"). However, the bug is present also with the network stack code, even though it would take a very determined person to trigger a page allocation failure at the perfect time (a series of ifup/ifdown under memory pressure should eventually reproduce it given enough retries).
Fixes: d4fd0404c1c9 ("enetc: Introduce basic PF and VF ENETC ethernet drivers") Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Claudiu Manoil claudiu.manoil@nxp.com Link: https://lore.kernel.org/r/20221027182925.3256653-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/enetc/enetc.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index c0265a6f10c0..77d765809c1e 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -1800,7 +1800,12 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) else enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, ENETC_RXB_DMA_SIZE);
+ /* Also prepare the consumer index in case page allocation never + * succeeds. In that case, hardware will never advance producer index + * to match consumer index, and will drop all frames. + */ enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); + enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, 1);
/* enable Rx ints by setting pkt thr to 1 */ enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1);
From: D Scott Phillips scott@os.amperecomputing.com
[ Upstream commit 0e5d5ae837c8ce04d2ddb874ec5f920118bd9d31 ]
Per AmpereOne erratum AC03_CPU_12, "Branch history may allow control of speculative execution across software contexts," the AMPERE1 core needs the bhb clearing loop to mitigate Spectre-BHB, with a loop iteration count of 11.
Signed-off-by: D Scott Phillips scott@os.amperecomputing.com Link: https://lore.kernel.org/r/20221011022140.432370-1-scott@os.amperecomputing.c... Reviewed-by: James Morse james.morse@arm.com Signed-off-by: Catalin Marinas catalin.marinas@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm64/include/asm/cputype.h | 4 ++++ arch/arm64/kernel/proton-pack.c | 6 ++++++ 2 files changed, 10 insertions(+)
--- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -60,6 +60,7 @@ #define ARM_CPU_IMP_FUJITSU 0x46 #define ARM_CPU_IMP_HISI 0x48 #define ARM_CPU_IMP_APPLE 0x61 +#define ARM_CPU_IMP_AMPERE 0xC0
#define ARM_CPU_PART_AEM_V8 0xD0F #define ARM_CPU_PART_FOUNDATION 0xD00 @@ -112,6 +113,8 @@ #define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_FIRESTORM 0x023
+#define AMPERE_CPU_PART_AMPERE1 0xAC3 + #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) @@ -151,6 +154,7 @@ #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) +#define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
/* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ #define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -868,6 +868,10 @@ u8 spectre_bhb_loop_affected(int scope) MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), {}, }; + static const struct midr_range spectre_bhb_k11_list[] = { + MIDR_ALL_VERSIONS(MIDR_AMPERE1), + {}, + }; static const struct midr_range spectre_bhb_k8_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), @@ -878,6 +882,8 @@ u8 spectre_bhb_loop_affected(int scope) k = 32; else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) k = 24; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list)) + k = 11; else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) k = 8;
From: Yu Kuai yukuai3@huawei.com
This reverts commit 84f7a9de0602704bbec774a6c7f7c8c4994bee9c.
Because it introduces a problem that rq->__data_len is set to the wrong value.
before the patch: 1) nr_bytes = rq->__data_len 2) rq->__data_len = sdp->sector_size 3) scsi_init_io() 4) rq->__data_len = nr_bytes
after the patch: 1) rq->__data_len = sdp->sector_size 2) scsi_init_io() 3) rq->__data_len = rq->__data_len -> __data_len is wrong
It will cause that io can only complete one segment each time, and the io will requeue in scsi_io_completion_action(), which will cause severe performance degradation.
Scsi write same is removed in commit e383e16e84e9 ("scsi: sd: Remove WRITE_SAME support") from mainline, hence this patch is only needed for stable kernels.
Fixes: 84f7a9de0602 ("scsi: sd: Remove a local variable") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/scsi/sd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1072,6 +1072,7 @@ static blk_status_t sd_setup_write_same_ struct bio *bio = rq->bio; u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq)); u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); + unsigned int nr_bytes = blk_rq_bytes(rq); blk_status_t ret;
if (sdkp->device->no_write_same) @@ -1108,7 +1109,7 @@ static blk_status_t sd_setup_write_same_ */ rq->__data_len = sdp->sector_size; ret = scsi_alloc_sgtables(cmd); - rq->__data_len = blk_rq_bytes(rq); + rq->__data_len = nr_bytes;
return ret; }
From: Biju Das biju.das.jz@bp.renesas.com
commit d887087c896881715c1a82f1d4f71fbfe5344ffd upstream.
RZ/G2L has separate channel specific IRQs for transmit and error interrupts. But the IRQ handler processes both channels, even if there no interrupt occurred on one of the channels.
This patch fixes the issue by passing a channel specific context parameter instead of global one for the IRQ register and the IRQ handler, it just handles the channel which is triggered the interrupt.
Fixes: 76e9353a80e9 ("can: rcar_canfd: Add support for RZ/G2L family") Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Link: https://lore.kernel.org/all/20221025155657.1426948-3-biju.das.jz@bp.renesas.... Cc: stable@vger.kernel.org [mkl: adjust commit message] Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de [biju: fixed the conflicts manually] Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/can/rcar/rcar_canfd.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
--- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1195,11 +1195,9 @@ static void rcar_canfd_handle_channel_tx
static irqreturn_t rcar_canfd_channel_tx_interrupt(int irq, void *dev_id) { - struct rcar_canfd_global *gpriv = dev_id; - u32 ch; + struct rcar_canfd_channel *priv = dev_id;
- for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) - rcar_canfd_handle_channel_tx(gpriv, ch); + rcar_canfd_handle_channel_tx(priv->gpriv, priv->channel);
return IRQ_HANDLED; } @@ -1227,11 +1225,9 @@ static void rcar_canfd_handle_channel_er
static irqreturn_t rcar_canfd_channel_err_interrupt(int irq, void *dev_id) { - struct rcar_canfd_global *gpriv = dev_id; - u32 ch; + struct rcar_canfd_channel *priv = dev_id;
- for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) - rcar_canfd_handle_channel_err(gpriv, ch); + rcar_canfd_handle_channel_err(priv->gpriv, priv->channel);
return IRQ_HANDLED; } @@ -1649,6 +1645,7 @@ static int rcar_canfd_channel_probe(stru priv->ndev = ndev; priv->base = gpriv->base; priv->channel = ch; + priv->gpriv = gpriv; priv->can.clock.freq = fcan_freq; dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq);
@@ -1677,7 +1674,7 @@ static int rcar_canfd_channel_probe(stru } err = devm_request_irq(&pdev->dev, err_irq, rcar_canfd_channel_err_interrupt, 0, - irq_name, gpriv); + irq_name, priv); if (err) { dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n", err_irq, err); @@ -1691,7 +1688,7 @@ static int rcar_canfd_channel_probe(stru } err = devm_request_irq(&pdev->dev, tx_irq, rcar_canfd_channel_tx_interrupt, 0, - irq_name, gpriv); + irq_name, priv); if (err) { dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n", tx_irq, err); @@ -1715,7 +1712,6 @@ static int rcar_canfd_channel_probe(stru
priv->can.do_set_mode = rcar_canfd_do_set_mode; priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; - priv->gpriv = gpriv; SET_NETDEV_DEV(ndev, &pdev->dev);
netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
From: Biju Das biju.das.jz@bp.renesas.com
commit 702de2c21eed04c67cefaaedc248ef16e5f6b293 upstream.
We are seeing an IRQ storm on the global receive IRQ line under heavy CAN bus load conditions with both CAN channels enabled.
Conditions:
The global receive IRQ line is shared between can0 and can1, either of the channels can trigger interrupt while the other channel's IRQ line is disabled (RFIE).
When global a receive IRQ interrupt occurs, we mask the interrupt in the IRQ handler. Clearing and unmasking of the interrupt is happening in rx_poll(). There is a race condition where rx_poll() unmasks the interrupt, but the next IRQ handler does not mask the IRQ due to NAPIF_STATE_MISSED flag (e.g.: can0 RX FIFO interrupt is disabled and can1 is triggering RX interrupt, the delay in rx_poll() processing results in setting NAPIF_STATE_MISSED flag) leading to an IRQ storm.
This patch fixes the issue by checking IRQ active and enabled before handling the IRQ on a particular channel.
Fixes: dd3bd23eb438 ("can: rcar_canfd: Add Renesas R-Car CAN FD driver") Suggested-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Link: https://lore.kernel.org/all/20221025155657.1426948-2-biju.das.jz@bp.renesas.... Cc: stable@vger.kernel.org [mkl: adjust commit message] Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de [biju: removed gpriv from RCANFD_RFCC_RFIE macro] Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/can/rcar/rcar_canfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -1106,11 +1106,13 @@ static void rcar_canfd_handle_global_rec { struct rcar_canfd_channel *priv = gpriv->ch[ch]; u32 ridx = ch + RCANFD_RFFIFO_IDX; - u32 sts; + u32 sts, cc;
/* Handle Rx interrupts */ sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); - if (likely(sts & RCANFD_RFSTS_RFIF)) { + cc = rcar_canfd_read(priv->base, RCANFD_RFCC(ridx)); + if (likely(sts & RCANFD_RFSTS_RFIF && + cc & RCANFD_RFCC_RFIE)) { if (napi_schedule_prep(&priv->napi)) { /* Disable Rx FIFO interrupts */ rcar_canfd_clear_bit(priv->base,
From: Lino Sanfilippo LinoSanfilippo@gmx.de
commit 0ed12afa5655512ee418047fb3546d229df20aa1 upstream.
Several drivers that support setting the RS485 configuration via userspace implement one or more of the following tasks:
- in case of an invalid RTS configuration (both RTS after send and RTS on send set or both unset) fall back to enable RTS on send and disable RTS after send
- nullify the padding field of the returned serial_rs485 struct
- copy the configuration into the uart port struct
- limit RTS delays to 100 ms
Move these tasks into the serial core to make them generic and to provide a consistent behaviour among all drivers.
Signed-off-by: Lino Sanfilippo LinoSanfilippo@gmx.de Link: https://lore.kernel.org/r/20220410104642.32195-2-LinoSanfilippo@gmx.de Signed-off-by: Daisuke Mizobuchi mizo@atmark-techno.com Signed-off-by: Dominique Martinet dominique.martinet@atmark-techno.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/serial_core.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
--- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -42,6 +42,11 @@ static struct lock_class_key port_lock_k
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+/* + * Max time with active RTS before/after data is sent. + */ +#define RS485_MAX_RTS_DELAY 100 /* msecs */ + static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); @@ -1299,8 +1304,36 @@ static int uart_set_rs485_config(struct if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user))) return -EFAULT;
+ /* pick sane settings if the user hasn't */ + if (!(rs485.flags & SER_RS485_RTS_ON_SEND) == + !(rs485.flags & SER_RS485_RTS_AFTER_SEND)) { + dev_warn_ratelimited(port->dev, + "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", + port->name, port->line); + rs485.flags |= SER_RS485_RTS_ON_SEND; + rs485.flags &= ~SER_RS485_RTS_AFTER_SEND; + } + + if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) { + rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY; + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay before sending clamped to %u ms\n", + port->name, port->line, rs485.delay_rts_before_send); + } + + if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) { + rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY; + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay after sending clamped to %u ms\n", + port->name, port->line, rs485.delay_rts_after_send); + } + /* Return clean padding area to userspace */ + memset(rs485.padding, 0, sizeof(rs485.padding)); + spin_lock_irqsave(&port->lock, flags); ret = port->rs485_config(port, &rs485); + if (!ret) + port->rs485 = rs485; spin_unlock_irqrestore(&port->lock, flags); if (ret) return ret;
From: Lukas Wunner lukas@wunner.de
commit 7c7f9bc986e698873b489c371a08f206979d06b7 upstream.
When a UART port is newly registered, uart_configure_port() seeks to deassert RS485 Transmit Enable by setting the RTS bit in port->mctrl. However a number of UART drivers interpret a set RTS bit as *assertion* instead of deassertion: Affected drivers include those using serial8250_em485_config() (except 8250_bcm2835aux.c) and some using mctrl_gpio (e.g. imx.c).
Since the interpretation of the RTS bit is driver-specific, it is not suitable as a means to centrally deassert Transmit Enable in the serial core. Instead, the serial core must call on drivers to deassert it in their driver-specific way. One way to achieve that is to call ->rs485_config(). It implicitly deasserts Transmit Enable.
So amend uart_configure_port() and uart_resume_port() to invoke uart_rs485_config(). That allows removing calls to uart_rs485_config() from drivers' ->probe() hooks and declaring the function static.
Skip any invocation of ->set_mctrl() if RS485 is enabled. RS485 has no hardware flow control, so the modem control lines are irrelevant and need not be touched. When leaving RS485 mode, reset the modem control lines to the state stored in port->mctrl. That way, UARTs which are muxed between RS485 and RS232 transceivers drive the lines correctly when switched to RS232. (serial8250_do_startup() historically raises the OUT1 modem signal because otherwise interrupts are not signaled on ancient PC UARTs, but I believe that no longer applies to modern, RS485-capable UARTs and is thus safe to be skipped.)
imx.c modifies port->mctrl whenever Transmit Enable is asserted and deasserted. Stop it from doing that so port->mctrl reflects the RS232 line state.
8250_omap.c deasserts Transmit Enable on ->runtime_resume() by calling ->set_mctrl(). Because that is now a no-op in RS485 mode, amend the function to call serial8250_em485_stop_tx().
fsl_lpuart.c retrieves and applies the RS485 device tree properties after registering the UART port. Because applying now happens on registration in uart_configure_port(), move retrieval of the properties ahead of uart_add_one_port().
Link: https://lore.kernel.org/all/20220329085050.311408-1-matthias.schiffer@ew.tq-... Link: https://lore.kernel.org/all/8f538a8903795f22f9acc94a9a31b03c9c4ccacb.camel@g... Fixes: d3b3404df318 ("serial: Fix incorrect rs485 polarity on uart open") Cc: stable@vger.kernel.org # v4.14+ Reported-by: Matthias Schiffer matthias.schiffer@ew.tq-group.com Reported-by: Roosen Henri Henri.Roosen@ginzinger.com Tested-by: Matthias Schiffer matthias.schiffer@ew.tq-group.com Reviewed-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Lukas Wunner lukas@wunner.de Link: https://lore.kernel.org/r/2de36eba3fbe11278d5002e4e501afe0ceaca039.166386380... Signed-off-by: Daisuke Mizobuchi mizo@atmark-techno.com Signed-off-by: Dominique Martinet dominique.martinet@atmark-techno.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/8250/8250_omap.c | 3 +++ drivers/tty/serial/8250/8250_pci.c | 9 +-------- drivers/tty/serial/8250/8250_port.c | 12 +++++++----- drivers/tty/serial/fsl_lpuart.c | 8 +++----- drivers/tty/serial/imx.c | 8 ++------ drivers/tty/serial/serial_core.c | 30 +++++++++++++++++------------- 6 files changed, 33 insertions(+), 37 deletions(-)
--- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -342,6 +342,9 @@ static void omap8250_restore_regs(struct omap8250_update_mdr1(up, priv);
up->port.ops->set_mctrl(&up->port, up->port.mctrl); + + if (up->port.rs485.flags & SER_RS485_ENABLED) + serial8250_em485_stop_tx(up); }
/* --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1739,7 +1739,6 @@ static int pci_fintek_init(struct pci_de resource_size_t bar_data[3]; u8 config_base; struct serial_private *priv = pci_get_drvdata(dev); - struct uart_8250_port *port;
if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) || !(pci_resource_flags(dev, 4) & IORESOURCE_IO) || @@ -1786,13 +1785,7 @@ static int pci_fintek_init(struct pci_de
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
- if (priv) { - /* re-apply RS232/485 mode when - * pciserial_resume_ports() - */ - port = serial8250_get_port(priv->line[i]); - pci_fintek_rs485_config(&port->port, NULL); - } else { + if (!priv) { /* First init without port data * force init to RS232 Mode */ --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -600,7 +600,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); static int serial8250_em485_init(struct uart_8250_port *p) { if (p->em485) - return 0; + goto deassert_rts;
p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC); if (!p->em485) @@ -616,7 +616,9 @@ static int serial8250_em485_init(struct p->em485->active_timer = NULL; p->em485->tx_stopped = true;
- p->rs485_stop_tx(p); +deassert_rts: + if (p->em485->tx_stopped) + p->rs485_stop_tx(p);
return 0; } @@ -2034,6 +2036,9 @@ EXPORT_SYMBOL_GPL(serial8250_do_set_mctr
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { + if (port->rs485.flags & SER_RS485_ENABLED) + return; + if (port->set_mctrl) port->set_mctrl(port, mctrl); else @@ -3191,9 +3196,6 @@ static void serial8250_config_port(struc if (flags & UART_CONFIG_TYPE) autoconfig(up);
- if (port->rs485.flags & SER_RS485_ENABLED) - port->rs485_config(port, &port->rs485); - /* if access method is AU, it is a 16550 with a quirk */ if (port->type == PORT_16550A && port->iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2733,10 +2733,6 @@ static int lpuart_probe(struct platform_ if (ret) goto failed_reset;
- ret = uart_add_one_port(&lpuart_reg, &sport->port); - if (ret) - goto failed_attach_port; - ret = uart_get_rs485_mode(&sport->port); if (ret) goto failed_get_rs485; @@ -2748,7 +2744,9 @@ static int lpuart_probe(struct platform_ sport->port.rs485.delay_rts_after_send) dev_err(&pdev->dev, "driver doesn't support RTS delays\n");
- sport->port.rs485_config(&sport->port, &sport->port.rs485); + ret = uart_add_one_port(&lpuart_reg, &sport->port); + if (ret) + goto failed_attach_port;
ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0, DRIVER_NAME, sport); --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -380,8 +380,7 @@ static void imx_uart_rts_active(struct i { *ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
- sport->port.mctrl |= TIOCM_RTS; - mctrl_gpio_set(sport->gpios, sport->port.mctrl); + mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS); }
/* called with port.lock taken and irqs caller dependent */ @@ -390,8 +389,7 @@ static void imx_uart_rts_inactive(struct *ucr2 &= ~UCR2_CTSC; *ucr2 |= UCR2_CTS;
- sport->port.mctrl &= ~TIOCM_RTS; - mctrl_gpio_set(sport->gpios, sport->port.mctrl); + mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS); }
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) @@ -2318,8 +2316,6 @@ static int imx_uart_probe(struct platfor dev_err(&pdev->dev, "low-active RTS not possible when receiver is off, enabling receiver\n");
- imx_uart_rs485_config(&sport->port, &sport->port.rs485); - /* Disable interrupts before requesting them */ ucr1 = imx_uart_readl(sport, UCR1); ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | UCR1_RTSDEN); --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -149,15 +149,10 @@ uart_update_mctrl(struct uart_port *port unsigned long flags; unsigned int old;
- if (port->rs485.flags & SER_RS485_ENABLED) { - set &= ~TIOCM_RTS; - clear &= ~TIOCM_RTS; - } - spin_lock_irqsave(&port->lock, flags); old = port->mctrl; port->mctrl = (old & ~clear) | set; - if (old != port->mctrl) + if (old != port->mctrl && !(port->rs485.flags & SER_RS485_ENABLED)) port->ops->set_mctrl(port, port->mctrl); spin_unlock_irqrestore(&port->lock, flags); } @@ -1332,8 +1327,13 @@ static int uart_set_rs485_config(struct
spin_lock_irqsave(&port->lock, flags); ret = port->rs485_config(port, &rs485); - if (!ret) + if (!ret) { port->rs485 = rs485; + + /* Reset RTS and other mctrl lines when disabling RS485 */ + if (!(rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); + } spin_unlock_irqrestore(&port->lock, flags); if (ret) return ret; @@ -2306,7 +2306,8 @@ int uart_resume_port(struct uart_driver
uart_change_pm(state, UART_PM_STATE_ON); spin_lock_irq(&uport->lock); - ops->set_mctrl(uport, 0); + if (!(uport->rs485.flags & SER_RS485_ENABLED)) + ops->set_mctrl(uport, 0); spin_unlock_irq(&uport->lock); if (console_suspend_enabled || !uart_console(uport)) { /* Protected by port mutex for now */ @@ -2317,7 +2318,10 @@ int uart_resume_port(struct uart_driver if (tty) uart_change_speed(tty, state, NULL); spin_lock_irq(&uport->lock); - ops->set_mctrl(uport, uport->mctrl); + if (!(uport->rs485.flags & SER_RS485_ENABLED)) + ops->set_mctrl(uport, uport->mctrl); + else + uport->rs485_config(uport, &uport->rs485); ops->start_tx(uport); spin_unlock_irq(&uport->lock); tty_port_set_initialized(port, 1); @@ -2423,10 +2427,10 @@ uart_configure_port(struct uart_driver * */ spin_lock_irqsave(&port->lock, flags); port->mctrl &= TIOCM_DTR; - if (port->rs485.flags & SER_RS485_ENABLED && - !(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) - port->mctrl |= TIOCM_RTS; - port->ops->set_mctrl(port, port->mctrl); + if (!(port->rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); + else + port->rs485_config(port, &port->rs485); spin_unlock_irqrestore(&port->lock, flags);
/*
From: Kuniyuki Iwashima kuniyu@amazon.com
commit 3c52c6bb831f6335c176a0fc7214e26f43adbd11 upstream.
syzbot reported a memory leak [0] related to IPV6_ADDRFORM.
The scenario is that while one thread is converting an IPv6 socket into IPv4 with IPV6_ADDRFORM, another thread calls do_ipv6_setsockopt() and allocates memory to inet6_sk(sk)->XXX after conversion.
Then, the converted sk with (tcp|udp)_prot never frees the IPv6 resources, which inet6_destroy_sock() should have cleaned up.
setsockopt(IPV6_ADDRFORM) setsockopt(IPV6_DSTOPTS) +-----------------------+ +----------------------+ - do_ipv6_setsockopt(sk, ...) - sockopt_lock_sock(sk) - do_ipv6_setsockopt(sk, ...) - lock_sock(sk) ^._ called via tcpv6_prot - WRITE_ONCE(sk->sk_prot, &tcp_prot) before WRITE_ONCE() - xchg(&np->opt, NULL) - txopt_put(opt) - sockopt_release_sock(sk) - release_sock(sk) - sockopt_lock_sock(sk) - lock_sock(sk) - ipv6_set_opt_hdr(sk, ...) - ipv6_update_options(sk, opt) - xchg(&inet6_sk(sk)->opt, opt) ^._ opt is never freed.
- sockopt_release_sock(sk) - release_sock(sk)
Since IPV6_DSTOPTS allocates options under lock_sock(), we can avoid this memory leak by testing whether sk_family is changed by IPV6_ADDRFORM after acquiring the lock.
This issue exists from the initial commit between IPV6_ADDRFORM and IPV6_PKTOPTIONS.
[0]: BUG: memory leak unreferenced object 0xffff888009ab9f80 (size 96): comm "syz-executor583", pid 328, jiffies 4294916198 (age 13.034s) hex dump (first 32 bytes): 01 00 00 00 48 00 00 00 08 00 00 00 00 00 00 00 ....H........... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<000000002ee98ae1>] kmalloc include/linux/slab.h:605 [inline] [<000000002ee98ae1>] sock_kmalloc+0xb3/0x100 net/core/sock.c:2566 [<0000000065d7b698>] ipv6_renew_options+0x21e/0x10b0 net/ipv6/exthdrs.c:1318 [<00000000a8c756d7>] ipv6_set_opt_hdr net/ipv6/ipv6_sockglue.c:354 [inline] [<00000000a8c756d7>] do_ipv6_setsockopt.constprop.0+0x28b7/0x4350 net/ipv6/ipv6_sockglue.c:668 [<000000002854d204>] ipv6_setsockopt+0xdf/0x190 net/ipv6/ipv6_sockglue.c:1021 [<00000000e69fdcf8>] tcp_setsockopt+0x13b/0x2620 net/ipv4/tcp.c:3789 [<0000000090da4b9b>] __sys_setsockopt+0x239/0x620 net/socket.c:2252 [<00000000b10d192f>] __do_sys_setsockopt net/socket.c:2263 [inline] [<00000000b10d192f>] __se_sys_setsockopt net/socket.c:2260 [inline] [<00000000b10d192f>] __x64_sys_setsockopt+0xbe/0x160 net/socket.c:2260 [<000000000a80d7aa>] do_syscall_x64 arch/x86/entry/common.c:50 [inline] [<000000000a80d7aa>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 [<000000004562b5c6>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot syzkaller@googlegroups.com Signed-off-by: Kuniyuki Iwashima kuniyu@amazon.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Meena Shanmugam meenashanmugam@google.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv6/ipv6_sockglue.c | 7 +++++++ 1 file changed, 7 insertions(+)
--- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -417,6 +417,12 @@ static int do_ipv6_setsockopt(struct soc rtnl_lock(); lock_sock(sk);
+ /* Another thread has converted the socket into IPv4 with + * IPV6_ADDRFORM concurrently. + */ + if (unlikely(sk->sk_family != AF_INET6)) + goto unlock; + switch (optname) {
case IPV6_ADDRFORM: @@ -976,6 +982,7 @@ done: break; }
+unlock: release_sock(sk); if (needs_rtnl) rtnl_unlock();
On Wed, Nov 02, 2022 at 03:31:46AM +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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.
Successfully cross-compiled for arm64 (bcm2711_defconfig, GCC 10.2.0) and powerpc (ps3_defconfig, GCC 12.2.0).
Tested-by: Bagas Sanjaya bagasdotme@gmail.com
On 11/1/22 19:31, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.77-rc1... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y and the diffstat can be found below.
thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Tested-by: Florian Fainelli f.fainelli@gmail.com
On Wed, Nov 02, 2022 at 03:31:46AM +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
Build results: total: 154 pass: 154 fail: 0 Qemu test results: total: 489 pass: 489 fail: 0
Tested-by: Guenter Roeck linux@roeck-us.net
Guenter
On 11/1/22 7:31 PM, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.77-rc1... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y and the diffstat can be found below.
thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Tested-by: Ron Economos re@w6rz.net
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
Compiled and booted on my x86_64 and ARM64 test systems. No errors or regressions.
Tested-by: Allen Pais apais@linux.microsoft.com
Thanks.
On Wed, 2 Nov 2022 at 08:29, Greg Kroah-Hartman gregkh@linuxfoundation.org wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.77-rc1... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Tested-by: Linux Kernel Functional Testing lkft@linaro.org
## Build * kernel: 5.15.77-rc1 * git: https://gitlab.com/Linaro/lkft/mirrors/stable/linux-stable-rc * git branch: linux-5.15.y * git commit: 55ed865a9c8fe0489641ddc8e9a4ee35d74767aa * git describe: v5.15.76-133-g55ed865a9c8f * test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.15.y/build/v5.15....
## No Test Regressions (compared to v5.15.76)
## No Metric Regressions (compared to v5.15.76)
## No Test Fixes (compared to v5.15.76)
## No Metric Fixes (compared to v5.15.76)
## Test result summary total: 156317, pass: 131770, fail: 4147, skip: 19975, xfail: 425
## Build Summary * arc: 5 total, 5 passed, 0 failed * arm: 149 total, 148 passed, 1 failed * arm64: 47 total, 45 passed, 2 failed * i386: 37 total, 35 passed, 2 failed * mips: 27 total, 27 passed, 0 failed * parisc: 6 total, 6 passed, 0 failed * powerpc: 30 total, 30 passed, 0 failed * riscv: 10 total, 10 passed, 0 failed * s390: 12 total, 12 passed, 0 failed * sh: 12 total, 12 passed, 0 failed * sparc: 6 total, 6 passed, 0 failed * x86_64: 40 total, 38 passed, 2 failed
## Test suites summary * fwts * kselftest-android * kselftest-arm64 * kselftest-arm64/arm64.btitest.bti_c_func * kselftest-arm64/arm64.btitest.bti_j_func * kselftest-arm64/arm64.btitest.bti_jc_func * kselftest-arm64/arm64.btitest.bti_none_func * kselftest-arm64/arm64.btitest.nohint_func * kselftest-arm64/arm64.btitest.paciasp_func * kselftest-arm64/arm64.nobtitest.bti_c_func * kselftest-arm64/arm64.nobtitest.bti_j_func * kselftest-arm64/arm64.nobtitest.bti_jc_func * kselftest-arm64/arm64.nobtitest.bti_none_func * kselftest-arm64/arm64.nobtitest.nohint_func * kselftest-arm64/arm64.nobtitest.paciasp_func * kselftest-breakpoints * kselftest-capabilities * kselftest-cgroup * kselftest-clone3 * kselftest-core * kselftest-cpu-hotplug * kselftest-cpufreq * kselftest-drivers-dma-buf * kselftest-efivarfs * kselftest-filesystems * kselftest-filesystems-binderfs * kselftest-firmware * kselftest-fpu * kselftest-futex * kselftest-gpio * kselftest-intel_pstate * kselftest-ipc * kselftest-ir * kselftest-kcmp * kselftest-kexec * kselftest-kvm * kselftest-lib * kselftest-livepatch * kselftest-membarrier * kselftest-memfd * kselftest-memory-hotplug * kselftest-mincore * kselftest-mount * kselftest-mqueue * kselftest-net * kselftest-net-forwarding * kselftest-net-mptcp * kselftest-netfilter * kselftest-nsfs * kselftest-openat2 * kselftest-pid_namespace * kselftest-pidfd * kselftest-proc * kselftest-pstore * kselftest-ptrace * kselftest-rseq * kselftest-rtc * kselftest-seccomp * kselftest-sigaltstack * kselftest-size * kselftest-splice * kselftest-static_keys * kselftest-sync * kselftest-sysctl * kselftest-tc-testing * kselftest-timens * kselftest-timers * kselftest-tmpfs * kselftest-tpm2 * kselftest-user * kselftest-vm * kselftest-x86 * kselftest-zram * kunit * kvm-unit-tests * libgpiod * libhugetlbfs * log-parser-boot * log-parser-test * ltp-cap_bounds * ltp-commands * ltp-containers * ltp-controllers * ltp-cpuhotplug * ltp-crypto * ltp-cve * ltp-dio * ltp-fcntl-locktests * ltp-filecaps * ltp-fs * ltp-fs_bind * ltp-fs_perms_simple * ltp-fsx * ltp-hugetlb * ltp-io * ltp-ipc * ltp-math * ltp-mm * ltp-nptl * ltp-open-posix-tests * ltp-pty * ltp-sched * ltp-securebits * ltp-smoke * ltp-syscalls * ltp-tracing * network-basic-tests * perf * perf/Zstd-perf.data-compression * rcutorture * v4l2-compliance * vdso
-- Linaro LKFT https://lkft.linaro.org
Hi Greg,
On Wed, Nov 02, 2022 at 03:31:46AM +0100, Greg Kroah-Hartman wrote:
This is the start of the stable review cycle for the 5.15.77 release. There are 132 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, 04 Nov 2022 02:20:38 +0000. Anything received after that time might be too late.
Build test (gcc version 12.2.1 20221016): mips: 62 configs -> no failure arm: 99 configs -> no failure arm64: 3 configs -> no failure x86_64: 4 configs -> no failure alpha allmodconfig -> no failure csky allmodconfig -> no failure powerpc allmodconfig -> no failure riscv allmodconfig -> no failure s390 allmodconfig -> no failure xtensa allmodconfig -> no failure
Boot test: x86_64: Booted on my test laptop. No regression. x86_64: Booted on qemu. No regression. [1] arm64: Booted on rpi4b (4GB model). No regression. [2]
[1]. https://openqa.qa.codethink.co.uk/tests/2092 [2]. https://openqa.qa.codethink.co.uk/tests/2095
Tested-by: Sudip Mukherjee sudip.mukherjee@codethink.co.uk
linux-stable-mirror@lists.linaro.org