summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/accel/amdxdna/aie2_ctx.c55
-rw-r--r--drivers/accel/amdxdna/aie2_message.c51
-rw-r--r--drivers/accel/amdxdna/aie2_pci.c102
-rw-r--r--drivers/accel/amdxdna/aie2_pci.h1
-rw-r--r--drivers/accel/amdxdna/aie2_pm.c2
-rw-r--r--drivers/accel/amdxdna/amdxdna_ctx.c51
-rw-r--r--drivers/accel/amdxdna/amdxdna_ctx.h3
-rw-r--r--drivers/accel/amdxdna/amdxdna_gem.c38
-rw-r--r--drivers/accel/amdxdna/amdxdna_mailbox.c91
-rw-r--r--drivers/accel/amdxdna/amdxdna_mailbox.h31
-rw-r--r--drivers/accel/amdxdna/amdxdna_pci_drv.c3
-rw-r--r--drivers/accel/amdxdna/amdxdna_pm.c2
-rw-r--r--drivers/accel/amdxdna/amdxdna_pm.h11
-rw-r--r--drivers/accel/amdxdna/amdxdna_ubuf.c6
-rw-r--r--drivers/accel/amdxdna/npu1_regs.c4
-rw-r--r--drivers/accel/amdxdna/npu4_regs.c2
-rw-r--r--drivers/accel/amdxdna/npu5_regs.c2
-rw-r--r--drivers/accel/amdxdna/npu6_regs.c2
-rw-r--r--drivers/accel/ethosu/ethosu_gem.c14
-rw-r--r--drivers/accel/ethosu/ethosu_job.c26
-rw-r--r--drivers/acpi/acpica/acpredef.h5
-rw-r--r--drivers/acpi/device_pm.c9
-rw-r--r--drivers/acpi/osi.c13
-rw-r--r--drivers/acpi/sleep.c8
-rw-r--r--drivers/ata/libata-core.c10
-rw-r--r--drivers/ata/libata-eh.c23
-rw-r--r--drivers/ata/libata-scsi.c1
-rw-r--r--drivers/base/base.h11
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/property.c27
-rw-r--r--drivers/block/drbd/drbd_actlog.c53
-rw-r--r--drivers/block/drbd/drbd_interval.h5
-rw-r--r--drivers/block/drbd/drbd_main.c14
-rw-r--r--drivers/block/drbd/drbd_receiver.c4
-rw-r--r--drivers/block/drbd/drbd_req.c3
-rw-r--r--drivers/block/zloop.c31
-rw-r--r--drivers/bluetooth/hci_qca.c24
-rw-r--r--drivers/char/ipmi/ipmi_ipmb.c5
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c141
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c37
-rw-r--r--drivers/char/ipmi/ipmi_si_ls2k.c2
-rw-r--r--drivers/char/random.c12
-rw-r--r--drivers/clk/imx/clk-imx8qxp.c24
-rw-r--r--drivers/clk/imx/clk-scu.c12
-rw-r--r--drivers/clk/imx/clk-scu.h2
-rw-r--r--drivers/cpufreq/intel_pstate.c14
-rw-r--r--drivers/crypto/atmel-sha204a.c5
-rw-r--r--drivers/crypto/ccp/sev-dev-tsm.c2
-rw-r--r--drivers/crypto/ccp/sev-dev.c10
-rw-r--r--drivers/cxl/core/core.h18
-rw-r--r--drivers/cxl/core/hdm.c2
-rw-r--r--drivers/cxl/core/mbox.c11
-rw-r--r--drivers/cxl/core/memdev.c13
-rw-r--r--drivers/cxl/core/pmem.c42
-rw-r--r--drivers/cxl/core/port.c52
-rw-r--r--drivers/cxl/core/region.c4
-rw-r--r--drivers/cxl/cxl.h7
-rw-r--r--drivers/cxl/pmem.c22
-rw-r--r--drivers/dpll/zl3073x/core.c7
-rw-r--r--drivers/dpll/zl3073x/core.h28
-rw-r--r--drivers/dpll/zl3073x/dpll.c7
-rw-r--r--drivers/dpll/zl3073x/ref.c25
-rw-r--r--drivers/dpll/zl3073x/regs.h1
-rw-r--r--drivers/firewire/ohci.c2
-rw-r--r--drivers/firmware/efi/mokvar-table.c2
-rw-r--r--drivers/gpio/gpiolib-shared.c6
-rw-r--r--drivers/gpio/gpiolib.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c116
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c64
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v12_0.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v15_0.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c16
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c6
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/mp/mp_15_0_0_offset.h18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c3
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c23
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-dp.c4
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c6
-rw-r--r--drivers/gpu/drm/drm_client_modeset.c3
-rw-r--r--drivers/gpu/drm/drm_gpusvm.c10
-rw-r--r--drivers/gpu/drm/drm_pagemap.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_alpm.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c11
-rw-r--r--drivers/gpu/drm/imx/ipuv3/parallel-display.c4
-rw-r--r--drivers/gpu/drm/logicvc/logicvc_drm.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c12
-rw-r--r--drivers/gpu/drm/panthor/panthor_sched.c9
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c16
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c1
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c6
-rw-r--r--drivers/gpu/drm/tiny/sharp-memory.c4
-rw-r--r--drivers/gpu/drm/ttm/tests/ttm_bo_test.c4
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c11
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool_internal.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c9
-rw-r--r--drivers/gpu/drm/xe/regs/xe_engine_regs.h6
-rw-r--r--drivers/gpu/drm/xe/xe_configfs.c1
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.c23
-rw-r--r--drivers/gpu/drm/xe/xe_gsc_proxy.c43
-rw-r--r--drivers/gpu/drm/xe/xe_gsc_types.h2
-rw-r--r--drivers/gpu/drm/xe/xe_gt.c66
-rw-r--r--drivers/gpu/drm/xe/xe_lrc.h3
-rw-r--r--drivers/gpu/drm/xe/xe_reg_sr.c4
-rw-r--r--drivers/gpu/drm/xe/xe_ring_ops.c9
-rw-r--r--drivers/gpu/drm/xe/xe_sync.c30
-rw-r--r--drivers/gpu/drm/xe/xe_vm_madvise.c3
-rw-r--r--drivers/gpu/drm/xe/xe_wa.c13
-rw-r--r--drivers/hid/hid-apple.c7
-rw-r--r--drivers/hid/hid-asus.c18
-rw-r--r--drivers/hid/hid-cmedia.c2
-rw-r--r--drivers/hid/hid-creative-sb0540.c2
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-magicmouse.c6
-rw-r--r--drivers/hid/hid-mcp2221.c2
-rw-r--r--drivers/hid/hid-multitouch.c43
-rw-r--r--drivers/hid/hid-zydacron.c2
-rw-r--r--drivers/hid/intel-ish-hid/ipc/hw-ish.h2
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c12
-rw-r--r--drivers/hid/usbhid/hid-pidff.c11
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/aht10.c6
-rw-r--r--drivers/hwmon/it87.c5
-rw-r--r--drivers/hwmon/macsmc-hwmon.c53
-rw-r--r--drivers/hwmon/max6639.c2
-rw-r--r--drivers/hwmon/pmbus/q54sj108a2.c19
-rw-r--r--drivers/hwmon/sa67mcu-hwmon.c161
-rw-r--r--drivers/i2c/busses/i2c-i801.c14
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/core/cache.c13
-rw-r--r--drivers/infiniband/core/cma.c6
-rw-r--r--drivers/infiniband/core/core_priv.h3
-rw-r--r--drivers/infiniband/core/device.c34
-rw-r--r--drivers/infiniband/core/umem_dmabuf.c4
-rw-r--r--drivers/infiniband/core/uverbs_std_types_dmabuf.c2
-rw-r--r--drivers/infiniband/hw/bng_re/bng_dev.c56
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c2
-rw-r--r--drivers/infiniband/hw/ionic/ionic_controlpath.c2
-rw-r--r--drivers/infiniband/hw/ionic/ionic_ibdev.c2
-rw-r--r--drivers/infiniband/hw/irdma/verbs.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c5
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c4
-rw-r--r--drivers/irqchip/irq-gic-v5-irs.c2
-rw-r--r--drivers/irqchip/irq-ls-extirq.c53
-rw-r--r--drivers/irqchip/irq-mmp.c2
-rw-r--r--drivers/irqchip/irq-sifive-plic.c7
-rw-r--r--drivers/media/dvb-core/dmxdev.c4
-rw-r--r--drivers/media/dvb-core/dvb_net.c3
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c38
-rw-r--r--drivers/mmc/host/mmci_qcom_dml.c1
-rw-r--r--drivers/mmc/host/sdhci-brcmstb.c2
-rw-r--r--drivers/net/bonding/bond_main.c9
-rw-r--r--drivers/net/bonding/bond_options.c2
-rw-r--r--drivers/net/can/dummy_can.c1
-rw-r--r--drivers/net/can/spi/mcp251x.c15
-rw-r--r--drivers/net/can/usb/ems_usb.c7
-rw-r--r--drivers/net/can/usb/esd_usb.c30
-rw-r--r--drivers/net/can/usb/etas_es58x/es58x_core.c8
-rw-r--r--drivers/net/can/usb/f81604.c45
-rw-r--r--drivers/net/can/usb/gs_usb.c22
-rw-r--r--drivers/net/can/usb/ucan.c2
-rw-r--r--drivers/net/dsa/realtek/rtl8365mb.c2
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c9
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-common.h2
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c10
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-main.c1
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c13
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c10
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c2
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx_dqo.c56
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h4
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h2
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c31
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c15
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c41
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_trace.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c5
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c17
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_base.c38
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c15
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c51
-rw-r--r--drivers/net/ethernet/intel/ice/ice_idc.c44
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c15
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c7
-rw-r--r--drivers/net/ethernet/intel/ice/ice_txrx.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_xsk.c3
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_ethtool.c3
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c1
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.c14
-rw-r--r--drivers/net/ethernet/intel/idpf/xdp.c6
-rw-r--r--drivers/net/ethernet/intel/idpf/xsk.c1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_xsk.c38
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c34
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ptp.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c3
-rw-r--r--drivers/net/ethernet/intel/libeth/xsk.c1
-rw-r--r--drivers/net/ethernet/intel/libie/fwlog.c4
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c40
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_rx.c27
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c38
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c28
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sriov.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c4
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c5
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c27
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c54
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c60
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-nuss.c2
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c9
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.c8
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c5
-rw-r--r--drivers/net/ethernet/xscale/ptp_ixp46x.c3
-rw-r--r--drivers/net/netconsole.c5
-rw-r--r--drivers/net/ovpn/tcp.c53
-rw-r--r--drivers/net/phy/phy_device.c25
-rw-r--r--drivers/net/phy/qcom/qca807x.c2
-rw-r--r--drivers/net/team/team_core.c26
-rw-r--r--drivers/net/usb/kalmia.c7
-rw-r--r--drivers/net/usb/kaweth.c15
-rw-r--r--drivers/net/usb/lan78xx.c2
-rw-r--r--drivers/net/usb/pegasus.c48
-rw-r--r--drivers/net/usb/r8152.c1
-rw-r--r--drivers/net/vxlan/vxlan_core.c5
-rw-r--r--drivers/net/wan/farsync.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c36
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h2
-rw-r--r--drivers/net/wireless/marvell/libertas/main.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/mac.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c2
-rw-r--r--drivers/net/wireless/st/cw1200/pm.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--drivers/net/xen-netfront.c34
-rw-r--r--drivers/nfc/pn533/usb.c1
-rw-r--r--drivers/nvme/host/core.c28
-rw-r--r--drivers/nvme/host/fabrics.c4
-rw-r--r--drivers/nvme/host/multipath.c14
-rw-r--r--drivers/nvme/host/nvme.h57
-rw-r--r--drivers/nvme/host/pci.c186
-rw-r--r--drivers/nvme/host/pr.c4
-rw-r--r--drivers/nvme/host/sysfs.c23
-rw-r--r--drivers/nvme/host/tcp.c5
-rw-r--r--drivers/nvme/target/fcloop.c15
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c25
-rw-r--r--drivers/pci/xen-pcifront.c8
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs42l43.c5
-rw-r--r--drivers/pinctrl/cix/pinctrl-sky1.c3
-rw-r--r--drivers/pinctrl/meson/pinctrl-amlogic-a4.c3
-rw-r--r--drivers/pinctrl/pinconf-generic.c4
-rw-r--r--drivers/pinctrl/pinctrl-amdisp.c2
-rw-r--r--drivers/pinctrl/pinctrl-cy8c95x0.c4
-rw-r--r--drivers/pinctrl/pinctrl-equilibrium.c31
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c12
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qcs615.c1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660-lpass-lpi.c4
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c51
-rw-r--r--drivers/platform/x86/asus-armoury.h75
-rw-r--r--drivers/platform/x86/dell/alienware-wmi-wmax.c2
-rw-r--r--drivers/platform/x86/dell/dell-wmi-base.c6
-rw-r--r--drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c1
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c9
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c12
-rw-r--r--drivers/platform/x86/intel/hid.c19
-rw-r--r--drivers/platform/x86/intel/int3472/discrete.c7
-rw-r--r--drivers/platform/x86/lenovo/thinkpad_acpi.c6
-rw-r--r--drivers/platform/x86/oxpec.c30
-rw-r--r--drivers/platform/x86/redmi-wmi.c25
-rw-r--r--drivers/platform/x86/touchscreen_dmi.c18
-rw-r--r--drivers/platform/x86/uniwill/uniwill-acpi.c110
-rw-r--r--drivers/platform/x86/uniwill/uniwill-wmi.h6
-rw-r--r--drivers/pmdomain/bcm/bcm2835-power.c6
-rw-r--r--drivers/pmdomain/imx/gpcv2.c4
-rw-r--r--drivers/pmdomain/rockchip/pm-domains.c2
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/bq257xx-regulator.c3
-rw-r--r--drivers/regulator/fp9931.c7
-rw-r--r--drivers/regulator/mt6363-regulator.c4
-rw-r--r--drivers/regulator/pf9453-regulator.c2
-rw-r--r--drivers/regulator/tps65185.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c36
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h3
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c44
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c5
-rw-r--r--drivers/scsi/scsi_devinfo.c2
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--drivers/scsi/ses.c5
-rw-r--r--drivers/scsi/snic/vnic_dev.c9
-rw-r--r--drivers/scsi/storvsc_drv.c5
-rw-r--r--drivers/scsi/xen-scsifront.c2
-rw-r--r--drivers/spi/spi-dw-dma.c2
-rw-r--r--drivers/spi/spi-stm32.c3
-rw-r--r--drivers/target/target_core_configfs.c15
-rw-r--r--drivers/ufs/core/ufshcd.c47
-rw-r--r--drivers/video/fbdev/au1100fb.c8
-rw-r--r--drivers/xen/xen-acpi-processor.c7
-rw-r--r--drivers/xen/xen-pciback/xenbus.c10
-rw-r--r--drivers/xen/xenbus/xenbus_client.c17
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c42
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c2
331 files changed, 3372 insertions, 1645 deletions
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 4503c7c77a3e..afee5e667f77 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -23,9 +23,9 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_pm.h"
-static bool force_cmdlist;
+static bool force_cmdlist = true;
module_param(force_cmdlist, bool, 0600);
-MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default false)");
+MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default true)");
#define HWCTX_MAX_TIMEOUT 60000 /* milliseconds */
@@ -53,6 +53,7 @@ static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwct
{
drm_sched_stop(&hwctx->priv->sched, bad_job);
aie2_destroy_context(xdna->dev_handle, hwctx);
+ drm_sched_start(&hwctx->priv->sched, 0);
}
static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx)
@@ -80,7 +81,6 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
}
out:
- drm_sched_start(&hwctx->priv->sched, 0);
XDNA_DBG(xdna, "%s restarted, ret %d", hwctx->name, ret);
return ret;
}
@@ -186,13 +186,13 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size)
cmd_abo = job->cmd_bo;
if (unlikely(job->job_timeout)) {
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT);
+ amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT);
ret = -EINVAL;
goto out;
}
if (unlikely(!data) || unlikely(size != sizeof(u32))) {
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
+ amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
goto out;
}
@@ -202,7 +202,7 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size)
if (status == AIE2_STATUS_SUCCESS)
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED);
else
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR);
+ amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ERROR);
out:
aie2_sched_notify(job);
@@ -244,13 +244,13 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
cmd_abo = job->cmd_bo;
if (unlikely(job->job_timeout)) {
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT);
+ amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT);
ret = -EINVAL;
goto out;
}
if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) {
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
+ amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
goto out;
}
@@ -270,19 +270,12 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
fail_cmd_idx, fail_cmd_status);
if (fail_cmd_status == AIE2_STATUS_SUCCESS) {
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
+ amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
- goto out;
+ } else {
+ amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ERROR);
}
- amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR);
-
- if (amdxdna_cmd_get_op(cmd_abo) == ERT_CMD_CHAIN) {
- struct amdxdna_cmd_chain *cc = amdxdna_cmd_get_payload(cmd_abo, NULL);
- cc->error_index = fail_cmd_idx;
- if (cc->error_index >= cc->command_count)
- cc->error_index = 0;
- }
out:
aie2_sched_notify(job);
return ret;
@@ -297,19 +290,23 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
struct dma_fence *fence;
int ret;
- if (!hwctx->priv->mbox_chann)
+ ret = amdxdna_pm_resume_get(hwctx->client->xdna);
+ if (ret)
return NULL;
- if (!mmget_not_zero(job->mm))
+ if (!hwctx->priv->mbox_chann) {
+ amdxdna_pm_suspend_put(hwctx->client->xdna);
+ return NULL;
+ }
+
+ if (!mmget_not_zero(job->mm)) {
+ amdxdna_pm_suspend_put(hwctx->client->xdna);
return ERR_PTR(-ESRCH);
+ }
kref_get(&job->refcnt);
fence = dma_fence_get(job->fence);
- ret = amdxdna_pm_resume_get(hwctx->client->xdna);
- if (ret)
- goto out;
-
if (job->drv_cmd) {
switch (job->drv_cmd->opcode) {
case SYNC_DEBUG_BO:
@@ -497,7 +494,7 @@ static void aie2_release_resource(struct amdxdna_hwctx *hwctx)
if (AIE2_FEATURE_ON(xdna->dev_handle, AIE2_TEMPORAL_ONLY)) {
ret = aie2_destroy_context(xdna->dev_handle, hwctx);
- if (ret)
+ if (ret && ret != -ENODEV)
XDNA_ERR(xdna, "Destroy temporal only context failed, ret %d", ret);
} else {
ret = xrs_release_resource(xdna->xrs_hdl, (uintptr_t)hwctx);
@@ -629,7 +626,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
goto free_entity;
}
- ret = amdxdna_pm_resume_get(xdna);
+ ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_col_list;
@@ -760,7 +757,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
if (!hwctx->cus)
return -ENOMEM;
- ret = amdxdna_pm_resume_get(xdna);
+ ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_cus;
@@ -1070,6 +1067,8 @@ void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo,
ret = dma_resv_wait_timeout(gobj->resv, DMA_RESV_USAGE_BOOKKEEP,
true, MAX_SCHEDULE_TIMEOUT);
- if (!ret || ret == -ERESTARTSYS)
+ if (!ret)
XDNA_ERR(xdna, "Failed to wait for bo, ret %ld", ret);
+ else if (ret == -ERESTARTSYS)
+ XDNA_DBG(xdna, "Wait for bo interrupted by signal");
}
diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c
index 7d7dcfeaf794..ffcf3be79e23 100644
--- a/drivers/accel/amdxdna/aie2_message.c
+++ b/drivers/accel/amdxdna/aie2_message.c
@@ -40,11 +40,8 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev,
return -ENODEV;
ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg);
- if (ret == -ETIME) {
- xdna_mailbox_stop_channel(ndev->mgmt_chann);
- xdna_mailbox_destroy_channel(ndev->mgmt_chann);
- ndev->mgmt_chann = NULL;
- }
+ if (ret == -ETIME)
+ aie2_destroy_mgmt_chann(ndev);
if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) {
XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x",
@@ -216,8 +213,10 @@ static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id)
req.context_id = id;
ret = aie2_send_mgmt_msg_wait(ndev, &msg);
- if (ret)
+ if (ret && ret != -ENODEV)
XDNA_WARN(xdna, "Destroy context failed, ret %d", ret);
+ else if (ret == -ENODEV)
+ XDNA_DBG(xdna, "Destroy context: device already stopped");
return ret;
}
@@ -294,13 +293,20 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct
}
intr_reg = i2x.mb_head_ptr_reg + 4;
- hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x,
- intr_reg, ret);
+ hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox);
if (!hwctx->priv->mbox_chann) {
XDNA_ERR(xdna, "Not able to create channel");
ret = -EINVAL;
goto del_ctx_req;
}
+
+ ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, &i2x,
+ intr_reg, ret);
+ if (ret) {
+ XDNA_ERR(xdna, "Not able to create channel");
+ ret = -EINVAL;
+ goto free_channel;
+ }
ndev->hwctx_num++;
XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id);
@@ -308,6 +314,8 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct
return 0;
+free_channel:
+ xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
del_ctx_req:
aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
return ret;
@@ -318,9 +326,12 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc
struct amdxdna_dev *xdna = ndev->xdna;
int ret;
+ if (!hwctx->priv->mbox_chann)
+ return 0;
+
xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
- xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann);
+ xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id);
hwctx->priv->mbox_chann = NULL;
hwctx->fw_ctx_id = -1;
@@ -694,11 +705,11 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz
u32 cmd_len;
void *cmd;
- memset(npu_slot, 0, sizeof(*npu_slot));
cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
if (*size < sizeof(*npu_slot) + cmd_len)
return -EINVAL;
+ memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@@ -719,7 +730,6 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
- memset(npu_slot, 0, sizeof(*npu_slot));
sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*sn);
if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -728,6 +738,7 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
+ memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@@ -751,7 +762,6 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
u32 cmd_len;
u32 arg_sz;
- memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -760,6 +770,7 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
+ memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@@ -787,7 +798,6 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
- memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -796,6 +806,7 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
+ memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->type = EXEC_NPU_TYPE_ELF;
npu_slot->inst_buf_addr = pd->inst_buf;
npu_slot->save_buf_addr = pd->save_buf;
@@ -909,6 +920,20 @@ void aie2_msg_init(struct amdxdna_dev_hdl *ndev)
ndev->exec_msg_ops = &legacy_exec_message_ops;
}
+void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev)
+{
+ struct amdxdna_dev *xdna = ndev->xdna;
+
+ drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
+
+ if (!ndev->mgmt_chann)
+ return;
+
+ xdna_mailbox_stop_channel(ndev->mgmt_chann);
+ xdna_mailbox_free_channel(ndev->mgmt_chann);
+ ndev->mgmt_chann = NULL;
+}
+
static inline struct amdxdna_gem_obj *
aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job)
{
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index 2a51b2658bfc..4924a9da55b6 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -32,6 +32,11 @@ static int aie2_max_col = XRS_MAX_COL;
module_param(aie2_max_col, uint, 0600);
MODULE_PARM_DESC(aie2_max_col, "Maximum column could be used");
+static char *npu_fw[] = {
+ "npu_7.sbin",
+ "npu.sbin"
+};
+
/*
* The management mailbox channel is allocated by firmware.
* The related register and ring buffer information is on SRAM BAR.
@@ -323,10 +328,9 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna)
return;
}
+ aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL);
aie2_mgmt_fw_fini(ndev);
- xdna_mailbox_stop_channel(ndev->mgmt_chann);
- xdna_mailbox_destroy_channel(ndev->mgmt_chann);
- ndev->mgmt_chann = NULL;
+ aie2_destroy_mgmt_chann(ndev);
drmm_kfree(&xdna->ddev, ndev->mbox);
ndev->mbox = NULL;
aie2_psp_stop(ndev->psp_hdl);
@@ -357,10 +361,29 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
}
pci_set_master(pdev);
+ mbox_res.ringbuf_base = ndev->sram_base;
+ mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar);
+ mbox_res.mbox_base = ndev->mbox_base;
+ mbox_res.mbox_size = MBOX_SIZE(ndev);
+ mbox_res.name = "xdna_mailbox";
+ ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
+ if (!ndev->mbox) {
+ XDNA_ERR(xdna, "failed to create mailbox device");
+ ret = -ENODEV;
+ goto disable_dev;
+ }
+
+ ndev->mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox);
+ if (!ndev->mgmt_chann) {
+ XDNA_ERR(xdna, "failed to alloc channel");
+ ret = -ENODEV;
+ goto disable_dev;
+ }
+
ret = aie2_smu_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init smu, ret %d", ret);
- goto disable_dev;
+ goto free_channel;
}
ret = aie2_psp_start(ndev->psp_hdl);
@@ -375,18 +398,6 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
goto stop_psp;
}
- mbox_res.ringbuf_base = ndev->sram_base;
- mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar);
- mbox_res.mbox_base = ndev->mbox_base;
- mbox_res.mbox_size = MBOX_SIZE(ndev);
- mbox_res.name = "xdna_mailbox";
- ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
- if (!ndev->mbox) {
- XDNA_ERR(xdna, "failed to create mailbox device");
- ret = -ENODEV;
- goto stop_psp;
- }
-
mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx);
if (mgmt_mb_irq < 0) {
ret = mgmt_mb_irq;
@@ -395,52 +406,55 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
}
xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4;
- ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox,
- &ndev->mgmt_x2i,
- &ndev->mgmt_i2x,
- xdna_mailbox_intr_reg,
- mgmt_mb_irq);
- if (!ndev->mgmt_chann) {
- XDNA_ERR(xdna, "failed to create management mailbox channel");
+ ret = xdna_mailbox_start_channel(ndev->mgmt_chann,
+ &ndev->mgmt_x2i,
+ &ndev->mgmt_i2x,
+ xdna_mailbox_intr_reg,
+ mgmt_mb_irq);
+ if (ret) {
+ XDNA_ERR(xdna, "failed to start management mailbox channel");
ret = -EINVAL;
goto stop_psp;
}
- ret = aie2_pm_init(ndev);
+ ret = aie2_mgmt_fw_init(ndev);
if (ret) {
- XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
- goto destroy_mgmt_chann;
+ XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
+ goto stop_fw;
}
- ret = aie2_mgmt_fw_init(ndev);
+ ret = aie2_pm_init(ndev);
if (ret) {
- XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
- goto destroy_mgmt_chann;
+ XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
+ goto stop_fw;
}
ret = aie2_mgmt_fw_query(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
- goto destroy_mgmt_chann;
+ goto stop_fw;
}
ret = aie2_error_async_events_alloc(ndev);
if (ret) {
XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret);
- goto destroy_mgmt_chann;
+ goto stop_fw;
}
ndev->dev_status = AIE2_DEV_START;
return 0;
-destroy_mgmt_chann:
+stop_fw:
+ aie2_suspend_fw(ndev);
xdna_mailbox_stop_channel(ndev->mgmt_chann);
- xdna_mailbox_destroy_channel(ndev->mgmt_chann);
stop_psp:
aie2_psp_stop(ndev->psp_hdl);
fini_smu:
aie2_smu_fini(ndev);
+free_channel:
+ xdna_mailbox_free_channel(ndev->mgmt_chann);
+ ndev->mgmt_chann = NULL;
disable_dev:
pci_disable_device(pdev);
@@ -451,7 +465,6 @@ static int aie2_hw_suspend(struct amdxdna_dev *xdna)
{
struct amdxdna_client *client;
- guard(mutex)(&xdna->dev_lock);
list_for_each_entry(client, &xdna->client_list, node)
aie2_hwctx_suspend(client);
@@ -489,6 +502,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
struct psp_config psp_conf;
const struct firmware *fw;
unsigned long bars = 0;
+ char *fw_full_path;
int i, nvec, ret;
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
@@ -503,7 +517,19 @@ static int aie2_init(struct amdxdna_dev *xdna)
ndev->priv = xdna->dev_info->dev_priv;
ndev->xdna = xdna;
- ret = request_firmware(&fw, ndev->priv->fw_path, &pdev->dev);
+ for (i = 0; i < ARRAY_SIZE(npu_fw); i++) {
+ fw_full_path = kasprintf(GFP_KERNEL, "%s%s", ndev->priv->fw_path, npu_fw[i]);
+ if (!fw_full_path)
+ return -ENOMEM;
+
+ ret = firmware_request_nowarn(&fw, fw_full_path, &pdev->dev);
+ kfree(fw_full_path);
+ if (!ret) {
+ XDNA_INFO(xdna, "Load firmware %s%s", ndev->priv->fw_path, npu_fw[i]);
+ break;
+ }
+ }
+
if (ret) {
XDNA_ERR(xdna, "failed to request_firmware %s, ret %d",
ndev->priv->fw_path, ret);
@@ -951,7 +977,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
- ret = amdxdna_pm_resume_get(xdna);
+ ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@@ -1044,7 +1070,7 @@ static int aie2_get_array(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
- ret = amdxdna_pm_resume_get(xdna);
+ ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@@ -1134,7 +1160,7 @@ static int aie2_set_state(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
- ret = amdxdna_pm_resume_get(xdna);
+ ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h
index b20a3661078c..e72311c77996 100644
--- a/drivers/accel/amdxdna/aie2_pci.h
+++ b/drivers/accel/amdxdna/aie2_pci.h
@@ -303,6 +303,7 @@ int aie2_get_array_async_error(struct amdxdna_dev_hdl *ndev,
/* aie2_message.c */
void aie2_msg_init(struct amdxdna_dev_hdl *ndev);
+void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev);
int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev);
int aie2_resume_fw(struct amdxdna_dev_hdl *ndev);
int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value);
diff --git a/drivers/accel/amdxdna/aie2_pm.c b/drivers/accel/amdxdna/aie2_pm.c
index 579b8be13b18..29bd4403a94d 100644
--- a/drivers/accel/amdxdna/aie2_pm.c
+++ b/drivers/accel/amdxdna/aie2_pm.c
@@ -31,7 +31,7 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
{
int ret;
- ret = amdxdna_pm_resume_get(ndev->xdna);
+ ret = amdxdna_pm_resume_get_locked(ndev->xdna);
if (ret)
return ret;
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c
index 59fa3800b9d3..666dfd7b2a80 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.c
+++ b/drivers/accel/amdxdna/amdxdna_ctx.c
@@ -104,7 +104,10 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
if (size) {
count = FIELD_GET(AMDXDNA_CMD_COUNT, cmd->header);
- if (unlikely(count <= num_masks)) {
+ if (unlikely(count <= num_masks ||
+ count * sizeof(u32) +
+ offsetof(struct amdxdna_cmd, data[0]) >
+ abo->mem.size)) {
*size = 0;
return NULL;
}
@@ -132,6 +135,33 @@ u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
return INVALID_CU_IDX;
}
+int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
+ struct amdxdna_sched_job *job, u32 cmd_idx,
+ enum ert_cmd_state error_state)
+{
+ struct amdxdna_client *client = job->hwctx->client;
+ struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd_chain *cc = NULL;
+
+ cmd->header &= ~AMDXDNA_CMD_STATE;
+ cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
+
+ if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {
+ cc = amdxdna_cmd_get_payload(abo, NULL);
+ cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0;
+ abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD);
+ if (!abo)
+ return -EINVAL;
+ cmd = abo->mem.kva;
+ }
+
+ memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
+ if (cc)
+ amdxdna_gem_put_obj(abo);
+
+ return 0;
+}
+
/*
* This should be called in close() and remove(). DO NOT call in other syscalls.
* This guarantee that when hwctx and resources will be released, if user
@@ -266,9 +296,9 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
struct amdxdna_drm_config_hwctx *args = data;
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_hwctx *hwctx;
- int ret, idx;
u32 buf_size;
void *buf;
+ int ret;
u64 val;
if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad)))
@@ -310,20 +340,17 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
return -EINVAL;
}
- mutex_lock(&xdna->dev_lock);
- idx = srcu_read_lock(&client->hwctx_srcu);
+ guard(mutex)(&xdna->dev_lock);
hwctx = xa_load(&client->hwctx_xa, args->handle);
if (!hwctx) {
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
ret = -EINVAL;
- goto unlock_srcu;
+ goto free_buf;
}
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
-unlock_srcu:
- srcu_read_unlock(&client->hwctx_srcu, idx);
- mutex_unlock(&xdna->dev_lock);
+free_buf:
kfree(buf);
return ret;
}
@@ -334,7 +361,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
struct amdxdna_hwctx *hwctx;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
- int ret, idx;
+ int ret;
if (!xdna->dev_info->ops->hwctx_sync_debug_bo)
return -EOPNOTSUPP;
@@ -345,17 +372,15 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
abo = to_xdna_obj(gobj);
guard(mutex)(&xdna->dev_lock);
- idx = srcu_read_lock(&client->hwctx_srcu);
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
if (!hwctx) {
ret = -EINVAL;
- goto unlock_srcu;
+ goto put_obj;
}
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
-unlock_srcu:
- srcu_read_unlock(&client->hwctx_srcu, idx);
+put_obj:
drm_gem_object_put(gobj);
return ret;
}
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h
index 16c85f08f03c..fbdf9d000871 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.h
+++ b/drivers/accel/amdxdna/amdxdna_ctx.h
@@ -167,6 +167,9 @@ amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size);
u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo);
+int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
+ struct amdxdna_sched_job *job, u32 cmd_idx,
+ enum ert_cmd_state error_state);
void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
void amdxdna_hwctx_remove_all(struct amdxdna_client *client);
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index 8c290ddd3251..d60db49ead71 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -21,8 +21,6 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_ubuf.h"
-#define XDNA_MAX_CMD_BO_SIZE SZ_32K
-
MODULE_IMPORT_NS("DMA_BUF");
static int
@@ -745,12 +743,6 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_gem_obj *abo;
- int ret;
-
- if (args->size > XDNA_MAX_CMD_BO_SIZE) {
- XDNA_ERR(xdna, "Command bo size 0x%llx too large", args->size);
- return ERR_PTR(-EINVAL);
- }
if (args->size < sizeof(struct amdxdna_cmd)) {
XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
@@ -764,17 +756,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
abo->type = AMDXDNA_BO_CMD;
abo->client = filp->driver_priv;
- ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
- if (ret) {
- XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
- goto release_obj;
- }
-
return abo;
-
-release_obj:
- drm_gem_object_put(to_gobj(abo));
- return ERR_PTR(ret);
}
int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@@ -871,6 +853,7 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
+ int ret;
gobj = drm_gem_object_lookup(client->filp, bo_hdl);
if (!gobj) {
@@ -879,9 +862,26 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
}
abo = to_xdna_obj(gobj);
- if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
+ if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
+ goto put_obj;
+
+ if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
return abo;
+ if (abo->mem.size > SZ_32K) {
+ XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
+ goto put_obj;
+ }
+
+ ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
+ if (ret) {
+ XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
+ goto put_obj;
+ }
+
+ return abo;
+
+put_obj:
drm_gem_object_put(gobj);
return NULL;
}
diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.c b/drivers/accel/amdxdna/amdxdna_mailbox.c
index 235a94047530..46d844a73a94 100644
--- a/drivers/accel/amdxdna/amdxdna_mailbox.c
+++ b/drivers/accel/amdxdna/amdxdna_mailbox.c
@@ -460,26 +460,49 @@ msg_id_failed:
return ret;
}
-struct mailbox_channel *
-xdna_mailbox_create_channel(struct mailbox *mb,
- const struct xdna_mailbox_chann_res *x2i,
- const struct xdna_mailbox_chann_res *i2x,
- u32 iohub_int_addr,
- int mb_irq)
+struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb)
{
struct mailbox_channel *mb_chann;
- int ret;
-
- if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
- pr_err("Ring buf size must be power of 2");
- return NULL;
- }
mb_chann = kzalloc_obj(*mb_chann);
if (!mb_chann)
return NULL;
+ INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
+ mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
+ if (!mb_chann->work_q) {
+ MB_ERR(mb_chann, "Create workqueue failed");
+ goto free_chann;
+ }
mb_chann->mb = mb;
+
+ return mb_chann;
+
+free_chann:
+ kfree(mb_chann);
+ return NULL;
+}
+
+void xdna_mailbox_free_channel(struct mailbox_channel *mb_chann)
+{
+ destroy_workqueue(mb_chann->work_q);
+ kfree(mb_chann);
+}
+
+int
+xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
+ const struct xdna_mailbox_chann_res *x2i,
+ const struct xdna_mailbox_chann_res *i2x,
+ u32 iohub_int_addr,
+ int mb_irq)
+{
+ int ret;
+
+ if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
+ pr_err("Ring buf size must be power of 2");
+ return -EINVAL;
+ }
+
mb_chann->msix_irq = mb_irq;
mb_chann->iohub_int_addr = iohub_int_addr;
memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i));
@@ -489,61 +512,37 @@ xdna_mailbox_create_channel(struct mailbox *mb,
mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I);
mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X);
- INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
- mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
- if (!mb_chann->work_q) {
- MB_ERR(mb_chann, "Create workqueue failed");
- goto free_and_out;
- }
-
/* Everything look good. Time to enable irq handler */
ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann);
if (ret) {
MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, ret);
- goto destroy_wq;
+ return ret;
}
mb_chann->bad_state = false;
mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
- MB_DBG(mb_chann, "Mailbox channel created (irq: %d)", mb_chann->msix_irq);
- return mb_chann;
-
-destroy_wq:
- destroy_workqueue(mb_chann->work_q);
-free_and_out:
- kfree(mb_chann);
- return NULL;
+ MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq);
+ return 0;
}
-int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann)
+void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
{
struct mailbox_msg *mb_msg;
unsigned long msg_id;
- MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
+ /* Disable an irq and wait. This might sleep. */
free_irq(mb_chann->msix_irq, mb_chann);
- destroy_workqueue(mb_chann->work_q);
- /* We can clean up and release resources */
+ /* Cancel RX work and wait for it to finish */
+ drain_workqueue(mb_chann->work_q);
+
+ /* We can clean up and release resources */
xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg)
mailbox_release_msg(mb_chann, mb_msg);
-
xa_destroy(&mb_chann->chan_xa);
- MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq);
- kfree(mb_chann);
- return 0;
-}
-
-void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
-{
- /* Disable an irq and wait. This might sleep. */
- disable_irq(mb_chann->msix_irq);
-
- /* Cancel RX work and wait for it to finish */
- cancel_work_sync(&mb_chann->rx_work);
- MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
+ MB_DBG(mb_chann, "Mailbox channel stopped, irq: %d", mb_chann->msix_irq);
}
struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
diff --git a/drivers/accel/amdxdna/amdxdna_mailbox.h b/drivers/accel/amdxdna/amdxdna_mailbox.h
index ea367f2fb738..8b1e00945da4 100644
--- a/drivers/accel/amdxdna/amdxdna_mailbox.h
+++ b/drivers/accel/amdxdna/amdxdna_mailbox.h
@@ -74,9 +74,16 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
const struct xdna_mailbox_res *res);
/*
- * xdna_mailbox_create_channel() -- Create a mailbox channel instance
+ * xdna_mailbox_alloc_channel() -- alloc a mailbox channel
*
- * @mailbox: the handle return from xdna_mailbox_create()
+ * @mb: mailbox handle
+ */
+struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb);
+
+/*
+ * xdna_mailbox_start_channel() -- start a mailbox channel instance
+ *
+ * @mb_chann: the handle return from xdna_mailbox_alloc_channel()
* @x2i: host to firmware mailbox resources
* @i2x: firmware to host mailbox resources
* @xdna_mailbox_intr_reg: register addr of MSI-X interrupt
@@ -84,28 +91,24 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
*
* Return: If success, return a handle of mailbox channel. Otherwise, return NULL.
*/
-struct mailbox_channel *
-xdna_mailbox_create_channel(struct mailbox *mailbox,
- const struct xdna_mailbox_chann_res *x2i,
- const struct xdna_mailbox_chann_res *i2x,
- u32 xdna_mailbox_intr_reg,
- int mb_irq);
+int
+xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
+ const struct xdna_mailbox_chann_res *x2i,
+ const struct xdna_mailbox_chann_res *i2x,
+ u32 xdna_mailbox_intr_reg,
+ int mb_irq);
/*
- * xdna_mailbox_destroy_channel() -- destroy mailbox channel
+ * xdna_mailbox_free_channel() -- free mailbox channel
*
* @mailbox_chann: the handle return from xdna_mailbox_create_channel()
- *
- * Return: if success, return 0. otherwise return error code
*/
-int xdna_mailbox_destroy_channel(struct mailbox_channel *mailbox_chann);
+void xdna_mailbox_free_channel(struct mailbox_channel *mailbox_chann);
/*
* xdna_mailbox_stop_channel() -- stop mailbox channel
*
* @mailbox_chann: the handle return from xdna_mailbox_create_channel()
- *
- * Return: if success, return 0. otherwise return error code
*/
void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann);
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 4ada45d06fcf..a4384593bdcc 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -23,6 +23,9 @@ MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
+MODULE_FIRMWARE("amdnpu/1502_00/npu_7.sbin");
+MODULE_FIRMWARE("amdnpu/17f0_10/npu_7.sbin");
+MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
/*
* 0.0: Initial version
diff --git a/drivers/accel/amdxdna/amdxdna_pm.c b/drivers/accel/amdxdna/amdxdna_pm.c
index d024d480521c..b1fafddd7ad5 100644
--- a/drivers/accel/amdxdna/amdxdna_pm.c
+++ b/drivers/accel/amdxdna/amdxdna_pm.c
@@ -16,6 +16,7 @@ int amdxdna_pm_suspend(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
+ guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->suspend)
ret = xdna->dev_info->ops->suspend(xdna);
@@ -28,6 +29,7 @@ int amdxdna_pm_resume(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
+ guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->resume)
ret = xdna->dev_info->ops->resume(xdna);
diff --git a/drivers/accel/amdxdna/amdxdna_pm.h b/drivers/accel/amdxdna/amdxdna_pm.h
index 77b2d6e45570..3d26b973e0e3 100644
--- a/drivers/accel/amdxdna/amdxdna_pm.h
+++ b/drivers/accel/amdxdna/amdxdna_pm.h
@@ -15,4 +15,15 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna);
void amdxdna_pm_init(struct amdxdna_dev *xdna);
void amdxdna_pm_fini(struct amdxdna_dev *xdna);
+static inline int amdxdna_pm_resume_get_locked(struct amdxdna_dev *xdna)
+{
+ int ret;
+
+ mutex_unlock(&xdna->dev_lock);
+ ret = amdxdna_pm_resume_get(xdna);
+ mutex_lock(&xdna->dev_lock);
+
+ return ret;
+}
+
#endif /* _AMDXDNA_PM_H_ */
diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.c b/drivers/accel/amdxdna/amdxdna_ubuf.c
index b509f10b155c..fb71d6e3f44d 100644
--- a/drivers/accel/amdxdna/amdxdna_ubuf.c
+++ b/drivers/accel/amdxdna/amdxdna_ubuf.c
@@ -7,6 +7,7 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include <linux/dma-buf.h>
+#include <linux/overflow.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
@@ -176,7 +177,10 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
goto free_ent;
}
- exp_info.size += va_ent[i].len;
+ if (check_add_overflow(exp_info.size, va_ent[i].len, &exp_info.size)) {
+ ret = -EINVAL;
+ goto free_ent;
+ }
}
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;
diff --git a/drivers/accel/amdxdna/npu1_regs.c b/drivers/accel/amdxdna/npu1_regs.c
index 6f36a27b5a02..1320e924e548 100644
--- a/drivers/accel/amdxdna/npu1_regs.c
+++ b/drivers/accel/amdxdna/npu1_regs.c
@@ -67,12 +67,12 @@ const struct dpm_clk_freq npu1_dpm_clk_table[] = {
static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = {
{ .major = 5, .min_minor = 7 },
- { .features = BIT_U64(AIE2_NPU_COMMAND), .min_minor = 8 },
+ { .features = BIT_U64(AIE2_NPU_COMMAND), .major = 5, .min_minor = 8 },
{ 0 }
};
static const struct amdxdna_dev_priv npu1_dev_priv = {
- .fw_path = "amdnpu/1502_00/npu.sbin",
+ .fw_path = "amdnpu/1502_00/",
.rt_config = npu1_default_rt_cfg,
.dpm_clk_tbl = npu1_dpm_clk_table,
.fw_feature_tbl = npu1_fw_feature_table,
diff --git a/drivers/accel/amdxdna/npu4_regs.c b/drivers/accel/amdxdna/npu4_regs.c
index a8d6f76dde5f..ce25eef5fc34 100644
--- a/drivers/accel/amdxdna/npu4_regs.c
+++ b/drivers/accel/amdxdna/npu4_regs.c
@@ -98,7 +98,7 @@ const struct aie2_fw_feature_tbl npu4_fw_feature_table[] = {
};
static const struct amdxdna_dev_priv npu4_dev_priv = {
- .fw_path = "amdnpu/17f0_10/npu.sbin",
+ .fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,
diff --git a/drivers/accel/amdxdna/npu5_regs.c b/drivers/accel/amdxdna/npu5_regs.c
index c0a35cfd886c..c0ac5daf32ee 100644
--- a/drivers/accel/amdxdna/npu5_regs.c
+++ b/drivers/accel/amdxdna/npu5_regs.c
@@ -63,7 +63,7 @@
#define NPU5_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu5_dev_priv = {
- .fw_path = "amdnpu/17f0_11/npu.sbin",
+ .fw_path = "amdnpu/17f0_11/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,
diff --git a/drivers/accel/amdxdna/npu6_regs.c b/drivers/accel/amdxdna/npu6_regs.c
index 1fb07df99186..ce591ed0d483 100644
--- a/drivers/accel/amdxdna/npu6_regs.c
+++ b/drivers/accel/amdxdna/npu6_regs.c
@@ -63,7 +63,7 @@
#define NPU6_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu6_dev_priv = {
- .fw_path = "amdnpu/17f0_10/npu.sbin",
+ .fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,
diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c
index 4fbd4bbf2909..7994e7073903 100644
--- a/drivers/accel/ethosu/ethosu_gem.c
+++ b/drivers/accel/ethosu/ethosu_gem.c
@@ -154,7 +154,7 @@ static void cmd_state_init(struct cmd_state *st)
static u64 cmd_to_addr(u32 *cmd)
{
- return ((u64)((cmd[0] & 0xff0000) << 16)) | cmd[1];
+ return (((u64)cmd[0] & 0xff0000) << 16) | cmd[1];
}
static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
@@ -245,11 +245,14 @@ static int calc_sizes(struct drm_device *ddev,
((st->ifm.stride_kernel >> 1) & 0x1) + 1;
u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) +
(st->ifm.stride_kernel & 0x1) + 1;
- u32 ifm_height = st->ofm.height[2] * stride_y +
+ s32 ifm_height = st->ofm.height[2] * stride_y +
st->ifm.height[2] - (st->ifm.pad_top + st->ifm.pad_bottom);
- u32 ifm_width = st->ofm.width * stride_x +
+ s32 ifm_width = st->ofm.width * stride_x +
st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right);
+ if (ifm_height < 0 || ifm_width < 0)
+ return -EINVAL;
+
len = feat_matrix_length(info, &st->ifm, ifm_width,
ifm_height, st->ifm.depth);
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
@@ -417,7 +420,10 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return ret;
break;
case NPU_OP_ELEMENTWISE:
- use_ifm2 = !((st.ifm2.broadcast == 8) || (param == 5) ||
+ use_scale = ethosu_is_u65(edev) ?
+ (st.ifm2.broadcast & 0x80) :
+ (st.ifm2.broadcast == 8);
+ use_ifm2 = !(use_scale || (param == 5) ||
(param == 6) || (param == 7) || (param == 0x24));
use_ifm = st.ifm.broadcast != 8;
ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2);
diff --git a/drivers/accel/ethosu/ethosu_job.c b/drivers/accel/ethosu/ethosu_job.c
index 8598a3634340..ec85f4156744 100644
--- a/drivers/accel/ethosu/ethosu_job.c
+++ b/drivers/accel/ethosu/ethosu_job.c
@@ -143,23 +143,29 @@ out:
return ret;
}
+static void ethosu_job_err_cleanup(struct ethosu_job *job)
+{
+ unsigned int i;
+
+ for (i = 0; i < job->region_cnt; i++)
+ drm_gem_object_put(job->region_bo[i]);
+
+ drm_gem_object_put(job->cmd_bo);
+
+ kfree(job);
+}
+
static void ethosu_job_cleanup(struct kref *ref)
{
struct ethosu_job *job = container_of(ref, struct ethosu_job,
refcount);
- unsigned int i;
pm_runtime_put_autosuspend(job->dev->base.dev);
dma_fence_put(job->done_fence);
dma_fence_put(job->inference_done_fence);
- for (i = 0; i < job->region_cnt; i++)
- drm_gem_object_put(job->region_bo[i]);
-
- drm_gem_object_put(job->cmd_bo);
-
- kfree(job);
+ ethosu_job_err_cleanup(job);
}
static void ethosu_job_put(struct ethosu_job *job)
@@ -454,12 +460,16 @@ static int ethosu_ioctl_submit_job(struct drm_device *dev, struct drm_file *file
}
}
ret = ethosu_job_push(ejob);
+ if (!ret) {
+ ethosu_job_put(ejob);
+ return 0;
+ }
out_cleanup_job:
if (ret)
drm_sched_job_cleanup(&ejob->base);
out_put_job:
- ethosu_job_put(ejob);
+ ethosu_job_err_cleanup(ejob);
return ret;
}
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index 5f70b196e0aa..6c9b5bf7d392 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -379,8 +379,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_CPC", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */
- PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0,
- 0, 0, 0),
+ PACKAGE_INFO(ACPI_PTYPE1_VAR,
+ ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER |
+ ACPI_RTYPE_PACKAGE, 0, 0, 0, 0),
{{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index f2579611e0a5..aa55ecfc2923 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1457,15 +1457,6 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
return 0;
/*
- * Skip devices whose ACPI companions don't support power management and
- * don't have a wakeup GPE.
- */
- if (!acpi_device_power_manageable(adev) && !acpi_device_can_wakeup(adev)) {
- dev_dbg(dev, "No ACPI power management or wakeup GPE\n");
- return 0;
- }
-
- /*
* Only attach the power domain to the first device if the
* companion is shared by multiple. This is to prevent doing power
* management twice.
diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c
index f2c943b934be..9470f1830ff5 100644
--- a/drivers/acpi/osi.c
+++ b/drivers/acpi/osi.c
@@ -390,6 +390,19 @@ static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = {
},
/*
+ * The screen backlight turns off during udev device creation
+ * when returning true for _OSI("Windows 2009")
+ */
+ {
+ .callback = dmi_disable_osi_win7,
+ .ident = "Acer Aspire One D255",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AOD255"),
+ },
+ },
+
+ /*
* The wireless hotkey does not work on those machines when
* returning true for _OSI("Windows 2012")
*/
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 66ec81e306d4..132a9df98471 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -386,6 +386,14 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "80E1"),
},
},
+ {
+ .callback = init_nvs_save_s3,
+ .ident = "Lenovo G70-35",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "80Q5"),
+ },
+ },
/*
* ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using
* the Low Power S0 Idle firmware interface (see
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 11909417f017..6c4e567b6582 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4189,6 +4189,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
ATA_QUIRK_FIRMWARE_WARN },
/* Seagate disks with LPM issues */
+ { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM },
{ "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM },
/* drives which fail FPDMA_AA activation (some may freeze afterwards)
@@ -4231,6 +4232,7 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_QUIRK_BRIDGE_OK },
{ "BUFFALO HD-QSU2/R5", NULL, ATA_QUIRK_BRIDGE_OK },
+ { "QEMU HARDDISK", "2.5+", ATA_QUIRK_BRIDGE_OK },
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_QUIRK_1_5_GBPS },
@@ -6269,10 +6271,6 @@ static void ata_port_detach(struct ata_port *ap)
}
}
- /* Make sure the deferred qc work finished. */
- cancel_work_sync(&ap->deferred_qc_work);
- WARN_ON(ap->deferred_qc);
-
/* Tell EH to disable all devices */
ap->pflags |= ATA_PFLAG_UNLOADING;
ata_port_schedule_eh(ap);
@@ -6283,9 +6281,11 @@ static void ata_port_detach(struct ata_port *ap)
/* wait till EH commits suicide */
ata_port_wait_eh(ap);
- /* it better be dead now */
+ /* It better be dead now and not have any remaining deferred qc. */
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
+ WARN_ON(ap->deferred_qc);
+ cancel_work_sync(&ap->deferred_qc_work);
cancel_delayed_work_sync(&ap->hotplug_task);
cancel_delayed_work_sync(&ap->scsi_rescan_task);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 72a22b6c9682..23be85418b3b 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -640,12 +640,29 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
set_host_byte(scmd, DID_OK);
ata_qc_for_each_raw(ap, qc, i) {
- if (qc->flags & ATA_QCFLAG_ACTIVE &&
- qc->scsicmd == scmd)
+ if (qc->scsicmd != scmd)
+ continue;
+ if ((qc->flags & ATA_QCFLAG_ACTIVE) ||
+ qc == ap->deferred_qc)
break;
}
- if (i < ATA_MAX_QUEUE) {
+ if (i < ATA_MAX_QUEUE && qc == ap->deferred_qc) {
+ /*
+ * This is a deferred command that timed out while
+ * waiting for the command queue to drain. Since the qc
+ * is not active yet (deferred_qc is still set, so the
+ * deferred qc work has not issued the command yet),
+ * simply signal the timeout by finishing the SCSI
+ * command and clear the deferred qc to prevent the
+ * deferred qc work from issuing this qc.
+ */
+ WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE);
+ ap->deferred_qc = NULL;
+ cancel_work(&ap->deferred_qc_work);
+ set_host_byte(scmd, DID_TIME_OUT);
+ scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+ } else if (i < ATA_MAX_QUEUE) {
/* the scmd has an associated qc */
if (!(qc->flags & ATA_QCFLAG_EH)) {
/* which hasn't failed yet, timeout */
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index c0dd75a0287c..ad798e5246b4 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1699,6 +1699,7 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
scmd = qc->scsicmd;
ap->deferred_qc = NULL;
+ cancel_work(&ap->deferred_qc_work);
ata_qc_free(qc);
scmd->result = (DID_SOFT_ERROR << 16);
scsi_done(scmd);
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 79d031d2d845..1af95ac68b77 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -179,19 +179,10 @@ void device_release_driver_internal(struct device *dev, const struct device_driv
void driver_detach(const struct device_driver *drv);
void driver_deferred_probe_del(struct device *dev);
void device_set_deferred_probe_reason(const struct device *dev, struct va_format *vaf);
-static inline int driver_match_device_locked(const struct device_driver *drv,
- struct device *dev)
-{
- device_lock_assert(dev);
-
- return drv->bus->match ? drv->bus->match(dev, drv) : 1;
-}
-
static inline int driver_match_device(const struct device_driver *drv,
struct device *dev)
{
- guard(device)(dev);
- return driver_match_device_locked(drv, dev);
+ return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
static inline void dev_sync_state(struct device *dev)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 0354f209529c..bea8da5f8a3a 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -928,7 +928,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
bool async_allowed;
int ret;
- ret = driver_match_device_locked(drv, dev);
+ ret = driver_match_device(drv, dev);
if (ret == 0) {
/* no match */
return 0;
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 6a63860579dd..8d9a34be57fb 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -797,7 +797,18 @@ struct fwnode_handle *
fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
struct fwnode_handle *child)
{
- return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
+ struct fwnode_handle *next;
+
+ if (IS_ERR_OR_NULL(fwnode))
+ return NULL;
+
+ /* Try to find a child in primary fwnode */
+ next = fwnode_call_ptr_op(fwnode, get_next_child_node, child);
+ if (next)
+ return next;
+
+ /* When no more children in primary, continue with secondary */
+ return fwnode_call_ptr_op(fwnode->secondary, get_next_child_node, child);
}
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
@@ -841,19 +852,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
struct fwnode_handle *device_get_next_child_node(const struct device *dev,
struct fwnode_handle *child)
{
- const struct fwnode_handle *fwnode = dev_fwnode(dev);
- struct fwnode_handle *next;
-
- if (IS_ERR_OR_NULL(fwnode))
- return NULL;
-
- /* Try to find a child in primary fwnode */
- next = fwnode_get_next_child_node(fwnode, child);
- if (next)
- return next;
-
- /* When no more children in primary, continue with secondary */
- return fwnode_get_next_child_node(fwnode->secondary, child);
+ return fwnode_get_next_child_node(dev_fwnode(dev), child);
}
EXPORT_SYMBOL_GPL(device_get_next_child_node);
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 742b2908ff68..b3dbf6c76e98 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -483,38 +483,20 @@ void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i)
int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
{
- struct lru_cache *al = device->act_log;
/* for bios crossing activity log extent boundaries,
* we may need to activate two extents in one go */
unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
- unsigned nr_al_extents;
- unsigned available_update_slots;
unsigned enr;
- D_ASSERT(device, first <= last);
-
- nr_al_extents = 1 + last - first; /* worst case: all touched extends are cold. */
- available_update_slots = min(al->nr_elements - al->used,
- al->max_pending_changes - al->pending_changes);
-
- /* We want all necessary updates for a given request within the same transaction
- * We could first check how many updates are *actually* needed,
- * and use that instead of the worst-case nr_al_extents */
- if (available_update_slots < nr_al_extents) {
- /* Too many activity log extents are currently "hot".
- *
- * If we have accumulated pending changes already,
- * we made progress.
- *
- * If we cannot get even a single pending change through,
- * stop the fast path until we made some progress,
- * or requests to "cold" extents could be starved. */
- if (!al->pending_changes)
- __set_bit(__LC_STARVING, &device->act_log->flags);
- return -ENOBUFS;
+ if (i->partially_in_al_next_enr) {
+ D_ASSERT(device, first < i->partially_in_al_next_enr);
+ D_ASSERT(device, last >= i->partially_in_al_next_enr);
+ first = i->partially_in_al_next_enr;
}
+ D_ASSERT(device, first <= last);
+
/* Is resync active in this area? */
for (enr = first; enr <= last; enr++) {
struct lc_element *tmp;
@@ -529,14 +511,21 @@ int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *
}
}
- /* Checkout the refcounts.
- * Given that we checked for available elements and update slots above,
- * this has to be successful. */
+ /* Try to checkout the refcounts. */
for (enr = first; enr <= last; enr++) {
struct lc_element *al_ext;
al_ext = lc_get_cumulative(device->act_log, enr);
- if (!al_ext)
- drbd_info(device, "LOGIC BUG for enr=%u\n", enr);
+
+ if (!al_ext) {
+ /* Did not work. We may have exhausted the possible
+ * changes per transaction. Or raced with someone
+ * "locking" it against changes.
+ * Remember where to continue from.
+ */
+ if (enr > first)
+ i->partially_in_al_next_enr = enr;
+ return -ENOBUFS;
+ }
}
return 0;
}
@@ -556,7 +545,11 @@ void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i)
for (enr = first; enr <= last; enr++) {
extent = lc_find(device->act_log, enr);
- if (!extent) {
+ /* Yes, this masks a bug elsewhere. However, during normal
+ * operation this is harmless, so no need to crash the kernel
+ * by the BUG_ON(refcount == 0) in lc_put().
+ */
+ if (!extent || extent->refcnt == 0) {
drbd_err(device, "al_complete_io() called on inactive extent %u\n", enr);
continue;
}
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h
index 366489b72fe9..5d3213b81eed 100644
--- a/drivers/block/drbd/drbd_interval.h
+++ b/drivers/block/drbd/drbd_interval.h
@@ -8,12 +8,15 @@
struct drbd_interval {
struct rb_node rb;
sector_t sector; /* start sector of the interval */
- unsigned int size; /* size in bytes */
sector_t end; /* highest interval end in subtree */
+ unsigned int size; /* size in bytes */
unsigned int local:1 /* local or remote request? */;
unsigned int waiting:1; /* someone is waiting for completion */
unsigned int completed:1; /* this has been completed already;
* ignore for conflict detection */
+
+ /* to resume a partially successful drbd_al_begin_io_nonblock(); */
+ unsigned int partially_in_al_next_enr;
};
static inline void drbd_clear_interval(struct drbd_interval *i)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index b8f0eddf7e87..200d464e984b 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -32,6 +32,7 @@
#include <linux/memcontrol.h>
#include <linux/mm_inline.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/random.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
@@ -732,9 +733,9 @@ int drbd_send_sync_param(struct drbd_peer_device *peer_device)
}
if (apv >= 88)
- strcpy(p->verify_alg, nc->verify_alg);
+ strscpy(p->verify_alg, nc->verify_alg);
if (apv >= 89)
- strcpy(p->csums_alg, nc->csums_alg);
+ strscpy(p->csums_alg, nc->csums_alg);
rcu_read_unlock();
return drbd_send_command(peer_device, sock, cmd, size, NULL, 0);
@@ -745,6 +746,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
struct drbd_socket *sock;
struct p_protocol *p;
struct net_conf *nc;
+ size_t integrity_alg_len;
int size, cf;
sock = &connection->data;
@@ -762,8 +764,10 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
}
size = sizeof(*p);
- if (connection->agreed_pro_version >= 87)
- size += strlen(nc->integrity_alg) + 1;
+ if (connection->agreed_pro_version >= 87) {
+ integrity_alg_len = strlen(nc->integrity_alg) + 1;
+ size += integrity_alg_len;
+ }
p->protocol = cpu_to_be32(nc->wire_protocol);
p->after_sb_0p = cpu_to_be32(nc->after_sb_0p);
@@ -778,7 +782,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
p->conn_flags = cpu_to_be32(cf);
if (connection->agreed_pro_version >= 87)
- strcpy(p->integrity_alg, nc->integrity_alg);
+ strscpy(p->integrity_alg, nc->integrity_alg, integrity_alg_len);
rcu_read_unlock();
return __conn_send_command(connection, sock, cmd, size, NULL, 0);
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 3cfef456a1f3..58b95bf4bdca 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -3801,14 +3801,14 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i
*new_net_conf = *old_net_conf;
if (verify_tfm) {
- strcpy(new_net_conf->verify_alg, p->verify_alg);
+ strscpy(new_net_conf->verify_alg, p->verify_alg);
new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1;
crypto_free_shash(peer_device->connection->verify_tfm);
peer_device->connection->verify_tfm = verify_tfm;
drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg);
}
if (csums_tfm) {
- strcpy(new_net_conf->csums_alg, p->csums_alg);
+ strscpy(new_net_conf->csums_alg, p->csums_alg);
new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1;
crypto_free_shash(peer_device->connection->csums_tfm);
peer_device->connection->csums_tfm = csums_tfm;
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index d15826f6ee81..70f75ef07945 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -621,7 +621,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
break;
case READ_COMPLETED_WITH_ERROR:
- drbd_set_out_of_sync(peer_device, req->i.sector, req->i.size);
+ drbd_set_out_of_sync(first_peer_device(device),
+ req->i.sector, req->i.size);
drbd_report_io_error(device, req);
__drbd_chk_io_error(device, DRBD_READ_ERROR);
fallthrough;
diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c
index 65a40266437c..51c043342127 100644
--- a/drivers/block/zloop.c
+++ b/drivers/block/zloop.c
@@ -542,6 +542,21 @@ out:
zloop_put_cmd(cmd);
}
+/*
+ * Sync the entire FS containing the zone files instead of walking all files.
+ */
+static int zloop_flush(struct zloop_device *zlo)
+{
+ struct super_block *sb = file_inode(zlo->data_dir)->i_sb;
+ int ret;
+
+ down_read(&sb->s_umount);
+ ret = sync_filesystem(sb);
+ up_read(&sb->s_umount);
+
+ return ret;
+}
+
static void zloop_handle_cmd(struct zloop_cmd *cmd)
{
struct request *rq = blk_mq_rq_from_pdu(cmd);
@@ -562,11 +577,7 @@ static void zloop_handle_cmd(struct zloop_cmd *cmd)
zloop_rw(cmd);
return;
case REQ_OP_FLUSH:
- /*
- * Sync the entire FS containing the zone files instead of
- * walking all files
- */
- cmd->ret = sync_filesystem(file_inode(zlo->data_dir)->i_sb);
+ cmd->ret = zloop_flush(zlo);
break;
case REQ_OP_ZONE_RESET:
cmd->ret = zloop_reset_zone(zlo, rq_zone_no(rq));
@@ -981,7 +992,8 @@ static int zloop_ctl_add(struct zloop_options *opts)
struct queue_limits lim = {
.max_hw_sectors = SZ_1M >> SECTOR_SHIFT,
.chunk_sectors = opts->zone_size,
- .features = BLK_FEAT_ZONED,
+ .features = BLK_FEAT_ZONED | BLK_FEAT_WRITE_CACHE,
+
};
unsigned int nr_zones, i, j;
struct zloop_device *zlo;
@@ -1162,7 +1174,12 @@ static int zloop_ctl_remove(struct zloop_options *opts)
int ret;
if (!(opts->mask & ZLOOP_OPT_ID)) {
- pr_err("No ID specified\n");
+ pr_err("No ID specified for remove\n");
+ return -EINVAL;
+ }
+
+ if (opts->mask & ~ZLOOP_OPT_ID) {
+ pr_err("Invalid option specified for remove\n");
return -EINVAL;
}
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 5b02e7c3f56d..bb9f002aa85e 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2046,19 +2046,23 @@ retry:
}
out:
- if (ret && retries < MAX_INIT_RETRIES) {
- bt_dev_warn(hdev, "Retry BT power ON:%d", retries);
+ if (ret) {
qca_power_shutdown(hu);
- if (hu->serdev) {
- serdev_device_close(hu->serdev);
- ret = serdev_device_open(hu->serdev);
- if (ret) {
- bt_dev_err(hdev, "failed to open port");
- return ret;
+
+ if (retries < MAX_INIT_RETRIES) {
+ bt_dev_warn(hdev, "Retry BT power ON:%d", retries);
+ if (hu->serdev) {
+ serdev_device_close(hu->serdev);
+ ret = serdev_device_open(hu->serdev);
+ if (ret) {
+ bt_dev_err(hdev, "failed to open port");
+ return ret;
+ }
}
+ retries++;
+ goto retry;
}
- retries++;
- goto retry;
+ return ret;
}
/* Setup bdaddr */
diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c
index 3a51e58b2487..28818952a7a4 100644
--- a/drivers/char/ipmi/ipmi_ipmb.c
+++ b/drivers/char/ipmi/ipmi_ipmb.c
@@ -202,11 +202,16 @@ static int ipmi_ipmb_slave_cb(struct i2c_client *client,
break;
case I2C_SLAVE_READ_REQUESTED:
+ *val = 0xff;
+ ipmi_ipmb_check_msg_done(iidev);
+ break;
+
case I2C_SLAVE_STOP:
ipmi_ipmb_check_msg_done(iidev);
break;
case I2C_SLAVE_READ_PROCESSED:
+ *val = 0xff;
break;
}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index c530966c4e07..c41f51c82edd 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -602,6 +602,22 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
static int __scan_channels(struct ipmi_smi *intf,
struct ipmi_device_id *id, bool rescan);
+static void ipmi_lock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
+ unsigned long *flags)
+{
+ if (run_to_completion)
+ return;
+ spin_lock_irqsave(&intf->xmit_msgs_lock, *flags);
+}
+
+static void ipmi_unlock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
+ unsigned long *flags)
+{
+ if (run_to_completion)
+ return;
+ spin_unlock_irqrestore(&intf->xmit_msgs_lock, *flags);
+}
+
static void free_ipmi_user(struct kref *ref)
{
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
@@ -1869,21 +1885,32 @@ static struct ipmi_smi_msg *smi_add_send_msg(struct ipmi_smi *intf,
return smi_msg;
}
-static void smi_send(struct ipmi_smi *intf,
+static int smi_send(struct ipmi_smi *intf,
const struct ipmi_smi_handlers *handlers,
struct ipmi_smi_msg *smi_msg, int priority)
{
int run_to_completion = READ_ONCE(intf->run_to_completion);
unsigned long flags = 0;
+ int rv = 0;
- if (!run_to_completion)
- spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+ ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
smi_msg = smi_add_send_msg(intf, smi_msg, priority);
- if (!run_to_completion)
- spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+ ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
- if (smi_msg)
- handlers->sender(intf->send_info, smi_msg);
+ if (smi_msg) {
+ rv = handlers->sender(intf->send_info, smi_msg);
+ if (rv) {
+ ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
+ intf->curr_msg = NULL;
+ ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
+ /*
+ * Something may have been added to the transmit
+ * queue, so schedule a check for that.
+ */
+ queue_work(system_wq, &intf->smi_work);
+ }
+ }
+ return rv;
}
static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
@@ -2296,6 +2323,7 @@ static int i_ipmi_request(struct ipmi_user *user,
struct ipmi_recv_msg *recv_msg;
int run_to_completion = READ_ONCE(intf->run_to_completion);
int rv = 0;
+ bool in_seq_table = false;
if (supplied_recv) {
recv_msg = supplied_recv;
@@ -2349,33 +2377,50 @@ static int i_ipmi_request(struct ipmi_user *user,
rv = i_ipmi_req_ipmb(intf, addr, msgid, msg, smi_msg, recv_msg,
source_address, source_lun,
retries, retry_time_ms);
+ in_seq_table = true;
} else if (is_ipmb_direct_addr(addr)) {
rv = i_ipmi_req_ipmb_direct(intf, addr, msgid, msg, smi_msg,
recv_msg, source_lun);
} else if (is_lan_addr(addr)) {
rv = i_ipmi_req_lan(intf, addr, msgid, msg, smi_msg, recv_msg,
source_lun, retries, retry_time_ms);
+ in_seq_table = true;
} else {
- /* Unknown address type. */
+ /* Unknown address type. */
ipmi_inc_stat(intf, sent_invalid_commands);
rv = -EINVAL;
}
- if (rv) {
-out_err:
- if (!supplied_smi)
- ipmi_free_smi_msg(smi_msg);
- if (!supplied_recv)
- ipmi_free_recv_msg(recv_msg);
- } else {
+ if (!rv) {
dev_dbg(intf->si_dev, "Send: %*ph\n",
smi_msg->data_size, smi_msg->data);
- smi_send(intf, intf->handlers, smi_msg, priority);
+ rv = smi_send(intf, intf->handlers, smi_msg, priority);
+ if (rv != IPMI_CC_NO_ERROR)
+ /* smi_send() returns an IPMI err, return a Linux one. */
+ rv = -EIO;
+ if (rv && in_seq_table) {
+ /*
+ * If it's in the sequence table, it will be
+ * retried later, so ignore errors.
+ */
+ rv = 0;
+ /* But we need to fix the timeout. */
+ intf_start_seq_timer(intf, smi_msg->msgid);
+ ipmi_free_smi_msg(smi_msg);
+ smi_msg = NULL;
+ }
}
+out_err:
if (!run_to_completion)
mutex_unlock(&intf->users_mutex);
+ if (rv) {
+ if (!supplied_smi)
+ ipmi_free_smi_msg(smi_msg);
+ if (!supplied_recv)
+ ipmi_free_recv_msg(recv_msg);
+ }
return rv;
}
@@ -3949,12 +3994,12 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
msg->data_size, msg->data);
- smi_send(intf, intf->handlers, msg, 0);
- /*
- * We used the message, so return the value that
- * causes it to not be freed or queued.
- */
- rv = -1;
+ if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+ /*
+ * We used the message, so return the value that
+ * causes it to not be freed or queued.
+ */
+ rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
@@ -4028,12 +4073,12 @@ static int handle_ipmb_direct_rcv_cmd(struct ipmi_smi *intf,
msg->data[4] = IPMI_INVALID_CMD_COMPLETION_CODE;
msg->data_size = 5;
- smi_send(intf, intf->handlers, msg, 0);
- /*
- * We used the message, so return the value that
- * causes it to not be freed or queued.
- */
- rv = -1;
+ if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+ /*
+ * We used the message, so return the value that
+ * causes it to not be freed or queued.
+ */
+ rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
daddr = (struct ipmi_ipmb_direct_addr *)&recv_msg->addr;
@@ -4173,7 +4218,7 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{
struct cmd_rcvr *rcvr;
- int rv = 0;
+ int rv = 0; /* Free by default */
unsigned char netfn;
unsigned char cmd;
unsigned char chan;
@@ -4226,12 +4271,12 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
msg->data_size, msg->data);
- smi_send(intf, intf->handlers, msg, 0);
- /*
- * We used the message, so return the value that
- * causes it to not be freed or queued.
- */
- rv = -1;
+ if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+ /*
+ * We used the message, so return the value that
+ * causes it to not be freed or queued.
+ */
+ rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr;
@@ -4824,8 +4869,7 @@ static void smi_work(struct work_struct *t)
* message delivery.
*/
restart:
- if (!run_to_completion)
- spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+ ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
if (intf->curr_msg == NULL && !intf->in_shutdown) {
struct list_head *entry = NULL;
@@ -4841,8 +4885,7 @@ restart:
intf->curr_msg = newmsg;
}
}
- if (!run_to_completion)
- spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+ ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
if (newmsg) {
cc = intf->handlers->sender(intf->send_info, newmsg);
@@ -4850,8 +4893,11 @@ restart:
if (newmsg->recv_msg)
deliver_err_response(intf,
newmsg->recv_msg, cc);
- else
- ipmi_free_smi_msg(newmsg);
+ ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
+ intf->curr_msg = NULL;
+ ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
+ ipmi_free_smi_msg(newmsg);
+ newmsg = NULL;
goto restart;
}
}
@@ -4919,16 +4965,14 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf,
spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
flags);
- if (!run_to_completion)
- spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+ ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
/*
* We can get an asynchronous event or receive message in addition
* to commands we send.
*/
if (msg == intf->curr_msg)
intf->curr_msg = NULL;
- if (!run_to_completion)
- spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+ ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
if (run_to_completion)
smi_work(&intf->smi_work);
@@ -5041,7 +5085,12 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
ipmi_inc_stat(intf,
retransmitted_ipmb_commands);
- smi_send(intf, intf->handlers, smi_msg, 0);
+ /* If this fails we'll retry later or timeout. */
+ if (smi_send(intf, intf->handlers, smi_msg, 0) != IPMI_CC_NO_ERROR) {
+ /* But fix the timeout. */
+ intf_start_seq_timer(intf, smi_msg->msgid);
+ ipmi_free_smi_msg(smi_msg);
+ }
} else
ipmi_free_smi_msg(smi_msg);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 6bdf624c37ce..4a9e9de4d684 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -809,6 +809,12 @@ restart:
*/
return_hosed_msg(smi_info, IPMI_BUS_ERR);
}
+ if (smi_info->waiting_msg != NULL) {
+ /* Also handle if there was a message waiting. */
+ smi_info->curr_msg = smi_info->waiting_msg;
+ smi_info->waiting_msg = NULL;
+ return_hosed_msg(smi_info, IPMI_BUS_ERR);
+ }
smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_HOSED);
goto out;
}
@@ -918,9 +924,14 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
{
struct smi_info *smi_info = send_info;
unsigned long flags;
+ int rv = IPMI_CC_NO_ERROR;
debug_timestamp(smi_info, "Enqueue");
+ /*
+ * Check here for run to completion mode. A check under lock is
+ * later.
+ */
if (smi_info->si_state == SI_HOSED)
return IPMI_BUS_ERR;
@@ -934,18 +945,15 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
}
spin_lock_irqsave(&smi_info->si_lock, flags);
- /*
- * The following two lines don't need to be under the lock for
- * the lock's sake, but they do need SMP memory barriers to
- * avoid getting things out of order. We are already claiming
- * the lock, anyway, so just do it under the lock to avoid the
- * ordering problem.
- */
- BUG_ON(smi_info->waiting_msg);
- smi_info->waiting_msg = msg;
- check_start_timer_thread(smi_info);
+ if (smi_info->si_state == SI_HOSED) {
+ rv = IPMI_BUS_ERR;
+ } else {
+ BUG_ON(smi_info->waiting_msg);
+ smi_info->waiting_msg = msg;
+ check_start_timer_thread(smi_info);
+ }
spin_unlock_irqrestore(&smi_info->si_lock, flags);
- return IPMI_CC_NO_ERROR;
+ return rv;
}
static void set_run_to_completion(void *send_info, bool i_run_to_completion)
@@ -1113,7 +1121,9 @@ static void smi_timeout(struct timer_list *t)
* SI_USEC_PER_JIFFY);
smi_result = smi_event_handler(smi_info, time_diff);
- if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
+ if (smi_info->si_state == SI_HOSED) {
+ timeout = jiffies + SI_TIMEOUT_HOSED;
+ } else if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
/* Running with interrupts, only do long timeouts. */
timeout = jiffies + SI_TIMEOUT_JIFFIES;
smi_inc_stat(smi_info, long_timeouts);
@@ -2226,7 +2236,8 @@ static void wait_msg_processed(struct smi_info *smi_info)
unsigned long jiffies_now;
long time_diff;
- while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
+ while (smi_info->si_state != SI_HOSED &&
+ (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL))) {
jiffies_now = jiffies;
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
* SI_USEC_PER_JIFFY);
diff --git a/drivers/char/ipmi/ipmi_si_ls2k.c b/drivers/char/ipmi/ipmi_si_ls2k.c
index 45442c257efd..4c1da80f256c 100644
--- a/drivers/char/ipmi/ipmi_si_ls2k.c
+++ b/drivers/char/ipmi/ipmi_si_ls2k.c
@@ -168,7 +168,7 @@ static void ipmi_ls2k_remove(struct platform_device *pdev)
ipmi_si_remove_by_dev(&pdev->dev);
}
-struct platform_driver ipmi_ls2k_platform_driver = {
+static struct platform_driver ipmi_ls2k_platform_driver = {
.driver = {
.name = "ls2k-ipmi-si",
},
diff --git a/drivers/char/random.c b/drivers/char/random.c
index dcd002e1b890..7ff4d29911fd 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -96,8 +96,7 @@ static ATOMIC_NOTIFIER_HEAD(random_ready_notifier);
/* Control how we warn userspace. */
static struct ratelimit_state urandom_warning =
RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_RELEASE);
-static int ratelimit_disable __read_mostly =
- IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
+static int ratelimit_disable __read_mostly = 0;
module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
@@ -168,12 +167,6 @@ int __cold execute_with_initialized_rng(struct notifier_block *nb)
return ret;
}
-#define warn_unseeded_randomness() \
- if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
- printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
- __func__, (void *)_RET_IP_, crng_init)
-
-
/*********************************************************************
*
* Fast key erasure RNG, the "crng".
@@ -434,7 +427,6 @@ static void _get_random_bytes(void *buf, size_t len)
*/
void get_random_bytes(void *buf, size_t len)
{
- warn_unseeded_randomness();
_get_random_bytes(buf, len);
}
EXPORT_SYMBOL(get_random_bytes);
@@ -523,8 +515,6 @@ type get_random_ ##type(void) \
struct batch_ ##type *batch; \
unsigned long next_gen; \
\
- warn_unseeded_randomness(); \
- \
if (!crng_ready()) { \
_get_random_bytes(&ret, sizeof(ret)); \
return ret; \
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
index 3ae162625bb1..c781425a005e 100644
--- a/drivers/clk/imx/clk-imx8qxp.c
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -346,7 +346,29 @@ static struct platform_driver imx8qxp_clk_driver = {
},
.probe = imx8qxp_clk_probe,
};
-module_platform_driver(imx8qxp_clk_driver);
+
+static int __init imx8qxp_clk_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&imx8qxp_clk_driver);
+ if (ret)
+ return ret;
+
+ ret = imx_clk_scu_module_init();
+ if (ret)
+ platform_driver_unregister(&imx8qxp_clk_driver);
+
+ return ret;
+}
+module_init(imx8qxp_clk_init);
+
+static void __exit imx8qxp_clk_exit(void)
+{
+ imx_clk_scu_module_exit();
+ platform_driver_unregister(&imx8qxp_clk_driver);
+}
+module_exit(imx8qxp_clk_exit);
MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8QXP clock driver");
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 33e637ad3579..a85ec48a798b 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -191,6 +191,16 @@ static bool imx_scu_clk_is_valid(u32 rsrc_id)
return p != NULL;
}
+int __init imx_clk_scu_module_init(void)
+{
+ return platform_driver_register(&imx_clk_scu_driver);
+}
+
+void __exit imx_clk_scu_module_exit(void)
+{
+ return platform_driver_unregister(&imx_clk_scu_driver);
+}
+
int imx_clk_scu_init(struct device_node *np,
const struct imx_clk_scu_rsrc_table *data)
{
@@ -215,7 +225,7 @@ int imx_clk_scu_init(struct device_node *np,
rsrc_table = data;
}
- return platform_driver_register(&imx_clk_scu_driver);
+ return 0;
}
/*
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index af7b697f51ca..ca82f2cce897 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -25,6 +25,8 @@ extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl;
extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp;
extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm;
+int __init imx_clk_scu_module_init(void);
+void __exit imx_clk_scu_module_exit(void);
int imx_clk_scu_init(struct device_node *np,
const struct imx_clk_scu_rsrc_table *data);
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index a48af3540c74..11c58af41900 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1476,13 +1476,13 @@ static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,
refresh_frequency_limits(policy);
}
-static bool intel_pstate_update_max_freq(struct cpudata *cpudata)
+static bool intel_pstate_update_max_freq(int cpu)
{
- struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
if (!policy)
return false;
- __intel_pstate_update_max_freq(policy, cpudata);
+ __intel_pstate_update_max_freq(policy, all_cpu_data[cpu]);
return true;
}
@@ -1501,7 +1501,7 @@ static void intel_pstate_update_limits_for_all(void)
int cpu;
for_each_possible_cpu(cpu)
- intel_pstate_update_max_freq(all_cpu_data[cpu]);
+ intel_pstate_update_max_freq(cpu);
mutex_lock(&hybrid_capacity_lock);
@@ -1647,8 +1647,8 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type)
{
struct cpudata *cpudata = all_cpu_data[cpu];
- unsigned int freq = cpudata->pstate.turbo_freq;
struct freq_qos_request *req;
+ unsigned int freq;
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
if (!policy)
@@ -1661,6 +1661,8 @@ static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type)
if (hwp_active)
intel_pstate_get_hwp_cap(cpudata);
+ freq = cpudata->pstate.turbo_freq;
+
if (type == FREQ_QOS_MIN) {
freq = DIV_ROUND_UP(freq * global.min_perf_pct, 100);
} else {
@@ -1908,7 +1910,7 @@ static void intel_pstate_notify_work(struct work_struct *work)
struct cpudata *cpudata =
container_of(to_delayed_work(work), struct cpudata, hwp_notify_work);
- if (intel_pstate_update_max_freq(cpudata)) {
+ if (intel_pstate_update_max_freq(cpudata->cpu)) {
/*
* The driver will not be unregistered while this function is
* running, so update the capacity without acquiring the driver
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 8adc7fe71c04..98d1023007e3 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -52,9 +52,10 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
rng->priv = 0;
} else {
work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
- if (!work_data)
+ if (!work_data) {
+ atomic_dec(&i2c_priv->tfm_count);
return -ENOMEM;
-
+ }
work_data->ctx = i2c_priv;
work_data->client = i2c_priv->client;
diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-tsm.c
index adc9542ae806..b07ae529b591 100644
--- a/drivers/crypto/ccp/sev-dev-tsm.c
+++ b/drivers/crypto/ccp/sev-dev-tsm.c
@@ -378,9 +378,9 @@ void sev_tsm_init_locked(struct sev_device *sev, void *tio_status_page)
return;
error_exit:
- kfree(t);
pr_err("Failed to enable SEV-TIO: ret=%d en=%d initdone=%d SEV=%d\n",
ret, t->tio_en, t->tio_init_done, boot_cpu_has(X86_FEATURE_SEV));
+ kfree(t);
}
void sev_tsm_uninit(struct sev_device *sev)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 096f993974d1..8b2dfc11289b 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1105,15 +1105,12 @@ struct page *snp_alloc_hv_fixed_pages(unsigned int num_2mb_pages)
{
struct psp_device *psp_master = psp_get_master_device();
struct snp_hv_fixed_pages_entry *entry;
- struct sev_device *sev;
unsigned int order;
struct page *page;
- if (!psp_master || !psp_master->sev_data)
+ if (!psp_master)
return NULL;
- sev = psp_master->sev_data;
-
order = get_order(PMD_SIZE * num_2mb_pages);
/*
@@ -1126,7 +1123,8 @@ struct page *snp_alloc_hv_fixed_pages(unsigned int num_2mb_pages)
* This API uses SNP_INIT_EX to transition allocated pages to HV_Fixed
* page state, fail if SNP is already initialized.
*/
- if (sev->snp_initialized)
+ if (psp_master->sev_data &&
+ ((struct sev_device *)psp_master->sev_data)->snp_initialized)
return NULL;
/* Re-use freed pages that match the request */
@@ -1162,7 +1160,7 @@ void snp_free_hv_fixed_pages(struct page *page)
struct psp_device *psp_master = psp_get_master_device();
struct snp_hv_fixed_pages_entry *entry, *nentry;
- if (!psp_master || !psp_master->sev_data)
+ if (!psp_master)
return;
/*
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 007b8aff0238..5b0570df0fd9 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -152,6 +152,24 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);
int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
struct access_coordinate *c);
+static inline struct device *port_to_host(struct cxl_port *port)
+{
+ struct cxl_port *parent = is_cxl_root(port) ? NULL :
+ to_cxl_port(port->dev.parent);
+
+ /*
+ * The host of CXL root port and the first level of ports is
+ * the platform firmware device, the host of all other ports
+ * is their parent port.
+ */
+ if (!parent)
+ return port->uport_dev;
+ else if (is_cxl_root(parent))
+ return parent->uport_dev;
+ else
+ return &parent->dev;
+}
+
static inline struct device *dport_to_host(struct cxl_dport *dport)
{
struct cxl_port *port = dport->port;
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index e3f0c39e6812..c222e98ae736 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -904,7 +904,7 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld)
if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
return;
- if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags))
+ if (cxld->flags & CXL_DECODER_F_LOCK)
return;
if (port->commit_end == id)
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index fa6dd0c94656..e7a6452bf544 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -311,6 +311,7 @@ static bool cxl_mem_raw_command_allowed(u16 opcode)
* cxl_payload_from_user_allowed() - Check contents of in_payload.
* @opcode: The mailbox command opcode.
* @payload_in: Pointer to the input payload passed in from user space.
+ * @in_size: Size of @payload_in in bytes.
*
* Return:
* * true - payload_in passes check for @opcode.
@@ -325,12 +326,15 @@ static bool cxl_mem_raw_command_allowed(u16 opcode)
*
* The specific checks are determined by the opcode.
*/
-static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
+static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in,
+ size_t in_size)
{
switch (opcode) {
case CXL_MBOX_OP_SET_PARTITION_INFO: {
struct cxl_mbox_set_partition_info *pi = payload_in;
+ if (in_size < sizeof(*pi))
+ return false;
if (pi->flags & CXL_SET_PARTITION_IMMEDIATE_FLAG)
return false;
break;
@@ -338,6 +342,8 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
case CXL_MBOX_OP_CLEAR_LOG: {
const uuid_t *uuid = (uuid_t *)payload_in;
+ if (in_size < sizeof(uuid_t))
+ return false;
/*
* Restrict the ‘Clear log’ action to only apply to
* Vendor debug logs.
@@ -365,7 +371,8 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd,
if (IS_ERR(mbox_cmd->payload_in))
return PTR_ERR(mbox_cmd->payload_in);
- if (!cxl_payload_from_user_allowed(opcode, mbox_cmd->payload_in)) {
+ if (!cxl_payload_from_user_allowed(opcode, mbox_cmd->payload_in,
+ in_size)) {
dev_dbg(cxl_mbox->host, "%s: input payload not allowed\n",
cxl_mem_opcode_to_name(opcode));
kvfree(mbox_cmd->payload_in);
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index f547d8ac34c7..273c22118d3d 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -1089,10 +1089,8 @@ static int cxlmd_add(struct cxl_memdev *cxlmd, struct cxl_dev_state *cxlds)
DEFINE_FREE(put_cxlmd, struct cxl_memdev *,
if (!IS_ERR_OR_NULL(_T)) put_device(&_T->dev))
-static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
+static bool cxl_memdev_attach_failed(struct cxl_memdev *cxlmd)
{
- int rc;
-
/*
* If @attach is provided fail if the driver is not attached upon
* return. Note that failure here could be the result of a race to
@@ -1100,7 +1098,14 @@ static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
* succeeded and then cxl_mem unbound before the lock is acquired.
*/
guard(device)(&cxlmd->dev);
- if (cxlmd->attach && !cxlmd->dev.driver) {
+ return (cxlmd->attach && !cxlmd->dev.driver);
+}
+
+static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
+{
+ int rc;
+
+ if (cxl_memdev_attach_failed(cxlmd)) {
cxl_memdev_unregister(cxlmd);
return ERR_PTR(-ENXIO);
}
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index 3c6e76721522..68462e38a977 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -115,15 +115,17 @@ static void unregister_nvb(void *_cxl_nvb)
device_unregister(&cxl_nvb->dev);
}
-/**
- * devm_cxl_add_nvdimm_bridge() - add the root of a LIBNVDIMM topology
- * @host: platform firmware root device
- * @port: CXL port at the root of a CXL topology
- *
- * Return: bridge device that can host cxl_nvdimm objects
- */
-struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
- struct cxl_port *port)
+static bool cxl_nvdimm_bridge_failed_attach(struct cxl_nvdimm_bridge *cxl_nvb)
+{
+ struct device *dev = &cxl_nvb->dev;
+
+ guard(device)(dev);
+ /* If the device has no driver, then it failed to attach. */
+ return dev->driver == NULL;
+}
+
+struct cxl_nvdimm_bridge *__devm_cxl_add_nvdimm_bridge(struct device *host,
+ struct cxl_port *port)
{
struct cxl_nvdimm_bridge *cxl_nvb;
struct device *dev;
@@ -145,6 +147,11 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
if (rc)
goto err;
+ if (cxl_nvdimm_bridge_failed_attach(cxl_nvb)) {
+ unregister_nvb(cxl_nvb);
+ return ERR_PTR(-ENODEV);
+ }
+
rc = devm_add_action_or_reset(host, unregister_nvb, cxl_nvb);
if (rc)
return ERR_PTR(rc);
@@ -155,7 +162,7 @@ err:
put_device(dev);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, "CXL");
+EXPORT_SYMBOL_FOR_MODULES(__devm_cxl_add_nvdimm_bridge, "cxl_pmem");
static void cxl_nvdimm_release(struct device *dev)
{
@@ -255,6 +262,21 @@ int devm_cxl_add_nvdimm(struct device *host, struct cxl_port *port,
if (!cxl_nvb)
return -ENODEV;
+ /*
+ * Take the uport_dev lock to guard against race of nvdimm_bus object.
+ * cxl_acpi_probe() registers the nvdimm_bus and is done under the
+ * root port uport_dev lock.
+ *
+ * Take the cxl_nvb device lock to ensure that cxl_nvb driver is in a
+ * consistent state. And the driver registers nvdimm_bus.
+ */
+ guard(device)(cxl_nvb->port->uport_dev);
+ guard(device)(&cxl_nvb->dev);
+ if (!cxl_nvb->nvdimm_bus) {
+ rc = -ENODEV;
+ goto err_alloc;
+ }
+
cxl_nvd = cxl_nvdimm_alloc(cxl_nvb, cxlmd);
if (IS_ERR(cxl_nvd)) {
rc = PTR_ERR(cxl_nvd);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index b69c2529744c..0c5957d1d329 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -615,22 +615,8 @@ struct cxl_port *parent_port_of(struct cxl_port *port)
static void unregister_port(void *_port)
{
struct cxl_port *port = _port;
- struct cxl_port *parent = parent_port_of(port);
- struct device *lock_dev;
- /*
- * CXL root port's and the first level of ports are unregistered
- * under the platform firmware device lock, all other ports are
- * unregistered while holding their parent port lock.
- */
- if (!parent)
- lock_dev = port->uport_dev;
- else if (is_cxl_root(parent))
- lock_dev = parent->uport_dev;
- else
- lock_dev = &parent->dev;
-
- device_lock_assert(lock_dev);
+ device_lock_assert(port_to_host(port));
port->dead = true;
device_unregister(&port->dev);
}
@@ -1427,20 +1413,11 @@ static struct device *grandparent(struct device *dev)
return NULL;
}
-static struct device *endpoint_host(struct cxl_port *endpoint)
-{
- struct cxl_port *port = to_cxl_port(endpoint->dev.parent);
-
- if (is_cxl_root(port))
- return port->uport_dev;
- return &port->dev;
-}
-
static void delete_endpoint(void *data)
{
struct cxl_memdev *cxlmd = data;
struct cxl_port *endpoint = cxlmd->endpoint;
- struct device *host = endpoint_host(endpoint);
+ struct device *host = port_to_host(endpoint);
scoped_guard(device, host) {
if (host->driver && !endpoint->dead) {
@@ -1456,7 +1433,7 @@ static void delete_endpoint(void *data)
int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
{
- struct device *host = endpoint_host(endpoint);
+ struct device *host = port_to_host(endpoint);
struct device *dev = &cxlmd->dev;
get_device(host);
@@ -1790,7 +1767,16 @@ static struct cxl_dport *find_or_add_dport(struct cxl_port *port,
{
struct cxl_dport *dport;
- device_lock_assert(&port->dev);
+ /*
+ * The port is already visible in CXL hierarchy, but it may still
+ * be in the process of binding to the CXL port driver at this point.
+ *
+ * port creation and driver binding are protected by the port's host
+ * lock, so acquire the host lock here to ensure the port has completed
+ * driver binding before proceeding with dport addition.
+ */
+ guard(device)(port_to_host(port));
+ guard(device)(&port->dev);
dport = cxl_find_dport_by_dev(port, dport_dev);
if (!dport) {
dport = probe_dport(port, dport_dev);
@@ -1857,13 +1843,11 @@ retry:
* RP port enumerated by cxl_acpi without dport will
* have the dport added here.
*/
- scoped_guard(device, &port->dev) {
- dport = find_or_add_dport(port, dport_dev);
- if (IS_ERR(dport)) {
- if (PTR_ERR(dport) == -EAGAIN)
- goto retry;
- return PTR_ERR(dport);
- }
+ dport = find_or_add_dport(port, dport_dev);
+ if (IS_ERR(dport)) {
+ if (PTR_ERR(dport) == -EAGAIN)
+ goto retry;
+ return PTR_ERR(dport);
}
rc = cxl_add_ep(dport, &cxlmd->dev);
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index fec37af1dfbf..42874948b589 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -1100,12 +1100,12 @@ static int cxl_rr_assign_decoder(struct cxl_port *port, struct cxl_region *cxlr,
static void cxl_region_setup_flags(struct cxl_region *cxlr,
struct cxl_decoder *cxld)
{
- if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags)) {
+ if (cxld->flags & CXL_DECODER_F_LOCK) {
set_bit(CXL_REGION_F_LOCK, &cxlr->flags);
clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
}
- if (test_bit(CXL_DECODER_F_NORMALIZED_ADDRESSING, &cxld->flags))
+ if (cxld->flags & CXL_DECODER_F_NORMALIZED_ADDRESSING)
set_bit(CXL_REGION_F_NORMALIZED_ADDRESSING, &cxlr->flags);
}
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 04c673e7cdb0..9b947286eb9b 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -574,11 +574,16 @@ struct cxl_nvdimm_bridge {
#define CXL_DEV_ID_LEN 19
+enum {
+ CXL_NVD_F_INVALIDATED = 0,
+};
+
struct cxl_nvdimm {
struct device dev;
struct cxl_memdev *cxlmd;
u8 dev_id[CXL_DEV_ID_LEN]; /* for nvdimm, string of 'serial' */
u64 dirty_shutdowns;
+ unsigned long flags;
};
struct cxl_pmem_region_mapping {
@@ -920,6 +925,8 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv);
struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev);
struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port);
+struct cxl_nvdimm_bridge *__devm_cxl_add_nvdimm_bridge(struct device *host,
+ struct cxl_port *port);
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm(struct device *dev);
int devm_cxl_add_nvdimm(struct device *host, struct cxl_port *port,
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index 6a97e4e490b6..082ec0f1c3a0 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -13,6 +13,20 @@
static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
+/**
+ * devm_cxl_add_nvdimm_bridge() - add the root of a LIBNVDIMM topology
+ * @host: platform firmware root device
+ * @port: CXL port at the root of a CXL topology
+ *
+ * Return: bridge device that can host cxl_nvdimm objects
+ */
+struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
+ struct cxl_port *port)
+{
+ return __devm_cxl_add_nvdimm_bridge(host, port);
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, "CXL");
+
static void clear_exclusive(void *mds)
{
clear_exclusive_cxl_commands(mds, exclusive_cmds);
@@ -129,6 +143,9 @@ static int cxl_nvdimm_probe(struct device *dev)
struct nvdimm *nvdimm;
int rc;
+ if (test_bit(CXL_NVD_F_INVALIDATED, &cxl_nvd->flags))
+ return -EBUSY;
+
set_exclusive_cxl_commands(mds, exclusive_cmds);
rc = devm_add_action_or_reset(dev, clear_exclusive, mds);
if (rc)
@@ -309,8 +326,10 @@ static int detach_nvdimm(struct device *dev, void *data)
scoped_guard(device, dev) {
if (dev->driver) {
cxl_nvd = to_cxl_nvdimm(dev);
- if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data)
+ if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data) {
release = true;
+ set_bit(CXL_NVD_F_INVALIDATED, &cxl_nvd->flags);
+ }
}
}
if (release)
@@ -353,6 +372,7 @@ static struct cxl_driver cxl_nvdimm_bridge_driver = {
.probe = cxl_nvdimm_bridge_probe,
.id = CXL_DEVICE_NVDIMM_BRIDGE,
.drv = {
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
.suppress_bind_attrs = true,
},
};
diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
index 63bd97181b9e..37f3c33570ee 100644
--- a/drivers/dpll/zl3073x/core.c
+++ b/drivers/dpll/zl3073x/core.c
@@ -981,11 +981,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
}
/* Add devres action to release DPLL related resources */
- rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
- if (rc)
- goto error;
-
- return 0;
+ return devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
error:
zl3073x_dev_dpll_fini(zldev);
@@ -1026,6 +1022,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
"Unknown or non-match chip ID: 0x%0x\n",
id);
}
+ zldev->chip_id = id;
/* Read revision, firmware version and custom config version */
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h
index dddfcacea5c0..fd2af3c62a7d 100644
--- a/drivers/dpll/zl3073x/core.h
+++ b/drivers/dpll/zl3073x/core.h
@@ -35,6 +35,7 @@ struct zl3073x_dpll;
* @dev: pointer to device
* @regmap: regmap to access device registers
* @multiop_lock: to serialize multiple register operations
+ * @chip_id: chip ID read from hardware
* @ref: array of input references' invariants
* @out: array of outs' invariants
* @synth: array of synths' invariants
@@ -48,6 +49,7 @@ struct zl3073x_dev {
struct device *dev;
struct regmap *regmap;
struct mutex multiop_lock;
+ u16 chip_id;
/* Invariants */
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
@@ -144,6 +146,32 @@ int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
+/**
+ * zl3073x_dev_is_ref_phase_comp_32bit - check ref phase comp register size
+ * @zldev: pointer to zl3073x device
+ *
+ * Some chip IDs have a 32-bit wide ref_phase_offset_comp register instead
+ * of the default 48-bit.
+ *
+ * Return: true if the register is 32-bit, false if 48-bit
+ */
+static inline bool
+zl3073x_dev_is_ref_phase_comp_32bit(struct zl3073x_dev *zldev)
+{
+ switch (zldev->chip_id) {
+ case 0x0E30:
+ case 0x0E93:
+ case 0x0E94:
+ case 0x0E95:
+ case 0x0E96:
+ case 0x0E97:
+ case 0x1F60:
+ return true;
+ default:
+ return false;
+ }
+}
+
static inline bool
zl3073x_is_n_pin(u8 id)
{
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index d33175d192c8..aaa14ea5e670 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -475,8 +475,11 @@ zl3073x_dpll_input_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
ref_id = zl3073x_input_pin_ref_get(pin->id);
ref = zl3073x_ref_state_get(zldev, ref_id);
- /* Perform sign extension for 48bit signed value */
- phase_comp = sign_extend64(ref->phase_comp, 47);
+ /* Perform sign extension based on register width */
+ if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
+ phase_comp = sign_extend64(ref->phase_comp, 31);
+ else
+ phase_comp = sign_extend64(ref->phase_comp, 47);
/* Reverse two's complement negation applied during set and convert
* to 32bit signed int
diff --git a/drivers/dpll/zl3073x/ref.c b/drivers/dpll/zl3073x/ref.c
index aa2de13effa8..6b65e6103999 100644
--- a/drivers/dpll/zl3073x/ref.c
+++ b/drivers/dpll/zl3073x/ref.c
@@ -121,8 +121,16 @@ int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
return rc;
/* Read phase compensation register */
- rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
- &ref->phase_comp);
+ if (zl3073x_dev_is_ref_phase_comp_32bit(zldev)) {
+ u32 val;
+
+ rc = zl3073x_read_u32(zldev, ZL_REG_REF_PHASE_OFFSET_COMP_32,
+ &val);
+ ref->phase_comp = val;
+ } else {
+ rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
+ &ref->phase_comp);
+ }
if (rc)
return rc;
@@ -179,9 +187,16 @@ int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
if (!rc && dref->sync_ctrl != ref->sync_ctrl)
rc = zl3073x_write_u8(zldev, ZL_REG_REF_SYNC_CTRL,
ref->sync_ctrl);
- if (!rc && dref->phase_comp != ref->phase_comp)
- rc = zl3073x_write_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
- ref->phase_comp);
+ if (!rc && dref->phase_comp != ref->phase_comp) {
+ if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
+ rc = zl3073x_write_u32(zldev,
+ ZL_REG_REF_PHASE_OFFSET_COMP_32,
+ ref->phase_comp);
+ else
+ rc = zl3073x_write_u48(zldev,
+ ZL_REG_REF_PHASE_OFFSET_COMP,
+ ref->phase_comp);
+ }
if (rc)
return rc;
diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h
index d837bee72b17..5573d7188406 100644
--- a/drivers/dpll/zl3073x/regs.h
+++ b/drivers/dpll/zl3073x/regs.h
@@ -194,6 +194,7 @@
#define ZL_REF_CONFIG_DIFF_EN BIT(2)
#define ZL_REG_REF_PHASE_OFFSET_COMP ZL_REG(10, 0x28, 6)
+#define ZL_REG_REF_PHASE_OFFSET_COMP_32 ZL_REG(10, 0x28, 4)
#define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1)
#define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0)
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 1c868c1e4a49..8153d62c58f0 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -848,7 +848,7 @@ static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci,
{
struct device *dev = ohci->card.device;
unsigned int i;
- struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES];
+ struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES] = { NULL };
dma_addr_t dma_addrs[AR_BUFFERS];
void *vaddr;
struct descriptor *d;
diff --git a/drivers/firmware/efi/mokvar-table.c b/drivers/firmware/efi/mokvar-table.c
index 4ff0c2926097..6842aa96d704 100644
--- a/drivers/firmware/efi/mokvar-table.c
+++ b/drivers/firmware/efi/mokvar-table.c
@@ -85,7 +85,7 @@ static struct kobject *mokvar_kobj;
* as an alternative to ordinary EFI variables, due to platform-dependent
* limitations. The memory occupied by this table is marked as reserved.
*
- * This routine must be called before efi_free_boot_services() in order
+ * This routine must be called before efi_unmap_boot_services() in order
* to guarantee that it can mark the table as reserved.
*
* Implicit inputs:
diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index d2614ace4de1..17a7128b6bd9 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -748,14 +748,14 @@ static bool gpio_shared_entry_is_really_shared(struct gpio_shared_entry *entry)
static void gpio_shared_free_exclusive(void)
{
struct gpio_shared_entry *entry, *epos;
+ struct gpio_shared_ref *ref, *rpos;
list_for_each_entry_safe(entry, epos, &gpio_shared_list, list) {
if (gpio_shared_entry_is_really_shared(entry))
continue;
- gpio_shared_drop_ref(list_first_entry(&entry->refs,
- struct gpio_shared_ref,
- list));
+ list_for_each_entry_safe(ref, rpos, &entry->refs, list)
+ gpio_shared_drop_ref(ref);
gpio_shared_drop_entry(entry);
}
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 86a171e96b0e..ada572aaebd6 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3267,8 +3267,12 @@ static int gpiochip_get(struct gpio_chip *gc, unsigned int offset)
/* Make sure this is called after checking for gc->get(). */
ret = gc->get(gc, offset);
- if (ret > 1)
- ret = -EBADE;
+ if (ret > 1) {
+ gpiochip_warn(gc,
+ "invalid return value from gc->get(): %d, consider fixing the driver\n",
+ ret);
+ ret = !!ret;
+ }
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
index afe5ca81beec..db7858fe0c3d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c
@@ -641,6 +641,7 @@ static void aca_error_fini(struct aca_error *aerr)
aca_bank_error_remove(aerr, bank_error);
out_unlock:
+ mutex_unlock(&aerr->lock);
mutex_destroy(&aerr->lock);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 06c1913d5a3f..29b400cdd6d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1439,7 +1439,10 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
*process_info = info;
}
- vm->process_info = *process_info;
+ if (cmpxchg(&vm->process_info, NULL, *process_info) != NULL) {
+ ret = -EINVAL;
+ goto already_acquired;
+ }
/* Validate page directory and attach eviction fence */
ret = amdgpu_bo_reserve(vm->root.bo, true);
@@ -1479,6 +1482,7 @@ validate_pd_fail:
amdgpu_bo_unreserve(vm->root.bo);
reserve_pd_fail:
vm->process_info = NULL;
+already_acquired:
if (info) {
dma_fence_put(&info->eviction_fence->base);
*process_info = NULL;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d9789e0b5201..3e19b51a2763 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -7059,6 +7059,15 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
dev_info(adev->dev, "PCI error: slot reset callback!!\n");
memset(&reset_context, 0, sizeof(reset_context));
+ INIT_LIST_HEAD(&device_list);
+ hive = amdgpu_get_xgmi_hive(adev);
+ if (hive) {
+ mutex_lock(&hive->hive_lock);
+ list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
+ list_add_tail(&tmp_adev->reset_list, &device_list);
+ } else {
+ list_add_tail(&adev->reset_list, &device_list);
+ }
if (adev->pcie_reset_ctx.swus)
link_dev = adev->pcie_reset_ctx.swus;
@@ -7099,19 +7108,13 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
reset_context.reset_req_dev = adev;
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
- INIT_LIST_HEAD(&device_list);
- hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
- mutex_lock(&hive->hive_lock);
reset_context.hive = hive;
- list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+ list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
tmp_adev->pcie_reset_ctx.in_link_reset = true;
- list_add_tail(&tmp_adev->reset_list, &device_list);
- }
} else {
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
- list_add_tail(&adev->reset_list, &device_list);
}
r = amdgpu_device_asic_reset(adev, &device_list, &reset_context);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
index 6e8aad91bcd3..0d3c18f04ac3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
@@ -332,13 +332,13 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
if (!context || !context->initialized) {
dev_err(adev->dev, "TA is not initialized\n");
ret = -EINVAL;
- goto err_free_shared_buf;
+ goto free_shared_buf;
}
if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
dev_err(adev->dev, "Unsupported function to invoke TA\n");
ret = -EOPNOTSUPP;
- goto err_free_shared_buf;
+ goto free_shared_buf;
}
context->session_id = ta_id;
@@ -346,7 +346,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
mutex_lock(&psp->ras_context.mutex);
ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (ret)
- goto err_free_shared_buf;
+ goto unlock;
ret = psp_fn_ta_invoke(psp, cmd_id);
if (ret || context->resp_status) {
@@ -354,15 +354,17 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
ret, context->resp_status);
if (!ret) {
ret = -EINVAL;
- goto err_free_shared_buf;
+ goto unlock;
}
}
if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT;
-err_free_shared_buf:
+unlock:
mutex_unlock(&psp->ras_context.mutex);
+
+free_shared_buf:
kfree(shared_buf);
return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 9d67b770bcc2..7c450350847d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -446,8 +446,7 @@ static int amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue)
return ret;
}
-static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
- int queue_id)
+static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
@@ -461,7 +460,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
uq_funcs->mqd_destroy(queue);
amdgpu_userq_fence_driver_free(queue);
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
- xa_erase_irq(&uq_mgr->userq_xa, (unsigned long)queue_id);
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
@@ -470,12 +468,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
up_read(&adev->reset_domain->sem);
}
-static struct amdgpu_usermode_queue *
-amdgpu_userq_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
-{
- return xa_load(&uq_mgr->userq_xa, qid);
-}
-
void
amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr)
@@ -625,22 +617,13 @@ unref_bo:
}
static int
-amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
+amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
{
- struct amdgpu_fpriv *fpriv = filp->driver_priv;
- struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
- struct amdgpu_usermode_queue *queue;
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
mutex_lock(&uq_mgr->userq_mutex);
- queue = amdgpu_userq_find(uq_mgr, queue_id);
- if (!queue) {
- drm_dbg_driver(adev_to_drm(uq_mgr->adev), "Invalid queue id to destroy\n");
- mutex_unlock(&uq_mgr->userq_mutex);
- return -EINVAL;
- }
amdgpu_userq_wait_for_last_fence(queue);
/* Cancel any pending hang detection work and cleanup */
if (queue->hang_detect_fence) {
@@ -672,7 +655,7 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n");
queue->state = AMDGPU_USERQ_STATE_HUNG;
}
- amdgpu_userq_cleanup(queue, queue_id);
+ amdgpu_userq_cleanup(queue);
mutex_unlock(&uq_mgr->userq_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -680,6 +663,37 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
return r;
}
+static void amdgpu_userq_kref_destroy(struct kref *kref)
+{
+ int r;
+ struct amdgpu_usermode_queue *queue =
+ container_of(kref, struct amdgpu_usermode_queue, refcount);
+ struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
+
+ r = amdgpu_userq_destroy(uq_mgr, queue);
+ if (r)
+ drm_file_err(uq_mgr->file, "Failed to destroy usermode queue %d\n", r);
+}
+
+struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid)
+{
+ struct amdgpu_usermode_queue *queue;
+
+ xa_lock(&uq_mgr->userq_xa);
+ queue = xa_load(&uq_mgr->userq_xa, qid);
+ if (queue)
+ kref_get(&queue->refcount);
+ xa_unlock(&uq_mgr->userq_xa);
+
+ return queue;
+}
+
+void amdgpu_userq_put(struct amdgpu_usermode_queue *queue)
+{
+ if (queue)
+ kref_put(&queue->refcount, amdgpu_userq_kref_destroy);
+}
+
static int amdgpu_userq_priority_permit(struct drm_file *filp,
int priority)
{
@@ -834,6 +848,9 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
goto unlock;
}
+ /* drop this refcount during queue destroy */
+ kref_init(&queue->refcount);
+
/* Wait for mode-1 reset to complete */
down_read(&adev->reset_domain->sem);
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
@@ -985,7 +1002,9 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
union drm_amdgpu_userq *args = data;
- int r;
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_usermode_queue *queue;
+ int r = 0;
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
@@ -1000,11 +1019,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
drm_file_err(filp, "Failed to create usermode queue\n");
break;
- case AMDGPU_USERQ_OP_FREE:
- r = amdgpu_userq_destroy(filp, args->in.queue_id);
- if (r)
- drm_file_err(filp, "Failed to destroy usermode queue\n");
+ case AMDGPU_USERQ_OP_FREE: {
+ xa_lock(&fpriv->userq_mgr.userq_xa);
+ queue = __xa_erase(&fpriv->userq_mgr.userq_xa, args->in.queue_id);
+ xa_unlock(&fpriv->userq_mgr.userq_xa);
+ if (!queue)
+ return -ENOENT;
+
+ amdgpu_userq_put(queue);
break;
+ }
default:
drm_dbg_driver(dev, "Invalid user queue op specified: %d\n", args->in.op);
@@ -1023,16 +1047,23 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
/* Resume all the queues for this process */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
+ queue = amdgpu_userq_get(uq_mgr, queue_id);
+ if (!queue)
+ continue;
+
if (!amdgpu_userq_buffer_vas_mapped(queue)) {
drm_file_err(uq_mgr->file,
"trying restore queue without va mapping\n");
queue->state = AMDGPU_USERQ_STATE_INVALID_VA;
+ amdgpu_userq_put(queue);
continue;
}
r = amdgpu_userq_restore_helper(queue);
if (r)
ret = r;
+
+ amdgpu_userq_put(queue);
}
if (ret)
@@ -1266,9 +1297,13 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
amdgpu_userq_detect_and_reset_queues(uq_mgr);
/* Try to unmap all the queues in this process ctx */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
+ queue = amdgpu_userq_get(uq_mgr, queue_id);
+ if (!queue)
+ continue;
r = amdgpu_userq_preempt_helper(queue);
if (r)
ret = r;
+ amdgpu_userq_put(queue);
}
if (ret)
@@ -1301,16 +1336,24 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
int ret;
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
+ queue = amdgpu_userq_get(uq_mgr, queue_id);
+ if (!queue)
+ continue;
+
struct dma_fence *f = queue->last_fence;
- if (!f || dma_fence_is_signaled(f))
+ if (!f || dma_fence_is_signaled(f)) {
+ amdgpu_userq_put(queue);
continue;
+ }
ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100));
if (ret <= 0) {
drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n",
f->context, f->seqno);
+ amdgpu_userq_put(queue);
return -ETIMEDOUT;
}
+ amdgpu_userq_put(queue);
}
return 0;
@@ -1361,20 +1404,23 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *f
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
{
struct amdgpu_usermode_queue *queue;
- unsigned long queue_id;
+ unsigned long queue_id = 0;
+
+ for (;;) {
+ xa_lock(&userq_mgr->userq_xa);
+ queue = xa_find(&userq_mgr->userq_xa, &queue_id, ULONG_MAX,
+ XA_PRESENT);
+ if (queue)
+ __xa_erase(&userq_mgr->userq_xa, queue_id);
+ xa_unlock(&userq_mgr->userq_xa);
- cancel_delayed_work_sync(&userq_mgr->resume_work);
+ if (!queue)
+ break;
- mutex_lock(&userq_mgr->userq_mutex);
- amdgpu_userq_detect_and_reset_queues(userq_mgr);
- xa_for_each(&userq_mgr->userq_xa, queue_id, queue) {
- amdgpu_userq_wait_for_last_fence(queue);
- amdgpu_userq_unmap_helper(queue);
- amdgpu_userq_cleanup(queue, queue_id);
+ amdgpu_userq_put(queue);
}
xa_destroy(&userq_mgr->userq_xa);
- mutex_unlock(&userq_mgr->userq_mutex);
mutex_destroy(&userq_mgr->userq_mutex);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index 5845d8959034..736c1d38297c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -74,6 +74,7 @@ struct amdgpu_usermode_queue {
struct dentry *debugfs_queue;
struct delayed_work hang_detect_work;
struct dma_fence *hang_detect_fence;
+ struct kref refcount;
struct list_head userq_va_list;
};
@@ -112,6 +113,9 @@ struct amdgpu_db_info {
struct amdgpu_userq_obj *db_obj;
};
+struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid);
+void amdgpu_userq_put(struct amdgpu_usermode_queue *queue);
+
int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 8013260e29dc..5239b06b9ab0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -35,6 +35,8 @@
static const struct dma_fence_ops amdgpu_userq_fence_ops;
static struct kmem_cache *amdgpu_userq_fence_slab;
+#define AMDGPU_USERQ_MAX_HANDLES (1U << 16)
+
int amdgpu_userq_fence_slab_init(void)
{
amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
@@ -464,7 +466,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
struct drm_amdgpu_userq_signal *args = data;
struct drm_gem_object **gobj_write = NULL;
struct drm_gem_object **gobj_read = NULL;
- struct amdgpu_usermode_queue *queue;
+ struct amdgpu_usermode_queue *queue = NULL;
struct amdgpu_userq_fence *userq_fence;
struct drm_syncobj **syncobj = NULL;
u32 *bo_handles_write, num_write_bo_handles;
@@ -478,6 +480,11 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
+ if (args->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
+ args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
+ args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
+ return -EINVAL;
+
num_syncobj_handles = args->num_syncobj_handles;
syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles),
size_mul(sizeof(u32), num_syncobj_handles));
@@ -546,7 +553,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
}
/* Retrieve the user queue */
- queue = xa_load(&userq_mgr->userq_xa, args->queue_id);
+ queue = amdgpu_userq_get(userq_mgr, args->queue_id);
if (!queue) {
r = -ENOENT;
goto put_gobj_write;
@@ -641,6 +648,9 @@ free_syncobj:
free_syncobj_handles:
kfree(syncobj_handles);
+ if (queue)
+ amdgpu_userq_put(queue);
+
return r;
}
@@ -653,7 +663,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
struct drm_amdgpu_userq_wait *wait_info = data;
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr;
- struct amdgpu_usermode_queue *waitq;
+ struct amdgpu_usermode_queue *waitq = NULL;
struct drm_gem_object **gobj_write;
struct drm_gem_object **gobj_read;
struct dma_fence **fences = NULL;
@@ -664,6 +674,11 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
+ if (wait_info->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
+ wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
+ wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
+ return -EINVAL;
+
num_read_bo_handles = wait_info->num_bo_read_handles;
bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles),
size_mul(sizeof(u32), num_read_bo_handles));
@@ -833,7 +848,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
DMA_RESV_USAGE_READ, fence) {
- if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
+ if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@@ -850,7 +865,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
DMA_RESV_USAGE_WRITE, fence) {
- if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
+ if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@@ -874,8 +889,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
goto free_fences;
dma_fence_unwrap_for_each(f, &iter, fence) {
- if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
+ if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
+ dma_fence_put(fence);
goto free_fences;
}
@@ -898,8 +914,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (r)
goto free_fences;
- if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
+ if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
+ dma_fence_put(fence);
goto free_fences;
}
@@ -912,7 +929,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
*/
num_fences = dma_fence_dedup_array(fences, num_fences);
- waitq = xa_load(&userq_mgr->userq_xa, wait_info->waitq_id);
+ waitq = amdgpu_userq_get(userq_mgr, wait_info->waitq_id);
if (!waitq) {
r = -EINVAL;
goto free_fences;
@@ -969,32 +986,14 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
r = -EFAULT;
goto free_fences;
}
-
- kfree(fences);
- kfree(fence_info);
}
- drm_exec_fini(&exec);
- for (i = 0; i < num_read_bo_handles; i++)
- drm_gem_object_put(gobj_read[i]);
- kfree(gobj_read);
-
- for (i = 0; i < num_write_bo_handles; i++)
- drm_gem_object_put(gobj_write[i]);
- kfree(gobj_write);
-
- kfree(timeline_points);
- kfree(timeline_handles);
- kfree(syncobj_handles);
- kfree(bo_handles_write);
- kfree(bo_handles_read);
-
- return 0;
-
free_fences:
- while (num_fences-- > 0)
- dma_fence_put(fences[num_fences]);
- kfree(fences);
+ if (fences) {
+ while (num_fences-- > 0)
+ dma_fence_put(fences[num_fences]);
+ kfree(fences);
+ }
free_fence_info:
kfree(fence_info);
exec_fini:
@@ -1018,5 +1017,8 @@ free_bo_handles_write:
free_bo_handles_read:
kfree(bo_handles_read);
+ if (waitq)
+ amdgpu_userq_put(waitq);
+
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 09ebb13ca5e8..a926a330700e 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -720,11 +720,6 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
mes_set_hw_res_pkt.oversubscription_timer = 50;
- if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x7f)
- mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
- else
- dev_info_once(mes->adev->dev,
- "MES FW version must be >= 0x7f to enable LR compute workaround.\n");
if (amdgpu_mes_log_enable) {
mes_set_hw_res_pkt.enable_mes_event_int_logging = 1;
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
index b1c864dc79a8..5bfa5d1d0b36 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c
@@ -779,11 +779,6 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
mes_set_hw_res_pkt.use_different_vmid_compute = 1;
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
- if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x82)
- mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
- else
- dev_info_once(adev->dev,
- "MES FW version must be >= 0x82 to enable LR compute workaround.\n");
/*
* Keep oversubscribe timer for sdma . When we have unmapped doorbell
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
index 723ddae17644..73a709773e85 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
@@ -69,12 +69,12 @@ static int psp_v15_0_0_ring_stop(struct psp_context *psp,
0x80000000, 0x80000000, false);
} else {
/* Write the ring destroy command*/
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64,
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64,
GFX_CTRL_CMD_ID_DESTROY_RINGS);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) */
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
}
@@ -116,7 +116,7 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
} else {
/* Wait for sOS ready for ring creation */
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
@@ -125,23 +125,23 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
/* Write low address of the ring to C2PMSG_69 */
psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_69, psp_ring_reg);
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_69, psp_ring_reg);
/* Write high address of the ring to C2PMSG_70 */
psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_70, psp_ring_reg);
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_70, psp_ring_reg);
/* Write size of ring to C2PMSG_71 */
psp_ring_reg = ring->ring_size;
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_71, psp_ring_reg);
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_71, psp_ring_reg);
/* Write the ring initialization command to C2PMSG_64 */
psp_ring_reg = ring_type;
psp_ring_reg = psp_ring_reg << 16;
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, psp_ring_reg);
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64, psp_ring_reg);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) in C2PMSG_64 */
- ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
+ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
}
@@ -174,7 +174,7 @@ static uint32_t psp_v15_0_0_ring_get_wptr(struct psp_context *psp)
if (amdgpu_sriov_vf(adev))
data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102);
else
- data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67);
+ data = RREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67);
return data;
}
@@ -188,7 +188,7 @@ static void psp_v15_0_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101,
GFX_CTRL_CMD_ID_CONSUME_CMD);
} else
- WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67, value);
+ WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67, value);
}
static const struct psp_funcs psp_v15_0_0_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index 8122a5cacf07..a0ad1f8a76f0 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -858,7 +858,9 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
AMD_CG_SUPPORT_IH_CG |
AMD_CG_SUPPORT_BIF_MGCG |
AMD_CG_SUPPORT_BIF_LS;
- adev->pg_flags = AMD_PG_SUPPORT_VCN |
+ adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_JPEG_DPG |
AMD_PG_SUPPORT_JPEG |
AMD_PG_SUPPORT_GFX_PG;
adev->external_rev_id = adev->rev_id + 0x1;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 0202df5db1e1..6109124f852e 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -174,6 +174,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
fw_shared->sq.is_enabled = 1;
+ fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);
+ fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
+ AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
+
if (amdgpu_vcnfw_log)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 2ba98f384685..cd1e58b8defc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1706,6 +1706,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
struct drm_atomic_state *state = plane_state->state;
const struct amdgpu_device *adev = drm_to_adev(colorop->dev);
+ bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
const struct drm_device *dev = colorop->dev;
const struct drm_color_lut32 *lut3d;
uint32_t lut3d_size;
@@ -1722,7 +1723,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
}
if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) {
- if (!adev->dm.dc->caps.color.dpp.hw_3d_lut) {
+ if (!has_3dlut) {
drm_dbg(dev, "3D LUT is not supported by hardware\n");
return -EINVAL;
}
@@ -1875,6 +1876,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
struct drm_colorop *colorop = plane_state->color_pipeline;
struct drm_device *dev = plane_state->plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
+ bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
int ret;
/* 1D Curve - DEGAM TF */
@@ -1907,7 +1909,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
if (ret)
return ret;
- if (adev->dm.dc->caps.color.dpp.hw_3d_lut) {
+ if (has_3dlut) {
/* 1D Curve & LUT - SHAPER TF & LUT */
colorop = colorop->next;
if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index f25c0ede7199..d59ba82d3d7c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -60,6 +60,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
struct drm_device *dev = plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
+ bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
int ret;
int i = 0;
@@ -112,7 +113,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
i++;
- if (adev->dm.dc->caps.color.dpp.hw_3d_lut) {
+ if (has_3dlut) {
/* 1D curve - SHAPER TF */
ops[i] = kzalloc_obj(*ops[0]);
if (!ops[i]) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 130190e8a1b2..304437c2284d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -765,15 +765,15 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->adev->mode_info.crtcs[crtc_index] = acrtc;
/* Don't enable DRM CRTC degamma property for
- * 1. Degamma is replaced by color pipeline.
- * 2. DCE since it doesn't support programmable degamma anywhere.
- * 3. DCN401 since pre-blending degamma LUT doesn't apply to cursor.
+ * 1. DCE since it doesn't support programmable degamma anywhere.
+ * 2. DCN401 since pre-blending degamma LUT doesn't apply to cursor.
+ * Note: DEGAMMA properties are created even if the primary plane has the
+ * COLOR_PIPELINE property. User space can use either the DEGAMMA properties
+ * or the COLOR_PIPELINE property. An atomic commit which attempts to enable
+ * both is rejected.
*/
- if (plane->color_pipeline_property)
- has_degamma = false;
- else
- has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch &&
- dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01;
+ has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch &&
+ dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01;
drm_crtc_enable_color_mgmt(&acrtc->base, has_degamma ? MAX_COLOR_LUT_ENTRIES : 0,
true, MAX_COLOR_LUT_ENTRIES);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 70587e5a8d46..127207e18dcb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1256,6 +1256,14 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
if (ret)
return ret;
+ /* Reject commits that attempt to use both COLOR_PIPELINE and CRTC DEGAMMA_LUT */
+ if (new_plane_state->color_pipeline && new_crtc_state->degamma_lut) {
+ drm_dbg_atomic(plane->dev,
+ "[PLANE:%d:%s] COLOR_PIPELINE and CRTC DEGAMMA_LUT cannot be enabled simultaneously\n",
+ plane->base.id, plane->name);
+ return -EINVAL;
+ }
+
ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 246893d80f1f..baf820e6eae8 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -170,11 +170,11 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (sink == NULL)
goto fail;
- stream = kzalloc_obj(struct dc_stream_state);
+ stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
if (stream == NULL)
goto fail;
- stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_KERNEL);
+ stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
if (stream->update_scratch == NULL)
goto fail;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index b91517b9fedc..eb198d52a115 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -72,7 +72,11 @@ void dcn401_initialize_min_clocks(struct dc *dc)
* audio corruption. Read current DISPCLK from DENTIST and request the same
* freq to ensure that the timing is valid and unchanged.
*/
- clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
+ if (dc->clk_mgr->funcs->get_dispclk_from_dentist) {
+ clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
+ } else {
+ clocks->dispclk_khz = dc->clk_mgr->boot_snapshot.dispclk * 1000;
+ }
}
clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
clocks->fclk_p_state_change_support = true;
diff --git a/drivers/gpu/drm/amd/include/asic_reg/mp/mp_15_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/mp/mp_15_0_0_offset.h
index 0e4c195297a4..fe97943b9b97 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/mp/mp_15_0_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/mp/mp_15_0_0_offset.h
@@ -82,6 +82,24 @@
#define regMPASP_SMN_IH_SW_INT_CTRL 0x0142
#define regMPASP_SMN_IH_SW_INT_CTRL_BASE_IDX 0
+// addressBlock: mp_SmuMpASPPub_PcruDec
+// base address: 0x3800000
+#define regMPASP_PCRU1_MPASP_C2PMSG_64 0x4280
+#define regMPASP_PCRU1_MPASP_C2PMSG_64_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_65 0x4281
+#define regMPASP_PCRU1_MPASP_C2PMSG_65_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_66 0x4282
+#define regMPASP_PCRU1_MPASP_C2PMSG_66_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_67 0x4283
+#define regMPASP_PCRU1_MPASP_C2PMSG_67_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_68 0x4284
+#define regMPASP_PCRU1_MPASP_C2PMSG_68_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_69 0x4285
+#define regMPASP_PCRU1_MPASP_C2PMSG_69_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_70 0x4286
+#define regMPASP_PCRU1_MPASP_C2PMSG_70_BASE_IDX 3
+#define regMPASP_PCRU1_MPASP_C2PMSG_71 0x4287
+#define regMPASP_PCRU1_MPASP_C2PMSG_71_BASE_IDX 3
// addressBlock: mp_SmuMp1_SmnDec
// base address: 0x0
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index e030f1e186cb..b32c053950c9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2034,6 +2034,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
smu, SMU_DRIVER_TABLE_GPU_METRICS);
SmuMetricsExternal_t metrics_ext;
SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
+ uint32_t mp1_ver = amdgpu_ip_version(smu->adev, MP1_HWIP, 0);
int ret = 0;
ret = smu_cmn_get_metrics_table(smu,
@@ -2058,7 +2059,12 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
- gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
+
+ if ((mp1_ver == IP_VERSION(13, 0, 0) && smu->smc_fw_version <= 0x004e1e00) ||
+ (mp1_ver == IP_VERSION(13, 0, 10) && smu->smc_fw_version <= 0x00500800))
+ gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
+ else
+ gpu_metrics->energy_accumulator = UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index af0482c9caa7..f08cfa510a8a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2065,7 +2065,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
- gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
+ gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ?
+ metrics->EnergyAccumulator : UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 930aaa659c97..ec632f268644 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1881,6 +1881,14 @@ static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi, struct device
return 0;
}
+static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
+{
+ if (dsi->te_gpio) {
+ free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
+ gpiod_put(dsi->te_gpio);
+ }
+}
+
static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
@@ -1961,7 +1969,7 @@ of_find_panel_or_bridge:
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
ret = samsung_dsim_register_te_irq(dsi, &device->dev);
if (ret)
- return ret;
+ goto err_remove_bridge;
}
// The next bridge can be used by host_ops->attach
@@ -1982,15 +1990,12 @@ of_find_panel_or_bridge:
err_release_next_bridge:
drm_bridge_put(dsi->bridge.next_bridge);
dsi->bridge.next_bridge = NULL;
- return ret;
-}
-static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
-{
- if (dsi->te_gpio) {
- free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
- gpiod_put(dsi->te_gpio);
- }
+ if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
+ samsung_dsim_unregister_te_irq(dsi);
+err_remove_bridge:
+ drm_bridge_remove(&dsi->bridge);
+ return ret;
}
static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index 4ab6922dd79c..fd23ca2834b0 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -2049,7 +2049,9 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
bridge->ycbcr_420_allowed = true;
- devm_drm_bridge_add(dev, bridge);
+ ret = devm_drm_bridge_add(dev, bridge);
+ if (ret)
+ return ERR_PTR(ret);
dp->aux.dev = dev;
dp->aux.drm_dev = encoder->dev;
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 276d05d25ad8..98d64ad791d0 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -1415,6 +1415,7 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
{
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
struct device_node *np = pdata->dev->of_node;
+ const struct i2c_client *client = to_i2c_client(pdata->dev);
int ret;
pdata->next_bridge = devm_drm_of_get_bridge(&adev->dev, np, 1, 0);
@@ -1433,8 +1434,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP;
if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) {
- pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT |
- DRM_BRIDGE_OP_HPD;
+ pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT;
+ if (client->irq)
+ pdata->bridge.ops |= DRM_BRIDGE_OP_HPD;
/*
* If comms were already enabled they would have been enabled
* with the wrong value of HPD_DISABLE. Update it now. Comms
diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 262b1b8773c5..bb49b8361271 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -930,7 +930,8 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
mutex_unlock(&client->modeset_mutex);
out:
kfree(crtcs);
- modes_destroy(dev, modes, connector_count);
+ if (modes)
+ modes_destroy(dev, modes, connector_count);
kfree(modes);
kfree(offsets);
kfree(enabled);
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 24180bfdf5a2..9ef9e52c0547 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1338,14 +1338,14 @@ bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
/**
- * drm_gpusvm_range_pages_valid_unlocked() - GPU SVM range pages valid unlocked
+ * drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
* @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
+ * @svm_pages: Pointer to the GPU SVM pages structure
*
- * This function determines if a GPU SVM range pages are valid. Expected be
- * called without holding gpusvm->notifier_lock.
+ * This function determines if a GPU SVM pages are valid. Expected be called
+ * without holding gpusvm->notifier_lock.
*
- * Return: True if GPU SVM range has valid pages, False otherwise
+ * Return: True if GPU SVM pages are valid, False otherwise
*/
static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_pages *svm_pages)
diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index bdc79140875c..862675ac5bb2 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -480,18 +480,8 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
.start = start,
.end = end,
.pgmap_owner = pagemap->owner,
- /*
- * FIXME: MIGRATE_VMA_SELECT_DEVICE_PRIVATE intermittently
- * causes 'xe_exec_system_allocator --r *race*no*' to trigger aa
- * engine reset and a hard hang due to getting stuck on a folio
- * lock. This should work and needs to be root-caused. The only
- * downside of not selecting MIGRATE_VMA_SELECT_DEVICE_PRIVATE
- * is that device-to-device migrations won’t work; instead,
- * memory will bounce through system memory. This path should be
- * rare and only occur when the madvise attributes of memory are
- * changed or atomics are being used.
- */
- .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT,
+ .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT |
+ MIGRATE_VMA_SELECT_DEVICE_PRIVATE,
};
unsigned long i, npages = npages_in_range(start, end);
unsigned long own_pages = 0, migrated_pages = 0;
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index 7ce8c674bb03..07ffee38974b 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -562,12 +562,7 @@ void intel_alpm_disable(struct intel_dp *intel_dp)
mutex_lock(&intel_dp->alpm.lock);
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
- ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE |
- ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
-
- intel_de_rmw(display,
- PORT_ALPM_CTL(cpu_transcoder),
- PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
+ ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE, 0);
drm_dbg_kms(display->drm, "Disabling ALPM\n");
mutex_unlock(&intel_dp->alpm.lock);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 62208ffc5101..4ce1173a2e91 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1307,9 +1307,14 @@ static bool psr2_granularity_check(struct intel_crtc_state *crtc_state,
u16 sink_y_granularity = crtc_state->has_panel_replay ?
connector->dp.panel_replay_caps.su_y_granularity :
connector->dp.psr_caps.su_y_granularity;
- u16 sink_w_granularity = crtc_state->has_panel_replay ?
- connector->dp.panel_replay_caps.su_w_granularity :
- connector->dp.psr_caps.su_w_granularity;
+ u16 sink_w_granularity;
+
+ if (crtc_state->has_panel_replay)
+ sink_w_granularity = connector->dp.panel_replay_caps.su_w_granularity ==
+ DP_PANEL_REPLAY_FULL_LINE_GRANULARITY ?
+ crtc_hdisplay : connector->dp.panel_replay_caps.su_w_granularity;
+ else
+ sink_w_granularity = connector->dp.psr_caps.su_w_granularity;
/* PSR2 HW only send full lines so we only need to validate the width */
if (crtc_hdisplay % sink_w_granularity)
diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index dea85577513a..4ce772bc3cb3 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -256,7 +256,9 @@ static int imx_pd_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, imxpd);
- devm_drm_bridge_add(dev, &imxpd->bridge);
+ ret = devm_drm_bridge_add(dev, &imxpd->bridge);
+ if (ret)
+ return ret;
return component_add(dev, &imx_pd_ops);
}
diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.c b/drivers/gpu/drm/logicvc/logicvc_drm.c
index 204b0fee55d0..bbebf4fc7f51 100644
--- a/drivers/gpu/drm/logicvc/logicvc_drm.c
+++ b/drivers/gpu/drm/logicvc/logicvc_drm.c
@@ -92,7 +92,6 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
struct device *dev = drm_dev->dev;
struct device_node *of_node = dev->of_node;
struct logicvc_drm_config *config = &logicvc->config;
- struct device_node *layers_node;
int ret;
logicvc_of_property_parse_bool(of_node, LOGICVC_OF_PROPERTY_DITHERING,
@@ -128,7 +127,8 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
if (ret)
return ret;
- layers_node = of_get_child_by_name(of_node, "layers");
+ struct device_node *layers_node __free(device_node) =
+ of_get_child_by_name(of_node, "layers");
if (!layers_node) {
drm_err(drm_dev, "Missing non-optional layers node\n");
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 00d4530aea71..cc239492c7f0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1230,6 +1230,9 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
u8 size = msg->size;
int ret;
+ if (pm_runtime_suspended(nv_connector->base.dev->dev))
+ return -EBUSY;
+
nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
if (!nv_encoder)
return -ENODEV;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
index e10192fe1d0f..0121d5639471 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
@@ -737,8 +737,8 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
if (!obj)
goto done;
- if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
- WARN_ON(obj->buffer.length != 4))
+ if (obj->type != ACPI_TYPE_BUFFER ||
+ obj->buffer.length != 4)
goto done;
caps->status = 0;
@@ -773,8 +773,8 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_METHOD_DATA *jt)
if (!obj)
goto done;
- if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
- WARN_ON(obj->buffer.length != 4))
+ if (obj->type != ACPI_TYPE_BUFFER ||
+ obj->buffer.length != 4)
goto done;
jt->status = 0;
@@ -861,8 +861,8 @@ r535_gsp_acpi_dod(acpi_handle handle, DOD_METHOD_DATA *dod)
_DOD = output.pointer;
- if (WARN_ON(_DOD->type != ACPI_TYPE_PACKAGE) ||
- WARN_ON(_DOD->package.count > ARRAY_SIZE(dod->acpiIdList)))
+ if (_DOD->type != ACPI_TYPE_PACKAGE ||
+ _DOD->package.count > ARRAY_SIZE(dod->acpiIdList))
return;
for (int i = 0; i < _DOD->package.count; i++) {
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index bd703a2904a1..a70f1db0764e 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -893,14 +893,15 @@ panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue
out_sync:
/* Make sure the CPU caches are invalidated before the seqno is read.
- * drm_gem_shmem_sync() is a NOP if map_wc=true, so no need to check
+ * panthor_gem_sync() is a NOP if map_wc=true, so no need to check
* it here.
*/
- panthor_gem_sync(&bo->base.base, queue->syncwait.offset,
+ panthor_gem_sync(&bo->base.base,
+ DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE,
+ queue->syncwait.offset,
queue->syncwait.sync64 ?
sizeof(struct panthor_syncobj_64b) :
- sizeof(struct panthor_syncobj_32b),
- DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE);
+ sizeof(struct panthor_syncobj_32b));
return queue->syncwait.kmap + queue->syncwait.offset;
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index f74a0aa85ba8..29f2b7d24fe5 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -1122,6 +1122,7 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+ int bpp;
int ret;
if (device->lanes > dsi->num_data_lanes) {
@@ -1131,7 +1132,8 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
return -EINVAL;
}
- switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
+ bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+ switch (bpp) {
case 24:
break;
case 18:
@@ -1162,6 +1164,18 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
drm_bridge_add(&dsi->bridge);
+ /*
+ * Report the required division ratio setting for the MIPI clock dividers.
+ *
+ * vclk * bpp = hsclk * 8 * num_lanes
+ *
+ * vclk * DSI_AB_divider = hsclk * 16
+ *
+ * which simplifies to...
+ * DSI_AB_divider = bpp * 2 / num_lanes
+ */
+ rzg2l_cpg_dsi_div_set_divider(bpp * 2 / dsi->lanes, PLL5_TARGET_DSI);
+
return 0;
}
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index e6ee35406165..2d5cb21a05b6 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -361,6 +361,7 @@ static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
/**
* drm_sched_job_done - complete a job
* @s_job: pointer to the job which is done
+ * @result: 0 on success, -ERRNO on error
*
* Finish the job's fence and resubmit the work items.
*/
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 6ecf9e2ff61b..c77455b1834d 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -737,6 +737,7 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
unsigned int height = drm_rect_height(rect);
unsigned int line_length = DIV_ROUND_UP(width, 8);
unsigned int page_height = SSD130X_PAGE_HEIGHT;
+ u8 page_start = ssd130x->page_offset + y / page_height;
unsigned int pages = DIV_ROUND_UP(height, page_height);
struct drm_device *drm = &ssd130x->drm;
u32 array_idx = 0;
@@ -774,14 +775,11 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
*/
if (!ssd130x->page_address_mode) {
- u8 page_start;
-
/* Set address range for horizontal addressing mode */
ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
if (ret < 0)
return ret;
- page_start = ssd130x->page_offset + y / page_height;
ret = ssd130x_set_page_range(ssd130x, page_start, pages);
if (ret < 0)
return ret;
@@ -813,7 +811,7 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
*/
if (ssd130x->page_address_mode) {
ret = ssd130x_set_page_pos(ssd130x,
- ssd130x->page_offset + i,
+ page_start + i,
ssd130x->col_offset + x);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/tiny/sharp-memory.c b/drivers/gpu/drm/tiny/sharp-memory.c
index 64272cd0f6e2..cbf69460ebf3 100644
--- a/drivers/gpu/drm/tiny/sharp-memory.c
+++ b/drivers/gpu/drm/tiny/sharp-memory.c
@@ -541,8 +541,8 @@ static int sharp_memory_probe(struct spi_device *spi)
smd = devm_drm_dev_alloc(dev, &sharp_memory_drm_driver,
struct sharp_memory_device, drm);
- if (!smd)
- return -ENOMEM;
+ if (IS_ERR(smd))
+ return PTR_ERR(smd);
spi_set_drvdata(spi, smd);
diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
index d468f8322072..f3103307b5df 100644
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_test.c
@@ -222,13 +222,13 @@ static void ttm_bo_reserve_interrupted(struct kunit *test)
KUNIT_FAIL(test, "Couldn't create ttm bo reserve task\n");
/* Take a lock so the threaded reserve has to wait */
- mutex_lock(&bo->base.resv->lock.base);
+ dma_resv_lock(bo->base.resv, NULL);
wake_up_process(task);
msleep(20);
err = kthread_stop(task);
- mutex_unlock(&bo->base.resv->lock.base);
+ dma_resv_unlock(bo->base.resv);
KUNIT_ASSERT_EQ(test, err, -ERESTARTSYS);
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index acb9197db879..0765d69423d2 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1107,8 +1107,7 @@ struct ttm_bo_swapout_walk {
static s64
ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
{
- struct ttm_resource *res = bo->resource;
- struct ttm_place place = { .mem_type = res->mem_type };
+ struct ttm_place place = { .mem_type = bo->resource->mem_type };
struct ttm_bo_swapout_walk *swapout_walk =
container_of(walk, typeof(*swapout_walk), walk);
struct ttm_operation_ctx *ctx = walk->arg.ctx;
@@ -1148,7 +1147,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
/*
* Move to system cached
*/
- if (res->mem_type != TTM_PL_SYSTEM) {
+ if (bo->resource->mem_type != TTM_PL_SYSTEM) {
struct ttm_resource *evict_mem;
struct ttm_place hop;
@@ -1180,15 +1179,15 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
if (ttm_tt_is_populated(tt)) {
spin_lock(&bdev->lru_lock);
- ttm_resource_del_bulk_move(res, bo);
+ ttm_resource_del_bulk_move(bo->resource, bo);
spin_unlock(&bdev->lru_lock);
ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
spin_lock(&bdev->lru_lock);
if (ret)
- ttm_resource_add_bulk_move(res, bo);
- ttm_resource_move_to_lru_tail(res);
+ ttm_resource_add_bulk_move(bo->resource, bo);
+ ttm_resource_move_to_lru_tail(bo->resource);
spin_unlock(&bdev->lru_lock);
}
diff --git a/drivers/gpu/drm/ttm/ttm_pool_internal.h b/drivers/gpu/drm/ttm/ttm_pool_internal.h
index 82c4b7e56a99..24c179fd69d1 100644
--- a/drivers/gpu/drm/ttm/ttm_pool_internal.h
+++ b/drivers/gpu/drm/ttm/ttm_pool_internal.h
@@ -17,7 +17,7 @@ static inline bool ttm_pool_uses_dma32(struct ttm_pool *pool)
return pool->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32;
}
-static inline bool ttm_pool_beneficial_order(struct ttm_pool *pool)
+static inline unsigned int ttm_pool_beneficial_order(struct ttm_pool *pool)
{
return pool->alloc_flags & 0xff;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 2170b45c30e9..f45d93e8c1c8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -105,6 +105,7 @@ struct vmw_cmdbuf_context {
* @handle: DMA address handle for the command buffer space if @using_mob is
* false. Immutable.
* @size: The size of the command buffer space. Immutable.
+ * @id: Monotonically increasing ID of the last cmdbuf submitted.
* @num_contexts: Number of contexts actually enabled.
*/
struct vmw_cmdbuf_man {
@@ -132,6 +133,7 @@ struct vmw_cmdbuf_man {
bool has_pool;
dma_addr_t handle;
size_t size;
+ u64 id;
u32 num_contexts;
};
@@ -303,6 +305,8 @@ static int vmw_cmdbuf_header_submit(struct vmw_cmdbuf_header *header)
struct vmw_cmdbuf_man *man = header->man;
u32 val;
+ header->cb_header->id = man->id++;
+
val = upper_32_bits(header->handle);
vmw_write(man->dev_priv, SVGA_REG_COMMAND_HIGH, val);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 3057f8baa7d2..e1f18020170a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1143,7 +1143,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
if (ret != 0) {
drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
- return PTR_ERR(vmw_bo);
+ return ret;
}
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
@@ -1199,7 +1199,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
if (ret != 0) {
drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
- return PTR_ERR(vmw_bo);
+ return ret;
}
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
index fd4e76486f2d..45561bc1c9ef 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
@@ -260,6 +260,13 @@ out_no_dirty:
return ret;
}
+static void vmw_bo_dirty_free(struct kref *kref)
+{
+ struct vmw_bo_dirty *dirty = container_of(kref, struct vmw_bo_dirty, ref_count);
+
+ kvfree(dirty);
+}
+
/**
* vmw_bo_dirty_release - Release a dirty-tracking user from a buffer object
* @vbo: The buffer object
@@ -274,7 +281,7 @@ void vmw_bo_dirty_release(struct vmw_bo *vbo)
{
struct vmw_bo_dirty *dirty = vbo->dirty;
- if (dirty && kref_put(&dirty->ref_count, (void *)kvfree))
+ if (dirty && kref_put(&dirty->ref_count, vmw_bo_dirty_free))
vbo->dirty = NULL;
}
diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
index 68172b0248a6..dc5a4fafa70c 100644
--- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
@@ -96,6 +96,12 @@
#define ENABLE_SEMAPHORE_POLL_BIT REG_BIT(13)
#define RING_CMD_CCTL(base) XE_REG((base) + 0xc4, XE_REG_OPTION_MASKED)
+
+#define CS_MMIO_GROUP_INSTANCE_SELECT(base) XE_REG((base) + 0xcc)
+#define SELECTIVE_READ_ADDRESSING REG_BIT(30)
+#define SELECTIVE_READ_GROUP REG_GENMASK(29, 23)
+#define SELECTIVE_READ_INSTANCE REG_GENMASK(22, 16)
+
/*
* CMD_CCTL read/write fields take a MOCS value and _not_ a table index.
* The lsb of each can be considered a separate enabling bit for encryption.
diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c
index c59b1414df22..7fd07d1280bb 100644
--- a/drivers/gpu/drm/xe/xe_configfs.c
+++ b/drivers/gpu/drm/xe/xe_configfs.c
@@ -830,6 +830,7 @@ static void xe_config_device_release(struct config_item *item)
mutex_destroy(&dev->lock);
+ kfree(dev->config.ctx_restore_mid_bb[0].cs);
kfree(dev->config.ctx_restore_post_bb[0].cs);
kfree(dev);
}
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 0ddae7fcfc97..8ecdf949f9e4 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -266,6 +266,16 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
return q;
}
+static void __xe_exec_queue_fini(struct xe_exec_queue *q)
+{
+ int i;
+
+ q->ops->fini(q);
+
+ for (i = 0; i < q->width; ++i)
+ xe_lrc_put(q->lrc[i]);
+}
+
static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags)
{
int i, err;
@@ -320,21 +330,10 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags)
return 0;
err_lrc:
- for (i = i - 1; i >= 0; --i)
- xe_lrc_put(q->lrc[i]);
+ __xe_exec_queue_fini(q);
return err;
}
-static void __xe_exec_queue_fini(struct xe_exec_queue *q)
-{
- int i;
-
- q->ops->fini(q);
-
- for (i = 0; i < q->width; ++i)
- xe_lrc_put(q->lrc[i]);
-}
-
struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm,
u32 logical_mask, u16 width,
struct xe_hw_engine *hwe, u32 flags,
diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c
index 42438b21f235..707db650a2ae 100644
--- a/drivers/gpu/drm/xe/xe_gsc_proxy.c
+++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c
@@ -435,15 +435,11 @@ static int proxy_channel_alloc(struct xe_gsc *gsc)
return 0;
}
-static void xe_gsc_proxy_remove(void *arg)
+static void xe_gsc_proxy_stop(struct xe_gsc *gsc)
{
- struct xe_gsc *gsc = arg;
struct xe_gt *gt = gsc_to_gt(gsc);
struct xe_device *xe = gt_to_xe(gt);
- if (!gsc->proxy.component_added)
- return;
-
/* disable HECI2 IRQs */
scoped_guard(xe_pm_runtime, xe) {
CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
@@ -455,6 +451,30 @@ static void xe_gsc_proxy_remove(void *arg)
}
xe_gsc_wait_for_worker_completion(gsc);
+ gsc->proxy.started = false;
+}
+
+static void xe_gsc_proxy_remove(void *arg)
+{
+ struct xe_gsc *gsc = arg;
+ struct xe_gt *gt = gsc_to_gt(gsc);
+ struct xe_device *xe = gt_to_xe(gt);
+
+ if (!gsc->proxy.component_added)
+ return;
+
+ /*
+ * GSC proxy start is an async process that can be ongoing during
+ * Xe module load/unload. Using devm managed action to register
+ * xe_gsc_proxy_stop could cause issues if Xe module unload has
+ * already started when the action is registered, potentially leading
+ * to the cleanup being called at the wrong time. Therefore, instead
+ * of registering a separate devm action to undo what is done in
+ * proxy start, we call it from here, but only if the start has
+ * completed successfully (tracked with the 'started' flag).
+ */
+ if (gsc->proxy.started)
+ xe_gsc_proxy_stop(gsc);
component_del(xe->drm.dev, &xe_gsc_proxy_component_ops);
gsc->proxy.component_added = false;
@@ -510,6 +530,7 @@ int xe_gsc_proxy_init(struct xe_gsc *gsc)
*/
int xe_gsc_proxy_start(struct xe_gsc *gsc)
{
+ struct xe_gt *gt = gsc_to_gt(gsc);
int err;
/* enable the proxy interrupt in the GSC shim layer */
@@ -521,12 +542,18 @@ int xe_gsc_proxy_start(struct xe_gsc *gsc)
*/
err = xe_gsc_proxy_request_handler(gsc);
if (err)
- return err;
+ goto err_irq_disable;
if (!xe_gsc_proxy_init_done(gsc)) {
- xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n");
- return -EIO;
+ xe_gt_err(gt, "GSC FW reports proxy init not completed\n");
+ err = -EIO;
+ goto err_irq_disable;
}
+ gsc->proxy.started = true;
return 0;
+
+err_irq_disable:
+ gsc_proxy_irq_toggle(gsc, false);
+ return err;
}
diff --git a/drivers/gpu/drm/xe/xe_gsc_types.h b/drivers/gpu/drm/xe/xe_gsc_types.h
index 97c056656df0..5aaa2a75861f 100644
--- a/drivers/gpu/drm/xe/xe_gsc_types.h
+++ b/drivers/gpu/drm/xe/xe_gsc_types.h
@@ -58,6 +58,8 @@ struct xe_gsc {
struct mutex mutex;
/** @proxy.component_added: whether the component has been added */
bool component_added;
+ /** @proxy.started: whether the proxy has been started */
+ bool started;
/** @proxy.bo: object to store message to and from the GSC */
struct xe_bo *bo;
/** @proxy.to_gsc: map of the memory used to send messages to the GSC */
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 9d090d0f2438..df6d04704823 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -210,11 +210,15 @@ static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q)
return ret;
}
+/* Dwords required to emit a RMW of a register */
+#define EMIT_RMW_DW 20
+
static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
{
- struct xe_reg_sr *sr = &q->hwe->reg_lrc;
+ struct xe_hw_engine *hwe = q->hwe;
+ struct xe_reg_sr *sr = &hwe->reg_lrc;
struct xe_reg_sr_entry *entry;
- int count_rmw = 0, count = 0, ret;
+ int count_rmw = 0, count_rmw_mcr = 0, count = 0, ret;
unsigned long idx;
struct xe_bb *bb;
size_t bb_len = 0;
@@ -224,6 +228,8 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
xa_for_each(&sr->xa, idx, entry) {
if (entry->reg.masked || entry->clr_bits == ~0)
++count;
+ else if (entry->reg.mcr)
+ ++count_rmw_mcr;
else
++count_rmw;
}
@@ -231,17 +237,35 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
if (count)
bb_len += count * 2 + 1;
- if (count_rmw)
- bb_len += count_rmw * 20 + 7;
+ /*
+ * RMW of MCR registers is the same as a normal RMW, except an
+ * additional LRI (3 dwords) is required per register to steer the read
+ * to a nom-terminated instance.
+ *
+ * We could probably shorten the batch slightly by eliding the
+ * steering for consecutive MCR registers that have the same
+ * group/instance target, but it's not worth the extra complexity to do
+ * so.
+ */
+ bb_len += count_rmw * EMIT_RMW_DW;
+ bb_len += count_rmw_mcr * (EMIT_RMW_DW + 3);
+
+ /*
+ * After doing all RMW, we need 7 trailing dwords to clean up,
+ * plus an additional 3 dwords to reset steering if any of the
+ * registers were MCR.
+ */
+ if (count_rmw || count_rmw_mcr)
+ bb_len += 7 + (count_rmw_mcr ? 3 : 0);
- if (q->hwe->class == XE_ENGINE_CLASS_RENDER)
+ if (hwe->class == XE_ENGINE_CLASS_RENDER)
/*
* Big enough to emit all of the context's 3DSTATE via
* xe_lrc_emit_hwe_state_instructions()
*/
- bb_len += xe_gt_lrc_size(gt, q->hwe->class) / sizeof(u32);
+ bb_len += xe_gt_lrc_size(gt, hwe->class) / sizeof(u32);
- xe_gt_dbg(gt, "LRC %s WA job: %zu dwords\n", q->hwe->name, bb_len);
+ xe_gt_dbg(gt, "LRC %s WA job: %zu dwords\n", hwe->name, bb_len);
bb = xe_bb_new(gt, bb_len, false);
if (IS_ERR(bb))
@@ -276,13 +300,23 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
}
}
- if (count_rmw) {
- /* Emit MI_MATH for each RMW reg: 20dw per reg + 7 trailing dw */
-
+ if (count_rmw || count_rmw_mcr) {
xa_for_each(&sr->xa, idx, entry) {
if (entry->reg.masked || entry->clr_bits == ~0)
continue;
+ if (entry->reg.mcr) {
+ struct xe_reg_mcr reg = { .__reg.raw = entry->reg.raw };
+ u8 group, instance;
+
+ xe_gt_mcr_get_nonterminated_steering(gt, reg, &group, &instance);
+ *cs++ = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1);
+ *cs++ = CS_MMIO_GROUP_INSTANCE_SELECT(hwe->mmio_base).addr;
+ *cs++ = SELECTIVE_READ_ADDRESSING |
+ REG_FIELD_PREP(SELECTIVE_READ_GROUP, group) |
+ REG_FIELD_PREP(SELECTIVE_READ_INSTANCE, instance);
+ }
+
*cs++ = MI_LOAD_REGISTER_REG | MI_LRR_DST_CS_MMIO;
*cs++ = entry->reg.addr;
*cs++ = CS_GPR_REG(0, 0).addr;
@@ -308,8 +342,9 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
*cs++ = CS_GPR_REG(0, 0).addr;
*cs++ = entry->reg.addr;
- xe_gt_dbg(gt, "REG[%#x] = ~%#x|%#x\n",
- entry->reg.addr, entry->clr_bits, entry->set_bits);
+ xe_gt_dbg(gt, "REG[%#x] = ~%#x|%#x%s\n",
+ entry->reg.addr, entry->clr_bits, entry->set_bits,
+ entry->reg.mcr ? " (MCR)" : "");
}
/* reset used GPR */
@@ -321,6 +356,13 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
*cs++ = 0;
*cs++ = CS_GPR_REG(0, 2).addr;
*cs++ = 0;
+
+ /* reset steering */
+ if (count_rmw_mcr) {
+ *cs++ = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1);
+ *cs++ = CS_MMIO_GROUP_INSTANCE_SELECT(q->hwe->mmio_base).addr;
+ *cs++ = 0;
+ }
}
cs = xe_lrc_emit_hwe_state_instructions(q, cs);
diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h
index c307a3fd9ea2..c1c615447c85 100644
--- a/drivers/gpu/drm/xe/xe_lrc.h
+++ b/drivers/gpu/drm/xe/xe_lrc.h
@@ -75,7 +75,8 @@ static inline struct xe_lrc *xe_lrc_get(struct xe_lrc *lrc)
*/
static inline void xe_lrc_put(struct xe_lrc *lrc)
{
- kref_put(&lrc->refcount, xe_lrc_destroy);
+ if (lrc)
+ kref_put(&lrc->refcount, xe_lrc_destroy);
}
/**
diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c
index 2e5c78940b41..a07be161cfa2 100644
--- a/drivers/gpu/drm/xe/xe_reg_sr.c
+++ b/drivers/gpu/drm/xe/xe_reg_sr.c
@@ -98,10 +98,12 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
*pentry = *e;
ret = xa_err(xa_store(&sr->xa, idx, pentry, GFP_KERNEL));
if (ret)
- goto fail;
+ goto fail_free;
return 0;
+fail_free:
+ kfree(pentry);
fail:
xe_gt_err(gt,
"discarding save-restore reg %04lx (clear: %08x, set: %08x, masked: %s, mcr: %s): ret=%d\n",
diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index 248620b0901d..53d420d72164 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -280,6 +280,9 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
+ /* Don't preempt fence signaling */
+ dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
+
if (job->user_fence.used) {
i = emit_flush_dw(dw, i);
i = emit_store_imm_ppgtt_posted(job->user_fence.addr,
@@ -345,6 +348,9 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc,
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
+ /* Don't preempt fence signaling */
+ dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
+
if (job->user_fence.used) {
i = emit_flush_dw(dw, i);
i = emit_store_imm_ppgtt_posted(job->user_fence.addr,
@@ -397,6 +403,9 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
+ /* Don't preempt fence signaling */
+ dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
+
i = emit_render_cache_flush(job, dw, i);
if (job->user_fence.used)
diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
index eb136390dafd..24d6d9af20d6 100644
--- a/drivers/gpu/drm/xe/xe_sync.c
+++ b/drivers/gpu/drm/xe/xe_sync.c
@@ -146,8 +146,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (!signal) {
sync->fence = drm_syncobj_fence_get(sync->syncobj);
- if (XE_IOCTL_DBG(xe, !sync->fence))
- return -EINVAL;
+ if (XE_IOCTL_DBG(xe, !sync->fence)) {
+ err = -EINVAL;
+ goto free_sync;
+ }
}
break;
@@ -167,17 +169,21 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (signal) {
sync->chain_fence = dma_fence_chain_alloc();
- if (!sync->chain_fence)
- return -ENOMEM;
+ if (!sync->chain_fence) {
+ err = -ENOMEM;
+ goto free_sync;
+ }
} else {
sync->fence = drm_syncobj_fence_get(sync->syncobj);
- if (XE_IOCTL_DBG(xe, !sync->fence))
- return -EINVAL;
+ if (XE_IOCTL_DBG(xe, !sync->fence)) {
+ err = -EINVAL;
+ goto free_sync;
+ }
err = dma_fence_chain_find_seqno(&sync->fence,
sync_in.timeline_value);
if (err)
- return err;
+ goto free_sync;
}
break;
@@ -200,8 +206,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence)))
return PTR_ERR(sync->ufence);
sync->ufence_chain_fence = dma_fence_chain_alloc();
- if (!sync->ufence_chain_fence)
- return -ENOMEM;
+ if (!sync->ufence_chain_fence) {
+ err = -ENOMEM;
+ goto free_sync;
+ }
sync->ufence_syncobj = ufence_syncobj;
}
@@ -216,6 +224,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
sync->timeline_value = sync_in.timeline_value;
return 0;
+
+free_sync:
+ xe_sync_entry_cleanup(sync);
+ return err;
}
ALLOW_ERROR_INJECTION(xe_sync_entry_parse, ERRNO);
diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
index 95bf53cc29e3..bc39a9a9790c 100644
--- a/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -453,7 +453,7 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
madvise_range.num_vmas,
args->atomic.val)) {
err = -EINVAL;
- goto madv_fini;
+ goto free_vmas;
}
}
@@ -490,6 +490,7 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
err_fini:
if (madvise_range.has_bo_vmas)
drm_exec_fini(&exec);
+free_vmas:
kfree(madvise_range.vmas);
madvise_range.vmas = NULL;
madv_fini:
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index c7b1bd79ab17..462c2fa712e0 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -241,12 +241,13 @@ static const struct xe_rtp_entry_sr gt_was[] = {
{ XE_RTP_NAME("16025250150"),
XE_RTP_RULES(GRAPHICS_VERSION(2001)),
- XE_RTP_ACTIONS(SET(LSN_VC_REG2,
- LSN_LNI_WGT(1) |
- LSN_LNE_WGT(1) |
- LSN_DIM_X_WGT(1) |
- LSN_DIM_Y_WGT(1) |
- LSN_DIM_Z_WGT(1)))
+ XE_RTP_ACTIONS(FIELD_SET(LSN_VC_REG2,
+ LSN_LNI_WGT_MASK | LSN_LNE_WGT_MASK |
+ LSN_DIM_X_WGT_MASK | LSN_DIM_Y_WGT_MASK |
+ LSN_DIM_Z_WGT_MASK,
+ LSN_LNI_WGT(1) | LSN_LNE_WGT(1) |
+ LSN_DIM_X_WGT(1) | LSN_DIM_Y_WGT(1) |
+ LSN_DIM_Z_WGT(1)))
},
/* Xe2_HPM */
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index b949b767cf08..fc5897a6bb53 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -365,6 +365,9 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
{ "A3R" },
{ "hfd.cn" },
{ "WKB603" },
+ { "TH87" }, /* EPOMAKER TH87 BT mode */
+ { "HFD Epomaker TH87" }, /* EPOMAKER TH87 USB mode */
+ { "2.4G Wireless Receiver" }, /* EPOMAKER TH87 dongle */
};
static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
@@ -686,9 +689,7 @@ static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev,
"fixing up Magic Keyboard battery report descriptor\n");
*rsize = *rsize - 1;
- rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
- if (!rdesc)
- return NULL;
+ rdesc = rdesc + 1;
rdesc[0] = 0x05;
rdesc[1] = 0x01;
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 8ffcd12038e8..687b785e2d0c 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1399,14 +1399,21 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if (*rsize == rsize_orig &&
rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) {
- *rsize = rsize_orig + 1;
- rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
- if (!rdesc)
- return NULL;
+ __u8 *new_rdesc;
+
+ new_rdesc = devm_kzalloc(&hdev->dev, rsize_orig + 1,
+ GFP_KERNEL);
+ if (!new_rdesc)
+ return rdesc;
hid_info(hdev, "Fixing up %s keyb report descriptor\n",
drvdata->quirks & QUIRK_T100CHI ?
"T100CHI" : "T90CHI");
+
+ memcpy(new_rdesc, rdesc, rsize_orig);
+ *rsize = rsize_orig + 1;
+ rdesc = new_rdesc;
+
memmove(rdesc + offs + 4, rdesc + offs + 2, 12);
rdesc[offs] = 0x19;
rdesc[offs + 1] = 0x00;
@@ -1491,6 +1498,9 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_XGM_2023),
+ },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
QUIRK_ROG_CLAYMORE_II_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
diff --git a/drivers/hid/hid-cmedia.c b/drivers/hid/hid-cmedia.c
index 6bc50df9b3e1..7b3dd4197875 100644
--- a/drivers/hid/hid-cmedia.c
+++ b/drivers/hid/hid-cmedia.c
@@ -99,7 +99,7 @@ static int cmhid_raw_event(struct hid_device *hid, struct hid_report *report,
{
struct cmhid *cm = hid_get_drvdata(hid);
- if (len != CM6533_JD_RAWEV_LEN)
+ if (len != CM6533_JD_RAWEV_LEN || !(hid->claimed & HID_CLAIMED_INPUT))
goto out;
if (memcmp(data+CM6533_JD_SFX_OFFSET, ji_sfx, sizeof(ji_sfx)))
goto out;
diff --git a/drivers/hid/hid-creative-sb0540.c b/drivers/hid/hid-creative-sb0540.c
index b4c8e7a5d3e0..dfd6add353d1 100644
--- a/drivers/hid/hid-creative-sb0540.c
+++ b/drivers/hid/hid-creative-sb0540.c
@@ -153,7 +153,7 @@ static int creative_sb0540_raw_event(struct hid_device *hid,
u64 code, main_code;
int key;
- if (len != 6)
+ if (len != 6 || !(hid->claimed & HID_CLAIMED_INPUT))
return 0;
/* From daemons/hw_hiddev.c sb0540_rec() in lirc */
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 3e299a30dcde..4ab7640b119a 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -229,6 +229,7 @@
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c
#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
+#define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 91f621ceb924..9eadf3252d0d 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -990,13 +990,11 @@ static const __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*/
if ((is_usb_magicmouse2(hdev->vendor, hdev->product) ||
is_usb_magictrackpad2(hdev->vendor, hdev->product)) &&
- *rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
+ *rsize >= 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
hid_info(hdev,
"fixing up magicmouse battery report descriptor\n");
*rsize = *rsize - 1;
- rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
- if (!rdesc)
- return NULL;
+ rdesc = rdesc + 1;
rdesc[0] = 0x05;
rdesc[1] = 0x01;
diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index 33603b019f97..ef3b5c77c38e 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -353,6 +353,8 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
usleep_range(90, 100);
retries++;
} else {
+ usleep_range(980, 1000);
+ mcp_cancel_last_cmd(mcp);
return ret;
}
} else {
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 7daa8f6d8187..b8a748bbf0fd 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -77,6 +77,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
#define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
#define MT_QUIRK_YOGABOOK9I BIT(24)
+#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(25)
#define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -214,6 +215,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
#define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017
#define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018
+#define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019
/* vendor specific classes */
#define MT_CLS_3M 0x0101
@@ -233,6 +235,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_SMART_TECH 0x0113
#define MT_CLS_APPLE_TOUCHBAR 0x0114
#define MT_CLS_YOGABOOK9I 0x0115
+#define MT_CLS_EGALAX_P80H84 0x0116
#define MT_CLS_SIS 0x0457
#define MT_DEFAULT_MAXCONTACT 10
@@ -334,6 +337,15 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_WIN8_PTP_BUTTONS,
.export_all_inputs = true },
+ { .name = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
+ .quirks = MT_QUIRK_ALWAYS_VALID |
+ MT_QUIRK_IGNORE_DUPLICATES |
+ MT_QUIRK_HOVERING |
+ MT_QUIRK_CONTACT_CNT_ACCURATE |
+ MT_QUIRK_STICKY_FINGERS |
+ MT_QUIRK_WIN8_PTP_BUTTONS |
+ MT_QUIRK_KEEP_LATENCY_ON_CLOSE,
+ .export_all_inputs = true },
/*
* vendor specific classes
@@ -438,6 +450,11 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_YOGABOOK9I,
.export_all_inputs = true
},
+ { .name = MT_CLS_EGALAX_P80H84,
+ .quirks = MT_QUIRK_ALWAYS_VALID |
+ MT_QUIRK_IGNORE_DUPLICATES |
+ MT_QUIRK_CONTACT_CNT_ACCURATE,
+ },
{ }
};
@@ -849,7 +866,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if ((cls->name == MT_CLS_WIN_8 ||
cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU ||
- cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP) &&
+ cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP ||
+ cls->name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE) &&
(field->application == HID_DG_TOUCHPAD ||
field->application == HID_DG_TOUCHSCREEN))
app->quirks |= MT_QUIRK_CONFIDENCE;
@@ -1762,7 +1780,8 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
int ret;
if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
- td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) {
+ td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
+ td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) {
if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
td->is_haptic_touchpad = false;
} else {
@@ -2075,7 +2094,12 @@ static void mt_on_hid_hw_open(struct hid_device *hdev)
static void mt_on_hid_hw_close(struct hid_device *hdev)
{
- mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
+ struct mt_device *td = hid_get_drvdata(hdev);
+
+ if (td->mtclass.quirks & MT_QUIRK_KEEP_LATENCY_ON_CLOSE)
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_NONE);
+ else
+ mt_set_modes(hdev, HID_LATENCY_HIGH, TOUCHPAD_REPORT_NONE);
}
/*
@@ -2215,8 +2239,9 @@ static const struct hid_device_id mt_devices[] = {
{ .driver_data = MT_CLS_EGALAX_SERIAL,
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C000) },
- { .driver_data = MT_CLS_EGALAX,
- MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ { .driver_data = MT_CLS_EGALAX_P80H84,
+ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8,
+ USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
/* Elan devices */
@@ -2461,6 +2486,14 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+ /* Uniwill touchpads */
+ { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
+ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+ USB_VENDOR_ID_PIXART, 0x0255) },
+ { .driver_data = MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE,
+ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+ USB_VENDOR_ID_PIXART, 0x0274) },
+
/* VTL panels */
{ .driver_data = MT_CLS_VTL,
MT_USB_DEVICE(USB_VENDOR_ID_VTL,
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c
index 3bdb26f45592..1aae80f848f5 100644
--- a/drivers/hid/hid-zydacron.c
+++ b/drivers/hid/hid-zydacron.c
@@ -114,7 +114,7 @@ static int zc_raw_event(struct hid_device *hdev, struct hid_report *report,
unsigned key;
unsigned short index;
- if (report->id == data[0]) {
+ if (report->id == data[0] && (hdev->claimed & HID_CLAIMED_INPUT)) {
/* break keys */
for (index = 0; index < 4; index++) {
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index fa5d68c36313..27389971b96c 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -39,6 +39,8 @@
#define PCI_DEVICE_ID_INTEL_ISH_PTL_H 0xE345
#define PCI_DEVICE_ID_INTEL_ISH_PTL_P 0xE445
#define PCI_DEVICE_ID_INTEL_ISH_WCL 0x4D45
+#define PCI_DEVICE_ID_INTEL_ISH_NVL_H 0xD354
+#define PCI_DEVICE_ID_INTEL_ISH_NVL_S 0x6E78
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 1612e8cb23f0..ed3405c05e73 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -28,11 +28,15 @@ enum ishtp_driver_data_index {
ISHTP_DRIVER_DATA_LNL_M,
ISHTP_DRIVER_DATA_PTL,
ISHTP_DRIVER_DATA_WCL,
+ ISHTP_DRIVER_DATA_NVL_H,
+ ISHTP_DRIVER_DATA_NVL_S,
};
#define ISH_FW_GEN_LNL_M "lnlm"
#define ISH_FW_GEN_PTL "ptl"
#define ISH_FW_GEN_WCL "wcl"
+#define ISH_FW_GEN_NVL_H "nvlh"
+#define ISH_FW_GEN_NVL_S "nvls"
#define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin"
#define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin"
@@ -47,6 +51,12 @@ static struct ishtp_driver_data ishtp_driver_data[] = {
[ISHTP_DRIVER_DATA_WCL] = {
.fw_generation = ISH_FW_GEN_WCL,
},
+ [ISHTP_DRIVER_DATA_NVL_H] = {
+ .fw_generation = ISH_FW_GEN_NVL_H,
+ },
+ [ISHTP_DRIVER_DATA_NVL_S] = {
+ .fw_generation = ISH_FW_GEN_NVL_S,
+ },
};
static const struct pci_device_id ish_pci_tbl[] = {
@@ -76,6 +86,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE_DATA(INTEL, ISH_PTL_H, ISHTP_DRIVER_DATA_PTL)},
{PCI_DEVICE_DATA(INTEL, ISH_PTL_P, ISHTP_DRIVER_DATA_PTL)},
{PCI_DEVICE_DATA(INTEL, ISH_WCL, ISHTP_DRIVER_DATA_WCL)},
+ {PCI_DEVICE_DATA(INTEL, ISH_NVL_H, ISHTP_DRIVER_DATA_NVL_H)},
+ {PCI_DEVICE_DATA(INTEL, ISH_NVL_S, ISHTP_DRIVER_DATA_NVL_S)},
{}
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index fdcf03408f47..fbf3dbc92e66 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -1452,10 +1452,13 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
hid_warn(pidff->hid, "unknown ramp effect layout\n");
if (PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
- if (test_and_clear_bit(FF_SPRING, dev->ffbit) ||
- test_and_clear_bit(FF_DAMPER, dev->ffbit) ||
- test_and_clear_bit(FF_FRICTION, dev->ffbit) ||
- test_and_clear_bit(FF_INERTIA, dev->ffbit))
+ bool test = false;
+
+ test |= test_and_clear_bit(FF_SPRING, dev->ffbit);
+ test |= test_and_clear_bit(FF_DAMPER, dev->ffbit);
+ test |= test_and_clear_bit(FF_FRICTION, dev->ffbit);
+ test |= test_and_clear_bit(FF_INERTIA, dev->ffbit);
+ if (test)
hid_warn(pidff->hid, "unknown condition effect layout\n");
}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 41c381764c2b..486152a8ea77 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1927,16 +1927,6 @@ config SENSORS_RASPBERRYPI_HWMON
This driver can also be built as a module. If so, the module
will be called raspberrypi-hwmon.
-config SENSORS_SA67MCU
- tristate "Kontron sa67mcu hardware monitoring driver"
- depends on MFD_SL28CPLD || COMPILE_TEST
- help
- If you say yes here you get support for the voltage and temperature
- monitor of the sa67 board management controller.
-
- This driver can also be built as a module. If so, the module
- will be called sa67mcu-hwmon.
-
config SENSORS_SL28CPLD
tristate "Kontron sl28cpld hardware monitoring driver"
depends on MFD_SL28CPLD || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index eade8e3b1bde..5833c807c688 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -199,7 +199,6 @@ obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o
obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
-obj-$(CONFIG_SENSORS_SA67MCU) += sa67mcu-hwmon.o
obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o
obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c
index 007befdba977..4ce019d2cc80 100644
--- a/drivers/hwmon/aht10.c
+++ b/drivers/hwmon/aht10.c
@@ -37,7 +37,9 @@
#define AHT10_CMD_MEAS 0b10101100
#define AHT10_CMD_RST 0b10111010
-#define DHT20_CMD_INIT 0x71
+#define AHT20_CMD_INIT 0b10111110
+
+#define DHT20_CMD_INIT 0b01110001
/*
* Flags in the answer byte/command
@@ -341,7 +343,7 @@ static int aht10_probe(struct i2c_client *client)
data->meas_size = AHT20_MEAS_SIZE;
data->crc8 = true;
crc8_populate_msb(crc8_table, AHT20_CRC8_POLY);
- data->init_cmd = AHT10_CMD_INIT;
+ data->init_cmd = AHT20_CMD_INIT;
break;
case dht20:
data->meas_size = AHT20_MEAS_SIZE;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index e233aafa8856..5cfb98a0512f 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -3590,10 +3590,13 @@ static int it87_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct it87_data *data = dev_get_drvdata(dev);
+ int err;
it87_resume_sio(pdev);
- it87_lock(data);
+ err = it87_lock(data);
+ if (err)
+ return err;
it87_check_pwm(dev);
it87_check_limit_regs(data);
diff --git a/drivers/hwmon/macsmc-hwmon.c b/drivers/hwmon/macsmc-hwmon.c
index 1c0bbec7e8eb..1500ec2cc9f8 100644
--- a/drivers/hwmon/macsmc-hwmon.c
+++ b/drivers/hwmon/macsmc-hwmon.c
@@ -22,6 +22,7 @@
#include <linux/bitfield.h>
#include <linux/hwmon.h>
+#include <linux/math64.h>
#include <linux/mfd/macsmc.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -130,7 +131,7 @@ static int macsmc_hwmon_read_ioft_scaled(struct apple_smc *smc, smc_key key,
if (ret < 0)
return ret;
- *p = mult_frac(val, scale, 65536);
+ *p = mul_u64_u32_div(val, scale, 65536);
return 0;
}
@@ -140,7 +141,7 @@ static int macsmc_hwmon_read_ioft_scaled(struct apple_smc *smc, smc_key key,
* them.
*/
static int macsmc_hwmon_read_f32_scaled(struct apple_smc *smc, smc_key key,
- int *p, int scale)
+ long *p, int scale)
{
u32 fval;
u64 val;
@@ -162,21 +163,21 @@ static int macsmc_hwmon_read_f32_scaled(struct apple_smc *smc, smc_key key,
val = 0;
else if (exp < 0)
val >>= -exp;
- else if (exp != 0 && (val & ~((1UL << (64 - exp)) - 1))) /* overflow */
+ else if (exp != 0 && (val & ~((1ULL << (64 - exp)) - 1))) /* overflow */
val = U64_MAX;
else
val <<= exp;
if (fval & FLT_SIGN_MASK) {
- if (val > (-(s64)INT_MIN))
- *p = INT_MIN;
+ if (val > (u64)LONG_MAX + 1)
+ *p = LONG_MIN;
else
- *p = -val;
+ *p = -(long)val;
} else {
- if (val > INT_MAX)
- *p = INT_MAX;
+ if (val > (u64)LONG_MAX)
+ *p = LONG_MAX;
else
- *p = val;
+ *p = (long)val;
}
return 0;
@@ -195,7 +196,7 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
switch (sensor->info.type_code) {
/* 32-bit IEEE 754 float */
case __SMC_KEY('f', 'l', 't', ' '): {
- u32 flt_ = 0;
+ long flt_ = 0;
ret = macsmc_hwmon_read_f32_scaled(smc, sensor->macsmc_key,
&flt_, scale);
@@ -214,7 +215,10 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
if (ret)
return ret;
- *val = (long)ioft;
+ if (ioft > LONG_MAX)
+ *val = LONG_MAX;
+ else
+ *val = (long)ioft;
break;
}
default:
@@ -224,29 +228,26 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
return 0;
}
-static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, int value)
+static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, long value)
{
u64 val;
u32 fval = 0;
- int exp = 0, neg;
+ int exp, neg;
+ neg = value < 0;
val = abs(value);
- neg = val != value;
if (val) {
- int msb = __fls(val) - exp;
-
- if (msb > 23) {
- val >>= msb - FLT_MANT_BIAS;
- exp -= msb - FLT_MANT_BIAS;
- } else if (msb < 23) {
- val <<= FLT_MANT_BIAS - msb;
- exp += msb;
- }
+ exp = __fls(val);
+
+ if (exp > 23)
+ val >>= exp - 23;
+ else
+ val <<= 23 - exp;
fval = FIELD_PREP(FLT_SIGN_MASK, neg) |
FIELD_PREP(FLT_EXP_MASK, exp + FLT_EXP_BIAS) |
- FIELD_PREP(FLT_MANT_MASK, val);
+ FIELD_PREP(FLT_MANT_MASK, val & FLT_MANT_MASK);
}
return apple_smc_write_u32(smc, key, fval);
@@ -663,8 +664,8 @@ static int macsmc_hwmon_populate_sensors(struct macsmc_hwmon *hwmon,
if (!hwmon->volt.sensors)
return -ENOMEM;
- for_each_child_of_node_with_prefix(hwmon_node, key_node, "volt-") {
- sensor = &hwmon->temp.sensors[hwmon->temp.count];
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "voltage-") {
+ sensor = &hwmon->volt.sensors[hwmon->volt.count];
if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
sensor->attrs = HWMON_I_INPUT;
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index a0a1dbbda887..9a3c515efe2e 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -607,7 +607,7 @@ static int max6639_init_client(struct i2c_client *client,
return err;
/* Fans PWM polarity high by default */
- err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00);
+ err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x02);
if (err)
return err;
diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c
index fc030ca34480..d5d60a9af8c5 100644
--- a/drivers/hwmon/pmbus/q54sj108a2.c
+++ b/drivers/hwmon/pmbus/q54sj108a2.c
@@ -79,7 +79,8 @@ static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
int idx = *idxp;
struct q54sj108a2_data *psu = to_psu(idxp, idx);
char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
- char data_char[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
+ char data_char[I2C_SMBUS_BLOCK_MAX * 2 + 2] = { 0 };
+ char *out = data;
char *res;
switch (idx) {
@@ -150,27 +151,27 @@ static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
if (rc < 0)
return rc;
- res = bin2hex(data, data_char, 32);
- rc = res - data;
-
+ res = bin2hex(data_char, data, rc);
+ rc = res - data_char;
+ out = data_char;
break;
case Q54SJ108A2_DEBUGFS_FLASH_KEY:
rc = i2c_smbus_read_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, data);
if (rc < 0)
return rc;
- res = bin2hex(data, data_char, 4);
- rc = res - data;
-
+ res = bin2hex(data_char, data, rc);
+ rc = res - data_char;
+ out = data_char;
break;
default:
return -EINVAL;
}
- data[rc] = '\n';
+ out[rc] = '\n';
rc += 2;
- return simple_read_from_buffer(buf, count, ppos, data, rc);
+ return simple_read_from_buffer(buf, count, ppos, out, rc);
}
static ssize_t q54sj108a2_debugfs_write(struct file *file, const char __user *buf,
diff --git a/drivers/hwmon/sa67mcu-hwmon.c b/drivers/hwmon/sa67mcu-hwmon.c
deleted file mode 100644
index 22f703b7b256..000000000000
--- a/drivers/hwmon/sa67mcu-hwmon.c
+++ /dev/null
@@ -1,161 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * sl67mcu hardware monitoring driver
- *
- * Copyright 2025 Kontron Europe GmbH
- */
-
-#include <linux/bitfield.h>
-#include <linux/hwmon.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/property.h>
-#include <linux/regmap.h>
-
-#define SA67MCU_VOLTAGE(n) (0x00 + ((n) * 2))
-#define SA67MCU_TEMP(n) (0x04 + ((n) * 2))
-
-struct sa67mcu_hwmon {
- struct regmap *regmap;
- u32 offset;
-};
-
-static int sa67mcu_hwmon_read(struct device *dev,
- enum hwmon_sensor_types type, u32 attr,
- int channel, long *input)
-{
- struct sa67mcu_hwmon *hwmon = dev_get_drvdata(dev);
- unsigned int offset;
- u8 reg[2];
- int ret;
-
- switch (type) {
- case hwmon_in:
- switch (attr) {
- case hwmon_in_input:
- offset = hwmon->offset + SA67MCU_VOLTAGE(channel);
- break;
- default:
- return -EOPNOTSUPP;
- }
- break;
- case hwmon_temp:
- switch (attr) {
- case hwmon_temp_input:
- offset = hwmon->offset + SA67MCU_TEMP(channel);
- break;
- default:
- return -EOPNOTSUPP;
- }
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- /* Reading the low byte will capture the value */
- ret = regmap_bulk_read(hwmon->regmap, offset, reg, ARRAY_SIZE(reg));
- if (ret)
- return ret;
-
- *input = reg[1] << 8 | reg[0];
-
- /* Temperatures are s16 and in 0.1degC steps. */
- if (type == hwmon_temp)
- *input = sign_extend32(*input, 15) * 100;
-
- return 0;
-}
-
-static const struct hwmon_channel_info * const sa67mcu_hwmon_info[] = {
- HWMON_CHANNEL_INFO(in,
- HWMON_I_INPUT | HWMON_I_LABEL,
- HWMON_I_INPUT | HWMON_I_LABEL),
- HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
- NULL
-};
-
-static const char *const sa67mcu_hwmon_in_labels[] = {
- "VDDIN",
- "VDD_RTC",
-};
-
-static int sa67mcu_hwmon_read_string(struct device *dev,
- enum hwmon_sensor_types type, u32 attr,
- int channel, const char **str)
-{
- switch (type) {
- case hwmon_in:
- switch (attr) {
- case hwmon_in_label:
- *str = sa67mcu_hwmon_in_labels[channel];
- return 0;
- default:
- return -EOPNOTSUPP;
- }
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static const struct hwmon_ops sa67mcu_hwmon_ops = {
- .visible = 0444,
- .read = sa67mcu_hwmon_read,
- .read_string = sa67mcu_hwmon_read_string,
-};
-
-static const struct hwmon_chip_info sa67mcu_hwmon_chip_info = {
- .ops = &sa67mcu_hwmon_ops,
- .info = sa67mcu_hwmon_info,
-};
-
-static int sa67mcu_hwmon_probe(struct platform_device *pdev)
-{
- struct sa67mcu_hwmon *hwmon;
- struct device *hwmon_dev;
- int ret;
-
- if (!pdev->dev.parent)
- return -ENODEV;
-
- hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
- if (!hwmon)
- return -ENOMEM;
-
- hwmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
- if (!hwmon->regmap)
- return -ENODEV;
-
- ret = device_property_read_u32(&pdev->dev, "reg", &hwmon->offset);
- if (ret)
- return -EINVAL;
-
- hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
- "sa67mcu_hwmon", hwmon,
- &sa67mcu_hwmon_chip_info,
- NULL);
- if (IS_ERR(hwmon_dev))
- dev_err(&pdev->dev, "failed to register as hwmon device");
-
- return PTR_ERR_OR_ZERO(hwmon_dev);
-}
-
-static const struct of_device_id sa67mcu_hwmon_of_match[] = {
- { .compatible = "kontron,sa67mcu-hwmon", },
- {}
-};
-MODULE_DEVICE_TABLE(of, sa67mcu_hwmon_of_match);
-
-static struct platform_driver sa67mcu_hwmon_driver = {
- .probe = sa67mcu_hwmon_probe,
- .driver = {
- .name = "sa67mcu-hwmon",
- .of_match_table = sa67mcu_hwmon_of_match,
- },
-};
-module_platform_driver(sa67mcu_hwmon_driver);
-
-MODULE_DESCRIPTION("sa67mcu Hardware Monitoring Driver");
-MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 9e1789725edf..32a3cef02c7b 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -310,9 +310,10 @@ struct i801_priv {
/*
* If set to true the host controller registers are reserved for
- * ACPI AML use.
+ * ACPI AML use. Needs extra protection by acpi_lock.
*/
bool acpi_reserved;
+ struct mutex acpi_lock;
};
#define FEATURE_SMBUS_PEC BIT(0)
@@ -894,8 +895,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
int hwpec, ret;
struct i801_priv *priv = i2c_get_adapdata(adap);
- if (priv->acpi_reserved)
+ mutex_lock(&priv->acpi_lock);
+ if (priv->acpi_reserved) {
+ mutex_unlock(&priv->acpi_lock);
return -EBUSY;
+ }
pm_runtime_get_sync(&priv->pci_dev->dev);
@@ -935,6 +939,7 @@ out:
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+ mutex_unlock(&priv->acpi_lock);
return ret;
}
@@ -1465,7 +1470,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
* further access from the driver itself. This device is now owned
* by the system firmware.
*/
- i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
+ mutex_lock(&priv->acpi_lock);
if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
priv->acpi_reserved = true;
@@ -1485,7 +1490,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
else
status = acpi_os_write_port(address, (u32)*value, bits);
- i2c_unlock_bus(&priv->adapter, I2C_LOCK_SEGMENT);
+ mutex_unlock(&priv->acpi_lock);
return status;
}
@@ -1545,6 +1550,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
priv->adapter.dev.parent = &dev->dev;
acpi_use_parent_companion(&priv->adapter.dev);
priv->adapter.retries = 3;
+ mutex_init(&priv->acpi_lock);
priv->pci_dev = dev;
priv->features = id->driver_data;
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 794b9778816b..78ac2ff5befd 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -6,6 +6,7 @@ menuconfig INFINIBAND
depends on INET
depends on m || IPV6 != m
depends on !ALPHA
+ select DMA_SHARED_BUFFER
select IRQ_POLL
select DIMLIB
help
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index b415d4aad04f..ee4a2bc68fb2 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -926,6 +926,13 @@ static int gid_table_setup_one(struct ib_device *ib_dev)
if (err)
return err;
+ /*
+ * Mark the device as ready for GID cache updates. This allows netdev
+ * event handlers to update the GID cache even before the device is
+ * fully registered.
+ */
+ ib_device_enable_gid_updates(ib_dev);
+
rdma_roce_rescan_device(ib_dev);
return err;
@@ -1637,6 +1644,12 @@ void ib_cache_release_one(struct ib_device *device)
void ib_cache_cleanup_one(struct ib_device *device)
{
+ /*
+ * Clear the GID updates mark first to prevent event handlers from
+ * accessing the device while it's being torn down.
+ */
+ ib_device_disable_gid_updates(device);
+
/* The cleanup function waits for all in-progress workqueue
* elements and cleans up the GID cache. This function should be
* called after the device was removed from the devices list and
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index e54c07c74575..9480d1a51c11 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2729,6 +2729,9 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv,
*to_destroy = NULL;
if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
return 0;
+ if (id_priv->restricted_node_type != RDMA_NODE_UNSPECIFIED &&
+ id_priv->restricted_node_type != cma_dev->device->node_type)
+ return 0;
dev_id_priv =
__rdma_create_id(net, cma_listen_handler, id_priv,
@@ -2736,6 +2739,7 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv,
if (IS_ERR(dev_id_priv))
return PTR_ERR(dev_id_priv);
+ dev_id_priv->restricted_node_type = id_priv->restricted_node_type;
dev_id_priv->state = RDMA_CM_ADDR_BOUND;
memcpy(cma_src_addr(dev_id_priv), cma_src_addr(id_priv),
rdma_addr_size(cma_src_addr(id_priv)));
@@ -4194,7 +4198,7 @@ int rdma_restrict_node_type(struct rdma_cm_id *id, u8 node_type)
}
mutex_lock(&lock);
- if (id_priv->cma_dev)
+ if (READ_ONCE(id_priv->state) != RDMA_CM_IDLE)
ret = -EALREADY;
else
id_priv->restricted_node_type = node_type;
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 05102769a918..a2c36666e6fc 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -100,6 +100,9 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter,
roce_netdev_callback cb,
void *cookie);
+void ib_device_enable_gid_updates(struct ib_device *device);
+void ib_device_disable_gid_updates(struct ib_device *device);
+
typedef int (*nldev_callback)(struct ib_device *device,
struct sk_buff *skb,
struct netlink_callback *cb,
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 1b5f1ee0a557..558b73940d66 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -93,6 +93,7 @@ static struct workqueue_struct *ib_unreg_wq;
static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC);
static DECLARE_RWSEM(devices_rwsem);
#define DEVICE_REGISTERED XA_MARK_1
+#define DEVICE_GID_UPDATES XA_MARK_2
static u32 highest_client_id;
#define CLIENT_REGISTERED XA_MARK_1
@@ -2412,11 +2413,42 @@ void ib_enum_all_roce_netdevs(roce_netdev_filter filter,
unsigned long index;
down_read(&devices_rwsem);
- xa_for_each_marked (&devices, index, dev, DEVICE_REGISTERED)
+ xa_for_each_marked(&devices, index, dev, DEVICE_GID_UPDATES)
ib_enum_roce_netdev(dev, filter, filter_cookie, cb, cookie);
up_read(&devices_rwsem);
}
+/**
+ * ib_device_enable_gid_updates - Mark device as ready for GID cache updates
+ * @device: Device to mark
+ *
+ * Called after GID table is allocated and initialized. After this mark is set,
+ * netdevice event handlers can update the device's GID cache. This allows
+ * events that arrive during device registration to be processed, avoiding
+ * stale GID entries when netdev properties change during the device
+ * registration process.
+ */
+void ib_device_enable_gid_updates(struct ib_device *device)
+{
+ down_write(&devices_rwsem);
+ xa_set_mark(&devices, device->index, DEVICE_GID_UPDATES);
+ up_write(&devices_rwsem);
+}
+
+/**
+ * ib_device_disable_gid_updates - Clear the GID updates mark
+ * @device: Device to unmark
+ *
+ * Called before GID table cleanup to prevent event handlers from accessing
+ * the device while it's being torn down.
+ */
+void ib_device_disable_gid_updates(struct ib_device *device)
+{
+ down_write(&devices_rwsem);
+ xa_clear_mark(&devices, device->index, DEVICE_GID_UPDATES);
+ up_write(&devices_rwsem);
+}
+
/*
* ib_enum_all_devs - enumerate all ib_devices
* @cb: Callback to call for each found ib_device
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index f5298c33e581..d30f24b90bca 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -218,13 +218,11 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
err = ib_umem_dmabuf_map_pages(umem_dmabuf);
if (err)
- goto err_unpin;
+ goto err_release;
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
return umem_dmabuf;
-err_unpin:
- dma_buf_unpin(umem_dmabuf->attach);
err_release:
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
ib_umem_release(&umem_dmabuf->umem);
diff --git a/drivers/infiniband/core/uverbs_std_types_dmabuf.c b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
index dfdfcd1d1a44..4a7f8b6f9dc8 100644
--- a/drivers/infiniband/core/uverbs_std_types_dmabuf.c
+++ b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
@@ -10,6 +10,8 @@
#include "rdma_core.h"
#include "uverbs.h"
+MODULE_IMPORT_NS("DMA_BUF");
+
static int uverbs_dmabuf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attachment)
{
diff --git a/drivers/infiniband/hw/bng_re/bng_dev.c b/drivers/infiniband/hw/bng_re/bng_dev.c
index cf3bf08e5f26..d34b5f88cd40 100644
--- a/drivers/infiniband/hw/bng_re/bng_dev.c
+++ b/drivers/infiniband/hw/bng_re/bng_dev.c
@@ -54,9 +54,6 @@ static void bng_re_destroy_chip_ctx(struct bng_re_dev *rdev)
{
struct bng_re_chip_ctx *chip_ctx;
- if (!rdev->chip_ctx)
- return;
-
kfree(rdev->dev_attr);
rdev->dev_attr = NULL;
@@ -124,12 +121,6 @@ static int bng_re_net_ring_free(struct bng_re_dev *rdev,
struct bnge_fw_msg fw_msg = {};
int rc = -EINVAL;
- if (!rdev)
- return rc;
-
- if (!aux_dev)
- return rc;
-
bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE);
req.ring_type = type;
req.ring_id = cpu_to_le16(fw_ring_id);
@@ -150,10 +141,7 @@ static int bng_re_net_ring_alloc(struct bng_re_dev *rdev,
struct hwrm_ring_alloc_input req = {};
struct hwrm_ring_alloc_output resp;
struct bnge_fw_msg fw_msg = {};
- int rc = -EINVAL;
-
- if (!aux_dev)
- return rc;
+ int rc;
bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_ALLOC);
req.enables = 0;
@@ -184,10 +172,7 @@ static int bng_re_stats_ctx_free(struct bng_re_dev *rdev)
struct hwrm_stat_ctx_free_input req = {};
struct hwrm_stat_ctx_free_output resp = {};
struct bnge_fw_msg fw_msg = {};
- int rc = -EINVAL;
-
- if (!aux_dev)
- return rc;
+ int rc;
bng_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_FREE);
req.stat_ctx_id = cpu_to_le32(rdev->stats_ctx.fw_id);
@@ -208,13 +193,10 @@ static int bng_re_stats_ctx_alloc(struct bng_re_dev *rdev)
struct hwrm_stat_ctx_alloc_output resp = {};
struct hwrm_stat_ctx_alloc_input req = {};
struct bnge_fw_msg fw_msg = {};
- int rc = -EINVAL;
+ int rc;
stats->fw_id = BNGE_INVALID_STATS_CTX_ID;
- if (!aux_dev)
- return rc;
-
bng_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_ALLOC);
req.update_period_ms = cpu_to_le32(1000);
req.stats_dma_addr = cpu_to_le64(stats->dma_map);
@@ -303,7 +285,7 @@ static int bng_re_dev_init(struct bng_re_dev *rdev)
if (rc) {
ibdev_err(&rdev->ibdev,
"Failed to register with netedev: %#x\n", rc);
- return -EINVAL;
+ goto reg_netdev_fail;
}
set_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
@@ -312,19 +294,16 @@ static int bng_re_dev_init(struct bng_re_dev *rdev)
ibdev_err(&rdev->ibdev,
"RoCE requires minimum 2 MSI-X vectors, but only %d reserved\n",
rdev->aux_dev->auxr_info->msix_requested);
- bnge_unregister_dev(rdev->aux_dev);
- clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
- return -EINVAL;
+ rc = -EINVAL;
+ goto msix_ctx_fail;
}
ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
rdev->aux_dev->auxr_info->msix_requested);
rc = bng_re_setup_chip_ctx(rdev);
if (rc) {
- bnge_unregister_dev(rdev->aux_dev);
- clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
- return -EINVAL;
+ goto msix_ctx_fail;
}
bng_re_query_hwrm_version(rdev);
@@ -333,16 +312,14 @@ static int bng_re_dev_init(struct bng_re_dev *rdev)
if (rc) {
ibdev_err(&rdev->ibdev,
"Failed to allocate RCFW Channel: %#x\n", rc);
- goto fail;
+ goto alloc_fw_chl_fail;
}
/* Allocate nq record memory */
rdev->nqr = kzalloc_obj(*rdev->nqr);
if (!rdev->nqr) {
- bng_re_destroy_chip_ctx(rdev);
- bnge_unregister_dev(rdev->aux_dev);
- clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto nq_alloc_fail;
}
rdev->nqr->num_msix = rdev->aux_dev->auxr_info->msix_requested;
@@ -411,9 +388,15 @@ disable_rcfw:
free_ring:
bng_re_net_ring_free(rdev, rdev->rcfw.creq.ring_id, type);
free_rcfw:
+ kfree(rdev->nqr);
+nq_alloc_fail:
bng_re_free_rcfw_channel(&rdev->rcfw);
-fail:
- bng_re_dev_uninit(rdev);
+alloc_fw_chl_fail:
+ bng_re_destroy_chip_ctx(rdev);
+msix_ctx_fail:
+ bnge_unregister_dev(rdev->aux_dev);
+ clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
+reg_netdev_fail:
return rc;
}
@@ -486,8 +469,7 @@ static void bng_re_remove(struct auxiliary_device *adev)
rdev = dev_info->rdev;
- if (rdev)
- bng_re_remove_device(rdev, adev);
+ bng_re_remove_device(rdev, adev);
kfree(dev_info);
}
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index b5b93b42e6c4..b0aa7c0238ed 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -1661,7 +1661,7 @@ static struct efa_mr *efa_alloc_mr(struct ib_pd *ibpd, int access_flags,
struct efa_mr *mr;
if (udata && udata->inlen &&
- !ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) {
+ !ib_is_udata_cleared(udata, 0, udata->inlen)) {
ibdev_dbg(&dev->ibdev,
"Incompatible ABI params, udata not cleared\n");
return ERR_PTR(-EINVAL);
diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index 5b3f40bd98d8..4842931f5316 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -1218,7 +1218,7 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx);
struct ionic_vcq *vcq = to_ionic_vcq(ibcq);
struct ionic_tbl_buf buf = {};
- struct ionic_cq_resp resp;
+ struct ionic_cq_resp resp = {};
struct ionic_cq_req req;
int udma_idx = 0, rc;
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index 164046d00e5d..bd4c73e530d0 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -81,6 +81,8 @@ static int ionic_query_port(struct ib_device *ibdev, u32 port,
return -EINVAL;
ndev = ib_device_get_netdev(ibdev, port);
+ if (!ndev)
+ return -ENODEV;
if (netif_running(ndev) && netif_carrier_ok(ndev)) {
attr->state = IB_PORT_ACTIVE;
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 15af53237217..7251cd7a2147 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -5212,7 +5212,7 @@ static int irdma_create_user_ah(struct ib_ah *ibah,
#define IRDMA_CREATE_AH_MIN_RESP_LEN offsetofend(struct irdma_create_ah_resp, rsvd)
struct irdma_ah *ah = container_of(ibah, struct irdma_ah, ibah);
struct irdma_device *iwdev = to_iwdev(ibah->pd->device);
- struct irdma_create_ah_resp uresp;
+ struct irdma_create_ah_resp uresp = {};
struct irdma_ah *parent_ah;
int err;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index ef0635064fba..5c182ae4fc2f 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -428,6 +428,8 @@ static int mthca_create_srq(struct ib_srq *ibsrq,
if (context && ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
mthca_free_srq(to_mdev(ibsrq->device), srq);
+ mthca_unmap_user_db(to_mdev(ibsrq->device), &context->uar,
+ context->db_tab, ucmd.db_index);
return -EFAULT;
}
@@ -436,6 +438,7 @@ static int mthca_create_srq(struct ib_srq *ibsrq,
static int mthca_destroy_srq(struct ib_srq *srq, struct ib_udata *udata)
{
+ mthca_free_srq(to_mdev(srq->device), to_msrq(srq));
if (udata) {
struct mthca_ucontext *context =
rdma_udata_to_drv_context(
@@ -446,8 +449,6 @@ static int mthca_destroy_srq(struct ib_srq *srq, struct ib_udata *udata)
mthca_unmap_user_db(to_mdev(srq->device), &context->uar,
context->db_tab, to_msrq(srq)->db_index);
}
-
- mthca_free_srq(to_mdev(srq->device), to_msrq(srq));
return 0;
}
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 30783814f9d9..291d7668cc8d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3474,6 +3474,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
int lpi_base;
int nr_lpis;
int nr_ites;
+ int id_bits;
int sz;
if (!its_alloc_device_table(its, dev_id))
@@ -3485,7 +3486,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
/*
* Even if the device wants a single LPI, the ITT must be
* sized as a power of two (and you need at least one bit...).
+ * Also honor the ITS's own EID limit.
*/
+ id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+ nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
sz = max(sz, ITS_ITT_ALIGN);
diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
index e518e5dfede7..f3fce0b1e25d 100644
--- a/drivers/irqchip/irq-gic-v5-irs.c
+++ b/drivers/irqchip/irq-gic-v5-irs.c
@@ -699,7 +699,7 @@ static int __init gicv5_irs_init(struct gicv5_irs_chip_data *irs_data)
*/
if (list_empty(&irs_nodes)) {
idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR0);
- gicv5_global_data.virt_capable = !FIELD_GET(GICV5_IRS_IDR0_VIRT, idr);
+ gicv5_global_data.virt_capable = !!FIELD_GET(GICV5_IRS_IDR0_VIRT, idr);
idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1);
irs_setup_pri_bits(idr);
diff --git a/drivers/irqchip/irq-ls-extirq.c b/drivers/irqchip/irq-ls-extirq.c
index a7e9c3885b09..d724fe843980 100644
--- a/drivers/irqchip/irq-ls-extirq.c
+++ b/drivers/irqchip/irq-ls-extirq.c
@@ -125,32 +125,45 @@ static const struct irq_domain_ops extirq_domain_ops = {
static int
ls_extirq_parse_map(struct ls_extirq_data *priv, struct device_node *node)
{
- struct of_imap_parser imap_parser;
- struct of_imap_item imap_item;
+ const __be32 *map;
+ u32 mapsize;
int ret;
- ret = of_imap_parser_init(&imap_parser, node, &imap_item);
- if (ret)
- return ret;
+ map = of_get_property(node, "interrupt-map", &mapsize);
+ if (!map)
+ return -ENOENT;
+ if (mapsize % sizeof(*map))
+ return -EINVAL;
+ mapsize /= sizeof(*map);
- for_each_of_imap_item(&imap_parser, &imap_item) {
+ while (mapsize) {
struct device_node *ipar;
- u32 hwirq;
- int i;
+ u32 hwirq, intsize, j;
- hwirq = imap_item.child_imap[0];
- if (hwirq >= MAXIRQ) {
- of_node_put(imap_item.parent_args.np);
+ if (mapsize < 3)
+ return -EINVAL;
+ hwirq = be32_to_cpup(map);
+ if (hwirq >= MAXIRQ)
return -EINVAL;
- }
priv->nirq = max(priv->nirq, hwirq + 1);
- ipar = of_node_get(imap_item.parent_args.np);
- priv->map[hwirq].fwnode = of_fwnode_handle(ipar);
+ ipar = of_find_node_by_phandle(be32_to_cpup(map + 2));
+ map += 3;
+ mapsize -= 3;
+ if (!ipar)
+ return -EINVAL;
+ priv->map[hwirq].fwnode = &ipar->fwnode;
+ ret = of_property_read_u32(ipar, "#interrupt-cells", &intsize);
+ if (ret)
+ return ret;
- priv->map[hwirq].param_count = imap_item.parent_args.args_count;
- for (i = 0; i < priv->map[hwirq].param_count; i++)
- priv->map[hwirq].param[i] = imap_item.parent_args.args[i];
+ if (intsize > mapsize)
+ return -EINVAL;
+
+ priv->map[hwirq].param_count = intsize;
+ for (j = 0; j < intsize; ++j)
+ priv->map[hwirq].param[j] = be32_to_cpup(map++);
+ mapsize -= intsize;
}
return 0;
}
@@ -177,8 +190,10 @@ static int ls_extirq_probe(struct platform_device *pdev)
return dev_err_probe(dev, -ENOMEM, "Failed to allocate memory\n");
priv->intpcr = devm_of_iomap(dev, node, 0, NULL);
- if (!priv->intpcr)
- return dev_err_probe(dev, -ENOMEM, "Cannot ioremap OF node %pOF\n", node);
+ if (IS_ERR(priv->intpcr)) {
+ return dev_err_probe(dev, PTR_ERR(priv->intpcr),
+ "Cannot ioremap OF node %pOF\n", node);
+ }
ret = ls_extirq_parse_map(priv, node);
if (ret)
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
index 09e640430208..8e210cb451be 100644
--- a/drivers/irqchip/irq-mmp.c
+++ b/drivers/irqchip/irq-mmp.c
@@ -136,7 +136,7 @@ static void icu_unmask_irq(struct irq_data *d)
}
}
-struct irq_chip icu_irq_chip = {
+static const struct irq_chip icu_irq_chip = {
.name = "icu_irq",
.irq_mask = icu_mask_irq,
.irq_mask_ack = icu_mask_ack_irq,
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 686d39254426..5b0dac104814 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -172,8 +172,13 @@ static void plic_irq_disable(struct irq_data *d)
static void plic_irq_eoi(struct irq_data *d)
{
struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
+ u32 __iomem *reg;
+ bool enabled;
+
+ reg = handler->enable_base + (d->hwirq / 32) * sizeof(u32);
+ enabled = readl(reg) & BIT(d->hwirq % 32);
- if (unlikely(irqd_irq_disabled(d))) {
+ if (unlikely(!enabled)) {
plic_toggle(handler, d->hwirq, 1);
writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
plic_toggle(handler, d->hwirq, 0);
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index 7cfed24054d0..3c8bc75e4d6c 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -168,7 +168,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
mutex_unlock(&dmxdev->mutex);
return -ENOMEM;
}
- dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+ dmxdev->dvr_buffer.data = mem;
+ dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE;
+ dvb_ringbuffer_reset(&dmxdev->dvr_buffer);
if (dmxdev->may_do_mmap)
dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
&dmxdev->mutex,
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index 8bb8dd34c223..a2159b2bc176 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -228,6 +228,9 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
unsigned char htype = p->ule_sndu_type & 0x00FF;
+ if (htype >= ARRAY_SIZE(ule_mandatory_ext_handlers))
+ return -1;
+
/* Discriminate mandatory and optional extension headers. */
if (hlen == 0) {
/* Mandatory extension header */
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 4e3423a19bdf..ac069d0c42b2 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -36,6 +36,8 @@ struct dw_mci_rockchip_priv_data {
int default_sample_phase;
int num_phases;
bool internal_phase;
+ int sample_phase;
+ int drv_phase;
};
/*
@@ -573,9 +575,43 @@ static void dw_mci_rockchip_remove(struct platform_device *pdev)
dw_mci_pltfm_remove(pdev);
}
+static int dw_mci_rockchip_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dw_mci *host = platform_get_drvdata(pdev);
+ struct dw_mci_rockchip_priv_data *priv = host->priv;
+
+ if (priv->internal_phase) {
+ priv->sample_phase = rockchip_mmc_get_phase(host, true);
+ priv->drv_phase = rockchip_mmc_get_phase(host, false);
+ }
+
+ return dw_mci_runtime_suspend(dev);
+}
+
+static int dw_mci_rockchip_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dw_mci *host = platform_get_drvdata(pdev);
+ struct dw_mci_rockchip_priv_data *priv = host->priv;
+ int ret;
+
+ ret = dw_mci_runtime_resume(dev);
+ if (ret)
+ return ret;
+
+ if (priv->internal_phase) {
+ rockchip_mmc_set_phase(host, true, priv->sample_phase);
+ rockchip_mmc_set_phase(host, false, priv->drv_phase);
+ mci_writel(host, MISC_CON, MEM_CLK_AUTOGATE_ENABLE);
+ }
+
+ return ret;
+}
+
static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
- RUNTIME_PM_OPS(dw_mci_runtime_suspend, dw_mci_runtime_resume, NULL)
+ RUNTIME_PM_OPS(dw_mci_rockchip_runtime_suspend, dw_mci_rockchip_runtime_resume, NULL)
};
static struct platform_driver dw_mci_rockchip_pltfm_driver = {
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index 3da6112fbe39..67371389cc33 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -109,6 +109,7 @@ static int of_get_dml_pipe_index(struct device_node *np, const char *name)
&dma_spec))
return -ENODEV;
+ of_node_put(dma_spec.np);
if (dma_spec.args_count)
return dma_spec.args[0];
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index c9442499876c..57e45951644e 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -116,7 +116,7 @@ static void sdhci_brcmstb_restore_regs(struct mmc_host *mmc, enum cfg_core_ver v
writel(sr->boot_main_ctl, priv->boot_regs + SDIO_BOOT_MAIN_CTL);
if (ver == SDIO_CFG_CORE_V1) {
- writel(sr->sd_pin_sel, cr + SDIO_CFG_SD_PIN_SEL);
+ writel(sr->sd_pin_sel, cr + SDIO_CFG_V1_SD_PIN_SEL);
return;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a1de08ee3815..14ed91391fcc 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -324,7 +324,7 @@ static bool bond_sk_check(struct bonding *bond)
}
}
-bool bond_xdp_check(struct bonding *bond, int mode)
+bool __bond_xdp_check(int mode, int xmit_policy)
{
switch (mode) {
case BOND_MODE_ROUNDROBIN:
@@ -335,7 +335,7 @@ bool bond_xdp_check(struct bonding *bond, int mode)
/* vlan+srcmac is not supported with XDP as in most cases the 802.1q
* payload is not in the packet due to hardware offload.
*/
- if (bond->params.xmit_policy != BOND_XMIT_POLICY_VLAN_SRCMAC)
+ if (xmit_policy != BOND_XMIT_POLICY_VLAN_SRCMAC)
return true;
fallthrough;
default:
@@ -343,6 +343,11 @@ bool bond_xdp_check(struct bonding *bond, int mode)
}
}
+bool bond_xdp_check(struct bonding *bond, int mode)
+{
+ return __bond_xdp_check(mode, bond->params.xmit_policy);
+}
+
/*---------------------------------- VLAN -----------------------------------*/
/* In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index dcee384c2f06..7380cc4ee75a 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1575,6 +1575,8 @@ static int bond_option_fail_over_mac_set(struct bonding *bond,
static int bond_option_xmit_hash_policy_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
+ if (bond->xdp_prog && !__bond_xdp_check(BOND_MODE(bond), newval->value))
+ return -EOPNOTSUPP;
netdev_dbg(bond->dev, "Setting xmit hash policy to %s (%llu)\n",
newval->string, newval->value);
bond->params.xmit_policy = newval->value;
diff --git a/drivers/net/can/dummy_can.c b/drivers/net/can/dummy_can.c
index 41953655e3d3..cd23de488edc 100644
--- a/drivers/net/can/dummy_can.c
+++ b/drivers/net/can/dummy_can.c
@@ -241,6 +241,7 @@ static int __init dummy_can_init(void)
dev->netdev_ops = &dummy_can_netdev_ops;
dev->ethtool_ops = &dummy_can_ethtool_ops;
+ dev->flags |= IFF_ECHO; /* enable echo handling */
priv = netdev_priv(dev);
priv->can.bittiming_const = &dummy_can_bittiming_const;
priv->can.bitrate_max = 20 * MEGA /* BPS */;
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index fa97adf25b73..bb7782582f40 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1214,6 +1214,7 @@ static int mcp251x_open(struct net_device *net)
{
struct mcp251x_priv *priv = netdev_priv(net);
struct spi_device *spi = priv->spi;
+ bool release_irq = false;
unsigned long flags = 0;
int ret;
@@ -1257,12 +1258,24 @@ static int mcp251x_open(struct net_device *net)
return 0;
out_free_irq:
- free_irq(spi->irq, priv);
+ /* The IRQ handler might be running, and if so it will be waiting
+ * for the lock. But free_irq() must wait for the handler to finish
+ * so calling it here would deadlock.
+ *
+ * Setting priv->force_quit will let the handler exit right away
+ * without any access to the hardware. This make it safe to call
+ * free_irq() after the lock is released.
+ */
+ priv->force_quit = 1;
+ release_irq = true;
+
mcp251x_hw_sleep(spi);
out_close:
mcp251x_power_enable(priv->transceiver, 0);
close_candev(net);
mutex_unlock(&priv->mcp_lock);
+ if (release_irq)
+ free_irq(spi->irq, priv);
return ret;
}
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 4c219a5b139b..9b25dda7c183 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -445,6 +445,11 @@ static void ems_usb_read_bulk_callback(struct urb *urb)
start = CPC_HEADER_SIZE;
while (msg_count) {
+ if (start + CPC_MSG_HEADER_LEN > urb->actual_length) {
+ netdev_err(netdev, "format error\n");
+ break;
+ }
+
msg = (struct ems_cpc_msg *)&ibuf[start];
switch (msg->type) {
@@ -474,7 +479,7 @@ static void ems_usb_read_bulk_callback(struct urb *urb)
start += CPC_MSG_HEADER_LEN + msg->length;
msg_count--;
- if (start > urb->transfer_buffer_length) {
+ if (start > urb->actual_length) {
netdev_err(netdev, "format error\n");
break;
}
diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
index 2892a68f510a..d257440fa01f 100644
--- a/drivers/net/can/usb/esd_usb.c
+++ b/drivers/net/can/usb/esd_usb.c
@@ -272,6 +272,9 @@ struct esd_usb {
struct usb_anchor rx_submitted;
+ unsigned int rx_pipe;
+ unsigned int tx_pipe;
+
int net_count;
u32 version;
int rxinitdone;
@@ -537,7 +540,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
}
resubmit_urb:
- usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
+ usb_fill_bulk_urb(urb, dev->udev, dev->rx_pipe,
urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
@@ -626,9 +629,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg)
{
int actual_length;
- return usb_bulk_msg(dev->udev,
- usb_sndbulkpipe(dev->udev, 2),
- msg,
+ return usb_bulk_msg(dev->udev, dev->tx_pipe, msg,
msg->hdr.len * sizeof(u32), /* convert to # of bytes */
&actual_length,
1000);
@@ -639,12 +640,8 @@ static int esd_usb_wait_msg(struct esd_usb *dev,
{
int actual_length;
- return usb_bulk_msg(dev->udev,
- usb_rcvbulkpipe(dev->udev, 1),
- msg,
- sizeof(*msg),
- &actual_length,
- 1000);
+ return usb_bulk_msg(dev->udev, dev->rx_pipe, msg,
+ sizeof(*msg), &actual_length, 1000);
}
static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
@@ -677,8 +674,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
urb->transfer_dma = buf_dma;
- usb_fill_bulk_urb(urb, dev->udev,
- usb_rcvbulkpipe(dev->udev, 1),
+ usb_fill_bulk_urb(urb, dev->udev, dev->rx_pipe,
buf, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -903,7 +899,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
/* hnd must not be 0 - MSB is stripped in txdone handling */
msg->tx.hnd = BIT(31) | i; /* returned in TX done message */
- usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
+ usb_fill_bulk_urb(urb, dev->udev, dev->tx_pipe, buf,
msg->hdr.len * sizeof(u32), /* convert to # of bytes */
esd_usb_write_bulk_callback, context);
@@ -1298,10 +1294,16 @@ done:
static int esd_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct usb_endpoint_descriptor *ep_in, *ep_out;
struct esd_usb *dev;
union esd_usb_msg *msg;
int i, err;
+ err = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out,
+ NULL, NULL);
+ if (err)
+ return err;
+
dev = kzalloc_obj(*dev);
if (!dev) {
err = -ENOMEM;
@@ -1309,6 +1311,8 @@ static int esd_usb_probe(struct usb_interface *intf,
}
dev->udev = interface_to_usbdev(intf);
+ dev->rx_pipe = usb_rcvbulkpipe(dev->udev, ep_in->bEndpointAddress);
+ dev->tx_pipe = usb_sndbulkpipe(dev->udev, ep_out->bEndpointAddress);
init_usb_anchor(&dev->rx_submitted);
diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index 2d248deb69dc..b259f6109808 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -1461,12 +1461,18 @@ static void es58x_read_bulk_callback(struct urb *urb)
}
resubmit_urb:
+ usb_anchor_urb(urb, &es58x_dev->rx_urbs);
ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (!ret)
+ return;
+
+ usb_unanchor_urb(urb);
+
if (ret == -ENODEV) {
for (i = 0; i < es58x_dev->num_can_ch; i++)
if (es58x_dev->netdev[i])
netif_device_detach(es58x_dev->netdev[i]);
- } else if (ret)
+ } else
dev_err_ratelimited(dev,
"Failed resubmitting read bulk urb: %pe\n",
ERR_PTR(ret));
diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c
index 76578063ac82..f12318268e46 100644
--- a/drivers/net/can/usb/f81604.c
+++ b/drivers/net/can/usb/f81604.c
@@ -413,6 +413,7 @@ static void f81604_read_bulk_callback(struct urb *urb)
{
struct f81604_can_frame *frame = urb->transfer_buffer;
struct net_device *netdev = urb->context;
+ struct f81604_port_priv *priv = netdev_priv(netdev);
int ret;
if (!netif_device_present(netdev))
@@ -445,10 +446,15 @@ static void f81604_read_bulk_callback(struct urb *urb)
f81604_process_rx_packet(netdev, frame);
resubmit_urb:
+ usb_anchor_urb(urb, &priv->urbs_anchor);
ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (!ret)
+ return;
+ usb_unanchor_urb(urb);
+
if (ret == -ENODEV)
netif_device_detach(netdev);
- else if (ret)
+ else
netdev_err(netdev,
"%s: failed to resubmit read bulk urb: %pe\n",
__func__, ERR_PTR(ret));
@@ -620,6 +626,12 @@ static void f81604_read_int_callback(struct urb *urb)
netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
ERR_PTR(urb->status));
+ if (urb->actual_length < sizeof(*data)) {
+ netdev_warn(netdev, "%s: short int URB: %u < %zu\n",
+ __func__, urb->actual_length, sizeof(*data));
+ goto resubmit_urb;
+ }
+
switch (urb->status) {
case 0: /* success */
break;
@@ -646,10 +658,15 @@ static void f81604_read_int_callback(struct urb *urb)
f81604_handle_tx(priv, data);
resubmit_urb:
+ usb_anchor_urb(urb, &priv->urbs_anchor);
ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (!ret)
+ return;
+ usb_unanchor_urb(urb);
+
if (ret == -ENODEV)
netif_device_detach(netdev);
- else if (ret)
+ else
netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
__func__, ERR_PTR(ret));
}
@@ -874,9 +891,27 @@ static void f81604_write_bulk_callback(struct urb *urb)
if (!netif_device_present(netdev))
return;
- if (urb->status)
- netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
- ERR_PTR(urb->status));
+ if (!urb->status)
+ return;
+
+ switch (urb->status) {
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ return;
+ default:
+ break;
+ }
+
+ if (net_ratelimit())
+ netdev_err(netdev, "%s: Tx URB error: %pe\n", __func__,
+ ERR_PTR(urb->status));
+
+ can_free_echo_skb(netdev, 0, NULL);
+ netdev->stats.tx_dropped++;
+ netdev->stats.tx_errors++;
+
+ netif_wake_queue(netdev);
}
static void f81604_clear_reg_work(struct work_struct *work)
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 9d27d6f0c0b5..ec9a7cbbbc69 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -772,9 +772,8 @@ device_detach:
}
}
-static int gs_usb_set_bittiming(struct net_device *netdev)
+static int gs_usb_set_bittiming(struct gs_can *dev)
{
- struct gs_can *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.bittiming;
struct gs_device_bittiming dbt = {
.prop_seg = cpu_to_le32(bt->prop_seg),
@@ -791,9 +790,8 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
GFP_KERNEL);
}
-static int gs_usb_set_data_bittiming(struct net_device *netdev)
+static int gs_usb_set_data_bittiming(struct gs_can *dev)
{
- struct gs_can *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.fd.data_bittiming;
struct gs_device_bittiming dbt = {
.prop_seg = cpu_to_le32(bt->prop_seg),
@@ -1057,6 +1055,20 @@ static int gs_can_open(struct net_device *netdev)
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
flags |= GS_CAN_MODE_HW_TIMESTAMP;
+ rc = gs_usb_set_bittiming(dev);
+ if (rc) {
+ netdev_err(netdev, "failed to set bittiming: %pe\n", ERR_PTR(rc));
+ goto out_usb_kill_anchored_urbs;
+ }
+
+ if (ctrlmode & CAN_CTRLMODE_FD) {
+ rc = gs_usb_set_data_bittiming(dev);
+ if (rc) {
+ netdev_err(netdev, "failed to set data bittiming: %pe\n", ERR_PTR(rc));
+ goto out_usb_kill_anchored_urbs;
+ }
+ }
+
/* finally start device */
dev->can.state = CAN_STATE_ERROR_ACTIVE;
dm.flags = cpu_to_le32(flags);
@@ -1370,7 +1382,6 @@ static struct gs_can *gs_make_candev(unsigned int channel,
dev->can.state = CAN_STATE_STOPPED;
dev->can.clock.freq = le32_to_cpu(bt_const.fclk_can);
dev->can.bittiming_const = &dev->bt_const;
- dev->can.do_set_bittiming = gs_usb_set_bittiming;
dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
@@ -1394,7 +1405,6 @@ static struct gs_can *gs_make_candev(unsigned int channel,
* GS_CAN_FEATURE_BT_CONST_EXT is set.
*/
dev->can.fd.data_bittiming_const = &dev->bt_const;
- dev->can.fd.do_set_data_bittiming = gs_usb_set_data_bittiming;
}
if (feature & GS_CAN_FEATURE_TERMINATION) {
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index c79508b1c43e..0ea0ac75e42f 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -748,7 +748,7 @@ static void ucan_read_bulk_callback(struct urb *urb)
len = le16_to_cpu(m->len);
/* check sanity (length of content) */
- if (urb->actual_length - pos < len) {
+ if ((len == 0) || (urb->actual_length - pos < len)) {
netdev_warn(up->netdev,
"invalid message (short; no data; l:%d)\n",
urb->actual_length);
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index c575e164368c..f938a3f701cc 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -769,7 +769,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
out:
rtl83xx_unlock(priv);
- return 0;
+ return ret;
}
static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 71a817c07a90..94d17b06da40 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2278,6 +2278,12 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
* change it through the dynamic interface later.
*/
dsa_switch_for_each_available_port(dp, ds) {
+ /* May be called during unbind when we unoffload a VLAN-aware
+ * bridge from port 1 while port 0 was already torn down
+ */
+ if (!dp->pl)
+ continue;
+
phylink_replay_link_begin(dp->pl);
mac[dp->index].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
}
@@ -2334,7 +2340,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
}
dsa_switch_for_each_available_port(dp, ds)
- phylink_replay_link_end(dp->pl);
+ if (dp->pl)
+ phylink_replay_link_end(dp->pl);
rc = sja1105_reload_cbs(priv);
if (rc < 0)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 711f295eb777..80c2c27ac9dc 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -431,7 +431,7 @@
#define MAC_SSIR_SSINC_INDEX 16
#define MAC_SSIR_SSINC_WIDTH 8
#define MAC_TCR_SS_INDEX 29
-#define MAC_TCR_SS_WIDTH 2
+#define MAC_TCR_SS_WIDTH 3
#define MAC_TCR_TE_INDEX 0
#define MAC_TCR_TE_WIDTH 1
#define MAC_TCR_VNE_INDEX 24
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 62bb4b8a68e1..8b79d88480db 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1120,7 +1120,6 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
struct xgbe_hw_if *hw_if = &pdata->hw_if;
- unsigned long flags;
DBGPR("-->xgbe_powerdown\n");
@@ -1131,8 +1130,6 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
return -EINVAL;
}
- spin_lock_irqsave(&pdata->lock, flags);
-
if (caller == XGMAC_DRIVER_CONTEXT)
netif_device_detach(netdev);
@@ -1148,8 +1145,6 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
pdata->power_down = 1;
- spin_unlock_irqrestore(&pdata->lock, flags);
-
DBGPR("<--xgbe_powerdown\n");
return 0;
@@ -1159,7 +1154,6 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
struct xgbe_hw_if *hw_if = &pdata->hw_if;
- unsigned long flags;
DBGPR("-->xgbe_powerup\n");
@@ -1170,8 +1164,6 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
return -EINVAL;
}
- spin_lock_irqsave(&pdata->lock, flags);
-
pdata->power_down = 0;
xgbe_napi_enable(pdata, 0);
@@ -1186,8 +1178,6 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
xgbe_start_timers(pdata);
- spin_unlock_irqrestore(&pdata->lock, flags);
-
DBGPR("<--xgbe_powerup\n");
return 0;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index d1f0419edb23..7d45ea22a02e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -76,7 +76,6 @@ struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
pdata->netdev = netdev;
pdata->dev = dev;
- spin_lock_init(&pdata->lock);
spin_lock_init(&pdata->xpcs_lock);
mutex_init(&pdata->rss_mutex);
spin_lock_init(&pdata->tstamp_lock);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 1269b8ce9249..e1d7d7150e16 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -1004,9 +1004,6 @@ struct xgbe_prv_data {
unsigned int pp3;
unsigned int pp4;
- /* Overall device lock */
- spinlock_t lock;
-
/* XPCS indirect addressing lock */
spinlock_t xpcs_lock;
unsigned int xpcs_window_def_reg;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index e062d5d400da..c426a41c3663 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6232,6 +6232,9 @@ int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
int rc;
set_bit(BNXT_FLTR_FW_DELETED, &fltr->base.state);
+ if (!test_bit(BNXT_STATE_OPEN, &bp->state))
+ return 0;
+
rc = hwrm_req_init(bp, req, HWRM_CFA_NTUPLE_FILTER_FREE);
if (rc)
return rc;
@@ -10879,12 +10882,10 @@ void bnxt_del_one_rss_ctx(struct bnxt *bp, struct bnxt_rss_ctx *rss_ctx,
struct bnxt_ntuple_filter *ntp_fltr;
int i;
- if (netif_running(bp->dev)) {
- bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic);
- for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) {
- if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID)
- bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i);
- }
+ bnxt_hwrm_vnic_free_one(bp, &rss_ctx->vnic);
+ for (i = 0; i < BNXT_MAX_CTX_PER_VNIC; i++) {
+ if (vnic->fw_rss_cos_lb_ctx[i] != INVALID_HW_RING_ID)
+ bnxt_hwrm_vnic_ctx_free_one(bp, vnic, i);
}
if (!all)
return;
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index def2dd231d1f..52c1cb9cb7e0 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -1533,7 +1533,7 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
if_id = (status & 0xFFFF0000) >> 16;
if (if_id >= ethsw->sw_attr.num_ifs) {
dev_err(dev, "Invalid if_id %d in IRQ status\n", if_id);
- goto out;
+ goto out_clear;
}
port_priv = ethsw->ports[if_id];
@@ -1553,6 +1553,7 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
dpaa2_switch_port_connect_mac(port_priv);
}
+out_clear:
err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
DPSW_IRQ_INDEX_IF, status);
if (err)
@@ -3034,6 +3035,13 @@ static int dpaa2_switch_init(struct fsl_mc_device *sw_dev)
goto err_close;
}
+ if (ethsw->sw_attr.num_ifs >= DPSW_MAX_IF) {
+ dev_err(dev, "DPSW num_ifs %u exceeds max %u\n",
+ ethsw->sw_attr.num_ifs, DPSW_MAX_IF);
+ err = -EINVAL;
+ goto err_close;
+ }
+
err = dpsw_get_api_version(ethsw->mc_io, 0,
&ethsw->major,
&ethsw->minor);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 70768392912c..a146ceaf2ed6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -3467,7 +3467,7 @@ static int enetc_int_vector_init(struct enetc_ndev_priv *priv, int i,
priv->rx_ring[i] = bdr;
err = __xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0,
- ENETC_RXB_DMA_SIZE_XDP);
+ ENETC_RXB_TRUESIZE);
if (err)
goto free_vector;
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index 9031dd619f68..4db9d4f9ed6f 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -167,6 +167,25 @@ gve_free_pending_packet(struct gve_tx_ring *tx,
}
}
+static void gve_unmap_packet(struct device *dev,
+ struct gve_tx_pending_packet_dqo *pkt)
+{
+ int i;
+
+ if (!pkt->num_bufs)
+ return;
+
+ /* SKB linear portion is guaranteed to be mapped */
+ dma_unmap_single(dev, dma_unmap_addr(pkt, dma[0]),
+ dma_unmap_len(pkt, len[0]), DMA_TO_DEVICE);
+ for (i = 1; i < pkt->num_bufs; i++) {
+ netmem_dma_unmap_page_attrs(dev, dma_unmap_addr(pkt, dma[i]),
+ dma_unmap_len(pkt, len[i]),
+ DMA_TO_DEVICE, 0);
+ }
+ pkt->num_bufs = 0;
+}
+
/* gve_tx_free_desc - Cleans up all pending tx requests and buffers.
*/
static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx)
@@ -176,21 +195,12 @@ static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx)
for (i = 0; i < tx->dqo.num_pending_packets; i++) {
struct gve_tx_pending_packet_dqo *cur_state =
&tx->dqo.pending_packets[i];
- int j;
-
- for (j = 0; j < cur_state->num_bufs; j++) {
- if (j == 0) {
- dma_unmap_single(tx->dev,
- dma_unmap_addr(cur_state, dma[j]),
- dma_unmap_len(cur_state, len[j]),
- DMA_TO_DEVICE);
- } else {
- dma_unmap_page(tx->dev,
- dma_unmap_addr(cur_state, dma[j]),
- dma_unmap_len(cur_state, len[j]),
- DMA_TO_DEVICE);
- }
- }
+
+ if (tx->dqo.qpl)
+ gve_free_tx_qpl_bufs(tx, cur_state);
+ else
+ gve_unmap_packet(tx->dev, cur_state);
+
if (cur_state->skb) {
dev_consume_skb_any(cur_state->skb);
cur_state->skb = NULL;
@@ -1154,22 +1164,6 @@ static void remove_from_list(struct gve_tx_ring *tx,
}
}
-static void gve_unmap_packet(struct device *dev,
- struct gve_tx_pending_packet_dqo *pkt)
-{
- int i;
-
- /* SKB linear portion is guaranteed to be mapped */
- dma_unmap_single(dev, dma_unmap_addr(pkt, dma[0]),
- dma_unmap_len(pkt, len[0]), DMA_TO_DEVICE);
- for (i = 1; i < pkt->num_bufs; i++) {
- netmem_dma_unmap_page_attrs(dev, dma_unmap_addr(pkt, dma[i]),
- dma_unmap_len(pkt, len[i]),
- DMA_TO_DEVICE, 0);
- }
- pkt->num_bufs = 0;
-}
-
/* Completion types and expected behavior:
* No Miss compl + Packet compl = Packet completed normally.
* Miss compl + Re-inject compl = Packet completed normally.
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index ba331899d186..d4a1041e456d 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -33,6 +33,7 @@
/* Extended Device Control */
#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */
+#define E1000_CTRL_EXT_DPG_EN 0x00000008 /* Dynamic Power Gating Enable */
#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index aa08f397988e..63ebe00376f5 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -117,7 +117,8 @@ enum e1000_boards {
board_pch_cnp,
board_pch_tgp,
board_pch_adp,
- board_pch_mtp
+ board_pch_mtp,
+ board_pch_ptp
};
struct e1000_ps_page {
@@ -527,6 +528,7 @@ extern const struct e1000_info e1000_pch_cnp_info;
extern const struct e1000_info e1000_pch_tgp_info;
extern const struct e1000_info e1000_pch_adp_info;
extern const struct e1000_info e1000_pch_mtp_info;
+extern const struct e1000_info e1000_pch_ptp_info;
extern const struct e1000_info e1000_es2_info;
void e1000e_ptp_init(struct e1000_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index fc8ed38aa095..c7ac599e5a7a 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -118,8 +118,6 @@ struct e1000_hw;
#define E1000_DEV_ID_PCH_ARL_I219_V24 0x57A1
#define E1000_DEV_ID_PCH_PTP_I219_LM25 0x57B3
#define E1000_DEV_ID_PCH_PTP_I219_V25 0x57B4
-#define E1000_DEV_ID_PCH_PTP_I219_LM26 0x57B5
-#define E1000_DEV_ID_PCH_PTP_I219_V26 0x57B6
#define E1000_DEV_ID_PCH_PTP_I219_LM27 0x57B7
#define E1000_DEV_ID_PCH_PTP_I219_V27 0x57B8
#define E1000_DEV_ID_PCH_NVL_I219_LM29 0x57B9
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 0ff8688ac3b8..dea208db1be5 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -528,7 +528,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->id = e1000_phy_unknown;
- if (hw->mac.type == e1000_pch_mtp) {
+ if (hw->mac.type == e1000_pch_mtp || hw->mac.type == e1000_pch_ptp) {
phy->retry_count = 2;
e1000e_enable_phy_retry(hw);
}
@@ -4932,6 +4932,15 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
reg |= E1000_KABGTXD_BGSQLBIAS;
ew32(KABGTXD, reg);
+ /* The hardware reset value of the DPG_EN bit is 1.
+ * Clear DPG_EN to prevent unexpected autonomous power gating.
+ */
+ if (hw->mac.type >= e1000_pch_ptp) {
+ reg = er32(CTRL_EXT);
+ reg &= ~E1000_CTRL_EXT_DPG_EN;
+ ew32(CTRL_EXT, reg);
+ }
+
return 0;
}
@@ -6208,3 +6217,23 @@ const struct e1000_info e1000_pch_mtp_info = {
.phy_ops = &ich8_phy_ops,
.nvm_ops = &spt_nvm_ops,
};
+
+const struct e1000_info e1000_pch_ptp_info = {
+ .mac = e1000_pch_ptp,
+ .flags = FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | FLAG_HAS_HW_TIMESTAMP
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+ | FLAG_HAS_AMT
+ | FLAG_HAS_FLASH
+ | FLAG_HAS_JUMBO_FRAMES
+ | FLAG_APME_IN_WUC,
+ .flags2 = FLAG2_HAS_PHY_STATS
+ | FLAG2_HAS_EEE,
+ .pba = 26,
+ .max_hw_frame_size = 9022,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &spt_nvm_ops,
+};
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index fd4b117ed20f..35dab1e3132f 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -55,6 +55,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_pch_tgp] = &e1000_pch_tgp_info,
[board_pch_adp] = &e1000_pch_adp_info,
[board_pch_mtp] = &e1000_pch_mtp_info,
+ [board_pch_ptp] = &e1000_pch_ptp_info,
};
struct e1000_reg_info {
@@ -7922,14 +7923,12 @@ static const struct pci_device_id e1000_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_V21), board_pch_mtp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ARL_I219_LM24), board_pch_mtp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ARL_I219_V24), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM25), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V25), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM26), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V26), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM27), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V27), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_LM29), board_pch_mtp },
- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_V29), board_pch_mtp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM25), board_pch_ptp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V25), board_pch_ptp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_LM27), board_pch_ptp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_PTP_I219_V27), board_pch_ptp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_LM29), board_pch_ptp },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_NVL_I219_V29), board_pch_ptp },
{ 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
};
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 7b9e147d7365..926d001b2150 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -3569,6 +3569,7 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
u16 pf_q = vsi->base_queue + ring->queue_index;
struct i40e_hw *hw = &vsi->back->hw;
struct i40e_hmc_obj_rxq rx_ctx;
+ u32 xdp_frame_sz;
int err = 0;
bool ok;
@@ -3578,49 +3579,47 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
memset(&rx_ctx, 0, sizeof(rx_ctx));
ring->rx_buf_len = vsi->rx_buf_len;
+ xdp_frame_sz = i40e_rx_pg_size(ring) / 2;
/* XDP RX-queue info only needed for RX rings exposed to XDP */
if (ring->vsi->type != I40E_VSI_MAIN)
goto skip;
- if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
- err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
- ring->queue_index,
- ring->q_vector->napi.napi_id,
- ring->rx_buf_len);
- if (err)
- return err;
- }
-
ring->xsk_pool = i40e_xsk_pool(ring);
if (ring->xsk_pool) {
- xdp_rxq_info_unreg(&ring->xdp_rxq);
+ xdp_frame_sz = xsk_pool_get_rx_frag_step(ring->xsk_pool);
ring->rx_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool);
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
ring->queue_index,
ring->q_vector->napi.napi_id,
- ring->rx_buf_len);
+ xdp_frame_sz);
if (err)
return err;
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
MEM_TYPE_XSK_BUFF_POOL,
NULL);
if (err)
- return err;
+ goto unreg_xdp;
dev_info(&vsi->back->pdev->dev,
"Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n",
ring->queue_index);
} else {
+ err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
+ ring->queue_index,
+ ring->q_vector->napi.napi_id,
+ xdp_frame_sz);
+ if (err)
+ return err;
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
MEM_TYPE_PAGE_SHARED,
NULL);
if (err)
- return err;
+ goto unreg_xdp;
}
skip:
- xdp_init_buff(&ring->xdp, i40e_rx_pg_size(ring) / 2, &ring->xdp_rxq);
+ xdp_init_buff(&ring->xdp, xdp_frame_sz, &ring->xdp_rxq);
rx_ctx.dbuff = DIV_ROUND_UP(ring->rx_buf_len,
BIT_ULL(I40E_RXQ_CTX_DBUFF_SHIFT));
@@ -3654,7 +3653,8 @@ skip:
dev_info(&vsi->back->pdev->dev,
"Failed to clear LAN Rx queue context on Rx ring %d (pf_q %d), error: %d\n",
ring->queue_index, pf_q, err);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto unreg_xdp;
}
/* set the context in the HMC */
@@ -3663,7 +3663,8 @@ skip:
dev_info(&vsi->back->pdev->dev,
"Failed to set LAN Rx queue context on Rx ring %d (pf_q %d), error: %d\n",
ring->queue_index, pf_q, err);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto unreg_xdp;
}
/* configure Rx buffer alignment */
@@ -3671,7 +3672,8 @@ skip:
if (I40E_2K_TOO_SMALL_WITH_PADDING) {
dev_info(&vsi->back->pdev->dev,
"2k Rx buffer is too small to fit standard MTU and skb_shared_info\n");
- return -EOPNOTSUPP;
+ err = -EOPNOTSUPP;
+ goto unreg_xdp;
}
clear_ring_build_skb_enabled(ring);
} else {
@@ -3701,6 +3703,11 @@ skip:
}
return 0;
+unreg_xdp:
+ if (ring->vsi->type == I40E_VSI_MAIN)
+ xdp_rxq_info_unreg(&ring->xdp_rxq);
+
+ return err;
}
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_trace.h b/drivers/net/ethernet/intel/i40e/i40e_trace.h
index 759f3d1c4c8f..dde0ccd789ed 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_trace.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_trace.h
@@ -88,7 +88,7 @@ TRACE_EVENT(i40e_napi_poll,
__entry->rx_clean_complete = rx_clean_complete;
__entry->tx_clean_complete = tx_clean_complete;
__entry->irq_num = q->irq_num;
- __entry->curr_cpu = get_cpu();
+ __entry->curr_cpu = smp_processor_id();
__assign_str(qname);
__assign_str(dev_name);
__assign_bitmask(irq_affinity, cpumask_bits(&q->affinity_mask),
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 34db7d8866b0..894f2d06d39d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1470,6 +1470,9 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
if (!rx_ring->rx_bi)
return;
+ if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
+ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+
if (rx_ring->xsk_pool) {
i40e_xsk_clean_rx_ring(rx_ring);
goto skip_free;
@@ -1527,8 +1530,6 @@ skip_free:
void i40e_free_rx_resources(struct i40e_ring *rx_ring)
{
i40e_clean_rx_ring(rx_ring);
- if (rx_ring->vsi->type == I40E_VSI_MAIN)
- xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
rx_ring->xdp_prog = NULL;
kfree(rx_ring->rx_bi);
rx_ring->rx_bi = NULL;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index bceaf4b1b85d..86c1964f42e1 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2793,7 +2793,22 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
netdev->watchdog_timeo = 5 * HZ;
netdev->min_mtu = ETH_MIN_MTU;
- netdev->max_mtu = LIBIE_MAX_MTU;
+
+ /* PF/VF API: vf_res->max_mtu is max frame size (not MTU).
+ * Convert to MTU.
+ */
+ if (!adapter->vf_res->max_mtu) {
+ netdev->max_mtu = LIBIE_MAX_MTU;
+ } else if (adapter->vf_res->max_mtu < LIBETH_RX_LL_LEN + ETH_MIN_MTU ||
+ adapter->vf_res->max_mtu >
+ LIBETH_RX_LL_LEN + LIBIE_MAX_MTU) {
+ netdev_warn_once(adapter->netdev,
+ "invalid max frame size %d from PF, using default MTU %d",
+ adapter->vf_res->max_mtu, LIBIE_MAX_MTU);
+ netdev->max_mtu = LIBIE_MAX_MTU;
+ } else {
+ netdev->max_mtu = adapter->vf_res->max_mtu - LIBETH_RX_LL_LEN;
+ }
if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index def7efa15447..2b2b22af42be 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -987,6 +987,7 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset);
void ice_print_link_msg(struct ice_vsi *vsi, bool isup);
int ice_plug_aux_dev(struct ice_pf *pf);
void ice_unplug_aux_dev(struct ice_pf *pf);
+void ice_rdma_finalize_setup(struct ice_pf *pf);
int ice_init_rdma(struct ice_pf *pf);
void ice_deinit_rdma(struct ice_pf *pf);
bool ice_is_wol_supported(struct ice_hw *hw);
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index eb77dfa934aa..1667f686ff75 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -124,6 +124,8 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
if (vsi->type == ICE_VSI_VF) {
ice_calc_vf_reg_idx(vsi->vf, q_vector);
goto out;
+ } else if (vsi->type == ICE_VSI_LB) {
+ goto skip_alloc;
} else if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);
@@ -659,33 +661,22 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
{
struct device *dev = ice_pf_to_dev(ring->vsi->back);
u32 num_bufs = ICE_DESC_UNUSED(ring);
- u32 rx_buf_len;
int err;
- if (ring->vsi->type == ICE_VSI_PF || ring->vsi->type == ICE_VSI_SF) {
- if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
- err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
- ring->q_index,
- ring->q_vector->napi.napi_id,
- ring->rx_buf_len);
- if (err)
- return err;
- }
-
+ if (ring->vsi->type == ICE_VSI_PF || ring->vsi->type == ICE_VSI_SF ||
+ ring->vsi->type == ICE_VSI_LB) {
ice_rx_xsk_pool(ring);
err = ice_realloc_rx_xdp_bufs(ring, ring->xsk_pool);
if (err)
return err;
if (ring->xsk_pool) {
- xdp_rxq_info_unreg(&ring->xdp_rxq);
-
- rx_buf_len =
- xsk_pool_get_rx_frame_size(ring->xsk_pool);
+ u32 frag_size =
+ xsk_pool_get_rx_frag_step(ring->xsk_pool);
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
ring->q_index,
ring->q_vector->napi.napi_id,
- rx_buf_len);
+ frag_size);
if (err)
return err;
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
@@ -702,14 +693,13 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
if (err)
return err;
- if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
- err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
- ring->q_index,
- ring->q_vector->napi.napi_id,
- ring->rx_buf_len);
- if (err)
- goto err_destroy_fq;
- }
+ err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
+ ring->q_index,
+ ring->q_vector->napi.napi_id,
+ ring->truesize);
+ if (err)
+ goto err_destroy_fq;
+
xdp_rxq_info_attach_page_pool(&ring->xdp_rxq,
ring->pp);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 6cd63190f55d..ce11fea122d0 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -1816,6 +1816,7 @@ static bool ice_should_retry_sq_send_cmd(u16 opcode)
case ice_aqc_opc_lldp_stop:
case ice_aqc_opc_lldp_start:
case ice_aqc_opc_lldp_filter_ctrl:
+ case ice_aqc_opc_sff_eeprom:
return true;
}
@@ -1841,6 +1842,7 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
{
struct libie_aq_desc desc_cpy;
bool is_cmd_for_retry;
+ u8 *buf_cpy = NULL;
u8 idx = 0;
u16 opcode;
int status;
@@ -1850,8 +1852,11 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
memset(&desc_cpy, 0, sizeof(desc_cpy));
if (is_cmd_for_retry) {
- /* All retryable cmds are direct, without buf. */
- WARN_ON(buf);
+ if (buf) {
+ buf_cpy = kmemdup(buf, buf_size, GFP_KERNEL);
+ if (!buf_cpy)
+ return -ENOMEM;
+ }
memcpy(&desc_cpy, desc, sizeof(desc_cpy));
}
@@ -1863,12 +1868,14 @@ ice_sq_send_cmd_retry(struct ice_hw *hw, struct ice_ctl_q_info *cq,
hw->adminq.sq_last_status != LIBIE_AQ_RC_EBUSY)
break;
+ if (buf_cpy)
+ memcpy(buf, buf_cpy, buf_size);
memcpy(desc, &desc_cpy, sizeof(desc_cpy));
-
msleep(ICE_SQ_SEND_DELAY_TIME_MS);
} while (++idx < ICE_SQ_SEND_MAX_EXECUTE);
+ kfree(buf_cpy);
return status;
}
@@ -6391,7 +6398,7 @@ int ice_lldp_fltr_add_remove(struct ice_hw *hw, struct ice_vsi *vsi, bool add)
struct ice_aqc_lldp_filter_ctrl *cmd;
struct libie_aq_desc desc;
- if (vsi->type != ICE_VSI_PF || !ice_fw_supports_lldp_fltr_ctrl(hw))
+ if (!ice_fw_supports_lldp_fltr_ctrl(hw))
return -EOPNOTSUPP;
cmd = libie_aq_raw(&desc);
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 0ea64b330614..301947d53ede 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -1289,6 +1289,10 @@ static u64 ice_loopback_test(struct net_device *netdev)
test_vsi->netdev = netdev;
tx_ring = test_vsi->tx_rings[0];
rx_ring = test_vsi->rx_rings[0];
+ /* Dummy q_vector and napi. Fill the minimum required for
+ * ice_rxq_pp_create().
+ */
+ rx_ring->q_vector->napi.dev = netdev;
if (ice_lbtest_prepare_rings(test_vsi)) {
ret = 2;
@@ -3328,7 +3332,7 @@ process_rx:
rx_rings = kzalloc_objs(*rx_rings, vsi->num_rxq);
if (!rx_rings) {
err = -ENOMEM;
- goto done;
+ goto free_xdp;
}
ice_for_each_rxq(vsi, i) {
@@ -3338,6 +3342,7 @@ process_rx:
rx_rings[i].cached_phctime = pf->ptp.cached_phc_time;
rx_rings[i].desc = NULL;
rx_rings[i].xdp_buf = NULL;
+ rx_rings[i].xdp_rxq = (struct xdp_rxq_info){ };
/* this is to allow wr32 to have something to write to
* during early allocation of Rx buffers
@@ -3355,7 +3360,7 @@ rx_unwind:
}
kfree(rx_rings);
err = -ENOMEM;
- goto free_tx;
+ goto free_xdp;
}
}
@@ -3407,6 +3412,13 @@ process_link:
}
goto done;
+free_xdp:
+ if (xdp_rings) {
+ ice_for_each_xdp_txq(vsi, i)
+ ice_free_tx_ring(&xdp_rings[i]);
+ kfree(xdp_rings);
+ }
+
free_tx:
/* error cleanup if the Rx allocations failed after getting Tx */
if (tx_rings) {
@@ -4505,7 +4517,7 @@ ice_get_module_eeprom(struct net_device *netdev,
u8 addr = ICE_I2C_EEPROM_DEV_ADDR;
struct ice_hw *hw = &pf->hw;
bool is_sfp = false;
- unsigned int i, j;
+ unsigned int i;
u16 offset = 0;
u8 page = 0;
int status;
@@ -4547,26 +4559,19 @@ ice_get_module_eeprom(struct net_device *netdev,
if (page == 0 || !(data[0x2] & 0x4)) {
u32 copy_len;
- /* If i2c bus is busy due to slow page change or
- * link management access, call can fail. This is normal.
- * So we retry this a few times.
- */
- for (j = 0; j < 4; j++) {
- status = ice_aq_sff_eeprom(hw, 0, addr, offset, page,
- !is_sfp, value,
- SFF_READ_BLOCK_SIZE,
- 0, NULL);
- netdev_dbg(netdev, "SFF %02X %02X %02X %X = %02X%02X%02X%02X.%02X%02X%02X%02X (%X)\n",
- addr, offset, page, is_sfp,
- value[0], value[1], value[2], value[3],
- value[4], value[5], value[6], value[7],
- status);
- if (status) {
- usleep_range(1500, 2500);
- memset(value, 0, SFF_READ_BLOCK_SIZE);
- continue;
- }
- break;
+ status = ice_aq_sff_eeprom(hw, 0, addr, offset, page,
+ !is_sfp, value,
+ SFF_READ_BLOCK_SIZE,
+ 0, NULL);
+ netdev_dbg(netdev, "SFF %02X %02X %02X %X = %02X%02X%02X%02X.%02X%02X%02X%02X (%pe)\n",
+ addr, offset, page, is_sfp,
+ value[0], value[1], value[2], value[3],
+ value[4], value[5], value[6], value[7],
+ ERR_PTR(status));
+ if (status) {
+ netdev_err(netdev, "%s: error reading module EEPROM: status %pe\n",
+ __func__, ERR_PTR(status));
+ return status;
}
/* Make sure we have enough room for the new block */
diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
index 3572b0e1d49f..102d63c3018b 100644
--- a/drivers/net/ethernet/intel/ice/ice_idc.c
+++ b/drivers/net/ethernet/intel/ice/ice_idc.c
@@ -361,6 +361,39 @@ void ice_unplug_aux_dev(struct ice_pf *pf)
}
/**
+ * ice_rdma_finalize_setup - Complete RDMA setup after VSI is ready
+ * @pf: ptr to ice_pf
+ *
+ * Sets VSI-dependent information and plugs aux device.
+ * Must be called after ice_init_rdma(), ice_vsi_rebuild(), and
+ * ice_dcb_rebuild() complete.
+ */
+void ice_rdma_finalize_setup(struct ice_pf *pf)
+{
+ struct device *dev = ice_pf_to_dev(pf);
+ struct iidc_rdma_priv_dev_info *privd;
+ int ret;
+
+ if (!ice_is_rdma_ena(pf) || !pf->cdev_info)
+ return;
+
+ privd = pf->cdev_info->iidc_priv;
+ if (!privd || !pf->vsi || !pf->vsi[0] || !pf->vsi[0]->netdev)
+ return;
+
+ /* Assign VSI info now that VSI is valid */
+ privd->netdev = pf->vsi[0]->netdev;
+ privd->vport_id = pf->vsi[0]->vsi_num;
+
+ /* Update QoS info after DCB has been rebuilt */
+ ice_setup_dcb_qos_info(pf, &privd->qos_info);
+
+ ret = ice_plug_aux_dev(pf);
+ if (ret)
+ dev_warn(dev, "Failed to plug RDMA aux device: %d\n", ret);
+}
+
+/**
* ice_init_rdma - initializes PF for RDMA use
* @pf: ptr to ice_pf
*/
@@ -398,22 +431,14 @@ int ice_init_rdma(struct ice_pf *pf)
}
cdev->iidc_priv = privd;
- privd->netdev = pf->vsi[0]->netdev;
privd->hw_addr = (u8 __iomem *)pf->hw.hw_addr;
cdev->pdev = pf->pdev;
- privd->vport_id = pf->vsi[0]->vsi_num;
pf->cdev_info->rdma_protocol |= IIDC_RDMA_PROTOCOL_ROCEV2;
- ice_setup_dcb_qos_info(pf, &privd->qos_info);
- ret = ice_plug_aux_dev(pf);
- if (ret)
- goto err_plug_aux_dev;
+
return 0;
-err_plug_aux_dev:
- pf->cdev_info->adev = NULL;
- xa_erase(&ice_aux_id, pf->aux_idx);
err_alloc_xa:
kfree(privd);
err_privd_alloc:
@@ -432,7 +457,6 @@ void ice_deinit_rdma(struct ice_pf *pf)
if (!ice_is_rdma_ena(pf))
return;
- ice_unplug_aux_dev(pf);
xa_erase(&ice_aux_id, pf->aux_idx);
kfree(pf->cdev_info->iidc_priv);
kfree(pf->cdev_info);
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index f91f8b672b02..689c6025ea82 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -107,10 +107,6 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
if (!vsi->rxq_map)
goto err_rxq_map;
- /* There is no need to allocate q_vectors for a loopback VSI. */
- if (vsi->type == ICE_VSI_LB)
- return 0;
-
/* allocate memory for q_vector pointers */
vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors,
sizeof(*vsi->q_vectors), GFP_KERNEL);
@@ -241,6 +237,8 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
case ICE_VSI_LB:
vsi->alloc_txq = 1;
vsi->alloc_rxq = 1;
+ /* A dummy q_vector, no actual IRQ. */
+ vsi->num_q_vectors = 1;
break;
default:
dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi_type);
@@ -2426,14 +2424,21 @@ static int ice_vsi_cfg_def(struct ice_vsi *vsi)
}
break;
case ICE_VSI_LB:
- ret = ice_vsi_alloc_rings(vsi);
+ ret = ice_vsi_alloc_q_vectors(vsi);
if (ret)
goto unroll_vsi_init;
+ ret = ice_vsi_alloc_rings(vsi);
+ if (ret)
+ goto unroll_alloc_q_vector;
+
ret = ice_vsi_alloc_ring_stats(vsi);
if (ret)
goto unroll_vector_base;
+ /* Simply map the dummy q_vector to the only rx_ring */
+ vsi->rx_rings[0]->q_vector = vsi->q_vectors[0];
+
break;
default:
/* clean up the resources and exit */
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index ebf48feffb30..e7308e381e2f 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5138,6 +5138,9 @@ int ice_load(struct ice_pf *pf)
if (err)
goto err_init_rdma;
+ /* Finalize RDMA: VSI already created, assign info and plug device */
+ ice_rdma_finalize_setup(pf);
+
ice_service_task_restart(pf);
clear_bit(ICE_DOWN, pf->state);
@@ -5169,6 +5172,7 @@ void ice_unload(struct ice_pf *pf)
devl_assert_locked(priv_to_devlink(pf));
+ ice_unplug_aux_dev(pf);
ice_deinit_rdma(pf);
ice_deinit_features(pf);
ice_tc_indir_block_unregister(vsi);
@@ -5595,6 +5599,7 @@ static int ice_suspend(struct device *dev)
*/
disabled = ice_service_task_stop(pf);
+ ice_unplug_aux_dev(pf);
ice_deinit_rdma(pf);
/* Already suspended?, then there is nothing to do */
@@ -7859,7 +7864,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
ice_health_clear(pf);
- ice_plug_aux_dev(pf);
+ ice_rdma_finalize_setup(pf);
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG))
ice_lag_rebuild(pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index a5bbce68f76c..a2cd4cf37734 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -560,7 +560,9 @@ void ice_clean_rx_ring(struct ice_rx_ring *rx_ring)
i = 0;
}
- if (rx_ring->vsi->type == ICE_VSI_PF &&
+ if ((rx_ring->vsi->type == ICE_VSI_PF ||
+ rx_ring->vsi->type == ICE_VSI_SF ||
+ rx_ring->vsi->type == ICE_VSI_LB) &&
xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) {
xdp_rxq_info_detach_mem_model(&rx_ring->xdp_rxq);
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index c673094663a3..0643017541c3 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -899,6 +899,9 @@ void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring)
u16 ntc = rx_ring->next_to_clean;
u16 ntu = rx_ring->next_to_use;
+ if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
+ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+
while (ntc != ntu) {
struct xdp_buff *xdp = *ice_xdp_buf(rx_ring, ntc);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
index 40e08a71d2d3..bb99d9e7c65d 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
@@ -307,9 +307,6 @@ static int idpf_del_flow_steer(struct net_device *netdev,
vport_config = vport->adapter->vport_config[np->vport_idx];
user_config = &vport_config->user_config;
- if (!idpf_sideband_action_ena(vport, fsp))
- return -EOPNOTSUPP;
-
rule = kzalloc_flex(*rule, rule_info, 1);
if (!rule)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index de3df705a7e6..cf966fe6c759 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1318,6 +1318,7 @@ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter,
free_rss_key:
kfree(rss_data->rss_key);
+ rss_data->rss_key = NULL;
free_qreg_chunks:
idpf_vport_deinit_queue_reg_chunks(adapter->vport_config[idx]);
free_vector_idxs:
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index 05a162094d10..252259993022 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -1314,6 +1314,9 @@ static void idpf_txq_group_rel(struct idpf_q_vec_rsrc *rsrc)
struct idpf_txq_group *txq_grp = &rsrc->txq_grps[i];
for (unsigned int j = 0; j < txq_grp->num_txq; j++) {
+ if (!txq_grp->txqs[j])
+ continue;
+
if (idpf_queue_has(FLOW_SCH_EN, txq_grp->txqs[j])) {
kfree(txq_grp->txqs[j]->refillq);
txq_grp->txqs[j]->refillq = NULL;
@@ -1339,6 +1342,9 @@ static void idpf_txq_group_rel(struct idpf_q_vec_rsrc *rsrc)
*/
static void idpf_rxq_sw_queue_rel(struct idpf_rxq_group *rx_qgrp)
{
+ if (!rx_qgrp->splitq.bufq_sets)
+ return;
+
for (unsigned int i = 0; i < rx_qgrp->splitq.num_bufq_sets; i++) {
struct idpf_bufq_set *bufq_set = &rx_qgrp->splitq.bufq_sets[i];
@@ -2336,7 +2342,7 @@ void idpf_wait_for_sw_marker_completion(const struct idpf_tx_queue *txq)
do {
struct idpf_splitq_4b_tx_compl_desc *tx_desc;
- struct idpf_tx_queue *target;
+ struct idpf_tx_queue *target = NULL;
u32 ctype_gen, id;
tx_desc = flow ? &complq->comp[ntc].common :
@@ -2356,14 +2362,14 @@ void idpf_wait_for_sw_marker_completion(const struct idpf_tx_queue *txq)
target = complq->txq_grp->txqs[id];
idpf_queue_clear(SW_MARKER, target);
- if (target == txq)
- break;
next:
if (unlikely(++ntc == complq->desc_count)) {
ntc = 0;
gen_flag = !gen_flag;
}
+ if (target == txq)
+ break;
} while (time_before(jiffies, timeout));
idpf_queue_assign(GEN_CHK, complq, gen_flag);
@@ -4059,7 +4065,7 @@ static int idpf_vport_intr_req_irq(struct idpf_vport *vport,
continue;
name = kasprintf(GFP_KERNEL, "%s-%s-%s-%d", drv_name, if_name,
- vec_name, vidx);
+ vec_name, vector);
err = request_irq(irq_num, idpf_vport_intr_clean_queues, 0,
name, q_vector);
diff --git a/drivers/net/ethernet/intel/idpf/xdp.c b/drivers/net/ethernet/intel/idpf/xdp.c
index 6ac9c6624c2a..cbccd4546768 100644
--- a/drivers/net/ethernet/intel/idpf/xdp.c
+++ b/drivers/net/ethernet/intel/idpf/xdp.c
@@ -47,12 +47,16 @@ static int __idpf_xdp_rxq_info_init(struct idpf_rx_queue *rxq, void *arg)
{
const struct idpf_vport *vport = rxq->q_vector->vport;
const struct idpf_q_vec_rsrc *rsrc;
+ u32 frag_size = 0;
bool split;
int err;
+ if (idpf_queue_has(XSK, rxq))
+ frag_size = rxq->bufq_sets[0].bufq.truesize;
+
err = __xdp_rxq_info_reg(&rxq->xdp_rxq, vport->netdev, rxq->idx,
rxq->q_vector->napi.napi_id,
- rxq->rx_buf_size);
+ frag_size);
if (err)
return err;
diff --git a/drivers/net/ethernet/intel/idpf/xsk.c b/drivers/net/ethernet/intel/idpf/xsk.c
index 676cbd80774d..d95d3efdfd36 100644
--- a/drivers/net/ethernet/intel/idpf/xsk.c
+++ b/drivers/net/ethernet/intel/idpf/xsk.c
@@ -403,6 +403,7 @@ int idpf_xskfq_init(struct idpf_buf_queue *bufq)
bufq->pending = fq.pending;
bufq->thresh = fq.thresh;
bufq->rx_buf_size = fq.buf_len;
+ bufq->truesize = fq.truesize;
if (!idpf_xskfq_refill(bufq))
netdev_err(bufq->pool->netdev,
diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
index 30ce5fbb5b77..ce4a7b58cad2 100644
--- a/drivers/net/ethernet/intel/igb/igb_xsk.c
+++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
@@ -524,6 +524,16 @@ bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool)
return nb_pkts < budget;
}
+static u32 igb_sw_irq_prep(struct igb_q_vector *q_vector)
+{
+ u32 eics = 0;
+
+ if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+ eics = q_vector->eims_value;
+
+ return eics;
+}
+
int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
{
struct igb_adapter *adapter = netdev_priv(dev);
@@ -542,20 +552,32 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
ring = adapter->tx_ring[qid];
- if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
- return -ENETDOWN;
-
if (!READ_ONCE(ring->xsk_pool))
return -EINVAL;
- if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
+ if (flags & XDP_WAKEUP_TX) {
+ if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
+ return -ENETDOWN;
+
+ eics |= igb_sw_irq_prep(ring->q_vector);
+ }
+
+ if (flags & XDP_WAKEUP_RX) {
+ /* If IGB_FLAG_QUEUE_PAIRS is active, the q_vector
+ * and NAPI is shared between RX and TX.
+ * If NAPI is already running it would be marked as missed
+ * from the TX path, making this RX call a NOP
+ */
+ ring = adapter->rx_ring[qid];
+ eics |= igb_sw_irq_prep(ring->q_vector);
+ }
+
+ if (eics) {
/* Cause software interrupt */
- if (adapter->flags & IGB_FLAG_HAS_MSIX) {
- eics |= ring->q_vector->eims_value;
+ if (adapter->flags & IGB_FLAG_HAS_MSIX)
wr32(E1000_EICS, eics);
- } else {
+ else
wr32(E1000_ICS, E1000_ICS_RXDMT0);
- }
}
return 0;
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 27e5c2109138..b2e8d0c0f827 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6906,28 +6906,29 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
return nxmit;
}
-static void igc_trigger_rxtxq_interrupt(struct igc_adapter *adapter,
- struct igc_q_vector *q_vector)
+static u32 igc_sw_irq_prep(struct igc_q_vector *q_vector)
{
- struct igc_hw *hw = &adapter->hw;
u32 eics = 0;
- eics |= q_vector->eims_value;
- wr32(IGC_EICS, eics);
+ if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+ eics = q_vector->eims_value;
+
+ return eics;
}
int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
{
struct igc_adapter *adapter = netdev_priv(dev);
- struct igc_q_vector *q_vector;
+ struct igc_hw *hw = &adapter->hw;
struct igc_ring *ring;
+ u32 eics = 0;
if (test_bit(__IGC_DOWN, &adapter->state))
return -ENETDOWN;
if (!igc_xdp_is_enabled(adapter))
return -ENXIO;
-
+ /* Check if queue_id is valid. Tx and Rx queue numbers are always same */
if (queue_id >= adapter->num_rx_queues)
return -EINVAL;
@@ -6936,9 +6937,22 @@ int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
if (!ring->xsk_pool)
return -ENXIO;
- q_vector = adapter->q_vector[queue_id];
- if (!napi_if_scheduled_mark_missed(&q_vector->napi))
- igc_trigger_rxtxq_interrupt(adapter, q_vector);
+ if (flags & XDP_WAKEUP_RX)
+ eics |= igc_sw_irq_prep(ring->q_vector);
+
+ if (flags & XDP_WAKEUP_TX) {
+ /* If IGC_FLAG_QUEUE_PAIRS is active, the q_vector
+ * and NAPI is shared between RX and TX.
+ * If NAPI is already running it would be marked as missed
+ * from the RX path, making this TX call a NOP
+ */
+ ring = adapter->tx_ring[queue_id];
+ eics |= igc_sw_irq_prep(ring->q_vector);
+ }
+
+ if (eics)
+ /* Cause software interrupt */
+ wr32(IGC_EICS, eics);
return 0;
}
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 7aae83c108fd..44ee19386766 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -550,7 +550,8 @@ static void igc_ptp_free_tx_buffer(struct igc_adapter *adapter,
tstamp->buffer_type = 0;
/* Trigger txrx interrupt for transmit completion */
- igc_xsk_wakeup(adapter->netdev, tstamp->xsk_queue_index, 0);
+ igc_xsk_wakeup(adapter->netdev, tstamp->xsk_queue_index,
+ XDP_WAKEUP_TX);
return;
}
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 74d320879513..b67b580f7f1c 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -852,7 +852,8 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
if (!mac->get_link_status)
goto out;
- if (hw->mac.type == ixgbe_mac_e610_vf) {
+ if (hw->mac.type == ixgbe_mac_e610_vf &&
+ hw->api_version >= ixgbe_mbox_api_16) {
ret_val = ixgbevf_get_pf_link_state(hw, speed, link_up);
if (ret_val)
goto out;
diff --git a/drivers/net/ethernet/intel/libeth/xsk.c b/drivers/net/ethernet/intel/libeth/xsk.c
index 846e902e31b6..4882951d5c9c 100644
--- a/drivers/net/ethernet/intel/libeth/xsk.c
+++ b/drivers/net/ethernet/intel/libeth/xsk.c
@@ -167,6 +167,7 @@ int libeth_xskfq_create(struct libeth_xskfq *fq)
fq->pending = fq->count;
fq->thresh = libeth_xdp_queue_threshold(fq->count);
fq->buf_len = xsk_pool_get_rx_frame_size(fq->pool);
+ fq->truesize = xsk_pool_get_rx_frag_step(fq->pool);
return 0;
}
diff --git a/drivers/net/ethernet/intel/libie/fwlog.c b/drivers/net/ethernet/intel/libie/fwlog.c
index 79020d990859..4d0c8370386b 100644
--- a/drivers/net/ethernet/intel/libie/fwlog.c
+++ b/drivers/net/ethernet/intel/libie/fwlog.c
@@ -1049,6 +1049,10 @@ void libie_fwlog_deinit(struct libie_fwlog *fwlog)
{
int status;
+ /* if FW logging isn't supported it means no configuration was done */
+ if (!libie_fwlog_supported(fwlog))
+ return;
+
/* make sure FW logging is disabled to not put the FW in a weird state
* for the next driver load
*/
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index ec55eb2a6c04..028dd55604ea 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -554,28 +554,43 @@ static void octep_clean_irqs(struct octep_device *oct)
}
/**
- * octep_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue.
+ * octep_update_pkt() - Update IQ/OQ IN/OUT_CNT registers.
*
* @iq: Octeon Tx queue data structure.
* @oq: Octeon Rx queue data structure.
*/
-static void octep_enable_ioq_irq(struct octep_iq *iq, struct octep_oq *oq)
+static void octep_update_pkt(struct octep_iq *iq, struct octep_oq *oq)
{
- u32 pkts_pend = oq->pkts_pending;
+ u32 pkts_pend = READ_ONCE(oq->pkts_pending);
+ u32 last_pkt_count = READ_ONCE(oq->last_pkt_count);
+ u32 pkts_processed = READ_ONCE(iq->pkts_processed);
+ u32 pkt_in_done = READ_ONCE(iq->pkt_in_done);
netdev_dbg(iq->netdev, "enabling intr for Q-%u\n", iq->q_no);
- if (iq->pkts_processed) {
- writel(iq->pkts_processed, iq->inst_cnt_reg);
- iq->pkt_in_done -= iq->pkts_processed;
- iq->pkts_processed = 0;
+ if (pkts_processed) {
+ writel(pkts_processed, iq->inst_cnt_reg);
+ readl(iq->inst_cnt_reg);
+ WRITE_ONCE(iq->pkt_in_done, (pkt_in_done - pkts_processed));
+ WRITE_ONCE(iq->pkts_processed, 0);
}
- if (oq->last_pkt_count - pkts_pend) {
- writel(oq->last_pkt_count - pkts_pend, oq->pkts_sent_reg);
- oq->last_pkt_count = pkts_pend;
+ if (last_pkt_count - pkts_pend) {
+ writel(last_pkt_count - pkts_pend, oq->pkts_sent_reg);
+ readl(oq->pkts_sent_reg);
+ WRITE_ONCE(oq->last_pkt_count, pkts_pend);
}
/* Flush the previous wrties before writing to RESEND bit */
- wmb();
+ smp_wmb();
+}
+
+/**
+ * octep_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue.
+ *
+ * @iq: Octeon Tx queue data structure.
+ * @oq: Octeon Rx queue data structure.
+ */
+static void octep_enable_ioq_irq(struct octep_iq *iq, struct octep_oq *oq)
+{
writeq(1UL << OCTEP_OQ_INTR_RESEND_BIT, oq->pkts_sent_reg);
writeq(1UL << OCTEP_IQ_INTR_RESEND_BIT, iq->inst_cnt_reg);
}
@@ -601,7 +616,8 @@ static int octep_napi_poll(struct napi_struct *napi, int budget)
if (tx_pending || rx_done >= budget)
return budget;
- napi_complete(napi);
+ octep_update_pkt(ioq_vector->iq, ioq_vector->oq);
+ napi_complete_done(napi, rx_done);
octep_enable_ioq_irq(ioq_vector->iq, ioq_vector->oq);
return rx_done;
}
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
index f2a7c6a76c74..74de19166488 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
@@ -324,10 +324,16 @@ static int octep_oq_check_hw_for_pkts(struct octep_device *oct,
struct octep_oq *oq)
{
u32 pkt_count, new_pkts;
+ u32 last_pkt_count, pkts_pending;
pkt_count = readl(oq->pkts_sent_reg);
- new_pkts = pkt_count - oq->last_pkt_count;
+ last_pkt_count = READ_ONCE(oq->last_pkt_count);
+ new_pkts = pkt_count - last_pkt_count;
+ if (pkt_count < last_pkt_count) {
+ dev_err(oq->dev, "OQ-%u pkt_count(%u) < oq->last_pkt_count(%u)\n",
+ oq->q_no, pkt_count, last_pkt_count);
+ }
/* Clear the hardware packets counter register if the rx queue is
* being processed continuously with-in a single interrupt and
* reached half its max value.
@@ -338,8 +344,9 @@ static int octep_oq_check_hw_for_pkts(struct octep_device *oct,
pkt_count = readl(oq->pkts_sent_reg);
new_pkts += pkt_count;
}
- oq->last_pkt_count = pkt_count;
- oq->pkts_pending += new_pkts;
+ WRITE_ONCE(oq->last_pkt_count, pkt_count);
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ WRITE_ONCE(oq->pkts_pending, (pkts_pending + new_pkts));
return new_pkts;
}
@@ -414,7 +421,7 @@ static int __octep_oq_process_rx(struct octep_device *oct,
u16 rx_ol_flags;
u32 read_idx;
- read_idx = oq->host_read_idx;
+ read_idx = READ_ONCE(oq->host_read_idx);
rx_bytes = 0;
desc_used = 0;
for (pkt = 0; pkt < pkts_to_process; pkt++) {
@@ -499,7 +506,7 @@ static int __octep_oq_process_rx(struct octep_device *oct,
napi_gro_receive(oq->napi, skb);
}
- oq->host_read_idx = read_idx;
+ WRITE_ONCE(oq->host_read_idx, read_idx);
oq->refill_count += desc_used;
oq->stats->packets += pkt;
oq->stats->bytes += rx_bytes;
@@ -522,22 +529,26 @@ int octep_oq_process_rx(struct octep_oq *oq, int budget)
{
u32 pkts_available, pkts_processed, total_pkts_processed;
struct octep_device *oct = oq->octep_dev;
+ u32 pkts_pending;
pkts_available = 0;
pkts_processed = 0;
total_pkts_processed = 0;
while (total_pkts_processed < budget) {
/* update pending count only when current one exhausted */
- if (oq->pkts_pending == 0)
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ if (pkts_pending == 0)
octep_oq_check_hw_for_pkts(oct, oq);
+ pkts_pending = READ_ONCE(oq->pkts_pending);
pkts_available = min(budget - total_pkts_processed,
- oq->pkts_pending);
+ pkts_pending);
if (!pkts_available)
break;
pkts_processed = __octep_oq_process_rx(oct, oq,
pkts_available);
- oq->pkts_pending -= pkts_processed;
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ WRITE_ONCE(oq->pkts_pending, (pkts_pending - pkts_processed));
total_pkts_processed += pkts_processed;
}
diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c
index 562fe945b422..7f1b93cffb98 100644
--- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c
@@ -286,28 +286,45 @@ static void octep_vf_clean_irqs(struct octep_vf_device *oct)
}
/**
- * octep_vf_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue.
+ * octep_vf_update_pkt() - Update IQ/OQ IN/OUT_CNT registers.
*
* @iq: Octeon Tx queue data structure.
* @oq: Octeon Rx queue data structure.
*/
-static void octep_vf_enable_ioq_irq(struct octep_vf_iq *iq, struct octep_vf_oq *oq)
+
+static void octep_vf_update_pkt(struct octep_vf_iq *iq, struct octep_vf_oq *oq)
{
- u32 pkts_pend = oq->pkts_pending;
+ u32 pkts_pend = READ_ONCE(oq->pkts_pending);
+ u32 last_pkt_count = READ_ONCE(oq->last_pkt_count);
+ u32 pkts_processed = READ_ONCE(iq->pkts_processed);
+ u32 pkt_in_done = READ_ONCE(iq->pkt_in_done);
netdev_dbg(iq->netdev, "enabling intr for Q-%u\n", iq->q_no);
- if (iq->pkts_processed) {
- writel(iq->pkts_processed, iq->inst_cnt_reg);
- iq->pkt_in_done -= iq->pkts_processed;
- iq->pkts_processed = 0;
+ if (pkts_processed) {
+ writel(pkts_processed, iq->inst_cnt_reg);
+ readl(iq->inst_cnt_reg);
+ WRITE_ONCE(iq->pkt_in_done, (pkt_in_done - pkts_processed));
+ WRITE_ONCE(iq->pkts_processed, 0);
}
- if (oq->last_pkt_count - pkts_pend) {
- writel(oq->last_pkt_count - pkts_pend, oq->pkts_sent_reg);
- oq->last_pkt_count = pkts_pend;
+ if (last_pkt_count - pkts_pend) {
+ writel(last_pkt_count - pkts_pend, oq->pkts_sent_reg);
+ readl(oq->pkts_sent_reg);
+ WRITE_ONCE(oq->last_pkt_count, pkts_pend);
}
/* Flush the previous wrties before writing to RESEND bit */
smp_wmb();
+}
+
+/**
+ * octep_vf_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue.
+ *
+ * @iq: Octeon Tx queue data structure.
+ * @oq: Octeon Rx queue data structure.
+ */
+static void octep_vf_enable_ioq_irq(struct octep_vf_iq *iq,
+ struct octep_vf_oq *oq)
+{
writeq(1UL << OCTEP_VF_OQ_INTR_RESEND_BIT, oq->pkts_sent_reg);
writeq(1UL << OCTEP_VF_IQ_INTR_RESEND_BIT, iq->inst_cnt_reg);
}
@@ -333,6 +350,7 @@ static int octep_vf_napi_poll(struct napi_struct *napi, int budget)
if (tx_pending || rx_done >= budget)
return budget;
+ octep_vf_update_pkt(ioq_vector->iq, ioq_vector->oq);
if (likely(napi_complete_done(napi, rx_done)))
octep_vf_enable_ioq_irq(ioq_vector->iq, ioq_vector->oq);
diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
index 6f865dbbba6c..b579d5b545c4 100644
--- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
@@ -325,9 +325,16 @@ static int octep_vf_oq_check_hw_for_pkts(struct octep_vf_device *oct,
struct octep_vf_oq *oq)
{
u32 pkt_count, new_pkts;
+ u32 last_pkt_count, pkts_pending;
pkt_count = readl(oq->pkts_sent_reg);
- new_pkts = pkt_count - oq->last_pkt_count;
+ last_pkt_count = READ_ONCE(oq->last_pkt_count);
+ new_pkts = pkt_count - last_pkt_count;
+
+ if (pkt_count < last_pkt_count) {
+ dev_err(oq->dev, "OQ-%u pkt_count(%u) < oq->last_pkt_count(%u)\n",
+ oq->q_no, pkt_count, last_pkt_count);
+ }
/* Clear the hardware packets counter register if the rx queue is
* being processed continuously with-in a single interrupt and
@@ -339,8 +346,9 @@ static int octep_vf_oq_check_hw_for_pkts(struct octep_vf_device *oct,
pkt_count = readl(oq->pkts_sent_reg);
new_pkts += pkt_count;
}
- oq->last_pkt_count = pkt_count;
- oq->pkts_pending += new_pkts;
+ WRITE_ONCE(oq->last_pkt_count, pkt_count);
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ WRITE_ONCE(oq->pkts_pending, (pkts_pending + new_pkts));
return new_pkts;
}
@@ -369,7 +377,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
struct sk_buff *skb;
u32 read_idx;
- read_idx = oq->host_read_idx;
+ read_idx = READ_ONCE(oq->host_read_idx);
rx_bytes = 0;
desc_used = 0;
for (pkt = 0; pkt < pkts_to_process; pkt++) {
@@ -463,7 +471,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
napi_gro_receive(oq->napi, skb);
}
- oq->host_read_idx = read_idx;
+ WRITE_ONCE(oq->host_read_idx, read_idx);
oq->refill_count += desc_used;
oq->stats->packets += pkt;
oq->stats->bytes += rx_bytes;
@@ -486,22 +494,26 @@ int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget)
{
u32 pkts_available, pkts_processed, total_pkts_processed;
struct octep_vf_device *oct = oq->octep_vf_dev;
+ u32 pkts_pending;
pkts_available = 0;
pkts_processed = 0;
total_pkts_processed = 0;
while (total_pkts_processed < budget) {
/* update pending count only when current one exhausted */
- if (oq->pkts_pending == 0)
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ if (pkts_pending == 0)
octep_vf_oq_check_hw_for_pkts(oct, oq);
+ pkts_pending = READ_ONCE(oq->pkts_pending);
pkts_available = min(budget - total_pkts_processed,
- oq->pkts_pending);
+ pkts_pending);
if (!pkts_available)
break;
pkts_processed = __octep_vf_oq_process_rx(oct, oq,
pkts_available);
- oq->pkts_pending -= pkts_processed;
+ pkts_pending = READ_ONCE(oq->pkts_pending);
+ WRITE_ONCE(oq->pkts_pending, (pkts_pending - pkts_processed));
total_pkts_processed += pkts_processed;
}
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e5e2ffa9c542..ddc321a02fda 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3748,12 +3748,21 @@ static int mtk_xdp_setup(struct net_device *dev, struct bpf_prog *prog,
mtk_stop(dev);
old_prog = rcu_replace_pointer(eth->prog, prog, lockdep_rtnl_is_held());
+
+ if (netif_running(dev) && need_update) {
+ int err;
+
+ err = mtk_open(dev);
+ if (err) {
+ rcu_assign_pointer(eth->prog, old_prog);
+
+ return err;
+ }
+ }
+
if (old_prog)
bpf_prog_put(old_prog);
- if (netif_running(dev) && need_update)
- return mtk_open(dev);
-
return 0;
}
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 415208abf10e..64e13747084e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -259,7 +259,6 @@ static void mlx5e_ipsec_init_limits(struct mlx5e_ipsec_sa_entry *sa_entry,
static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
struct mlx5_accel_esp_xfrm_attrs *attrs)
{
- struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
struct mlx5e_ipsec_addr *addrs = &attrs->addrs;
struct net_device *netdev = sa_entry->dev;
struct xfrm_state *x = sa_entry->x;
@@ -276,7 +275,7 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
attrs->type != XFRM_DEV_OFFLOAD_PACKET)
return;
- mlx5_query_mac_address(mdev, addr);
+ ether_addr_copy(addr, netdev->dev_addr);
switch (attrs->dir) {
case XFRM_DEV_OFFLOAD_IN:
src = attrs->dmac;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 82d4c14fdca0..1366f6e489bd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -4068,6 +4068,8 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
if (mlx5_mode == MLX5_ESWITCH_LEGACY)
esw->dev->priv.flags |= MLX5_PRIV_FLAGS_SWITCH_LEGACY;
+ if (mlx5_mode == MLX5_ESWITCH_OFFLOADS)
+ esw->dev->priv.flags &= ~MLX5_PRIV_FLAGS_SWITCH_LEGACY;
mlx5_eswitch_disable_locked(esw);
if (mlx5_mode == MLX5_ESWITCH_OFFLOADS) {
if (mlx5_devlink_trap_get_num_active(esw->dev)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index c326adb0c789..044adfdf9aa2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1869,8 +1869,12 @@ void mlx5_lag_disable_change(struct mlx5_core_dev *dev)
mutex_lock(&ldev->lock);
ldev->mode_changes_in_progress++;
- if (__mlx5_lag_is_active(ldev))
- mlx5_disable_lag(ldev);
+ if (__mlx5_lag_is_active(ldev)) {
+ if (ldev->mode == MLX5_LAG_MODE_MPESW)
+ mlx5_lag_disable_mpesw(ldev);
+ else
+ mlx5_disable_lag(ldev);
+ }
mutex_unlock(&ldev->lock);
mlx5_devcom_comp_unlock(dev->priv.hca_devcom_comp);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
index 24a91e7a20e2..74d5c2ed14ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -65,7 +65,7 @@ err_metadata:
return err;
}
-static int enable_mpesw(struct mlx5_lag *ldev)
+static int mlx5_lag_enable_mpesw(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0;
int err;
@@ -126,7 +126,7 @@ err_add_devices:
return err;
}
-static void disable_mpesw(struct mlx5_lag *ldev)
+void mlx5_lag_disable_mpesw(struct mlx5_lag *ldev)
{
if (ldev->mode == MLX5_LAG_MODE_MPESW) {
mlx5_mpesw_metadata_cleanup(ldev);
@@ -152,9 +152,9 @@ static void mlx5_mpesw_work(struct work_struct *work)
}
if (mpesww->op == MLX5_MPESW_OP_ENABLE)
- mpesww->result = enable_mpesw(ldev);
+ mpesww->result = mlx5_lag_enable_mpesw(ldev);
else if (mpesww->op == MLX5_MPESW_OP_DISABLE)
- disable_mpesw(ldev);
+ mlx5_lag_disable_mpesw(ldev);
unlock:
mutex_unlock(&ldev->lock);
mlx5_devcom_comp_unlock(devcom);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
index f5d9b5c97b0d..b767dbb4f457 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
@@ -31,6 +31,11 @@ int mlx5_lag_mpesw_do_mirred(struct mlx5_core_dev *mdev,
bool mlx5_lag_is_mpesw(struct mlx5_core_dev *dev);
void mlx5_lag_mpesw_disable(struct mlx5_core_dev *dev);
int mlx5_lag_mpesw_enable(struct mlx5_core_dev *dev);
+#ifdef CONFIG_MLX5_ESWITCH
+void mlx5_lag_disable_mpesw(struct mlx5_lag *ldev);
+#else
+static inline void mlx5_lag_disable_mpesw(struct mlx5_lag *ldev) {}
+#endif /* CONFIG_MLX5_ESWITCH */
#ifdef CONFIG_MLX5_ESWITCH
void mlx5_mpesw_speed_update_work(struct work_struct *work);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
index 4af82675ffe1..bf6f631cf2ce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
@@ -193,7 +193,9 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs)
err = pci_enable_sriov(pdev, num_vfs);
if (err) {
mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err);
+ devl_lock(devlink);
mlx5_device_disable_sriov(dev, num_vfs, true, true);
+ devl_unlock(devlink);
}
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c
index 1b08bbb7ad99..0ed81353f2e3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_dbg.c
@@ -1051,8 +1051,8 @@ static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn)
struct mlx5dr_table *tbl;
int ret;
- mutex_lock(&dmn->dump_info.dbg_mutex);
mlx5dr_domain_lock(dmn);
+ mutex_lock(&dmn->dump_info.dbg_mutex);
ret = dr_dump_domain(file, dmn);
if (ret < 0)
@@ -1065,8 +1065,8 @@ static int dr_dump_domain_all(struct seq_file *file, struct mlx5dr_domain *dmn)
}
unlock_mutex:
- mlx5dr_domain_unlock(dmn);
mutex_unlock(&dmn->dump_info.dbg_mutex);
+ mlx5dr_domain_unlock(dmn);
return ret;
}
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index f5deed37567b..37d2f108a839 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -1946,7 +1946,10 @@ static void mana_gd_cleanup(struct pci_dev *pdev)
mana_gd_remove_irqs(pdev);
- destroy_workqueue(gc->service_wq);
+ if (gc->service_wq) {
+ destroy_workqueue(gc->service_wq);
+ gc->service_wq = NULL;
+ }
dev_dbg(&pdev->dev, "mana gdma cleanup successful\n");
}
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 9919183ad39e..9017e806ecda 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1770,8 +1770,14 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
ndev = txq->ndev;
apc = netdev_priv(ndev);
+ /* Limit CQEs polled to 4 wraparounds of the CQ to ensure the
+ * doorbell can be rung in time for the hardware's requirement
+ * of at least one doorbell ring every 8 wraparounds.
+ */
comp_read = mana_gd_poll_cq(cq->gdma_cq, completions,
- CQE_POLLING_BUFFER);
+ min((cq->gdma_cq->queue_size /
+ COMP_ENTRY_SIZE) * 4,
+ CQE_POLLING_BUFFER));
if (comp_read < 1)
return;
@@ -2156,7 +2162,14 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
struct mana_rxq *rxq = cq->rxq;
int comp_read, i;
- comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
+ /* Limit CQEs polled to 4 wraparounds of the CQ to ensure the
+ * doorbell can be rung in time for the hardware's requirement
+ * of at least one doorbell ring every 8 wraparounds.
+ */
+ comp_read = mana_gd_poll_cq(cq->gdma_cq, comp,
+ min((cq->gdma_cq->queue_size /
+ COMP_ENTRY_SIZE) * 4,
+ CQE_POLLING_BUFFER));
WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
rxq->xdp_flush = false;
@@ -2201,11 +2214,11 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
mana_gd_ring_cq(gdma_queue, SET_ARM_BIT);
cq->work_done_since_doorbell = 0;
napi_complete_done(&cq->napi, w);
- } else if (cq->work_done_since_doorbell >
- cq->gdma_cq->queue_size / COMP_ENTRY_SIZE * 4) {
+ } else if (cq->work_done_since_doorbell >=
+ (cq->gdma_cq->queue_size / COMP_ENTRY_SIZE) * 4) {
/* MANA hardware requires at least one doorbell ring every 8
* wraparounds of CQ even if there is no need to arm the CQ.
- * This driver rings the doorbell as soon as we have exceeded
+ * This driver rings the doorbell as soon as it has processed
* 4 wraparounds.
*/
mana_gd_ring_cq(gdma_queue, 0);
@@ -3757,7 +3770,9 @@ void mana_rdma_remove(struct gdma_dev *gd)
}
WRITE_ONCE(gd->rdma_teardown, true);
- flush_workqueue(gc->service_wq);
+
+ if (gc->service_wq)
+ flush_workqueue(gc->service_wq);
if (gd->adev)
remove_adev(gd);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 51c96a738151..33667a26708c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -323,6 +323,7 @@ struct stmmac_priv {
void __iomem *ptpaddr;
void __iomem *estaddr;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ unsigned int num_double_vlans;
int sfty_irq;
int sfty_ce_irq;
int sfty_ue_irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index edf0799b7236..6827c99bde8c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -156,6 +156,7 @@ static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue);
static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue);
static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
u32 rxmode, u32 chan);
+static int stmmac_vlan_restore(struct stmmac_priv *priv);
#ifdef CONFIG_DEBUG_FS
static const struct net_device_ops stmmac_netdev_ops;
@@ -853,6 +854,7 @@ static int stmmac_init_timestamping(struct stmmac_priv *priv)
netdev_info(priv->dev,
"IEEE 1588-2008 Advanced Timestamp supported\n");
+ memset(&priv->tstamp_config, 0, sizeof(priv->tstamp_config));
priv->hwts_tx_en = 0;
priv->hwts_rx_en = 0;
@@ -4106,6 +4108,8 @@ static int __stmmac_open(struct net_device *dev,
phylink_start(priv->phylink);
+ stmmac_vlan_restore(priv);
+
ret = stmmac_request_irq(dev);
if (ret)
goto irq_error;
@@ -6765,6 +6769,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
hash = 0;
}
+ if (!netif_running(priv->dev))
+ return 0;
+
return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
}
@@ -6774,6 +6781,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
{
struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int num_double_vlans;
bool is_double = false;
int ret;
@@ -6785,7 +6793,8 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
is_double = true;
set_bit(vid, priv->active_vlans);
- ret = stmmac_vlan_update(priv, is_double);
+ num_double_vlans = priv->num_double_vlans + is_double;
+ ret = stmmac_vlan_update(priv, num_double_vlans);
if (ret) {
clear_bit(vid, priv->active_vlans);
goto err_pm_put;
@@ -6793,9 +6802,15 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
if (priv->hw->num_vlan) {
ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
- if (ret)
+ if (ret) {
+ clear_bit(vid, priv->active_vlans);
+ stmmac_vlan_update(priv, priv->num_double_vlans);
goto err_pm_put;
+ }
}
+
+ priv->num_double_vlans = num_double_vlans;
+
err_pm_put:
pm_runtime_put(priv->device);
@@ -6808,6 +6823,7 @@ err_pm_put:
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
{
struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int num_double_vlans;
bool is_double = false;
int ret;
@@ -6819,14 +6835,23 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
is_double = true;
clear_bit(vid, priv->active_vlans);
+ num_double_vlans = priv->num_double_vlans - is_double;
+ ret = stmmac_vlan_update(priv, num_double_vlans);
+ if (ret) {
+ set_bit(vid, priv->active_vlans);
+ goto del_vlan_error;
+ }
if (priv->hw->num_vlan) {
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
- if (ret)
+ if (ret) {
+ set_bit(vid, priv->active_vlans);
+ stmmac_vlan_update(priv, priv->num_double_vlans);
goto del_vlan_error;
+ }
}
- ret = stmmac_vlan_update(priv, is_double);
+ priv->num_double_vlans = num_double_vlans;
del_vlan_error:
pm_runtime_put(priv->device);
@@ -6834,6 +6859,23 @@ del_vlan_error:
return ret;
}
+static int stmmac_vlan_restore(struct stmmac_priv *priv)
+{
+ int ret;
+
+ if (!(priv->dev->features & NETIF_F_VLAN_FEATURES))
+ return 0;
+
+ if (priv->hw->num_vlan)
+ stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw);
+
+ ret = stmmac_vlan_update(priv, priv->num_double_vlans);
+ if (ret)
+ netdev_err(priv->dev, "Failed to restore VLANs\n");
+
+ return ret;
+}
+
static int stmmac_bpf(struct net_device *dev, struct netdev_bpf *bpf)
{
struct stmmac_priv *priv = netdev_priv(dev);
@@ -8258,10 +8300,10 @@ int stmmac_resume(struct device *dev)
stmmac_init_coalesce(priv);
phylink_rx_clk_stop_block(priv->phylink);
stmmac_set_rx_mode(ndev);
-
- stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
phylink_rx_clk_stop_unblock(priv->phylink);
+ stmmac_vlan_restore(priv);
+
stmmac_enable_all_queues(priv);
stmmac_enable_all_dma_irq(priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index b18404dd5a8b..e24efe3bfedb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -76,7 +76,9 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
}
hw->vlan_filter[0] = vid;
- vlan_write_single(dev, vid);
+
+ if (netif_running(dev))
+ vlan_write_single(dev, vid);
return 0;
}
@@ -97,12 +99,15 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev,
return -EPERM;
}
- ret = vlan_write_filter(dev, hw, index, val);
+ if (netif_running(dev)) {
+ ret = vlan_write_filter(dev, hw, index, val);
+ if (ret)
+ return ret;
+ }
- if (!ret)
- hw->vlan_filter[index] = val;
+ hw->vlan_filter[index] = val;
- return ret;
+ return 0;
}
static int vlan_del_hw_rx_fltr(struct net_device *dev,
@@ -115,7 +120,9 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
if (hw->num_vlan == 1) {
if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) {
hw->vlan_filter[0] = 0;
- vlan_write_single(dev, 0);
+
+ if (netif_running(dev))
+ vlan_write_single(dev, 0);
}
return 0;
}
@@ -124,25 +131,23 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev,
for (i = 0; i < hw->num_vlan; i++) {
if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) &&
((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid)) {
- ret = vlan_write_filter(dev, hw, i, 0);
- if (!ret)
- hw->vlan_filter[i] = 0;
- else
- return ret;
+ if (netif_running(dev)) {
+ ret = vlan_write_filter(dev, hw, i, 0);
+ if (ret)
+ return ret;
+ }
+
+ hw->vlan_filter[i] = 0;
}
}
- return ret;
+ return 0;
}
static void vlan_restore_hw_rx_fltr(struct net_device *dev,
struct mac_device_info *hw)
{
- void __iomem *ioaddr = hw->pcsr;
- u32 value;
- u32 hash;
- u32 val;
int i;
/* Single Rx VLAN Filter */
@@ -152,19 +157,8 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
}
/* Extended Rx VLAN Filter Enable */
- for (i = 0; i < hw->num_vlan; i++) {
- if (hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) {
- val = hw->vlan_filter[i];
- vlan_write_filter(dev, hw, i, val);
- }
- }
-
- hash = readl(ioaddr + VLAN_HASH_TABLE);
- if (hash & VLAN_VLHT) {
- value = readl(ioaddr + VLAN_TAG);
- value |= VLAN_VTHM;
- writel(value, ioaddr + VLAN_TAG);
- }
+ for (i = 0; i < hw->num_vlan; i++)
+ vlan_write_filter(dev, hw, i, hw->vlan_filter[i]);
}
static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
@@ -183,6 +177,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
value |= VLAN_EDVLP;
value |= VLAN_ESVL;
value |= VLAN_DOVLTC;
+ } else {
+ value &= ~VLAN_EDVLP;
+ value &= ~VLAN_ESVL;
+ value &= ~VLAN_DOVLTC;
}
writel(value, ioaddr + VLAN_TAG);
@@ -193,6 +191,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
value |= VLAN_EDVLP;
value |= VLAN_ESVL;
value |= VLAN_DOVLTC;
+ } else {
+ value &= ~VLAN_EDVLP;
+ value &= ~VLAN_ESVL;
+ value &= ~VLAN_DOVLTC;
}
writel(value | perfect_match, ioaddr + VLAN_TAG);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 5924db6be3fe..967918050433 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -391,7 +391,7 @@ static void am65_cpsw_nuss_ndo_slave_set_rx_mode(struct net_device *ndev)
cpsw_ale_set_allmulti(common->ale,
ndev->flags & IFF_ALLMULTI, port->port_id);
- port_mask = ALE_PORT_HOST;
+ port_mask = BIT(port->port_id) | ALE_PORT_HOST;
/* Clear all mcast from ALE */
cpsw_ale_flush_multicast(common->ale, port_mask, -1);
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index bb969dd435b4..be7b69319221 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -450,14 +450,13 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
ale->port_mask_bits);
if ((mask & port_mask) == 0)
return; /* ports dont intersect, not interested */
- mask &= ~port_mask;
+ mask &= (~port_mask | ALE_PORT_HOST);
- /* free if only remaining port is host port */
- if (mask)
+ if (mask == 0x0 || mask == ALE_PORT_HOST)
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+ else
cpsw_ale_set_port_mask(ale_entry, mask,
ale->port_mask_bits);
- else
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
}
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 0939994c932f..42a881bee109 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -273,6 +273,14 @@ static int prueth_emac_common_start(struct prueth *prueth)
if (ret)
goto disable_class;
+ /* Reset link state to force reconfiguration in
+ * emac_adjust_link(). Without this, if the link was already up
+ * before restart, emac_adjust_link() won't detect any state
+ * change and will skip critical configuration like writing
+ * speed to firmware.
+ */
+ emac->link = 0;
+
mutex_lock(&emac->ndev->phydev->lock);
emac_adjust_link(emac->ndev);
mutex_unlock(&emac->ndev->phydev->lock);
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index e1e7f65553e7..b0faa0f1780d 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -403,15 +403,12 @@ static int ixp4xx_hwtstamp_set(struct net_device *netdev,
int ret;
int ch;
- if (!cpu_is_ixp46x())
- return -EOPNOTSUPP;
-
if (!netif_running(netdev))
return -EINVAL;
ret = ixp46x_ptp_find(&port->timesync_regs, &port->phc_index);
if (ret)
- return ret;
+ return -EOPNOTSUPP;
ch = PORT2CHANNEL(port);
regs = port->timesync_regs;
diff --git a/drivers/net/ethernet/xscale/ptp_ixp46x.c b/drivers/net/ethernet/xscale/ptp_ixp46x.c
index 94203eb46e6b..93c64db22a69 100644
--- a/drivers/net/ethernet/xscale/ptp_ixp46x.c
+++ b/drivers/net/ethernet/xscale/ptp_ixp46x.c
@@ -232,6 +232,9 @@ static struct ixp_clock ixp_clock;
int ixp46x_ptp_find(struct ixp46x_ts_regs *__iomem *regs, int *phc_index)
{
+ if (!cpu_is_ixp46x())
+ return -ENODEV;
+
*regs = ixp_clock.regs;
*phc_index = ptp_clock_index(ixp_clock.ptp_clock);
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 37415cad69f5..3c9acd6e49e8 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -617,7 +617,7 @@ static ssize_t sysdata_release_enabled_show(struct config_item *item,
bool release_enabled;
dynamic_netconsole_mutex_lock();
- release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
+ release_enabled = !!(nt->sysdata_fields & SYSDATA_RELEASE);
dynamic_netconsole_mutex_unlock();
return sysfs_emit(buf, "%d\n", release_enabled);
@@ -1679,7 +1679,8 @@ static void send_msg_no_fragmentation(struct netconsole_target *nt,
if (release_len) {
release = init_utsname()->release;
- scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%s", release, msg);
+ scnprintf(nt->buf, MAX_PRINT_CHUNK, "%s,%.*s", release,
+ msg_len, msg);
msg_len += release_len;
} else {
memcpy(nt->buf, msg, msg_len);
diff --git a/drivers/net/ovpn/tcp.c b/drivers/net/ovpn/tcp.c
index ec2bbc28c196..5499c1572f3e 100644
--- a/drivers/net/ovpn/tcp.c
+++ b/drivers/net/ovpn/tcp.c
@@ -70,37 +70,56 @@ static void ovpn_tcp_to_userspace(struct ovpn_peer *peer, struct sock *sk,
peer->tcp.sk_cb.sk_data_ready(sk);
}
-static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
+static struct sk_buff *ovpn_tcp_skb_packet(const struct ovpn_peer *peer,
+ struct sk_buff *orig_skb,
+ const int pkt_len, const int pkt_off)
{
- struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp);
- struct strp_msg *msg = strp_msg(skb);
- size_t pkt_len = msg->full_len - 2;
- size_t off = msg->offset + 2;
- u8 opcode;
+ struct sk_buff *ovpn_skb;
+ int err;
- /* ensure skb->data points to the beginning of the openvpn packet */
- if (!pskb_pull(skb, off)) {
- net_warn_ratelimited("%s: packet too small for peer %u\n",
- netdev_name(peer->ovpn->dev), peer->id);
+ /* create a new skb with only the content of the current packet */
+ ovpn_skb = netdev_alloc_skb(peer->ovpn->dev, pkt_len);
+ if (unlikely(!ovpn_skb))
goto err;
- }
- /* strparser does not trim the skb for us, therefore we do it now */
- if (pskb_trim(skb, pkt_len) != 0) {
- net_warn_ratelimited("%s: trimming skb failed for peer %u\n",
+ skb_copy_header(ovpn_skb, orig_skb);
+ err = skb_copy_bits(orig_skb, pkt_off, skb_put(ovpn_skb, pkt_len),
+ pkt_len);
+ if (unlikely(err)) {
+ net_warn_ratelimited("%s: skb_copy_bits failed for peer %u\n",
netdev_name(peer->ovpn->dev), peer->id);
+ kfree_skb(ovpn_skb);
goto err;
}
- /* we need the first 4 bytes of data to be accessible
+ consume_skb(orig_skb);
+ return ovpn_skb;
+err:
+ kfree_skb(orig_skb);
+ return NULL;
+}
+
+static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
+{
+ struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp);
+ struct strp_msg *msg = strp_msg(skb);
+ int pkt_len = msg->full_len - 2;
+ u8 opcode;
+
+ /* we need at least 4 bytes of data in the packet
* to extract the opcode and the key ID later on
*/
- if (!pskb_may_pull(skb, OVPN_OPCODE_SIZE)) {
+ if (unlikely(pkt_len < OVPN_OPCODE_SIZE)) {
net_warn_ratelimited("%s: packet too small to fetch opcode for peer %u\n",
netdev_name(peer->ovpn->dev), peer->id);
goto err;
}
+ /* extract the packet into a new skb */
+ skb = ovpn_tcp_skb_packet(peer, skb, pkt_len, msg->offset + 2);
+ if (unlikely(!skb))
+ goto err;
+
/* DATA_V2 packets are handled in kernel, the rest goes to user space */
opcode = ovpn_opcode_from_skb(skb, 0);
if (unlikely(opcode != OVPN_DATA_V2)) {
@@ -113,7 +132,7 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
/* The packet size header must be there when sending the packet
* to userspace, therefore we put it back
*/
- skb_push(skb, 2);
+ *(__be16 *)__skb_push(skb, sizeof(u16)) = htons(pkt_len);
ovpn_tcp_to_userspace(peer, strp->sk, skb);
return;
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 02fc0133428d..3bd415710bf3 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1866,8 +1866,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
goto error;
phy_resume(phydev);
- if (!phydev->is_on_sfp_module)
- phy_led_triggers_register(phydev);
/**
* If the external phy used by current mac interface is managed by
@@ -1982,9 +1980,6 @@ void phy_detach(struct phy_device *phydev)
phydev->phy_link_change = NULL;
phydev->phylink = NULL;
- if (!phydev->is_on_sfp_module)
- phy_led_triggers_unregister(phydev);
-
if (phydev->mdio.dev.driver)
module_put(phydev->mdio.dev.driver->owner);
@@ -3778,16 +3773,27 @@ static int phy_probe(struct device *dev)
/* Set the state to READY by default */
phydev->state = PHY_READY;
+ /* Register the PHY LED triggers */
+ if (!phydev->is_on_sfp_module)
+ phy_led_triggers_register(phydev);
+
/* Get the LEDs from the device tree, and instantiate standard
* LEDs for them.
*/
- if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev))
+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev)) {
err = of_phy_leds(phydev);
+ if (err)
+ goto out;
+ }
+
+ return 0;
out:
+ if (!phydev->is_on_sfp_module)
+ phy_led_triggers_unregister(phydev);
+
/* Re-assert the reset signal on error */
- if (err)
- phy_device_reset(phydev, 1);
+ phy_device_reset(phydev, 1);
return err;
}
@@ -3801,6 +3807,9 @@ static int phy_remove(struct device *dev)
if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev))
phy_leds_unregister(phydev);
+ if (!phydev->is_on_sfp_module)
+ phy_led_triggers_unregister(phydev);
+
phydev->state = PHY_DOWN;
phy_cleanup_ports(phydev);
diff --git a/drivers/net/phy/qcom/qca807x.c b/drivers/net/phy/qcom/qca807x.c
index d8f1ce5a7128..6004da5741af 100644
--- a/drivers/net/phy/qcom/qca807x.c
+++ b/drivers/net/phy/qcom/qca807x.c
@@ -375,7 +375,7 @@ static int qca807x_gpio_get(struct gpio_chip *gc, unsigned int offset)
reg = QCA807X_MMD7_LED_FORCE_CTRL(offset);
val = phy_read_mmd(priv->phy, MDIO_MMD_AN, reg);
- return FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val);
+ return !!FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val);
}
static int qca807x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index 937dd6dc070b..b7282f5c9632 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -1290,7 +1290,7 @@ err_set_mtu:
static void __team_port_change_port_removed(struct team_port *port);
-static int team_port_del(struct team *team, struct net_device *port_dev)
+static int team_port_del(struct team *team, struct net_device *port_dev, bool unregister)
{
struct net_device *dev = team->dev;
struct team_port *port;
@@ -1328,7 +1328,13 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
__team_port_change_port_removed(port);
team_port_set_orig_dev_addr(port);
- dev_set_mtu(port_dev, port->orig.mtu);
+ if (unregister) {
+ netdev_lock_ops(port_dev);
+ __netif_set_mtu(port_dev, port->orig.mtu);
+ netdev_unlock_ops(port_dev);
+ } else {
+ dev_set_mtu(port_dev, port->orig.mtu);
+ }
kfree_rcu(port, rcu);
netdev_info(dev, "Port device %s removed\n", portname);
netdev_compute_master_upper_features(team->dev, true);
@@ -1632,7 +1638,7 @@ static void team_uninit(struct net_device *dev)
ASSERT_RTNL();
list_for_each_entry_safe(port, tmp, &team->port_list, list)
- team_port_del(team, port->dev);
+ team_port_del(team, port->dev, false);
__team_change_mode(team, NULL); /* cleanup */
__team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
@@ -1931,7 +1937,16 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
ASSERT_RTNL();
- return team_port_del(team, port_dev);
+ return team_port_del(team, port_dev, false);
+}
+
+static int team_del_slave_on_unregister(struct net_device *dev, struct net_device *port_dev)
+{
+ struct team *team = netdev_priv(dev);
+
+ ASSERT_RTNL();
+
+ return team_port_del(team, port_dev, true);
}
static netdev_features_t team_fix_features(struct net_device *dev,
@@ -2924,7 +2939,7 @@ static int team_device_event(struct notifier_block *unused,
!!netif_oper_up(port->dev));
break;
case NETDEV_UNREGISTER:
- team_del_slave(port->team->dev, dev);
+ team_del_slave_on_unregister(port->team->dev, dev);
break;
case NETDEV_FEAT_CHANGE:
if (!port->team->notifier_ctx) {
@@ -2997,3 +3012,4 @@ MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
MODULE_DESCRIPTION("Ethernet team device driver");
MODULE_ALIAS_RTNL_LINK(DRV_NAME);
+MODULE_IMPORT_NS("NETDEV_INTERNAL");
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index 613fc6910f14..ee9c48f7f68f 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -132,11 +132,18 @@ kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
{
int status;
u8 ethernet_addr[ETH_ALEN];
+ static const u8 ep_addr[] = {
+ 1 | USB_DIR_IN,
+ 2 | USB_DIR_OUT,
+ 0};
/* Don't bind to AT command interface */
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
return -EINVAL;
+ if (!usb_check_bulk_endpoints(intf, ep_addr))
+ return -ENODEV;
+
dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK);
dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK);
dev->status = NULL;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index c9efb7df892e..cb2472b59e10 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -765,7 +765,6 @@ static void kaweth_set_rx_mode(struct net_device *net)
netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap);
- netif_stop_queue(net);
if (net->flags & IFF_PROMISC) {
packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
@@ -775,7 +774,6 @@ static void kaweth_set_rx_mode(struct net_device *net)
}
kaweth->packet_filter_bitmap = packet_filter_bitmap;
- netif_wake_queue(net);
}
/****************************************************************
@@ -885,6 +883,13 @@ static int kaweth_probe(
const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
int result = 0;
int rv = -EIO;
+ static const u8 bulk_ep_addr[] = {
+ 1 | USB_DIR_IN,
+ 2 | USB_DIR_OUT,
+ 0};
+ static const u8 int_ep_addr[] = {
+ 3 | USB_DIR_IN,
+ 0};
dev_dbg(dev,
"Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
@@ -898,6 +903,12 @@ static int kaweth_probe(
(int)udev->descriptor.bLength,
(int)udev->descriptor.bDescriptorType);
+ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+ !usb_check_int_endpoints(intf, int_ep_addr)) {
+ dev_err(dev, "couldn't find required endpoints\n");
+ return -ENODEV;
+ }
+
netdev = alloc_etherdev(sizeof(*kaweth));
if (!netdev)
return -ENOMEM;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 8da8e04c3109..a0021df12fde 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2094,8 +2094,6 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev)
dev->mdiobus->phy_mask = ~(1 << 1);
break;
case ID_REV_CHIP_ID_7801_:
- /* scan thru PHYAD[2..0] */
- dev->mdiobus->phy_mask = ~(0xFF);
break;
}
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 4f539b5d509a..db85f40734d7 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -28,6 +28,17 @@ static const char driver_name[] = "pegasus";
BMSR_100FULL | BMSR_ANEGCAPABLE)
#define CARRIER_CHECK_DELAY (2 * HZ)
+/*
+ * USB endpoints.
+ */
+
+enum pegasus_usb_ep {
+ PEGASUS_USB_EP_CONTROL = 0,
+ PEGASUS_USB_EP_BULK_IN = 1,
+ PEGASUS_USB_EP_BULK_OUT = 2,
+ PEGASUS_USB_EP_INT_IN = 3,
+};
+
static bool loopback;
static bool mii_mode;
static char *devid;
@@ -542,7 +553,7 @@ static void read_bulk_callback(struct urb *urb)
goto tl_sched;
goon:
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
- usb_rcvbulkpipe(pegasus->usb, 1),
+ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus);
rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
@@ -582,7 +593,7 @@ static void rx_fixup(struct tasklet_struct *t)
return;
}
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
- usb_rcvbulkpipe(pegasus->usb, 1),
+ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus);
try_again:
@@ -710,7 +721,7 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb,
((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len);
usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
- usb_sndbulkpipe(pegasus->usb, 2),
+ usb_sndbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_OUT),
pegasus->tx_buff, count,
write_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
@@ -801,8 +812,19 @@ static void unlink_all_urbs(pegasus_t *pegasus)
static int alloc_urbs(pegasus_t *pegasus)
{
+ static const u8 bulk_ep_addr[] = {
+ 1 | USB_DIR_IN,
+ 2 | USB_DIR_OUT,
+ 0};
+ static const u8 int_ep_addr[] = {
+ 3 | USB_DIR_IN,
+ 0};
int res = -ENOMEM;
+ if (!usb_check_bulk_endpoints(pegasus->intf, bulk_ep_addr) ||
+ !usb_check_int_endpoints(pegasus->intf, int_ep_addr))
+ return -ENODEV;
+
pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->rx_urb) {
return res;
@@ -837,7 +859,7 @@ static int pegasus_open(struct net_device *net)
set_registers(pegasus, EthID, 6, net->dev_addr);
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
- usb_rcvbulkpipe(pegasus->usb, 1),
+ usb_rcvbulkpipe(pegasus->usb, PEGASUS_USB_EP_BULK_IN),
pegasus->rx_skb->data, PEGASUS_MTU,
read_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
@@ -848,7 +870,7 @@ static int pegasus_open(struct net_device *net)
}
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
- usb_rcvintpipe(pegasus->usb, 3),
+ usb_rcvintpipe(pegasus->usb, PEGASUS_USB_EP_INT_IN),
pegasus->intr_buff, sizeof(pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
@@ -1133,16 +1155,31 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus_t *pegasus;
int dev_index = id - pegasus_ids;
int res = -ENOMEM;
+ static const u8 bulk_ep_addr[] = {
+ PEGASUS_USB_EP_BULK_IN | USB_DIR_IN,
+ PEGASUS_USB_EP_BULK_OUT | USB_DIR_OUT,
+ 0};
+ static const u8 int_ep_addr[] = {
+ PEGASUS_USB_EP_INT_IN | USB_DIR_IN,
+ 0};
if (pegasus_blacklisted(dev))
return -ENODEV;
+ /* Verify that all required endpoints are present */
+ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+ !usb_check_int_endpoints(intf, int_ep_addr)) {
+ dev_err(&intf->dev, "Missing or invalid endpoints\n");
+ return -ENODEV;
+ }
+
net = alloc_etherdev(sizeof(struct pegasus));
if (!net)
goto out;
pegasus = netdev_priv(net);
pegasus->dev_index = dev_index;
+ pegasus->intf = intf;
res = alloc_urbs(pegasus);
if (res < 0) {
@@ -1154,7 +1191,6 @@ static int pegasus_probe(struct usb_interface *intf,
INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
- pegasus->intf = intf;
pegasus->usb = dev;
pegasus->net = net;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 4af85728ac4f..0c83bbbea2e7 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -10054,6 +10054,7 @@ static const struct usb_device_id rtl8152_table[] = {
{ USB_DEVICE(VENDOR_ID_DLINK, 0xb301) },
{ USB_DEVICE(VENDOR_ID_DELL, 0xb097) },
{ USB_DEVICE(VENDOR_ID_ASUS, 0x1976) },
+ { USB_DEVICE(VENDOR_ID_TRENDNET, 0xe02b) },
{}
};
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 05558b6afecd..17c941aac32d 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -2130,6 +2130,11 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
{
struct ipv6hdr *pip6;
+ /* check if nd_tbl is not initiliazed due to
+ * ipv6.disable=1 set during boot
+ */
+ if (!ipv6_stub->nd_tbl)
+ return false;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
return false;
pip6 = ipv6_hdr(skb);
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 957e0b272d54..73f393900710 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -2550,6 +2550,8 @@ fst_remove_one(struct pci_dev *pdev)
fst_disable_intr(card);
free_irq(card->irq, card);
+ tasklet_kill(&fst_tx_task);
+ tasklet_kill(&fst_int_task);
iounmap(card->ctlmem);
iounmap(card->mem);
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index c6b88909b6b7..b253d1e3f405 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -5430,7 +5430,7 @@ int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
ar->last_tx_power_update))
goto send_tx_power;
- params.pdev_id = ar->pdev->pdev_id;
+ params.pdev_id = ath12k_mac_get_target_pdev_id(ar);
params.vdev_id = arvif->vdev_id;
params.stats_id = WMI_REQUEST_PDEV_STAT;
ret = ath12k_mac_get_fw_stats(ar, &params);
@@ -13452,7 +13452,7 @@ void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
/* TODO: Use real NF instead of default one. */
signal = rate_info.rssi_comb;
- params.pdev_id = ar->pdev->pdev_id;
+ params.pdev_id = ath12k_mac_get_target_pdev_id(ar);
params.vdev_id = 0;
params.stats_id = WMI_REQUEST_VDEV_STAT;
@@ -13580,7 +13580,7 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->ab->dp->dp_lock);
if (!signal && ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
- params.pdev_id = ar->pdev->pdev_id;
+ params.pdev_id = ath12k_mac_get_target_pdev_id(ar);
params.vdev_id = 0;
params.stats_id = WMI_REQUEST_VDEV_STAT;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index eb7615a289f7..48fee9346de8 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -8241,8 +8241,6 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
struct ath12k_fw_stats *stats = parse->stats;
struct ath12k *ar;
struct ath12k_link_vif *arvif;
- struct ieee80211_sta *sta;
- struct ath12k_sta *ahsta;
struct ath12k_link_sta *arsta;
int i, ret = 0;
const void *data = ptr;
@@ -8278,21 +8276,19 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab,
arvif = ath12k_mac_get_arvif(ar, le32_to_cpu(src->vdev_id));
if (arvif) {
- sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
- arvif->bssid,
- NULL);
- if (sta) {
- ahsta = ath12k_sta_to_ahsta(sta);
- arsta = &ahsta->deflink;
+ spin_lock_bh(&ab->base_lock);
+ arsta = ath12k_link_sta_find_by_addr(ab, arvif->bssid);
+ if (arsta) {
arsta->rssi_beacon = le32_to_cpu(src->beacon_snr);
ath12k_dbg(ab, ATH12K_DBG_WMI,
"wmi stats vdev id %d snr %d\n",
src->vdev_id, src->beacon_snr);
} else {
- ath12k_dbg(ab, ATH12K_DBG_WMI,
- "not found station bssid %pM for vdev stat\n",
- arvif->bssid);
+ ath12k_warn(ab,
+ "not found link sta with bssid %pM for vdev stat\n",
+ arvif->bssid);
}
+ spin_unlock_bh(&ab->base_lock);
}
data += sizeof(*src);
@@ -8363,8 +8359,6 @@ static int ath12k_wmi_tlv_rssi_chain_parse(struct ath12k_base *ab,
struct ath12k_fw_stats *stats = parse->stats;
struct ath12k_link_vif *arvif;
struct ath12k_link_sta *arsta;
- struct ieee80211_sta *sta;
- struct ath12k_sta *ahsta;
struct ath12k *ar;
int vdev_id;
int j;
@@ -8400,19 +8394,15 @@ static int ath12k_wmi_tlv_rssi_chain_parse(struct ath12k_base *ab,
"stats bssid %pM vif %p\n",
arvif->bssid, arvif->ahvif->vif);
- sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
- arvif->bssid,
- NULL);
- if (!sta) {
- ath12k_dbg(ab, ATH12K_DBG_WMI,
- "not found station of bssid %pM for rssi chain\n",
- arvif->bssid);
+ guard(spinlock_bh)(&ab->base_lock);
+ arsta = ath12k_link_sta_find_by_addr(ab, arvif->bssid);
+ if (!arsta) {
+ ath12k_warn(ab,
+ "not found link sta with bssid %pM for rssi chain\n",
+ arvif->bssid);
return -EPROTO;
}
- ahsta = ath12k_sta_to_ahsta(sta);
- arsta = &ahsta->deflink;
-
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
ARRAY_SIZE(stats_rssi->rssi_avg_beacon));
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 28e5df04bd43..d24b80e492e0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -951,11 +951,10 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
goto out;
/* try to attach to the target device */
- sdiodev->bus = brcmf_sdio_probe(sdiodev);
- if (IS_ERR(sdiodev->bus)) {
- ret = PTR_ERR(sdiodev->bus);
+ ret = brcmf_sdio_probe(sdiodev);
+ if (ret)
goto out;
- }
+
brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
out:
if (ret)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 30c19591c018..30f6fcb68632 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4445,7 +4445,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
return fwreq;
}
-struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{
int ret;
struct brcmf_sdio *bus;
@@ -4551,11 +4551,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
goto fail;
}
- return bus;
+ return 0;
fail:
brcmf_sdio_remove(bus);
- return ERR_PTR(ret);
+ sdiodev->bus = NULL;
+ return ret;
}
/* Detach and free everything */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 0d18ed15b403..80180d5c6c87 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -358,7 +358,7 @@ void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev);
int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev);
int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev);
-struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdio_remove(struct brcmf_sdio *bus);
void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c
index d44e02c6fe38..dd97f1b61f4d 100644
--- a/drivers/net/wireless/marvell/libertas/main.c
+++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -799,8 +799,8 @@ static void lbs_free_adapter(struct lbs_private *priv)
{
lbs_free_cmd_buffer(priv);
kfifo_free(&priv->event_fifo);
- timer_delete(&priv->command_timer);
- timer_delete(&priv->tx_lockup_timer);
+ timer_delete_sync(&priv->command_timer);
+ timer_delete_sync(&priv->tx_lockup_timer);
}
static const struct net_device_ops lbs_netdev_ops = {
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 43704106cd80..eb28fe718e71 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3148,7 +3148,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
SET_NETDEV_DEV(dev, adapter->dev);
ret = dev_alloc_name(dev, name);
- if (ret)
+ if (ret < 0)
goto err_alloc_name;
priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC-%s",
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index 3304b5971be0..b41ca1410da9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -413,6 +413,7 @@ mt76_connac2_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + 1 + 2 &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 871b67101976..0d9435900423 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -668,6 +668,7 @@ mt7925_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
tid = MT_TX_ADDBA;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 2560e2f46e89..d4f3ee943b47 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -800,6 +800,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
u32 val;
if (ieee80211_is_action(fc) &&
+ skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
if (is_mt7990(&dev->mt76))
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 8c8e074a3a70..c7ae8031436a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -668,7 +668,7 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
struct ieee80211_conf *conf = &hw->conf;
- int status = -EOPNOTSUPP;
+ int status = 0;
mutex_lock(&common->mutex);
diff --git a/drivers/net/wireless/st/cw1200/pm.c b/drivers/net/wireless/st/cw1200/pm.c
index 120f0379f81d..84eb15d729c7 100644
--- a/drivers/net/wireless/st/cw1200/pm.c
+++ b/drivers/net/wireless/st/cw1200/pm.c
@@ -264,12 +264,14 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
wiphy_err(priv->hw->wiphy,
"PM request failed: %d. WoW is disabled.\n", ret);
cw1200_wow_resume(hw);
+ mutex_unlock(&priv->conf_mutex);
return -EBUSY;
}
/* Force resume if event is coming from the device. */
if (atomic_read(&priv->bh_rx)) {
cw1200_wow_resume(hw);
+ mutex_unlock(&priv->conf_mutex);
return -EAGAIN;
}
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 17dd417756f2..1c340a4a0930 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1875,6 +1875,8 @@ static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw)
wl->wow_enabled);
WARN_ON(!wl->wow_enabled);
+ mutex_lock(&wl->mutex);
+
ret = pm_runtime_force_resume(wl->dev);
if (ret < 0) {
wl1271_error("ELP wakeup failure!");
@@ -1891,8 +1893,6 @@ static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw)
run_irq_work = true;
spin_unlock_irqrestore(&wl->wl_lock, flags);
- mutex_lock(&wl->mutex);
-
/* test the recovery flag before calling any SDIO functions */
pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
&wl->flags);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d316b35f404b..2ed673649c48 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1646,7 +1646,7 @@ static int xennet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
/* avoid the race with XDP headroom adjustment */
wait_event(module_wq,
- xenbus_read_driver_state(np->xbdev->otherend) ==
+ xenbus_read_driver_state(np->xbdev, np->xbdev->otherend) ==
XenbusStateReconfigured);
np->netfront_xdp_enabled = true;
@@ -1764,9 +1764,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
do {
xenbus_switch_state(dev, XenbusStateInitialising);
err = wait_event_timeout(module_wq,
- xenbus_read_driver_state(dev->otherend) !=
+ xenbus_read_driver_state(dev, dev->otherend) !=
XenbusStateClosed &&
- xenbus_read_driver_state(dev->otherend) !=
+ xenbus_read_driver_state(dev, dev->otherend) !=
XenbusStateUnknown, XENNET_TIMEOUT);
} while (!err);
@@ -2626,31 +2626,31 @@ static void xennet_bus_close(struct xenbus_device *dev)
{
int ret;
- if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+ if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
return;
do {
xenbus_switch_state(dev, XenbusStateClosing);
ret = wait_event_timeout(module_wq,
- xenbus_read_driver_state(dev->otherend) ==
- XenbusStateClosing ||
- xenbus_read_driver_state(dev->otherend) ==
- XenbusStateClosed ||
- xenbus_read_driver_state(dev->otherend) ==
- XenbusStateUnknown,
- XENNET_TIMEOUT);
+ xenbus_read_driver_state(dev, dev->otherend) ==
+ XenbusStateClosing ||
+ xenbus_read_driver_state(dev, dev->otherend) ==
+ XenbusStateClosed ||
+ xenbus_read_driver_state(dev, dev->otherend) ==
+ XenbusStateUnknown,
+ XENNET_TIMEOUT);
} while (!ret);
- if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+ if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
return;
do {
xenbus_switch_state(dev, XenbusStateClosed);
ret = wait_event_timeout(module_wq,
- xenbus_read_driver_state(dev->otherend) ==
- XenbusStateClosed ||
- xenbus_read_driver_state(dev->otherend) ==
- XenbusStateUnknown,
- XENNET_TIMEOUT);
+ xenbus_read_driver_state(dev, dev->otherend) ==
+ XenbusStateClosed ||
+ xenbus_read_driver_state(dev, dev->otherend) ==
+ XenbusStateUnknown,
+ XENNET_TIMEOUT);
} while (!ret);
}
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
index 018a80674f06..0f12f86ebb02 100644
--- a/drivers/nfc/pn533/usb.c
+++ b/drivers/nfc/pn533/usb.c
@@ -628,6 +628,7 @@ static void pn533_usb_disconnect(struct usb_interface *interface)
usb_free_urb(phy->out_urb);
usb_free_urb(phy->ack_urb);
kfree(phy->ack_buffer);
+ usb_put_dev(phy->udev);
nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n");
}
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f5ebcaa2f859..58bf432ec5e6 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2046,14 +2046,10 @@ static u32 nvme_configure_atomic_write(struct nvme_ns *ns,
if (id->nabspf)
boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
} else {
- /*
- * Use the controller wide atomic write unit. This sucks
- * because the limit is defined in terms of logical blocks while
- * namespaces can have different formats, and because there is
- * no clear language in the specification prohibiting different
- * values for different controllers in the subsystem.
- */
- atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
+ if (ns->ctrl->awupf)
+ dev_info_once(ns->ctrl->device,
+ "AWUPF ignored, only NAWUPF accepted\n");
+ atomic_bs = bs;
}
lim->atomic_write_hw_max = atomic_bs;
@@ -3222,7 +3218,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
memcpy(subsys->model, id->mn, sizeof(subsys->model));
subsys->vendor_id = le16_to_cpu(id->vid);
subsys->cmic = id->cmic;
- subsys->awupf = le16_to_cpu(id->awupf);
/* Versions prior to 1.4 don't necessarily report a valid type */
if (id->cntrltype == NVME_CTRL_DISC ||
@@ -3655,6 +3650,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
dev_pm_qos_expose_latency_tolerance(ctrl->device);
else if (!ctrl->apst_enabled && prev_apst_enabled)
dev_pm_qos_hide_latency_tolerance(ctrl->device);
+ ctrl->awupf = le16_to_cpu(id->awupf);
out_free:
kfree(id);
return ret;
@@ -4186,13 +4182,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
nvme_mpath_add_disk(ns, info->anagrpid);
nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name);
- /*
- * Set ns->disk->device->driver_data to ns so we can access
- * ns->head->passthru_err_log_enabled in
- * nvme_io_passthru_err_log_enabled_[store | show]().
- */
- dev_set_drvdata(disk_to_dev(ns->disk), ns);
-
return;
out_cleanup_ns_from_list:
@@ -4865,6 +4854,13 @@ int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
if (ret)
return ret;
+ /*
+ * If a previous admin queue exists (e.g., from before a reset),
+ * put it now before allocating a new one to avoid orphaning it.
+ */
+ if (ctrl->admin_q)
+ blk_put_queue(ctrl->admin_q);
+
ctrl->admin_q = blk_mq_alloc_queue(set, &lim, NULL);
if (IS_ERR(ctrl->admin_q)) {
ret = PTR_ERR(ctrl->admin_q);
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 5fe09e327b3d..ac3d4f400601 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -1290,8 +1290,8 @@ void nvmf_free_options(struct nvmf_ctrl_options *opts)
kfree(opts->subsysnqn);
kfree(opts->host_traddr);
kfree(opts->host_iface);
- kfree(opts->dhchap_secret);
- kfree(opts->dhchap_ctrl_secret);
+ kfree_sensitive(opts->dhchap_secret);
+ kfree_sensitive(opts->dhchap_ctrl_secret);
kfree(opts);
}
EXPORT_SYMBOL_GPL(nvmf_free_options);
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 174027d1cc19..fc6800a9f7f9 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -1300,7 +1300,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
mutex_lock(&head->subsys->lock);
/*
* We are called when all paths have been removed, and at that point
- * head->list is expected to be empty. However, nvme_remove_ns() and
+ * head->list is expected to be empty. However, nvme_ns_remove() and
* nvme_init_ns_head() can run concurrently and so if head->delayed_
* removal_secs is configured, it is possible that by the time we reach
* this point, head->list may no longer be empty. Therefore, we recheck
@@ -1310,13 +1310,11 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
if (!list_empty(&head->list))
goto out;
- if (head->delayed_removal_secs) {
- /*
- * Ensure that no one could remove this module while the head
- * remove work is pending.
- */
- if (!try_module_get(THIS_MODULE))
- goto out;
+ /*
+ * Ensure that no one could remove this module while the head
+ * remove work is pending.
+ */
+ if (head->delayed_removal_secs && try_module_get(THIS_MODULE)) {
mod_delayed_work(nvme_wq, &head->remove_work,
head->delayed_removal_secs * HZ);
} else {
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 9a5f28c5103c..9971045dbc05 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -180,6 +180,60 @@ enum nvme_quirks {
NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22),
};
+static inline char *nvme_quirk_name(enum nvme_quirks q)
+{
+ switch (q) {
+ case NVME_QUIRK_STRIPE_SIZE:
+ return "stripe_size";
+ case NVME_QUIRK_IDENTIFY_CNS:
+ return "identify_cns";
+ case NVME_QUIRK_DEALLOCATE_ZEROES:
+ return "deallocate_zeroes";
+ case NVME_QUIRK_DELAY_BEFORE_CHK_RDY:
+ return "delay_before_chk_rdy";
+ case NVME_QUIRK_NO_APST:
+ return "no_apst";
+ case NVME_QUIRK_NO_DEEPEST_PS:
+ return "no_deepest_ps";
+ case NVME_QUIRK_QDEPTH_ONE:
+ return "qdepth_one";
+ case NVME_QUIRK_MEDIUM_PRIO_SQ:
+ return "medium_prio_sq";
+ case NVME_QUIRK_IGNORE_DEV_SUBNQN:
+ return "ignore_dev_subnqn";
+ case NVME_QUIRK_DISABLE_WRITE_ZEROES:
+ return "disable_write_zeroes";
+ case NVME_QUIRK_SIMPLE_SUSPEND:
+ return "simple_suspend";
+ case NVME_QUIRK_SINGLE_VECTOR:
+ return "single_vector";
+ case NVME_QUIRK_128_BYTES_SQES:
+ return "128_bytes_sqes";
+ case NVME_QUIRK_SHARED_TAGS:
+ return "shared_tags";
+ case NVME_QUIRK_NO_TEMP_THRESH_CHANGE:
+ return "no_temp_thresh_change";
+ case NVME_QUIRK_NO_NS_DESC_LIST:
+ return "no_ns_desc_list";
+ case NVME_QUIRK_DMA_ADDRESS_BITS_48:
+ return "dma_address_bits_48";
+ case NVME_QUIRK_SKIP_CID_GEN:
+ return "skip_cid_gen";
+ case NVME_QUIRK_BOGUS_NID:
+ return "bogus_nid";
+ case NVME_QUIRK_NO_SECONDARY_TEMP_THRESH:
+ return "no_secondary_temp_thresh";
+ case NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND:
+ return "force_no_simple_suspend";
+ case NVME_QUIRK_BROKEN_MSI:
+ return "broken_msi";
+ case NVME_QUIRK_DMAPOOL_ALIGN_512:
+ return "dmapool_align_512";
+ }
+
+ return "unknown";
+}
+
/*
* Common request structure for NVMe passthrough. All drivers must have
* this structure as the first member of their request-private data.
@@ -410,6 +464,8 @@ struct nvme_ctrl {
enum nvme_ctrl_type cntrltype;
enum nvme_dctype dctype;
+
+ u16 awupf; /* 0's based value. */
};
static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
@@ -442,7 +498,6 @@ struct nvme_subsystem {
u8 cmic;
enum nvme_subsys_type subtype;
u16 vendor_id;
- u16 awupf; /* 0's based value. */
struct ida ns_ida;
#ifdef CONFIG_NVME_MULTIPATH
enum nvme_iopolicy iopolicy;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 2f0c05719316..8d09fa7d7ff9 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -72,6 +72,13 @@
static_assert(MAX_PRP_RANGE / NVME_CTRL_PAGE_SIZE <=
(1 /* prp1 */ + NVME_MAX_NR_DESCRIPTORS * PRPS_PER_PAGE));
+struct quirk_entry {
+ u16 vendor_id;
+ u16 dev_id;
+ u32 enabled_quirks;
+ u32 disabled_quirks;
+};
+
static int use_threaded_interrupts;
module_param(use_threaded_interrupts, int, 0444);
@@ -102,6 +109,143 @@ static unsigned int io_queue_depth = 1024;
module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644);
MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2 and < 4096");
+static struct quirk_entry *nvme_pci_quirk_list;
+static unsigned int nvme_pci_quirk_count;
+
+/* Helper to parse individual quirk names */
+static int nvme_parse_quirk_names(char *quirk_str, struct quirk_entry *entry)
+{
+ int i;
+ size_t field_len;
+ bool disabled, found;
+ char *p = quirk_str, *field;
+
+ while ((field = strsep(&p, ",")) && *field) {
+ disabled = false;
+ found = false;
+
+ if (*field == '^') {
+ /* Skip the '^' character */
+ disabled = true;
+ field++;
+ }
+
+ field_len = strlen(field);
+ for (i = 0; i < 32; i++) {
+ unsigned int bit = 1U << i;
+ char *q_name = nvme_quirk_name(bit);
+ size_t q_len = strlen(q_name);
+
+ if (!strcmp(q_name, "unknown"))
+ break;
+
+ if (!strcmp(q_name, field) &&
+ q_len == field_len) {
+ if (disabled)
+ entry->disabled_quirks |= bit;
+ else
+ entry->enabled_quirks |= bit;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_err("nvme: unrecognized quirk %s\n", field);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+/* Helper to parse a single VID:DID:quirk_names entry */
+static int nvme_parse_quirk_entry(char *s, struct quirk_entry *entry)
+{
+ char *field;
+
+ field = strsep(&s, ":");
+ if (!field || kstrtou16(field, 16, &entry->vendor_id))
+ return -EINVAL;
+
+ field = strsep(&s, ":");
+ if (!field || kstrtou16(field, 16, &entry->dev_id))
+ return -EINVAL;
+
+ field = strsep(&s, ":");
+ if (!field)
+ return -EINVAL;
+
+ return nvme_parse_quirk_names(field, entry);
+}
+
+static int quirks_param_set(const char *value, const struct kernel_param *kp)
+{
+ int count, err, i;
+ struct quirk_entry *qlist;
+ char *field, *val, *sep_ptr;
+
+ err = param_set_copystring(value, kp);
+ if (err)
+ return err;
+
+ val = kstrdup(value, GFP_KERNEL);
+ if (!val)
+ return -ENOMEM;
+
+ if (!*val)
+ goto out_free_val;
+
+ count = 1;
+ for (i = 0; val[i]; i++) {
+ if (val[i] == '-')
+ count++;
+ }
+
+ qlist = kcalloc(count, sizeof(*qlist), GFP_KERNEL);
+ if (!qlist) {
+ err = -ENOMEM;
+ goto out_free_val;
+ }
+
+ i = 0;
+ sep_ptr = val;
+ while ((field = strsep(&sep_ptr, "-"))) {
+ if (nvme_parse_quirk_entry(field, &qlist[i])) {
+ pr_err("nvme: failed to parse quirk string %s\n",
+ value);
+ goto out_free_qlist;
+ }
+
+ i++;
+ }
+
+ kfree(nvme_pci_quirk_list);
+ nvme_pci_quirk_count = count;
+ nvme_pci_quirk_list = qlist;
+ goto out_free_val;
+
+out_free_qlist:
+ kfree(qlist);
+out_free_val:
+ kfree(val);
+ return err;
+}
+
+static char quirks_param[128];
+static const struct kernel_param_ops quirks_param_ops = {
+ .set = quirks_param_set,
+ .get = param_get_string,
+};
+
+static struct kparam_string quirks_param_string = {
+ .maxlen = sizeof(quirks_param),
+ .string = quirks_param,
+};
+
+module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0444);
+MODULE_PARM_DESC(quirks, "Enable/disable NVMe quirks by specifying "
+ "quirks=VID:DID:quirk_names");
+
static int io_queue_count_set(const char *val, const struct kernel_param *kp)
{
unsigned int n;
@@ -1496,7 +1640,8 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
struct nvme_queue *nvmeq = hctx->driver_data;
bool found;
- if (!nvme_cqe_pending(nvmeq))
+ if (!test_bit(NVMEQ_POLLED, &nvmeq->flags) ||
+ !nvme_cqe_pending(nvmeq))
return 0;
spin_lock(&nvmeq->cq_poll_lock);
@@ -2774,7 +2919,25 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
dev->nr_write_queues = write_queues;
dev->nr_poll_queues = poll_queues;
- nr_io_queues = dev->nr_allocated_queues - 1;
+ if (dev->ctrl.tagset) {
+ /*
+ * The set's maps are allocated only once at initialization
+ * time. We can't add special queues later if their mq_map
+ * wasn't preallocated.
+ */
+ if (dev->ctrl.tagset->nr_maps < 3)
+ dev->nr_poll_queues = 0;
+ if (dev->ctrl.tagset->nr_maps < 2)
+ dev->nr_write_queues = 0;
+ }
+
+ /*
+ * The initial number of allocated queue slots may be too large if the
+ * user reduced the special queue parameters. Cap the value to the
+ * number we need for this round.
+ */
+ nr_io_queues = min(nvme_max_io_queues(dev),
+ dev->nr_allocated_queues - 1);
result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
if (result < 0)
return result;
@@ -3458,12 +3621,25 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
return 0;
}
+static struct quirk_entry *detect_dynamic_quirks(struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i < nvme_pci_quirk_count; i++)
+ if (pdev->vendor == nvme_pci_quirk_list[i].vendor_id &&
+ pdev->device == nvme_pci_quirk_list[i].dev_id)
+ return &nvme_pci_quirk_list[i];
+
+ return NULL;
+}
+
static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
const struct pci_device_id *id)
{
unsigned long quirks = id->driver_data;
int node = dev_to_node(&pdev->dev);
struct nvme_dev *dev;
+ struct quirk_entry *qentry;
int ret = -ENOMEM;
dev = kzalloc_node(struct_size(dev, descriptor_pools, nr_node_ids),
@@ -3495,6 +3671,11 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
"platform quirk: setting simple suspend\n");
quirks |= NVME_QUIRK_SIMPLE_SUSPEND;
}
+ qentry = detect_dynamic_quirks(pdev);
+ if (qentry) {
+ quirks |= qentry->enabled_quirks;
+ quirks &= ~qentry->disabled_quirks;
+ }
ret = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_pci_ctrl_ops,
quirks);
if (ret)
@@ -4095,6 +4276,7 @@ static int __init nvme_init(void)
static void __exit nvme_exit(void)
{
+ kfree(nvme_pci_quirk_list);
pci_unregister_driver(&nvme_driver);
flush_workqueue(nvme_wq);
}
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index ad2ecc2f49a9..fe7dbe264815 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -242,7 +242,7 @@ static int nvme_pr_read_keys(struct block_device *bdev,
if (rse_len > U32_MAX)
return -EINVAL;
- rse = kzalloc(rse_len, GFP_KERNEL);
+ rse = kvzalloc(rse_len, GFP_KERNEL);
if (!rse)
return -ENOMEM;
@@ -267,7 +267,7 @@ static int nvme_pr_read_keys(struct block_device *bdev,
}
free_rse:
- kfree(rse);
+ kvfree(rse);
return ret;
}
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
index 29430949ce2f..16c6fea4b2db 100644
--- a/drivers/nvme/host/sysfs.c
+++ b/drivers/nvme/host/sysfs.c
@@ -601,6 +601,28 @@ static ssize_t dctype_show(struct device *dev,
}
static DEVICE_ATTR_RO(dctype);
+static ssize_t quirks_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int count = 0, i;
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
+ unsigned long quirks = ctrl->quirks;
+
+ if (!quirks)
+ return sysfs_emit(buf, "none\n");
+
+ for (i = 0; quirks; ++i) {
+ if (quirks & 1) {
+ count += sysfs_emit_at(buf, count, "%s\n",
+ nvme_quirk_name(BIT(i)));
+ }
+ quirks >>= 1;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_RO(quirks);
+
#ifdef CONFIG_NVME_HOST_AUTH
static ssize_t nvme_ctrl_dhchap_secret_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -742,6 +764,7 @@ static struct attribute *nvme_dev_attrs[] = {
&dev_attr_kato.attr,
&dev_attr_cntrltype.attr,
&dev_attr_dctype.attr,
+ &dev_attr_quirks.attr,
#ifdef CONFIG_NVME_HOST_AUTH
&dev_attr_dhchap_secret.attr,
&dev_attr_dhchap_ctrl_secret.attr,
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 9ab3f61196a3..243dab830dc8 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -25,7 +25,8 @@
struct nvme_tcp_queue;
-/* Define the socket priority to use for connections were it is desirable
+/*
+ * Define the socket priority to use for connections where it is desirable
* that the NIC consider performing optimized packet processing or filtering.
* A non-zero value being sufficient to indicate general consideration of any
* possible optimization. Making it a module param allows for alternative
@@ -926,7 +927,7 @@ static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb,
req->curr_bio = req->curr_bio->bi_next;
/*
- * If we don`t have any bios it means that controller
+ * If we don't have any bios it means the controller
* sent more data than we requested, hence error
*/
if (!req->curr_bio) {
diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
index 866048f07e61..b63af3b643a6 100644
--- a/drivers/nvme/target/fcloop.c
+++ b/drivers/nvme/target/fcloop.c
@@ -491,6 +491,7 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
struct fcloop_rport *rport = remoteport->private;
struct nvmet_fc_target_port *targetport = rport->targetport;
struct fcloop_tport *tport;
+ int ret = 0;
if (!targetport) {
/*
@@ -500,12 +501,18 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
* We end up here from delete association exchange:
* nvmet_fc_xmt_disconnect_assoc sends an async request.
*
- * Return success because this is what LLDDs do; silently
- * drop the response.
+ * Return success when remoteport is still online because this
+ * is what LLDDs do and silently drop the response. Otherwise,
+ * return with error to signal upper layer to perform the lsrsp
+ * resource cleanup.
*/
- lsrsp->done(lsrsp);
+ if (remoteport->port_state == FC_OBJSTATE_ONLINE)
+ lsrsp->done(lsrsp);
+ else
+ ret = -ENODEV;
+
kmem_cache_free(lsreq_cache, tls_req);
- return 0;
+ return ret;
}
memcpy(lsreq->rspaddr, lsrsp->rspbuf,
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 295076cf70de..c57ae4d6c5c0 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -905,6 +905,19 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
* supported, so we avoid reprogramming the region on every MSI,
* specifically unmapping immediately after writel().
*/
+ if (ep->msi_iatu_mapped && (ep->msi_msg_addr != msg_addr ||
+ ep->msi_map_size != map_size)) {
+ /*
+ * The host changed the MSI target address or the required
+ * mapping size changed. Reprogramming the iATU when there are
+ * operations in flight is unsafe on this controller. However,
+ * there is no unified way to check if we have operations in
+ * flight, thus we don't know if we should WARN() or not.
+ */
+ dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);
+ ep->msi_iatu_mapped = false;
+ }
+
if (!ep->msi_iatu_mapped) {
ret = dw_pcie_ep_map_addr(epc, func_no, 0,
ep->msi_mem_phys, msg_addr,
@@ -915,15 +928,6 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
ep->msi_iatu_mapped = true;
ep->msi_msg_addr = msg_addr;
ep->msi_map_size = map_size;
- } else if (WARN_ON_ONCE(ep->msi_msg_addr != msg_addr ||
- ep->msi_map_size != map_size)) {
- /*
- * The host changed the MSI target address or the required
- * mapping size changed. Reprogramming the iATU at runtime is
- * unsafe on this controller, so bail out instead of trying to
- * update the existing region.
- */
- return -EINVAL;
}
writel(msg_data | (interrupt_num - 1), ep->msi_mem + offset);
@@ -1010,6 +1014,9 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
writel(msg_data, ep->msi_mem + offset);
+ /* flush posted write before unmap */
+ readl(ep->msi_mem + offset);
+
dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);
return 0;
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index b8aaa292c3e7..cffc32d66032 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -856,7 +856,7 @@ static void pcifront_try_connect(struct pcifront_device *pdev)
int err;
/* Only connect once */
- if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitialised)
return;
@@ -876,7 +876,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
enum xenbus_state prev_state;
- prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+ prev_state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
if (prev_state >= XenbusStateClosing)
goto out;
@@ -895,7 +895,7 @@ out:
static void pcifront_attach_devices(struct pcifront_device *pdev)
{
- if (xenbus_read_driver_state(pdev->xdev->nodename) ==
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) ==
XenbusStateReconfiguring)
pcifront_connect(pdev);
}
@@ -909,7 +909,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
struct pci_dev *pci_dev;
char str[64];
- state = xenbus_read_driver_state(pdev->xdev->nodename);
+ state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
if (state == XenbusStateInitialised) {
dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n");
/* We missed Connected and need to initialize. */
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs42l43.c b/drivers/pinctrl/cirrus/pinctrl-cs42l43.c
index a8f82104a384..227c37c360e1 100644
--- a/drivers/pinctrl/cirrus/pinctrl-cs42l43.c
+++ b/drivers/pinctrl/cirrus/pinctrl-cs42l43.c
@@ -574,10 +574,9 @@ static int cs42l43_pin_probe(struct platform_device *pdev)
if (child) {
ret = devm_add_action_or_reset(&pdev->dev,
cs42l43_fwnode_put, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
+
if (!child->dev)
child->dev = priv->dev;
fwnode = child;
diff --git a/drivers/pinctrl/cix/pinctrl-sky1.c b/drivers/pinctrl/cix/pinctrl-sky1.c
index 5d0d8be815b2..938894058d86 100644
--- a/drivers/pinctrl/cix/pinctrl-sky1.c
+++ b/drivers/pinctrl/cix/pinctrl-sky1.c
@@ -522,11 +522,10 @@ static int __maybe_unused sky1_pinctrl_resume(struct device *dev)
return pinctrl_force_default(spctl->pctl);
}
-const struct dev_pm_ops sky1_pinctrl_pm_ops = {
+static const struct dev_pm_ops sky1_pinctrl_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(sky1_pinctrl_suspend,
sky1_pinctrl_resume)
};
-EXPORT_SYMBOL_GPL(sky1_pinctrl_pm_ops);
static int sky1_pinctrl_probe(struct platform_device *pdev)
{
diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
index dfa32b11555c..e2293a872dcb 100644
--- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
+++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c
@@ -679,7 +679,6 @@ static int aml_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
unsigned int *num_maps)
{
struct device *dev = pctldev->dev;
- struct device_node *pnode;
unsigned long *configs = NULL;
unsigned int num_configs = 0;
struct property *prop;
@@ -693,7 +692,7 @@ static int aml_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
return -ENOENT;
}
- pnode = of_get_parent(np);
+ struct device_node *pnode __free(device_node) = of_get_parent(np);
if (!pnode) {
dev_info(dev, "Missing function node\n");
return -EINVAL;
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 94b1d057197c..2b030bd0e6ad 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -351,13 +351,13 @@ int pinconf_generic_parse_dt_config(struct device_node *np,
ret = parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg);
if (ret)
- return ret;
+ goto out;
if (pctldev && pctldev->desc->num_custom_params &&
pctldev->desc->custom_params) {
ret = parse_dt_cfg(np, pctldev->desc->custom_params,
pctldev->desc->num_custom_params, cfg, &ncfg);
if (ret)
- return ret;
+ goto out;
}
/* no configs found at all */
diff --git a/drivers/pinctrl/pinctrl-amdisp.c b/drivers/pinctrl/pinctrl-amdisp.c
index efbf40c776ea..e0874cc086a7 100644
--- a/drivers/pinctrl/pinctrl-amdisp.c
+++ b/drivers/pinctrl/pinctrl-amdisp.c
@@ -80,7 +80,7 @@ static int amdisp_get_group_pins(struct pinctrl_dev *pctldev,
return 0;
}
-const struct pinctrl_ops amdisp_pinctrl_ops = {
+static const struct pinctrl_ops amdisp_pinctrl_ops = {
.get_groups_count = amdisp_get_groups_count,
.get_group_name = amdisp_get_group_name,
.get_group_pins = amdisp_get_group_pins,
diff --git a/drivers/pinctrl/pinctrl-cy8c95x0.c b/drivers/pinctrl/pinctrl-cy8c95x0.c
index a4b04bf6d081..5c055d344ac9 100644
--- a/drivers/pinctrl/pinctrl-cy8c95x0.c
+++ b/drivers/pinctrl/pinctrl-cy8c95x0.c
@@ -627,7 +627,7 @@ static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
bitmap_scatter(tmask, mask, chip->map, MAX_LINE);
bitmap_scatter(tval, val, chip->map, MAX_LINE);
- for_each_set_clump8(offset, bits, tmask, chip->tpin) {
+ for_each_set_clump8(offset, bits, tmask, chip->nport * BANK_SZ) {
unsigned int i = offset / 8;
write_val = bitmap_get_value8(tval, offset);
@@ -655,7 +655,7 @@ static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
bitmap_scatter(tmask, mask, chip->map, MAX_LINE);
bitmap_scatter(tval, val, chip->map, MAX_LINE);
- for_each_set_clump8(offset, bits, tmask, chip->tpin) {
+ for_each_set_clump8(offset, bits, tmask, chip->nport * BANK_SZ) {
unsigned int i = offset / 8;
ret = cy8c95x0_regmap_read_bits(chip, reg, i, bits, &read_val);
diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c
index 48b55c5bf8d4..ba1c867b7b89 100644
--- a/drivers/pinctrl/pinctrl-equilibrium.c
+++ b/drivers/pinctrl/pinctrl-equilibrium.c
@@ -23,7 +23,7 @@
#define PIN_NAME_LEN 10
#define PAD_REG_OFF 0x100
-static void eqbr_gpio_disable_irq(struct irq_data *d)
+static void eqbr_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct eqbr_gpio_ctrl *gctrl = gpiochip_get_data(gc);
@@ -36,7 +36,7 @@ static void eqbr_gpio_disable_irq(struct irq_data *d)
gpiochip_disable_irq(gc, offset);
}
-static void eqbr_gpio_enable_irq(struct irq_data *d)
+static void eqbr_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct eqbr_gpio_ctrl *gctrl = gpiochip_get_data(gc);
@@ -50,7 +50,7 @@ static void eqbr_gpio_enable_irq(struct irq_data *d)
raw_spin_unlock_irqrestore(&gctrl->lock, flags);
}
-static void eqbr_gpio_ack_irq(struct irq_data *d)
+static void eqbr_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct eqbr_gpio_ctrl *gctrl = gpiochip_get_data(gc);
@@ -62,10 +62,17 @@ static void eqbr_gpio_ack_irq(struct irq_data *d)
raw_spin_unlock_irqrestore(&gctrl->lock, flags);
}
-static void eqbr_gpio_mask_ack_irq(struct irq_data *d)
+static void eqbr_irq_mask_ack(struct irq_data *d)
{
- eqbr_gpio_disable_irq(d);
- eqbr_gpio_ack_irq(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct eqbr_gpio_ctrl *gctrl = gpiochip_get_data(gc);
+ unsigned int offset = irqd_to_hwirq(d);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&gctrl->lock, flags);
+ writel(BIT(offset), gctrl->membase + GPIO_IRNENCLR);
+ writel(BIT(offset), gctrl->membase + GPIO_IRNCR);
+ raw_spin_unlock_irqrestore(&gctrl->lock, flags);
}
static inline void eqbr_cfg_bit(void __iomem *addr,
@@ -92,7 +99,7 @@ static int eqbr_irq_type_cfg(struct gpio_irq_type *type,
return 0;
}
-static int eqbr_gpio_set_irq_type(struct irq_data *d, unsigned int type)
+static int eqbr_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct eqbr_gpio_ctrl *gctrl = gpiochip_get_data(gc);
@@ -166,11 +173,11 @@ static void eqbr_irq_handler(struct irq_desc *desc)
static const struct irq_chip eqbr_irq_chip = {
.name = "gpio_irq",
- .irq_mask = eqbr_gpio_disable_irq,
- .irq_unmask = eqbr_gpio_enable_irq,
- .irq_ack = eqbr_gpio_ack_irq,
- .irq_mask_ack = eqbr_gpio_mask_ack_irq,
- .irq_set_type = eqbr_gpio_set_irq_type,
+ .irq_ack = eqbr_irq_ack,
+ .irq_mask = eqbr_irq_mask,
+ .irq_mask_ack = eqbr_irq_mask_ack,
+ .irq_unmask = eqbr_irq_unmask,
+ .irq_set_type = eqbr_irq_set_type,
.flags = IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index d87c0b1de616..f15b18f334ee 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -3640,14 +3640,10 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
* or the gpio driver hasn't probed yet.
*/
scoped_guard(mutex, &bank->deferred_lock) {
- if (!gpio || !gpio->direction_output) {
- rc = rockchip_pinconf_defer_pin(bank,
- pin - bank->pin_base,
- param, arg);
- if (rc)
- return rc;
- break;
- }
+ if (!gpio || !gpio->direction_output)
+ return rockchip_pinconf_defer_pin(bank,
+ pin - bank->pin_base,
+ param, arg);
}
}
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615.c b/drivers/pinctrl/qcom/pinctrl-qcs615.c
index 4dfa820d4e77..f1c827ddbfbf 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcs615.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcs615.c
@@ -1067,6 +1067,7 @@ static const struct msm_pinctrl_soc_data qcs615_tlmm = {
.ntiles = ARRAY_SIZE(qcs615_tiles),
.wakeirq_map = qcs615_pdc_map,
.nwakeirq_map = ARRAY_SIZE(qcs615_pdc_map),
+ .wakeirq_dual_edge_errata = true,
};
static const struct of_device_id qcs615_tlmm_of_match[] = {
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sdm660-lpass-lpi.c
index d93af5f0e8d3..65411abfbfac 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm660-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm660-lpass-lpi.c
@@ -76,7 +76,7 @@ static const char * const pdm_clk_groups[] = { "gpio18" };
static const char * const pdm_rx_groups[] = { "gpio21", "gpio23", "gpio25" };
static const char * const pdm_sync_groups[] = { "gpio19" };
-const struct lpi_pingroup sdm660_lpi_pinctrl_groups[] = {
+static const struct lpi_pingroup sdm660_lpi_pinctrl_groups[] = {
LPI_PINGROUP_OFFSET(0, LPI_NO_SLEW, _, _, _, _, 0x0000),
LPI_PINGROUP_OFFSET(1, LPI_NO_SLEW, _, _, _, _, 0x1000),
LPI_PINGROUP_OFFSET(2, LPI_NO_SLEW, _, _, _, _, 0x2000),
@@ -113,7 +113,7 @@ const struct lpi_pingroup sdm660_lpi_pinctrl_groups[] = {
LPI_PINGROUP_OFFSET(31, LPI_NO_SLEW, _, _, _, _, 0xb010),
};
-const struct lpi_function sdm660_lpi_pinctrl_functions[] = {
+static const struct lpi_function sdm660_lpi_pinctrl_functions[] = {
LPI_FUNCTION(comp_rx),
LPI_FUNCTION(dmic1_clk),
LPI_FUNCTION(dmic1_data),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 48434292a39b..c990b6118172 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -204,6 +204,32 @@ sunxi_pinctrl_desc_find_function_by_pin(struct sunxi_pinctrl *pctl,
return NULL;
}
+static struct sunxi_desc_function *
+sunxi_pinctrl_desc_find_function_by_pin_and_mux(struct sunxi_pinctrl *pctl,
+ const u16 pin_num,
+ const u8 muxval)
+{
+ for (unsigned int i = 0; i < pctl->desc->npins; i++) {
+ const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+ struct sunxi_desc_function *func = pin->functions;
+
+ if (pin->pin.number != pin_num)
+ continue;
+
+ if (pin->variant && !(pctl->variant & pin->variant))
+ continue;
+
+ while (func->name) {
+ if (func->muxval == muxval)
+ return func;
+
+ func++;
+ }
+ }
+
+ return NULL;
+}
+
static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
@@ -930,6 +956,30 @@ static const struct pinmux_ops sunxi_pmx_ops = {
.strict = true,
};
+static int sunxi_pinctrl_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
+ const struct sunxi_desc_function *func;
+ u32 pin = offset + chip->base;
+ u32 reg, shift, mask;
+ u8 muxval;
+
+ sunxi_mux_reg(pctl, offset, &reg, &shift, &mask);
+
+ muxval = (readl(pctl->membase + reg) & mask) >> shift;
+
+ func = sunxi_pinctrl_desc_find_function_by_pin_and_mux(pctl, pin, muxval);
+ if (!func)
+ return -ENODEV;
+
+ if (!strcmp(func->name, "gpio_out"))
+ return GPIO_LINE_DIRECTION_OUT;
+ if (!strcmp(func->name, "gpio_in") || !strcmp(func->name, "irq"))
+ return GPIO_LINE_DIRECTION_IN;
+ return -EINVAL;
+}
+
static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@@ -1599,6 +1649,7 @@ int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
pctl->chip->request = gpiochip_generic_request;
pctl->chip->free = gpiochip_generic_free;
pctl->chip->set_config = gpiochip_generic_config;
+ pctl->chip->get_direction = sunxi_pinctrl_gpio_get_direction;
pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input;
pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output;
pctl->chip->get = sunxi_pinctrl_gpio_get;
diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h
index 6e9703bd5017..208f6fe16168 100644
--- a/drivers/platform/x86/asus-armoury.h
+++ b/drivers/platform/x86/asus-armoury.h
@@ -348,6 +348,35 @@ struct power_data {
static const struct dmi_system_id power_limits[] = {
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "FA401UM"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 80,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_max = 80,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 80,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 15,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 25,
+ .ppt_pl1_spl_max = 35,
+ .ppt_pl2_sppt_min = 31,
+ .ppt_pl2_sppt_max = 44,
+ .ppt_pl3_fppt_min = 45,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "FA401UV"),
},
.driver_data = &(struct power_data) {
@@ -1459,6 +1488,38 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GX650RX"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_def = 70,
+ .ppt_pl1_spl_max = 90,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_def = 70,
+ .ppt_pl2_sppt_max = 100,
+ .ppt_pl3_fppt_min = 28,
+ .ppt_pl3_fppt_def = 110,
+ .ppt_pl3_fppt_max = 125,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 76,
+ .nv_temp_target_max = 87,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_max = 50,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_max = 50,
+ .ppt_pl3_fppt_min = 28,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 76,
+ .nv_temp_target_max = 87,
+ },
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "G513I"),
},
.driver_data = &(struct power_data) {
@@ -1710,6 +1771,20 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "G733QS"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 80,
+ .ppt_pl2_sppt_min = 15,
+ .ppt_pl2_sppt_max = 80,
+ },
+ .requires_fan_curve = false,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "G814J"),
},
.driver_data = &(struct power_data) {
diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
index e69b50162bb1..d1b4df91401b 100644
--- a/drivers/platform/x86/dell/alienware-wmi-wmax.c
+++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c
@@ -175,7 +175,7 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18"),
},
- .driver_data = &generic_quirks,
+ .driver_data = &g_series_quirks,
},
{
.ident = "Alienware x15",
diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c
index 4eefbade2f5e..e7a411ae9ca1 100644
--- a/drivers/platform/x86/dell/dell-wmi-base.c
+++ b/drivers/platform/x86/dell/dell-wmi-base.c
@@ -80,6 +80,12 @@ static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
static const struct key_entry dell_wmi_keymap_type_0000[] = {
{ KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
+ /* Audio mute toggle */
+ { KE_KEY, 0x0109, { KEY_MUTE } },
+
+ /* Mic mute toggle */
+ { KE_KEY, 0x0150, { KEY_MICMUTE } },
+
/* Meta key lock */
{ KE_IGNORE, 0xe000, { KEY_RIGHTMETA } },
diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c b/drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c
index 86ec962aace9..e586f7957946 100644
--- a/drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c
+++ b/drivers/platform/x86/dell/dell-wmi-sysman/passwordattr-interface.c
@@ -93,7 +93,6 @@ int set_new_password(const char *password_type, const char *new)
if (ret < 0)
goto out;
- print_hex_dump_bytes("set new password data: ", DUMP_PREFIX_NONE, buffer, buffer_size);
ret = call_password_interface(wmi_priv.password_attr_wdev, buffer, buffer_size);
/* on success copy the new password to current password */
if (!ret)
diff --git a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
index 470b9f44ed7a..af4d1920d488 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
@@ -94,8 +94,11 @@ int hp_alloc_enumeration_data(void)
bioscfg_drv.enumeration_instances_count =
hp_get_instance_count(HP_WMI_BIOS_ENUMERATION_GUID);
- bioscfg_drv.enumeration_data = kzalloc_objs(*bioscfg_drv.enumeration_data,
- bioscfg_drv.enumeration_instances_count);
+ if (!bioscfg_drv.enumeration_instances_count)
+ return -EINVAL;
+ bioscfg_drv.enumeration_data = kvcalloc(bioscfg_drv.enumeration_instances_count,
+ sizeof(*bioscfg_drv.enumeration_data), GFP_KERNEL);
+
if (!bioscfg_drv.enumeration_data) {
bioscfg_drv.enumeration_instances_count = 0;
return -ENOMEM;
@@ -444,6 +447,6 @@ void hp_exit_enumeration_attributes(void)
}
bioscfg_drv.enumeration_instances_count = 0;
- kfree(bioscfg_drv.enumeration_data);
+ kvfree(bioscfg_drv.enumeration_data);
bioscfg_drv.enumeration_data = NULL;
}
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 304d9ac63c8a..68ede7e5757a 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -146,6 +146,7 @@ static const char * const omen_thermal_profile_boards[] = {
"8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB",
"8A15", "8A42",
"8BAD",
+ "8E41",
};
/* DMI Board names of Omen laptops that are specifically set to be thermal
@@ -166,18 +167,27 @@ static const char * const omen_timed_thermal_profile_boards[] = {
"8BAD",
};
-/* DMI Board names of Victus 16-d1xxx laptops */
+/* DMI Board names of Victus 16-d laptops */
static const char * const victus_thermal_profile_boards[] = {
+ "88F8",
"8A25",
};
/* DMI Board names of Victus 16-r and Victus 16-s laptops */
static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = {
{
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") },
+ .driver_data = (void *)&omen_v1_thermal_params,
+ },
+ {
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") },
.driver_data = (void *)&victus_s_thermal_params,
},
{
+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") },
+ .driver_data = (void *)&omen_v1_thermal_params,
+ },
+ {
.matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") },
.driver_data = (void *)&victus_s_thermal_params,
},
diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c
index 0f8684f4464b..95c405c8bac0 100644
--- a/drivers/platform/x86/intel/hid.c
+++ b/drivers/platform/x86/intel/hid.c
@@ -136,6 +136,13 @@ static const struct dmi_system_id button_array_table[] = {
},
},
{
+ .ident = "Lenovo ThinkPad X1 Fold 16 Gen 1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Fold 16 Gen 1"),
+ },
+ },
+ {
.ident = "Microsoft Surface Go 3",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
@@ -189,6 +196,18 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Dell Pro Rugged 12 Tablet RA02260"),
},
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell 14 Plus 2-in-1 DB04250"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell 16 Plus 2-in-1 DB06250"),
+ },
+ },
{ }
};
diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c
index 1455d9a7afca..1c65ce87cde0 100644
--- a/drivers/platform/x86/intel/int3472/discrete.c
+++ b/drivers/platform/x86/intel/int3472/discrete.c
@@ -223,6 +223,10 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
*con_id = "avdd";
*gpio_flags = GPIO_ACTIVE_HIGH;
break;
+ case INT3472_GPIO_TYPE_DOVDD:
+ *con_id = "dovdd";
+ *gpio_flags = GPIO_ACTIVE_HIGH;
+ break;
case INT3472_GPIO_TYPE_HANDSHAKE:
*con_id = "dvdd";
*gpio_flags = GPIO_ACTIVE_HIGH;
@@ -251,6 +255,7 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
* 0x0b Power enable
* 0x0c Clock enable
* 0x0d Privacy LED
+ * 0x10 DOVDD (digital I/O voltage)
* 0x13 Hotplug detect
*
* There are some known platform specific quirks where that does not quite
@@ -332,6 +337,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
case INT3472_GPIO_TYPE_CLK_ENABLE:
case INT3472_GPIO_TYPE_PRIVACY_LED:
case INT3472_GPIO_TYPE_POWER_ENABLE:
+ case INT3472_GPIO_TYPE_DOVDD:
case INT3472_GPIO_TYPE_HANDSHAKE:
gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, con_id, gpio_flags);
if (IS_ERR(gpio)) {
@@ -356,6 +362,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
case INT3472_GPIO_TYPE_POWER_ENABLE:
second_sensor = int3472->quirks.avdd_second_sensor;
fallthrough;
+ case INT3472_GPIO_TYPE_DOVDD:
case INT3472_GPIO_TYPE_HANDSHAKE:
ret = skl_int3472_register_regulator(int3472, gpio, enable_time_us,
con_id, second_sensor);
diff --git a/drivers/platform/x86/lenovo/thinkpad_acpi.c b/drivers/platform/x86/lenovo/thinkpad_acpi.c
index f9c736777908..8982d92dfd97 100644
--- a/drivers/platform/x86/lenovo/thinkpad_acpi.c
+++ b/drivers/platform/x86/lenovo/thinkpad_acpi.c
@@ -9525,14 +9525,16 @@ static int tpacpi_battery_get(int what, int battery, int *ret)
{
switch (what) {
case THRESHOLD_START:
- if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, ret, battery))
+ if (!battery_info.batteries[battery].start_support ||
+ ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_START, ret, battery)))
return -ENODEV;
/* The value is in the low 8 bits of the response */
*ret = *ret & 0xFF;
return 0;
case THRESHOLD_STOP:
- if ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_STOP, ret, battery))
+ if (!battery_info.batteries[battery].stop_support ||
+ ACPI_FAILURE(tpacpi_battery_acpi_eval(GET_STOP, ret, battery)))
return -ENODEV;
/* Value is in lower 8 bits */
*ret = *ret & 0xFF;
diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c
index 144a454103b9..6d4a53a2ed60 100644
--- a/drivers/platform/x86/oxpec.c
+++ b/drivers/platform/x86/oxpec.c
@@ -11,7 +11,7 @@
*
* Copyright (C) 2022 Joaquín I. Aramendía <samsagax@gmail.com>
* Copyright (C) 2024 Derek J. Clark <derekjohn.clark@gmail.com>
- * Copyright (C) 2025 Antheas Kapenekakis <lkml@antheas.dev>
+ * Copyright (C) 2025-2026 Antheas Kapenekakis <lkml@antheas.dev>
*/
#include <linux/acpi.h>
@@ -117,6 +117,13 @@ static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A2 Pro"),
+ },
+ .driver_data = (void *)aok_zoe_a1,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1X"),
},
.driver_data = (void *)oxp_fly,
@@ -145,6 +152,13 @@ static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER APEX"),
+ },
+ .driver_data = (void *)oxp_fly,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER F1"),
},
.driver_data = (void *)oxp_fly,
@@ -215,6 +229,13 @@ static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1z"),
+ },
+ .driver_data = (void *)oxp_x1,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1 A"),
},
.driver_data = (void *)oxp_x1,
@@ -229,6 +250,13 @@ static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1Air"),
+ },
+ .driver_data = (void *)oxp_x1,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1 mini"),
},
.driver_data = (void *)oxp_x1,
diff --git a/drivers/platform/x86/redmi-wmi.c b/drivers/platform/x86/redmi-wmi.c
index 949236b93a32..e5cb348e3a39 100644
--- a/drivers/platform/x86/redmi-wmi.c
+++ b/drivers/platform/x86/redmi-wmi.c
@@ -20,7 +20,10 @@
static const struct key_entry redmi_wmi_keymap[] = {
{KE_KEY, 0x00000201, {KEY_SELECTIVE_SCREENSHOT}},
{KE_KEY, 0x00000301, {KEY_ALL_APPLICATIONS}},
- {KE_KEY, 0x00001b01, {KEY_SETUP}},
+ {KE_KEY, 0x00001b01, {KEY_CONFIG}},
+ {KE_KEY, 0x00011b01, {KEY_CONFIG}},
+ {KE_KEY, 0x00010101, {KEY_SWITCHVIDEOMODE}},
+ {KE_KEY, 0x00001a01, {KEY_REFRESH_RATE_TOGGLE}},
/* AI button has code for each position */
{KE_KEY, 0x00011801, {KEY_ASSISTANT}},
@@ -32,6 +35,26 @@ static const struct key_entry redmi_wmi_keymap[] = {
{KE_IGNORE, 0x00050501, {}},
{KE_IGNORE, 0x000a0501, {}},
+ /* Xiaomi G Command Center */
+ {KE_KEY, 0x00010a01, {KEY_VENDOR}},
+
+ /* OEM preset power mode */
+ {KE_IGNORE, 0x00011601, {}},
+ {KE_IGNORE, 0x00021601, {}},
+ {KE_IGNORE, 0x00031601, {}},
+ {KE_IGNORE, 0x00041601, {}},
+
+ /* Fn Lock state */
+ {KE_IGNORE, 0x00000701, {}},
+ {KE_IGNORE, 0x00010701, {}},
+
+ /* Fn+`/1/2/3/4 */
+ {KE_KEY, 0x00011101, {KEY_F13}},
+ {KE_KEY, 0x00011201, {KEY_F14}},
+ {KE_KEY, 0x00011301, {KEY_F15}},
+ {KE_KEY, 0x00011401, {KEY_F16}},
+ {KE_KEY, 0x00011501, {KEY_F17}},
+
{KE_END}
};
diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
index bdc19cd8d3ed..d83c387821ea 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -410,6 +410,16 @@ static const struct ts_dmi_data gdix1002_upside_down_data = {
.properties = gdix1001_upside_down_props,
};
+static const struct property_entry gdix1001_y_inverted_props[] = {
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ { }
+};
+
+static const struct ts_dmi_data gdix1001_y_inverted_data = {
+ .acpi_name = "GDIX1001",
+ .properties = gdix1001_y_inverted_props,
+};
+
static const struct property_entry gp_electronic_t701_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
@@ -1659,6 +1669,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
},
},
{
+ /* SUPI S10 */
+ .driver_data = (void *)&gdix1001_y_inverted_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SUPI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "S10"),
+ },
+ },
+ {
/* Techbite Arc 11.6 */
.driver_data = (void *)&techbite_arc_11_6_data,
.matches = {
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index fee93537aa43..6341dca20b76 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -314,8 +314,8 @@
#define LED_CHANNELS 3
#define LED_MAX_BRIGHTNESS 200
-#define UNIWILL_FEATURE_FN_LOCK_TOGGLE BIT(0)
-#define UNIWILL_FEATURE_SUPER_KEY_TOGGLE BIT(1)
+#define UNIWILL_FEATURE_FN_LOCK BIT(0)
+#define UNIWILL_FEATURE_SUPER_KEY BIT(1)
#define UNIWILL_FEATURE_TOUCHPAD_TOGGLE BIT(2)
#define UNIWILL_FEATURE_LIGHTBAR BIT(3)
#define UNIWILL_FEATURE_BATTERY BIT(4)
@@ -330,6 +330,7 @@ struct uniwill_data {
struct acpi_battery_hook hook;
unsigned int last_charge_ctrl;
struct mutex battery_lock; /* Protects the list of currently registered batteries */
+ unsigned int last_status;
unsigned int last_switch_status;
struct mutex super_key_lock; /* Protects the toggling of the super key lock state */
struct list_head batteries;
@@ -377,11 +378,15 @@ static const struct key_entry uniwill_keymap[] = {
{ KE_IGNORE, UNIWILL_OSD_CAPSLOCK, { KEY_CAPSLOCK }},
{ KE_IGNORE, UNIWILL_OSD_NUMLOCK, { KEY_NUMLOCK }},
- /* Reported when the user locks/unlocks the super key */
- { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_ENABLE, { KEY_UNKNOWN }},
- { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_DISABLE, { KEY_UNKNOWN }},
+ /*
+ * Reported when the user enables/disables the super key.
+ * Those events might even be reported when the change was done
+ * using the sysfs attribute!
+ */
+ { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_DISABLE, { KEY_UNKNOWN }},
+ { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_ENABLE, { KEY_UNKNOWN }},
/* Optional, might not be reported by all devices */
- { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_CHANGED, { KEY_UNKNOWN }},
+ { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_STATE_CHANGED, { KEY_UNKNOWN }},
/* Reported in manual mode when toggling the airplane mode status */
{ KE_KEY, UNIWILL_OSD_RFKILL, { KEY_RFKILL }},
@@ -401,9 +406,6 @@ static const struct key_entry uniwill_keymap[] = {
/* Reported when the user wants to toggle the mute status */
{ KE_IGNORE, UNIWILL_OSD_MUTE, { KEY_MUTE }},
- /* Reported when the user locks/unlocks the Fn key */
- { KE_IGNORE, UNIWILL_OSD_FN_LOCK, { KEY_FN_ESC }},
-
/* Reported when the user wants to toggle the brightness of the keyboard */
{ KE_KEY, UNIWILL_OSD_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE }},
{ KE_KEY, UNIWILL_OSD_KB_LED_LEVEL0, { KEY_KBDILLUMTOGGLE }},
@@ -576,6 +578,7 @@ static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
case EC_ADDR_SECOND_FAN_RPM_1:
case EC_ADDR_SECOND_FAN_RPM_2:
case EC_ADDR_BAT_ALERT:
+ case EC_ADDR_BIOS_OEM:
case EC_ADDR_PWM_1:
case EC_ADDR_PWM_2:
case EC_ADDR_TRIGGER:
@@ -600,8 +603,8 @@ static const struct regmap_config uniwill_ec_config = {
.use_single_write = true,
};
-static ssize_t fn_lock_toggle_enable_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t fn_lock_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct uniwill_data *data = dev_get_drvdata(dev);
unsigned int value;
@@ -624,8 +627,7 @@ static ssize_t fn_lock_toggle_enable_store(struct device *dev, struct device_att
return count;
}
-static ssize_t fn_lock_toggle_enable_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct uniwill_data *data = dev_get_drvdata(dev);
unsigned int value;
@@ -638,10 +640,10 @@ static ssize_t fn_lock_toggle_enable_show(struct device *dev, struct device_attr
return sysfs_emit(buf, "%d\n", !!(value & FN_LOCK_STATUS));
}
-static DEVICE_ATTR_RW(fn_lock_toggle_enable);
+static DEVICE_ATTR_RW(fn_lock);
-static ssize_t super_key_toggle_enable_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t super_key_enable_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct uniwill_data *data = dev_get_drvdata(dev);
unsigned int value;
@@ -673,8 +675,7 @@ static ssize_t super_key_toggle_enable_store(struct device *dev, struct device_a
return count;
}
-static ssize_t super_key_toggle_enable_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t super_key_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct uniwill_data *data = dev_get_drvdata(dev);
unsigned int value;
@@ -687,7 +688,7 @@ static ssize_t super_key_toggle_enable_show(struct device *dev, struct device_at
return sysfs_emit(buf, "%d\n", !(value & SUPER_KEY_LOCK_STATUS));
}
-static DEVICE_ATTR_RW(super_key_toggle_enable);
+static DEVICE_ATTR_RW(super_key_enable);
static ssize_t touchpad_toggle_enable_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -881,8 +882,8 @@ static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
static struct attribute *uniwill_attrs[] = {
/* Keyboard-related */
- &dev_attr_fn_lock_toggle_enable.attr,
- &dev_attr_super_key_toggle_enable.attr,
+ &dev_attr_fn_lock.attr,
+ &dev_attr_super_key_enable.attr,
&dev_attr_touchpad_toggle_enable.attr,
/* Lightbar-related */
&dev_attr_rainbow_animation.attr,
@@ -897,13 +898,13 @@ static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *a
struct device *dev = kobj_to_dev(kobj);
struct uniwill_data *data = dev_get_drvdata(dev);
- if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
- if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK_TOGGLE))
+ if (attr == &dev_attr_fn_lock.attr) {
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
return attr->mode;
}
- if (attr == &dev_attr_super_key_toggle_enable.attr) {
- if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (attr == &dev_attr_super_key_enable.attr) {
+ if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
return attr->mode;
}
@@ -1357,6 +1358,9 @@ static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action
switch (action) {
case UNIWILL_OSD_BATTERY_ALERT:
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY))
+ return NOTIFY_DONE;
+
mutex_lock(&data->battery_lock);
list_for_each_entry(entry, &data->batteries, head) {
power_supply_changed(entry->battery);
@@ -1370,6 +1374,13 @@ static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action
*/
return NOTIFY_OK;
+ case UNIWILL_OSD_FN_LOCK:
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
+ return NOTIFY_DONE;
+
+ sysfs_notify(&data->dev->kobj, NULL, "fn_lock");
+
+ return NOTIFY_OK;
default:
mutex_lock(&data->input_lock);
sparse_keymap_report_event(data->input_device, action, 1, true);
@@ -1503,9 +1514,21 @@ static void uniwill_shutdown(struct platform_device *pdev)
regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
}
-static int uniwill_suspend_keyboard(struct uniwill_data *data)
+static int uniwill_suspend_fn_lock(struct uniwill_data *data)
{
- if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
+ return 0;
+
+ /*
+ * The EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it
+ * ourselves.
+ */
+ return regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &data->last_status);
+}
+
+static int uniwill_suspend_super_key(struct uniwill_data *data)
+{
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
return 0;
/*
@@ -1542,7 +1565,11 @@ static int uniwill_suspend(struct device *dev)
struct uniwill_data *data = dev_get_drvdata(dev);
int ret;
- ret = uniwill_suspend_keyboard(data);
+ ret = uniwill_suspend_fn_lock(data);
+ if (ret < 0)
+ return ret;
+
+ ret = uniwill_suspend_super_key(data);
if (ret < 0)
return ret;
@@ -1560,12 +1587,21 @@ static int uniwill_suspend(struct device *dev)
return 0;
}
-static int uniwill_resume_keyboard(struct uniwill_data *data)
+static int uniwill_resume_fn_lock(struct uniwill_data *data)
+{
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
+ return 0;
+
+ return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS,
+ data->last_status);
+}
+
+static int uniwill_resume_super_key(struct uniwill_data *data)
{
unsigned int value;
int ret;
- if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
+ if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
return 0;
ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
@@ -1608,7 +1644,11 @@ static int uniwill_resume(struct device *dev)
if (ret < 0)
return ret;
- ret = uniwill_resume_keyboard(data);
+ ret = uniwill_resume_fn_lock(data);
+ if (ret < 0)
+ return ret;
+
+ ret = uniwill_resume_super_key(data);
if (ret < 0)
return ret;
@@ -1643,16 +1683,16 @@ static struct platform_driver uniwill_driver = {
};
static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
- .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
UNIWILL_FEATURE_BATTERY |
UNIWILL_FEATURE_HWMON,
};
static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
- .features = UNIWILL_FEATURE_FN_LOCK_TOGGLE |
- UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
+ .features = UNIWILL_FEATURE_FN_LOCK |
+ UNIWILL_FEATURE_SUPER_KEY |
UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
UNIWILL_FEATURE_LIGHTBAR |
UNIWILL_FEATURE_BATTERY |
diff --git a/drivers/platform/x86/uniwill/uniwill-wmi.h b/drivers/platform/x86/uniwill/uniwill-wmi.h
index 48783b2e9ffb..fb1910c0f741 100644
--- a/drivers/platform/x86/uniwill/uniwill-wmi.h
+++ b/drivers/platform/x86/uniwill/uniwill-wmi.h
@@ -64,8 +64,8 @@
#define UNIWILL_OSD_KB_LED_LEVEL3 0x3E
#define UNIWILL_OSD_KB_LED_LEVEL4 0x3F
-#define UNIWILL_OSD_SUPER_KEY_LOCK_ENABLE 0x40
-#define UNIWILL_OSD_SUPER_KEY_LOCK_DISABLE 0x41
+#define UNIWILL_OSD_SUPER_KEY_DISABLE 0x40
+#define UNIWILL_OSD_SUPER_KEY_ENABLE 0x41
#define UNIWILL_OSD_MENU_JP 0x42
@@ -74,7 +74,7 @@
#define UNIWILL_OSD_RFKILL 0xA4
-#define UNIWILL_OSD_SUPER_KEY_LOCK_CHANGED 0xA5
+#define UNIWILL_OSD_SUPER_KEY_STATE_CHANGED 0xA5
#define UNIWILL_OSD_LIGHTBAR_STATE_CHANGED 0xA6
diff --git a/drivers/pmdomain/bcm/bcm2835-power.c b/drivers/pmdomain/bcm/bcm2835-power.c
index 1d29addfe036..0450202bbee2 100644
--- a/drivers/pmdomain/bcm/bcm2835-power.c
+++ b/drivers/pmdomain/bcm/bcm2835-power.c
@@ -580,11 +580,11 @@ static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
switch (id) {
case BCM2835_RESET_V3D:
- return !PM_READ(PM_GRAFX & PM_V3DRSTN);
+ return !(PM_READ(PM_GRAFX) & PM_V3DRSTN);
case BCM2835_RESET_H264:
- return !PM_READ(PM_IMAGE & PM_H264RSTN);
+ return !(PM_READ(PM_IMAGE) & PM_H264RSTN);
case BCM2835_RESET_ISP:
- return !PM_READ(PM_IMAGE & PM_ISPRSTN);
+ return !(PM_READ(PM_IMAGE) & PM_ISPRSTN);
default:
return -EINVAL;
}
diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
index cff738e4d546..a829f8da5be7 100644
--- a/drivers/pmdomain/imx/gpcv2.c
+++ b/drivers/pmdomain/imx/gpcv2.c
@@ -1416,7 +1416,9 @@ static int imx_pgc_domain_suspend(struct device *dev)
static int imx_pgc_domain_resume(struct device *dev)
{
- return pm_runtime_put(dev);
+ pm_runtime_put(dev);
+
+ return 0;
}
#endif
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
index 997e93c12951..44d34840ede7 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -1311,7 +1311,7 @@ static const struct rockchip_domain_info rk3576_pm_domains[] = {
static const struct rockchip_domain_info rk3588_pm_domains[] = {
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false, true),
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false, true),
- [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false, false),
+ [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false, true),
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false, false),
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false, false),
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false, false),
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index a708fc63f581..d10b6f9243d5 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -508,7 +508,7 @@ config REGULATOR_FP9931
This driver supports the FP9931/JD9930 voltage regulator chip
which is used to provide power to Electronic Paper Displays
so it is found in E-Book readers.
- If HWWON is enabled, it also provides temperature measurement.
+ If HWMON is enabled, it also provides temperature measurement.
config REGULATOR_LM363X
tristate "TI LM363X voltage regulators"
diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c
index fc1ccede4468..dab8f1ab4450 100644
--- a/drivers/regulator/bq257xx-regulator.c
+++ b/drivers/regulator/bq257xx-regulator.c
@@ -115,11 +115,10 @@ static void bq257xx_reg_dt_parse_gpio(struct platform_device *pdev)
return;
subchild = of_get_child_by_name(child, pdata->desc.of_match);
+ of_node_put(child);
if (!subchild)
return;
- of_node_put(child);
-
pdata->otg_en_gpio = devm_fwnode_gpiod_get_index(&pdev->dev,
of_fwnode_handle(subchild),
"enable", 0,
diff --git a/drivers/regulator/fp9931.c b/drivers/regulator/fp9931.c
index 7fbcc6327cc6..abea3b69d8a0 100644
--- a/drivers/regulator/fp9931.c
+++ b/drivers/regulator/fp9931.c
@@ -144,13 +144,12 @@ static int fp9931_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
return ret;
ret = regmap_read(data->regmap, FP9931_REG_TMST_VALUE, &val);
- if (ret)
- return ret;
+ if (!ret)
+ *temp = (s8)val * 1000;
pm_runtime_put_autosuspend(data->dev);
- *temp = (s8)val * 1000;
- return 0;
+ return ret;
}
static umode_t fp9931_hwmon_is_visible(const void *data,
diff --git a/drivers/regulator/mt6363-regulator.c b/drivers/regulator/mt6363-regulator.c
index 03af5fa53600..0aebcbda0a19 100644
--- a/drivers/regulator/mt6363-regulator.c
+++ b/drivers/regulator/mt6363-regulator.c
@@ -899,10 +899,8 @@ static int mt6363_regulator_probe(struct platform_device *pdev)
"Failed to map IRQ%d\n", info->hwirq);
ret = devm_add_action_or_reset(dev, mt6363_irq_remove, &info->virq);
- if (ret) {
- irq_dispose_mapping(info->hwirq);
+ if (ret)
return ret;
- }
config.driver_data = info;
INIT_DELAYED_WORK(&info->oc_work, mt6363_oc_irq_enable_work);
diff --git a/drivers/regulator/pf9453-regulator.c b/drivers/regulator/pf9453-regulator.c
index 779a6fdb0574..eed3055d1c1c 100644
--- a/drivers/regulator/pf9453-regulator.c
+++ b/drivers/regulator/pf9453-regulator.c
@@ -809,7 +809,7 @@ static int pf9453_i2c_probe(struct i2c_client *i2c)
}
ret = devm_request_threaded_irq(pf9453->dev, pf9453->irq, NULL, pf9453_irq_handler,
- (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
+ IRQF_ONESHOT,
"pf9453-irq", pf9453);
if (ret)
return dev_err_probe(pf9453->dev, ret, "Failed to request IRQ: %d\n", pf9453->irq);
diff --git a/drivers/regulator/tps65185.c b/drivers/regulator/tps65185.c
index 3286c9ab33d0..786622d8d598 100644
--- a/drivers/regulator/tps65185.c
+++ b/drivers/regulator/tps65185.c
@@ -332,6 +332,9 @@ static int tps65185_probe(struct i2c_client *client)
int i;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
data->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(data->regmap))
return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 94ad253d65a0..e9d9ac7da485 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -12025,6 +12025,8 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
iounmap(phba->sli4_hba.conf_regs_memmap_p);
if (phba->sli4_hba.dpp_regs_memmap_p)
iounmap(phba->sli4_hba.dpp_regs_memmap_p);
+ if (phba->sli4_hba.dpp_regs_memmap_wc_p)
+ iounmap(phba->sli4_hba.dpp_regs_memmap_wc_p);
break;
case LPFC_SLI_INTF_IF_TYPE_1:
break;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1cbfbe44cb7c..303523f754b8 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -15977,6 +15977,32 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset)
return NULL;
}
+static __maybe_unused void __iomem *
+lpfc_dpp_wc_map(struct lpfc_hba *phba, uint8_t dpp_barset)
+{
+
+ /* DPP region is supposed to cover 64-bit BAR2 */
+ if (dpp_barset != WQ_PCI_BAR_4_AND_5) {
+ lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
+ "3273 dpp_barset x%x != WQ_PCI_BAR_4_AND_5\n",
+ dpp_barset);
+ return NULL;
+ }
+
+ if (!phba->sli4_hba.dpp_regs_memmap_wc_p) {
+ void __iomem *dpp_map;
+
+ dpp_map = ioremap_wc(phba->pci_bar2_map,
+ pci_resource_len(phba->pcidev,
+ PCI_64BIT_BAR4));
+
+ if (dpp_map)
+ phba->sli4_hba.dpp_regs_memmap_wc_p = dpp_map;
+ }
+
+ return phba->sli4_hba.dpp_regs_memmap_wc_p;
+}
+
/**
* lpfc_modify_hba_eq_delay - Modify Delay Multiplier on EQs
* @phba: HBA structure that EQs are on.
@@ -16940,9 +16966,6 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
uint8_t dpp_barset;
uint32_t dpp_offset;
uint8_t wq_create_version;
-#ifdef CONFIG_X86
- unsigned long pg_addr;
-#endif
/* sanity check on queue memory */
if (!wq || !cq)
@@ -17128,14 +17151,15 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
#ifdef CONFIG_X86
/* Enable combined writes for DPP aperture */
- pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK;
- rc = set_memory_wc(pg_addr, 1);
- if (rc) {
+ bar_memmap_p = lpfc_dpp_wc_map(phba, dpp_barset);
+ if (!bar_memmap_p) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3272 Cannot setup Combined "
"Write on WQ[%d] - disable DPP\n",
wq->queue_id);
phba->cfg_enable_dpp = 0;
+ } else {
+ wq->dpp_regaddr = bar_memmap_p + dpp_offset;
}
#else
phba->cfg_enable_dpp = 0;
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index ee58383492b2..b6d90604bb61 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -785,6 +785,9 @@ struct lpfc_sli4_hba {
void __iomem *dpp_regs_memmap_p; /* Kernel memory mapped address for
* dpp registers
*/
+ void __iomem *dpp_regs_memmap_wc_p;/* Kernel memory mapped address for
+ * dpp registers with write combining
+ */
union {
struct {
/* IF Type 0, BAR 0 PCI cfg space reg mem map */
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 81150bef1145..c744210cc901 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -1618,6 +1618,7 @@ retry_bring_ioc_ready:
ioc_info(mrioc,
"successfully transitioned to %s state\n",
mpi3mr_iocstate_name(ioc_state));
+ mpi3mr_clear_reset_history(mrioc);
return 0;
}
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
@@ -1637,6 +1638,15 @@ retry_bring_ioc_ready:
elapsed_time_sec = jiffies_to_msecs(jiffies - start_time)/1000;
} while (elapsed_time_sec < mrioc->ready_timeout);
+ ioc_state = mpi3mr_get_iocstate(mrioc);
+ if (ioc_state == MRIOC_STATE_READY) {
+ ioc_info(mrioc,
+ "successfully transitioned to %s state after %llu seconds\n",
+ mpi3mr_iocstate_name(ioc_state), elapsed_time_sec);
+ mpi3mr_clear_reset_history(mrioc);
+ return 0;
+ }
+
out_failed:
elapsed_time_sec = jiffies_to_msecs(jiffies - start_time)/1000;
if ((retry < 2) && (elapsed_time_sec < (mrioc->ready_timeout - 60))) {
@@ -4807,21 +4817,25 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
}
for (i = 0; i < mrioc->num_queues; i++) {
- mrioc->op_reply_qinfo[i].qid = 0;
- mrioc->op_reply_qinfo[i].ci = 0;
- mrioc->op_reply_qinfo[i].num_replies = 0;
- mrioc->op_reply_qinfo[i].ephase = 0;
- atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0);
- atomic_set(&mrioc->op_reply_qinfo[i].in_use, 0);
- mpi3mr_memset_op_reply_q_buffers(mrioc, i);
-
- mrioc->req_qinfo[i].ci = 0;
- mrioc->req_qinfo[i].pi = 0;
- mrioc->req_qinfo[i].num_requests = 0;
- mrioc->req_qinfo[i].qid = 0;
- mrioc->req_qinfo[i].reply_qid = 0;
- spin_lock_init(&mrioc->req_qinfo[i].q_lock);
- mpi3mr_memset_op_req_q_buffers(mrioc, i);
+ if (mrioc->op_reply_qinfo) {
+ mrioc->op_reply_qinfo[i].qid = 0;
+ mrioc->op_reply_qinfo[i].ci = 0;
+ mrioc->op_reply_qinfo[i].num_replies = 0;
+ mrioc->op_reply_qinfo[i].ephase = 0;
+ atomic_set(&mrioc->op_reply_qinfo[i].pend_ios, 0);
+ atomic_set(&mrioc->op_reply_qinfo[i].in_use, 0);
+ mpi3mr_memset_op_reply_q_buffers(mrioc, i);
+ }
+
+ if (mrioc->req_qinfo) {
+ mrioc->req_qinfo[i].ci = 0;
+ mrioc->req_qinfo[i].pi = 0;
+ mrioc->req_qinfo[i].num_requests = 0;
+ mrioc->req_qinfo[i].qid = 0;
+ mrioc->req_qinfo[i].reply_qid = 0;
+ spin_lock_init(&mrioc->req_qinfo[i].q_lock);
+ mpi3mr_memset_op_req_q_buffers(mrioc, i);
+ }
}
atomic_set(&mrioc->pend_large_data_sz, 0);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6a8d35aea93a..645524f3fe2d 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -525,8 +525,9 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
} else {
task->task_done(task);
}
- rc = -ENODEV;
- goto err_out;
+ spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+ pm8001_dbg(pm8001_ha, IO, "pm8001_task_exec device gone\n");
+ return 0;
}
ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 0dada89d8d99..68a992494b12 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -190,7 +190,7 @@ static struct {
{"IBM", "2076", NULL, BLIST_NO_VPD_SIZE},
{"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
- {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN},
+ {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN | BLIST_SKIP_IO_HINTS},
{"IOMEGA", "Io20S *F", NULL, BLIST_KEY},
{"INSITE", "Floptical F*8I", NULL, BLIST_KEY},
{"INSITE", "I325VM", NULL, BLIST_KEY},
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 60c06fa4ec32..2cfcf1f5d6a4 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -361,6 +361,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
* since we use this queue depth most of times.
*/
if (scsi_realloc_sdev_budget_map(sdev, depth)) {
+ kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags);
put_device(&starget->dev);
kfree(sdev);
goto out;
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 35101e9b7ba7..8e1686358e25 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -528,9 +528,8 @@ struct efd {
};
static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
- void *data)
+ struct efd *efd)
{
- struct efd *efd = data;
int i;
struct ses_component *scomp;
@@ -683,7 +682,7 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
if (efd.addr) {
efd.dev = &sdev->sdev_gendev;
- enclosure_for_each_device(ses_enclosure_find_by_addr, &efd);
+ ses_enclosure_find_by_addr(edev, &efd);
}
}
diff --git a/drivers/scsi/snic/vnic_dev.c b/drivers/scsi/snic/vnic_dev.c
index c692de061f29..ed7771e62854 100644
--- a/drivers/scsi/snic/vnic_dev.c
+++ b/drivers/scsi/snic/vnic_dev.c
@@ -42,8 +42,6 @@ struct vnic_dev {
struct vnic_devcmd_notify *notify;
struct vnic_devcmd_notify notify_copy;
dma_addr_t notify_pa;
- u32 *linkstatus;
- dma_addr_t linkstatus_pa;
struct vnic_stats *stats;
dma_addr_t stats_pa;
struct vnic_devcmd_fw_info *fw_info;
@@ -650,8 +648,6 @@ int svnic_dev_init(struct vnic_dev *vdev, int arg)
int svnic_dev_link_status(struct vnic_dev *vdev)
{
- if (vdev->linkstatus)
- return *vdev->linkstatus;
if (!vnic_dev_notify_ready(vdev))
return 0;
@@ -686,11 +682,6 @@ void svnic_dev_unregister(struct vnic_dev *vdev)
sizeof(struct vnic_devcmd_notify),
vdev->notify,
vdev->notify_pa);
- if (vdev->linkstatus)
- dma_free_coherent(&vdev->pdev->dev,
- sizeof(u32),
- vdev->linkstatus,
- vdev->linkstatus_pa);
if (vdev->stats)
dma_free_coherent(&vdev->pdev->dev,
sizeof(struct vnic_stats),
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 664ad55728b5..ae1abab97835 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1856,8 +1856,9 @@ static enum scsi_qc_status storvsc_queuecommand(struct Scsi_Host *host,
cmd_request->payload_sz = payload_sz;
/* Invokes the vsc to start an IO */
- ret = storvsc_do_io(dev, cmd_request, get_cpu());
- put_cpu();
+ migrate_disable();
+ ret = storvsc_do_io(dev, cmd_request, smp_processor_id());
+ migrate_enable();
if (ret)
scsi_dma_unmap(scmnd);
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index 42cde0017f12..989bcaee42ca 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -1175,7 +1175,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev,
return;
}
- if (xenbus_read_driver_state(dev->nodename) ==
+ if (xenbus_read_driver_state(dev, dev->nodename) ==
XenbusStateInitialised)
scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index 65adec7c7524..fe726b9b1780 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -271,7 +271,7 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
msecs_to_jiffies(ms));
if (ms == 0) {
- dev_err(&dws->ctlr->cur_msg->spi->dev,
+ dev_err(&dws->ctlr->dev,
"DMA transaction timed out\n");
return -ETIMEDOUT;
}
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index b99de8c4cc99..33f211e159ef 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -1625,6 +1625,9 @@ static int stm32_spi_prepare_rx_dma_mdma_chaining(struct stm32_spi *spi,
return -EINVAL;
}
+ *rx_mdma_desc = _mdma_desc;
+ *rx_dma_desc = _dma_desc;
+
return 0;
}
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 17608ea39d5a..a1c91d4515bc 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -108,8 +108,8 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item,
const char *page, size_t count)
{
ssize_t read_bytes;
- struct file *fp;
ssize_t r = -EINVAL;
+ struct path path = {};
mutex_lock(&target_devices_lock);
if (target_devices) {
@@ -131,17 +131,14 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item,
db_root_stage[read_bytes - 1] = '\0';
/* validate new db root before accepting it */
- fp = filp_open(db_root_stage, O_RDONLY, 0);
- if (IS_ERR(fp)) {
+ r = kern_path(db_root_stage, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+ if (r) {
pr_err("db_root: cannot open: %s\n", db_root_stage);
+ if (r == -ENOTDIR)
+ pr_err("db_root: not a directory: %s\n", db_root_stage);
goto unlock;
}
- if (!S_ISDIR(file_inode(fp)->i_mode)) {
- filp_close(fp, NULL);
- pr_err("db_root: not a directory: %s\n", db_root_stage);
- goto unlock;
- }
- filp_close(fp, NULL);
+ path_put(&path);
strscpy(db_root, db_root_stage);
pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root);
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 847b55789bb8..899e663fea6e 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -24,6 +24,7 @@
#include <linux/pm_opp.h>
#include <linux/regulator/consumer.h>
#include <linux/sched/clock.h>
+#include <linux/sizes.h>
#include <linux/iopoll.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
@@ -517,8 +518,8 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, struct scsi_cmnd *cmd,
if (hba->mcq_enabled) {
struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq);
-
- hwq_id = hwq->id;
+ if (hwq)
+ hwq_id = hwq->id;
} else {
doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
}
@@ -4389,14 +4390,6 @@ out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
mutex_unlock(&hba->uic_cmd_mutex);
- /*
- * If the h8 exit fails during the runtime resume process, it becomes
- * stuck and cannot be recovered through the error handler. To fix
- * this, use link recovery instead of the error handler.
- */
- if (ret && hba->pm_op_in_progress)
- ret = ufshcd_link_recovery(hba);
-
return ret;
}
@@ -5249,6 +5242,25 @@ static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev)
hba->dev_info.rpmb_region_size[1] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION1_SIZE];
hba->dev_info.rpmb_region_size[2] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION2_SIZE];
hba->dev_info.rpmb_region_size[3] = desc_buf[RPMB_UNIT_DESC_PARAM_REGION3_SIZE];
+
+ if (hba->dev_info.wspecversion <= 0x0220) {
+ /*
+ * These older spec chips have only one RPMB region,
+ * sized between 128 kB minimum and 16 MB maximum.
+ * No per region size fields are provided (respective
+ * REGIONX_SIZE fields always contain zeros), so get
+ * it from the logical block count and size fields for
+ * compatibility
+ *
+ * (See JESD220C-2_2 Section 14.1.4.6
+ * RPMB Unit Descriptor,* offset 13h, 4 bytes)
+ */
+ hba->dev_info.rpmb_region_size[0] =
+ (get_unaligned_be64(desc_buf
+ + RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_COUNT)
+ << desc_buf[RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_SIZE])
+ / SZ_128K;
+ }
}
@@ -5963,6 +5975,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
hba->auto_bkops_enabled = false;
trace_ufshcd_auto_bkops_state(hba, "Disabled");
+ hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
hba->is_urgent_bkops_lvl_checked = false;
out:
return err;
@@ -6066,7 +6079,7 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
* impacted or critical. Handle these device by determining their urgent
* bkops status at runtime.
*/
- if (curr_status < BKOPS_STATUS_PERF_IMPACT) {
+ if ((curr_status > BKOPS_STATUS_NO_OP) && (curr_status < BKOPS_STATUS_PERF_IMPACT)) {
dev_err(hba->dev, "%s: device raised urgent BKOPS exception for bkops status %d\n",
__func__, curr_status);
/* update the current status as the urgent bkops level */
@@ -7097,7 +7110,7 @@ static irqreturn_t ufshcd_handle_mcq_cq_events(struct ufs_hba *hba)
ret = ufshcd_vops_get_outstanding_cqs(hba, &outstanding_cqs);
if (ret)
- outstanding_cqs = (1U << hba->nr_hw_queues) - 1;
+ outstanding_cqs = (1ULL << hba->nr_hw_queues) - 1;
/* Exclude the poll queues */
nr_queues = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL];
@@ -10179,7 +10192,15 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
} else {
dev_err(hba->dev, "%s: hibern8 exit failed %d\n",
__func__, ret);
- goto vendor_suspend;
+ /*
+ * If the h8 exit fails during the runtime resume
+ * process, it becomes stuck and cannot be recovered
+ * through the error handler. To fix this, use link
+ * recovery instead of the error handler.
+ */
+ ret = ufshcd_link_recovery(hba);
+ if (ret)
+ goto vendor_suspend;
}
} else if (ufshcd_is_link_off(hba)) {
/*
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 1a04154bc535..c54cfcd832bb 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -380,8 +380,12 @@ static struct au1100fb_panel known_lcd_panels[] =
#define panel_is_color(panel) (panel->control_base & LCD_CONTROL_PC)
#define panel_swap_rgb(panel) (panel->control_base & LCD_CONTROL_CCO)
-#if defined(CONFIG_COMPILE_TEST) && !defined(CONFIG_MIPS)
-/* This is only defined to be able to compile this driver on non-mips platforms */
+#if defined(CONFIG_COMPILE_TEST) && (!defined(CONFIG_MIPS) || defined(CONFIG_64BIT))
+/*
+ * KSEG1ADDR() is defined in arch/mips/include/asm/addrspace.h
+ * for 32 bit configurations. Provide a stub for compile testing
+ * on other platforms.
+ */
#define KSEG1ADDR(x) (x)
#endif
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 31903bfdce9f..897ae2a0b5a0 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -378,11 +378,8 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_psd[acpi_id].domain);
}
- status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- if (!pblk)
- return AE_OK;
- }
+ if (!pblk && !acpi_has_method(handle, "_CST"))
+ return AE_OK;
/* .. and it has a C-state */
__set_bit(acpi_id, acpi_id_cst_present);
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index 22ff9cf35fc4..b34785ba72e1 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -149,12 +149,12 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
mutex_lock(&pdev->dev_lock);
/* Make sure we only do this setup once */
- if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitialised)
goto out;
/* Wait for frontend to state that it has published the configuration */
- if (xenbus_read_driver_state(pdev->xdev->otherend) !=
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->otherend) !=
XenbusStateInitialised)
goto out;
@@ -374,7 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
mutex_lock(&pdev->dev_lock);
- if (xenbus_read_driver_state(pdev->xdev->nodename) != state)
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) != state)
goto out;
err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
@@ -572,7 +572,7 @@ static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
/* It's possible we could get the call to setup twice, so make sure
* we're not already connected.
*/
- if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+ if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitWait)
goto out;
@@ -662,7 +662,7 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
struct xen_pcibk_device *pdev =
container_of(watch, struct xen_pcibk_device, be_watch);
- switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
+ switch (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename)) {
case XenbusStateInitWait:
xen_pcibk_setup_backend(pdev);
break;
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 0ab1329e79de..27682cb5e58a 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -226,8 +226,9 @@ __xenbus_switch_state(struct xenbus_device *dev,
struct xenbus_transaction xbt;
int current_state;
int err, abort;
+ bool vanished = false;
- if (state == dev->state)
+ if (state == dev->state || dev->vanished)
return 0;
again:
@@ -242,6 +243,10 @@ again:
err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
if (err != 1)
goto abort;
+ if (current_state != dev->state && current_state == XenbusStateInitialising) {
+ vanished = true;
+ goto abort;
+ }
err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
if (err) {
@@ -256,7 +261,7 @@ abort:
if (err == -EAGAIN && !abort)
goto again;
xenbus_switch_fatal(dev, depth, err, "ending transaction");
- } else
+ } else if (!vanished)
dev->state = state;
return 0;
@@ -931,14 +936,20 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
/**
* xenbus_read_driver_state - read state from a store path
+ * @dev: xenbus device pointer
* @path: path for driver
*
* Returns: the state of the driver rooted at the given store path, or
* XenbusStateUnknown if no state can be read.
*/
-enum xenbus_state xenbus_read_driver_state(const char *path)
+enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
+ const char *path)
{
enum xenbus_state result;
+
+ if (dev && dev->vanished)
+ return XenbusStateUnknown;
+
int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
if (err)
result = XenbusStateUnknown;
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 9f9011cd7447..eb260eceb4d2 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -191,7 +191,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
return;
}
- state = xenbus_read_driver_state(dev->otherend);
+ state = xenbus_read_driver_state(dev, dev->otherend);
dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
state, xenbus_strstate(state), dev->otherend_watch.node, path);
@@ -364,7 +364,7 @@ void xenbus_dev_remove(struct device *_dev)
* closed.
*/
if (!drv->allow_rebind ||
- xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
+ xenbus_read_driver_state(dev, dev->nodename) == XenbusStateClosing)
xenbus_switch_state(dev, XenbusStateClosed);
}
EXPORT_SYMBOL_GPL(xenbus_dev_remove);
@@ -444,6 +444,9 @@ static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
info.dev = NULL;
bus_for_each_dev(bus, NULL, &info, cleanup_dev);
if (info.dev) {
+ dev_warn(&info.dev->dev,
+ "device forcefully removed from xenstore\n");
+ info.dev->vanished = true;
device_unregister(&info.dev->dev);
put_device(&info.dev->dev);
}
@@ -514,7 +517,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
size_t stringlen;
char *tmpstring;
- enum xenbus_state state = xenbus_read_driver_state(nodename);
+ enum xenbus_state state = xenbus_read_driver_state(NULL, nodename);
if (state != XenbusStateInitialising) {
/* Device is not new, so ignore it. This can happen if a
@@ -659,6 +662,39 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
return;
dev = xenbus_device_find(root, &bus->bus);
+ /*
+ * Backend domain crash results in not coordinated frontend removal,
+ * without going through XenbusStateClosing. If this is a new instance
+ * of the same device Xen tools will have reset the state to
+ * XenbusStateInitializing.
+ * It might be that the backend crashed early during the init phase of
+ * device setup, in which case the known state would have been
+ * XenbusStateInitializing. So test the backend domid to match the
+ * saved one. In case the new backend happens to have the same domid as
+ * the old one, we can just carry on, as there is no inconsistency
+ * resulting in this case.
+ */
+ if (dev && !strcmp(bus->root, "device")) {
+ enum xenbus_state state = xenbus_read_driver_state(dev, dev->nodename);
+ unsigned int backend = xenbus_read_unsigned(root, "backend-id",
+ dev->otherend_id);
+
+ if (state == XenbusStateInitialising &&
+ (state != dev->state || backend != dev->otherend_id)) {
+ /*
+ * State has been reset, assume the old one vanished
+ * and new one needs to be probed.
+ */
+ dev_warn(&dev->dev,
+ "state reset occurred, reconnecting\n");
+ dev->vanished = true;
+ }
+ if (dev->vanished) {
+ device_unregister(&dev->dev);
+ put_device(&dev->dev);
+ dev = NULL;
+ }
+ }
if (!dev)
xenbus_probe_node(bus, type, root);
else
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index f04707d1f667..ca04609730df 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -253,7 +253,7 @@ static int print_device_status(struct device *dev, void *data)
} else if (xendev->state < XenbusStateConnected) {
enum xenbus_state rstate = XenbusStateUnknown;
if (xendev->otherend)
- rstate = xenbus_read_driver_state(xendev->otherend);
+ rstate = xenbus_read_driver_state(xendev, xendev->otherend);
pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
xendev->nodename, xendev->state, rstate);
}