summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/atm/eni.c3
-rw-r--r--drivers/atm/fore200e.c2
-rw-r--r--drivers/atm/idt77105.c4
-rw-r--r--drivers/atm/lanai.c5
-rw-r--r--drivers/atm/uPD98402.c2
-rw-r--r--drivers/base/power/runtime.c62
-rw-r--r--drivers/base/swnode.c29
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/floppy.c1
-rw-r--r--drivers/block/rsxx/core.c1
-rw-r--r--drivers/block/umem.c5
-rw-r--r--drivers/block/zram/zram_drv.c17
-rw-r--r--drivers/bluetooth/btrsi.c1
-rw-r--r--drivers/char/applicom.c3
-rw-r--r--drivers/char/hw_random/pseries-rng.c3
-rw-r--r--drivers/char/toshiba.c1
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c4
-rw-r--r--drivers/clk/clk-bd718x7.c9
-rw-r--r--drivers/counter/stm32-timer-cnt.c55
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c2
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c6
-rw-r--r--drivers/crypto/nx/nx-842-pseries.c4
-rw-r--r--drivers/crypto/nx/nx.c4
-rw-r--r--drivers/extcon/Kconfig8
-rw-r--r--drivers/extcon/Makefile1
-rw-r--r--drivers/extcon/extcon-arizona.c1816
-rw-r--r--drivers/firmware/efi/efi.c3
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c2
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c16
-rw-r--r--drivers/firmware/efi/vars.c4
-rw-r--r--drivers/gpio/Kconfig10
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-bd71815.c185
-rw-r--r--drivers/gpio/gpio-pca953x.c78
-rw-r--r--drivers/gpio/gpiolib-acpi.c21
-rw-r--r--drivers/gpio/gpiolib.c29
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c26
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c31
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c96
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c8
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c48
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c66
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c48
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c2
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c32
-rw-r--r--drivers/gpu/drm/drm_ioc32.c11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c7
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c19
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c13
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h23
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c16
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c14
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_release.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_prime.c2
-rw-r--r--drivers/gpu/drm/tiny/gm12u320.c44
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c4
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c17
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h1
-rw-r--r--drivers/gpu/drm/udl/udl_main.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c2
-rw-r--r--drivers/iio/adc/Kconfig3
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c2
-rw-r--r--drivers/iio/adc/ad7949.c2
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c2
-rw-r--r--drivers/iio/gyro/mpu3050-core.c2
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c12
-rw-r--r--drivers/iio/imu/adis16400.c3
-rw-r--r--drivers/iio/light/hid-sensor-prox.c13
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c14
-rw-r--r--drivers/input/joydev.c1
-rw-r--r--drivers/input/misc/Kconfig11
-rw-r--r--drivers/input/misc/Makefile2
-rw-r--r--drivers/input/misc/atc260x-onkey.c305
-rw-r--r--drivers/iommu/amd/init.c36
-rw-r--r--drivers/iommu/tegra-smmu.c7
-rw-r--r--drivers/irqchip/Kconfig9
-rw-r--r--drivers/irqchip/irq-ingenic-tcu.c1
-rw-r--r--drivers/irqchip/irq-ingenic.c1
-rw-r--r--drivers/leds/trigger/ledtrig-tty.c11
-rw-r--r--drivers/md/bcache/super.c2
-rw-r--r--drivers/md/dm-crypt.c8
-rw-r--r--drivers/md/dm-writecache.c4
-rw-r--r--drivers/md/raid5-cache.c4
-rw-r--r--drivers/md/raid5-ppl.c2
-rw-r--r--drivers/media/firewire/firedtv-fw.c1
-rw-r--r--drivers/media/pci/cx18/cx18-alsa-main.c1
-rw-r--r--drivers/media/pci/cx18/cx18-driver.c1
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c1
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c1
-rw-r--r--drivers/media/pci/ivtv/ivtv-alsa-main.c1
-rw-r--r--drivers/media/pci/ivtv/ivtv-driver.c3
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c1
-rw-r--r--drivers/media/platform/atmel/atmel-isi.c1
-rw-r--r--drivers/media/platform/atmel/atmel-sama5d2-isc.c1
-rw-r--r--drivers/media/platform/marvell-ccic/cafe-driver.c4
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c1
-rw-r--r--drivers/media/platform/stm32/stm32-dcmi.c1
-rw-r--r--drivers/media/platform/vsp1/vsp1_drm.c6
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/keymaps/Makefile1
-rw-r--r--drivers/media/rc/keymaps/rc-cec.c28
-rw-r--r--drivers/media/rc/rc-main.c6
-rw-r--r--drivers/media/usb/cpia2/cpia2_v4l.c1
-rw-r--r--drivers/media/usb/tm6000/tm6000-alsa.c1
-rw-r--r--drivers/media/usb/tm6000/tm6000-dvb.c2
-rw-r--r--drivers/media/usb/usbtv/usbtv-audio.c2
-rw-r--r--drivers/mfd/Kconfig44
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/ab8500-core.c17
-rw-r--r--drivers/mfd/arizona-core.c20
-rw-r--r--drivers/mfd/atc260x-core.c310
-rw-r--r--drivers/mfd/atc260x-i2c.c64
-rw-r--r--drivers/mfd/ntxec.c221
-rw-r--r--drivers/mfd/rohm-bd71828.c486
-rw-r--r--drivers/mfd/rohm-bd718x7.c43
-rw-r--r--drivers/misc/fastrpc.c5
-rw-r--r--drivers/misc/habanalabs/common/debugfs.c5
-rw-r--r--drivers/misc/habanalabs/common/device.c40
-rw-r--r--drivers/misc/habanalabs/common/habanalabs.h2
-rw-r--r--drivers/misc/habanalabs/common/habanalabs_ioctl.c12
-rw-r--r--drivers/misc/habanalabs/common/irq.c2
-rw-r--r--drivers/misc/habanalabs/common/mmu/mmu.c38
-rw-r--r--drivers/misc/ibmvmc.c4
-rw-r--r--drivers/misc/pvpanic.c1
-rw-r--r--drivers/mmc/core/bus.c11
-rw-r--r--drivers/mmc/core/mmc.c15
-rw-r--r--drivers/mmc/host/mmci.c10
-rw-r--r--drivers/mtd/maps/sun_uflash.c1
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/bonding/bond_main.c8
-rw-r--r--drivers/net/can/flexcan.c24
-rw-r--r--drivers/net/can/m_can/tcan4x5x-core.c6
-rw-r--r--drivers/net/can/peak_canfd/peak_pciefd_main.c1
-rw-r--r--drivers/net/can/sja1000/ems_pci.c1
-rw-r--r--drivers/net/can/sja1000/ems_pcmcia.c1
-rw-r--r--drivers/net/can/sja1000/kvaser_pci.c1
-rw-r--r--drivers/net/can/sja1000/peak_pci.c2
-rw-r--r--drivers/net/can/sja1000/peak_pcmcia.c1
-rw-r--r--drivers/net/can/sja1000/plx_pci.c12
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c21
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb.c2
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_fd.c3
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_pro.c2
-rw-r--r--drivers/net/dsa/bcm_sf2.c6
-rw-r--r--drivers/net/dsa/mt7530.c4
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c6
-rw-r--r--drivers/net/dsa/xrs700x/xrs700x.c10
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c7
-rw-r--r--drivers/net/ethernet/broadcom/bcm4908_enet.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c17
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c15
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c8
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c23
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c93
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h5
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_hw.h20
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c104
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_vf.c7
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c7
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c15
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h6
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c7
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c4
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c22
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c6
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ipsec.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c4
-rw-r--r--drivers/net/ethernet/mediatek/mtk_star_emac.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/switchx2.c3
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c2
-rw-r--r--drivers/net/ethernet/mscc/Kconfig1
-rw-r--r--drivers/net/ethernet/mscc/ocelot_flower.c3
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c2
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c59
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c59
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c160
-rw-r--r--drivers/net/ethernet/sun/niu.c2
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c1
-rw-r--r--drivers/net/hamradio/6pack.c5
-rw-r--r--drivers/net/hamradio/scc.c1
-rw-r--r--drivers/net/hyperv/hyperv_net.h2
-rw-r--r--drivers/net/hyperv/netvsc_drv.c13
-rw-r--r--drivers/net/hyperv/rndis_filter.c2
-rw-r--r--drivers/net/netdevsim/netdev.c1
-rw-r--r--drivers/net/phy/dp83822.c9
-rw-r--r--drivers/net/phy/dp83tc811.c11
-rw-r--r--drivers/net/phy/phy.c6
-rw-r--r--drivers/net/phy/phy_device.c6
-rw-r--r--drivers/net/usb/cdc_ncm.c10
-rw-r--r--drivers/net/usb/qmi_wwan.c14
-rw-r--r--drivers/net/usb/r8152.c35
-rw-r--r--drivers/net/usb/usbnet.c2
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c8
-rw-r--r--drivers/net/wan/lapbether.c3
-rw-r--r--drivers/net/wireless/admtek/adm8211.c1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c6
-rw-r--r--drivers/net/wireless/atmel/atmel.c1
-rw-r--r--drivers/net/wireless/atmel/atmel_cs.c1
-rw-r--r--drivers/net/wireless/atmel/atmel_pci.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c1
-rw-r--r--drivers/net/wireless/cisco/airo.c1
-rw-r--r--drivers/net/wireless/cisco/airo_cs.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c3
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_cs.c1
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_pci.c1
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_plx.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c26
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/testmode.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2400pci.c1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500pci.c1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800pci.c1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800usb.c1
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_main.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c1
-rw-r--r--drivers/net/xen-netback/netback.c4
-rw-r--r--drivers/nvme/host/core.c79
-rw-r--r--drivers/nvme/host/fabrics.h7
-rw-r--r--drivers/nvme/host/fc.c9
-rw-r--r--drivers/nvme/host/pci.c1
-rw-r--r--drivers/nvme/host/rdma.c11
-rw-r--r--drivers/nvme/host/tcp.c20
-rw-r--r--drivers/nvme/host/zns.c9
-rw-r--r--drivers/nvme/target/core.c17
-rw-r--r--drivers/nvme/target/loop.c4
-rw-r--r--drivers/nvme/target/passthru.c6
-rw-r--r--drivers/nvme/target/rdma.c5
-rw-r--r--drivers/nvme/target/tcp.c2
-rw-r--r--drivers/opp/core.c48
-rw-r--r--drivers/opp/opp.h2
-rw-r--r--drivers/parport/parport_amiga.c1
-rw-r--r--drivers/parport/parport_atari.c1
-rw-r--r--drivers/parport/parport_gsc.c1
-rw-r--r--drivers/parport/parport_mfc3.c1
-rw-r--r--drivers/parport/parport_sunbpp.c1
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c14
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c3
-rw-r--r--drivers/pci/xen-pcifront.c4
-rw-r--r--drivers/perf/arm_dmc620_pmu.c1
-rw-r--r--drivers/power/supply/Kconfig2
-rw-r--r--drivers/power/supply/ab8500-bm.h733
-rw-r--r--drivers/power/supply/ab8500-chargalg.h51
-rw-r--r--drivers/power/supply/ab8500_bmdata.c3
-rw-r--r--drivers/power/supply/ab8500_btemp.c45
-rw-r--r--drivers/power/supply/ab8500_charger.c27
-rw-r--r--drivers/power/supply/ab8500_fg.c20
-rw-r--r--drivers/power/supply/abx500_chargalg.c22
-rw-r--r--drivers/power/supply/pm2301_charger.c4
-rw-r--r--drivers/pwm/Kconfig8
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-ntxec.c184
-rw-r--r--drivers/regulator/Kconfig11
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/bd71815-regulator.c652
-rw-r--r--drivers/regulator/bd71828-regulator.c51
-rw-r--r--drivers/regulator/bd718x7-regulator.c60
-rw-r--r--drivers/regulator/helpers.c101
-rw-r--r--drivers/regulator/mt6315-regulator.c4
-rw-r--r--drivers/regulator/pca9450-regulator.c10
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c6
-rw-r--r--drivers/regulator/rohm-regulator.c23
-rw-r--r--drivers/regulator/rt4831-regulator.c4
-rw-r--r--drivers/rtc/Kconfig14
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-bd70528.c104
-rw-r--r--drivers/rtc/rtc-ntxec.c145
-rw-r--r--drivers/s390/block/dasd.c7
-rw-r--r--drivers/s390/char/tty3270.c6
-rw-r--r--drivers/s390/char/zcore.c44
-rw-r--r--drivers/s390/cio/device_fsm.c2
-rw-r--r--drivers/s390/cio/vfio_ccw_ops.c6
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c2
-rw-r--r--drivers/s390/net/qeth_core.h3
-rw-r--r--drivers/s390/net/qeth_core_main.c128
-rw-r--r--drivers/sbus/char/display7seg.c1
-rw-r--r--drivers/scsi/hpsa.c1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c67
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c4
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c4
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c2
-rw-r--r--drivers/scsi/myrs.c2
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h2
-rw-r--r--drivers/scsi/sd_zbc.c19
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c1
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/ufs/ufs-mediatek.c2
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c10
-rw-r--r--drivers/scsi/ufs/ufshcd.c41
-rw-r--r--drivers/scsi/vmw_pvscsi.c2
-rw-r--r--drivers/scsi/vmw_pvscsi.h2
-rw-r--r--drivers/sh/maple/maple.c1
-rw-r--r--drivers/spi/spi-cadence-quadspi.c1
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c4
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c18
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c10
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236_common.c4
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c2
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c3
-rw-r--r--drivers/staging/comedi/drivers/das6402.c2
-rw-r--r--drivers/staging/comedi/drivers/das800.c2
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c2
-rw-r--r--drivers/staging/comedi/drivers/me4000.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c4
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c3
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c2
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c4
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c2
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c1
-rw-r--r--drivers/staging/ks7010/ks_wlan_net.c6
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c5
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c6
-rw-r--r--drivers/staging/rtl8192e/Kconfig1
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c7
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c2
-rw-r--r--drivers/staging/vt6655/rxtx.h4
-rw-r--r--drivers/staging/wfx/bh.c1
-rw-r--r--drivers/staging/wfx/bh.h4
-rw-r--r--drivers/staging/wfx/bus.h3
-rw-r--r--drivers/staging/wfx/bus_sdio.c6
-rw-r--r--drivers/staging/wfx/bus_spi.c7
-rw-r--r--drivers/staging/wfx/data_rx.c5
-rw-r--r--drivers/staging/wfx/data_tx.c5
-rw-r--r--drivers/staging/wfx/data_tx.h3
-rw-r--r--drivers/staging/wfx/debug.c6
-rw-r--r--drivers/staging/wfx/fwio.c2
-rw-r--r--drivers/staging/wfx/hif_api_cmd.h4
-rw-r--r--drivers/staging/wfx/hif_api_general.h9
-rw-r--r--drivers/staging/wfx/hif_tx.c4
-rw-r--r--drivers/staging/wfx/hif_tx_mib.c5
-rw-r--r--drivers/staging/wfx/hwio.c3
-rw-r--r--drivers/staging/wfx/hwio.h2
-rw-r--r--drivers/staging/wfx/key.c2
-rw-r--r--drivers/staging/wfx/key.h2
-rw-r--r--drivers/staging/wfx/main.c7
-rw-r--r--drivers/staging/wfx/main.h3
-rw-r--r--drivers/staging/wfx/queue.c4
-rw-r--r--drivers/staging/wfx/queue.h3
-rw-r--r--drivers/staging/wfx/scan.h2
-rw-r--r--drivers/staging/wfx/sta.c6
-rw-r--r--drivers/staging/wfx/sta.h2
-rw-r--r--drivers/staging/wfx/traces.h3
-rw-r--r--drivers/staging/wfx/wfx.h3
-rw-r--r--drivers/tee/optee/core.c1
-rw-r--r--drivers/thermal/thermal_sysfs.c3
-rw-r--r--drivers/thunderbolt/switch.c18
-rw-r--r--drivers/thunderbolt/tb.c4
-rw-r--r--drivers/tty/hvc/hvcs.c4
-rw-r--r--drivers/tty/pty.c15
-rw-r--r--drivers/tty/serial/icom.c2
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c1
-rw-r--r--drivers/tty/serial/max310x.c29
-rw-r--r--drivers/tty/tty_io.c5
-rw-r--r--drivers/usb/cdns3/cdnsp-ring.c5
-rw-r--r--drivers/usb/class/cdc-acm.c5
-rw-r--r--drivers/usb/class/usblp.c16
-rw-r--r--drivers/usb/core/usb.c32
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c18
-rw-r--r--drivers/usb/dwc3/gadget.c11
-rw-r--r--drivers/usb/gadget/configfs.c14
-rw-r--r--drivers/usb/gadget/function/f_uac1.c1
-rw-r--r--drivers/usb/gadget/function/f_uac2.c2
-rw-r--r--drivers/usb/gadget/function/u_ether_configfs.h5
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c4
-rw-r--r--drivers/usb/host/xhci-pci.c13
-rw-r--r--drivers/usb/host/xhci-ring.c3
-rw-r--r--drivers/usb/host/xhci.c78
-rw-r--r--drivers/usb/host/xhci.h1
-rw-r--r--drivers/usb/misc/ldusb.c1
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c2
-rw-r--r--drivers/usb/serial/ch341.c1
-rw-r--r--drivers/usb/serial/cp210x.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c26
-rw-r--r--drivers/usb/serial/xr_serial.c25
-rw-r--r--drivers/usb/storage/transport.c7
-rw-r--r--drivers/usb/storage/unusual_devs.h12
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c11
-rw-r--r--drivers/usb/typec/tps6598x.c1
-rw-r--r--drivers/usb/usbip/stub_dev.c42
-rw-r--r--drivers/usb/usbip/vhci_sysfs.c39
-rw-r--r--drivers/usb/usbip/vudc_sysfs.c49
-rw-r--r--drivers/vdpa/ifcvf/ifcvf_main.c5
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c4
-rw-r--r--drivers/vdpa/vdpa.c18
-rw-r--r--drivers/vdpa/vdpa_sim/vdpa_sim.c2
-rw-r--r--drivers/vdpa/vdpa_sim/vdpa_sim_net.c5
-rw-r--r--drivers/vfio/Kconfig4
-rw-r--r--drivers/vfio/platform/Kconfig4
-rw-r--r--drivers/vfio/vfio_iommu_type1.c20
-rw-r--r--drivers/vhost/vdpa.c20
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--drivers/video/fbdev/aty/atyfb.h3
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c9
-rw-r--r--drivers/virt/acrn/hsm.c11
-rw-r--r--drivers/virt/acrn/irqfd.c6
-rw-r--r--drivers/virtio/virtio.c6
-rw-r--r--drivers/virtio/virtio_mmio.c3
-rw-r--r--drivers/watchdog/cpu5wdt.c1
-rw-r--r--drivers/watchdog/cpwd.c1
-rw-r--r--drivers/watchdog/riowd.c1
-rw-r--r--drivers/xen/events/events_2l.c22
-rw-r--r--drivers/xen/events/events_base.c130
-rw-r--r--drivers/xen/events/events_fifo.c7
-rw-r--r--drivers/xen/events/events_internal.h14
-rw-r--r--drivers/xen/gntdev.c54
466 files changed, 6354 insertions, 3740 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 316a9947541f..b574cce98dc3 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -2260,7 +2260,8 @@ out:
return rc;
err_eni_release:
- eni_do_release(dev);
+ dev->phy = NULL;
+ iounmap(ENI_DEV(dev)->ioaddr);
err_unregister:
atm_dev_deregister(dev);
err_free_consistent:
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 9a70bee84125..495fd0a1f040 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -100,8 +100,6 @@ static LIST_HEAD(fore200e_boards);
MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
MODULE_DESCRIPTION("FORE Systems 200E-series ATM driver - version " FORE200E_VERSION);
-MODULE_SUPPORTED_DEVICE("PCA-200E, SBA-200E");
-
static const int fore200e_rx_buf_nbr[ BUFFER_SCHEME_NBR ][ BUFFER_MAGN_NBR ] = {
{ BUFFER_S1_NBR, BUFFER_L1_NBR },
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index 3c081b6171a8..bfca7b8a6f31 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -262,7 +262,7 @@ static int idt77105_start(struct atm_dev *dev)
{
unsigned long flags;
- if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
+ if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
return -ENOMEM;
PRIV(dev)->dev = dev;
spin_lock_irqsave(&idt77105_priv_lock, flags);
@@ -337,7 +337,7 @@ static int idt77105_stop(struct atm_dev *dev)
else
idt77105_all = walk->next;
dev->phy = NULL;
- dev->dev_data = NULL;
+ dev->phy_data = NULL;
kfree(walk);
break;
}
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index d7277c26e423..32d7aa141d96 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2233,6 +2233,7 @@ static int lanai_dev_open(struct atm_dev *atmdev)
conf1_write(lanai);
#endif
iounmap(lanai->base);
+ lanai->base = NULL;
error_pci:
pci_disable_device(lanai->pci);
error:
@@ -2245,6 +2246,8 @@ static int lanai_dev_open(struct atm_dev *atmdev)
static void lanai_dev_close(struct atm_dev *atmdev)
{
struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
+ if (lanai->base==NULL)
+ return;
printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n",
lanai->number);
lanai_timed_poll_stop(lanai);
@@ -2552,7 +2555,7 @@ static int lanai_init_one(struct pci_dev *pci,
struct atm_dev *atmdev;
int result;
- lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
+ lanai = kzalloc(sizeof(*lanai), GFP_KERNEL);
if (lanai == NULL) {
printk(KERN_ERR DEV_LABEL
": couldn't allocate dev_data structure!\n");
diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c
index 7850758b5bb8..239852d85558 100644
--- a/drivers/atm/uPD98402.c
+++ b/drivers/atm/uPD98402.c
@@ -211,7 +211,7 @@ static void uPD98402_int(struct atm_dev *dev)
static int uPD98402_start(struct atm_dev *dev)
{
DPRINTK("phy_start\n");
- if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
+ if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
return -ENOMEM;
spin_lock_init(&PRIV(dev)->lock);
memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 18b82427d0cb..a46a7e30881b 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct device *dev)
static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
- bool use_links = dev->power.links_count > 0;
- bool get = false;
int retval, idx;
- bool put;
+ bool use_links = dev->power.links_count > 0;
if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock);
- } else if (!use_links) {
- spin_unlock_irq(&dev->power.lock);
} else {
- get = dev->power.runtime_status == RPM_RESUMING;
-
spin_unlock_irq(&dev->power.lock);
- /* Resume suppliers if necessary. */
- if (get) {
+ /*
+ * Resume suppliers if necessary.
+ *
+ * The device's runtime PM status cannot change until this
+ * routine returns, so it is safe to read the status outside of
+ * the lock.
+ */
+ if (use_links && dev->power.runtime_status == RPM_RESUMING) {
idx = device_links_read_lock();
retval = rpm_get_suppliers(dev);
@@ -355,36 +355,24 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
if (dev->power.irq_safe) {
spin_lock(&dev->power.lock);
- return retval;
- }
-
- spin_lock_irq(&dev->power.lock);
-
- if (!use_links)
- return retval;
-
- /*
- * If the device is suspending and the callback has returned success,
- * drop the usage counters of the suppliers that have been reference
- * counted on its resume.
- *
- * Do that if the resume fails too.
- */
- put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
- if (put)
- __update_runtime_status(dev, RPM_SUSPENDED);
- else
- put = get && retval;
-
- if (put) {
- spin_unlock_irq(&dev->power.lock);
-
- idx = device_links_read_lock();
+ } else {
+ /*
+ * If the device is suspending and the callback has returned
+ * success, drop the usage counters of the suppliers that have
+ * been reference counted on its resume.
+ *
+ * Do that if resume fails too.
+ */
+ if (use_links
+ && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
+ || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+ idx = device_links_read_lock();
-fail:
- rpm_put_suppliers(dev);
+ fail:
+ rpm_put_suppliers(dev);
- device_links_read_unlock(idx);
+ device_links_read_unlock(idx);
+ }
spin_lock_irq(&dev->power.lock);
}
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 37179a8b1ceb..fa3719ef80e4 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -938,6 +938,9 @@ int software_node_register(const struct software_node *node)
if (software_node_to_swnode(node))
return -EEXIST;
+ if (node->parent && !parent)
+ return -EINVAL;
+
return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0));
}
EXPORT_SYMBOL_GPL(software_node_register);
@@ -1002,25 +1005,33 @@ EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
/**
* device_add_software_node - Assign software node to a device
* @dev: The device the software node is meant for.
- * @swnode: The software node.
+ * @node: The software node.
*
- * This function will register @swnode and make it the secondary firmware node
- * pointer of @dev. If @dev has no primary node, then @swnode will become the primary
- * node.
+ * This function will make @node the secondary firmware node pointer of @dev. If
+ * @dev has no primary node, then @node will become the primary node. The
+ * function will register @node automatically if it wasn't already registered.
*/
-int device_add_software_node(struct device *dev, const struct software_node *swnode)
+int device_add_software_node(struct device *dev, const struct software_node *node)
{
+ struct swnode *swnode;
int ret;
/* Only one software node per device. */
if (dev_to_swnode(dev))
return -EBUSY;
- ret = software_node_register(swnode);
- if (ret)
- return ret;
+ swnode = software_node_to_swnode(node);
+ if (swnode) {
+ kobject_get(&swnode->kobj);
+ } else {
+ ret = software_node_register(node);
+ if (ret)
+ return ret;
+
+ swnode = software_node_to_swnode(node);
+ }
- set_secondary_fwnode(dev, software_node_fwnode(swnode));
+ set_secondary_fwnode(dev, &swnode->fwnode);
return 0;
}
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 7d9cc433b758..5d9181382ce1 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1324,7 +1324,7 @@ struct bm_extent {
* A followup commit may allow even bigger BIO sizes,
* once we thought that through. */
#define DRBD_MAX_BIO_SIZE (1U << 20)
-#if DRBD_MAX_BIO_SIZE > (BIO_MAX_PAGES << PAGE_SHIFT)
+#if DRBD_MAX_BIO_SIZE > (BIO_MAX_VECS << PAGE_SHIFT)
#error Architecture not supported: DRBD_MAX_BIO_SIZE > BIO_MAX_SIZE
#endif
#define DRBD_MAX_BIO_SIZE_SAFE (1U << 12) /* Works always = 4k */
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 0b71292d9d5a..4aa9683ee0c1 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -5091,7 +5091,6 @@ module_param(floppy, charp, 0);
module_param(FLOPPY_IRQ, int, 0);
module_param(FLOPPY_DMA, int, 0);
MODULE_AUTHOR("Alain L. Knaff");
-MODULE_SUPPORTED_DEVICE("fd");
MODULE_LICENSE("GPL");
/* This doesn't actually get used other than for module information */
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c
index 5ac1881396af..227e1be4c6f9 100644
--- a/drivers/block/rsxx/core.c
+++ b/drivers/block/rsxx/core.c
@@ -871,6 +871,7 @@ static int rsxx_pci_probe(struct pci_dev *dev,
card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event");
if (!card->event_wq) {
dev_err(CARD_TO_DEV(card), "Failed card event setup.\n");
+ st = -ENOMEM;
goto failed_event_handler;
}
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 982732dbe82e..664280f23bee 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -877,6 +877,7 @@ static int mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (card->mm_pages[0].desc == NULL ||
card->mm_pages[1].desc == NULL) {
dev_printk(KERN_ERR, &card->dev->dev, "alloc failed\n");
+ ret = -ENOMEM;
goto failed_alloc;
}
reset_page(&card->mm_pages[0]);
@@ -888,8 +889,10 @@ static int mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
spin_lock_init(&card->lock);
card->queue = blk_alloc_queue(NUMA_NO_NODE);
- if (!card->queue)
+ if (!card->queue) {
+ ret = -ENOMEM;
goto failed_alloc;
+ }
tasklet_init(&card->tasklet, process_page, (unsigned long)card);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index a711a2e2a794..cf8deecc39ef 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -627,7 +627,7 @@ static ssize_t writeback_store(struct device *dev,
struct bio_vec bio_vec;
struct page *page;
ssize_t ret = len;
- int mode;
+ int mode, err;
unsigned long blk_idx = 0;
if (sysfs_streq(buf, "idle"))
@@ -638,8 +638,8 @@ static ssize_t writeback_store(struct device *dev,
if (strncmp(buf, PAGE_WB_SIG, sizeof(PAGE_WB_SIG) - 1))
return -EINVAL;
- ret = kstrtol(buf + sizeof(PAGE_WB_SIG) - 1, 10, &index);
- if (ret || index >= nr_pages)
+ if (kstrtol(buf + sizeof(PAGE_WB_SIG) - 1, 10, &index) ||
+ index >= nr_pages)
return -EINVAL;
nr_pages = 1;
@@ -663,7 +663,7 @@ static ssize_t writeback_store(struct device *dev,
goto release_init_lock;
}
- while (nr_pages--) {
+ for (; nr_pages != 0; index++, nr_pages--) {
struct bio_vec bvec;
bvec.bv_page = page;
@@ -728,12 +728,17 @@ static ssize_t writeback_store(struct device *dev,
* XXX: A single page IO would be inefficient for write
* but it would be not bad as starter.
*/
- ret = submit_bio_wait(&bio);
- if (ret) {
+ err = submit_bio_wait(&bio);
+ if (err) {
zram_slot_lock(zram, index);
zram_clear_flag(zram, index, ZRAM_UNDER_WB);
zram_clear_flag(zram, index, ZRAM_IDLE);
zram_slot_unlock(zram, index);
+ /*
+ * Return last IO error unless every IO were
+ * not suceeded.
+ */
+ ret = err;
continue;
}
diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
index 3951f7b23840..bea1595f6432 100644
--- a/drivers/bluetooth/btrsi.c
+++ b/drivers/bluetooth/btrsi.c
@@ -194,5 +194,4 @@ module_init(rsi_91x_bt_module_init);
module_exit(rsi_91x_bt_module_exit);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("RSI BT driver");
-MODULE_SUPPORTED_DEVICE("RSI-BT");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 14b2d8034c51..45ac7ab003ce 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -81,9 +81,6 @@ MODULE_DESCRIPTION("Driver for Applicom Profibus card");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(AC_MINOR);
-MODULE_SUPPORTED_DEVICE("ac");
-
-
static struct applicom_board {
unsigned long PhysIO;
void __iomem *RamIO;
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
index 8038a8a9fb58..f4949b689bd5 100644
--- a/drivers/char/hw_random/pseries-rng.c
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -54,10 +54,9 @@ static int pseries_rng_probe(struct vio_dev *dev,
return hwrng_register(&pseries_rng);
}
-static int pseries_rng_remove(struct vio_dev *dev)
+static void pseries_rng_remove(struct vio_dev *dev)
{
hwrng_unregister(&pseries_rng);
- return 0;
}
static const struct vio_device_id pseries_rng_driver_ids[] = {
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index aff0a8e44fff..776abbfd85d6 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -64,7 +64,6 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
MODULE_DESCRIPTION("Toshiba laptop SMM driver");
-MODULE_SUPPORTED_DEVICE("toshiba");
static DEFINE_MUTEX(tosh_mutex);
static int tosh_fn;
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 994385bf37c0..903604769de9 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -343,7 +343,7 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
*
* Return: Always 0.
*/
-static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
+static void tpm_ibmvtpm_remove(struct vio_dev *vdev)
{
struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
@@ -372,8 +372,6 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
kfree(ibmvtpm);
/* For tpm_ibmvtpm_get_desired_dma */
dev_set_drvdata(&vdev->dev, NULL);
-
- return 0;
}
/**
diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c
index 17d90e09f1c0..d9e70e506d18 100644
--- a/drivers/clk/clk-bd718x7.c
+++ b/drivers/clk/clk-bd718x7.c
@@ -13,6 +13,8 @@
#include <linux/regmap.h>
/* clk control registers */
+/* BD71815 */
+#define BD71815_REG_OUT32K 0x1d
/* BD70528 */
#define BD70528_REG_OUT32K 0x2c
/* BD71828 */
@@ -118,6 +120,10 @@ static int bd71837_clk_probe(struct platform_device *pdev)
c->reg = BD70528_REG_OUT32K;
c->mask = CLK_OUT_EN_MASK;
break;
+ case ROHM_CHIP_TYPE_BD71815:
+ c->reg = BD71815_REG_OUT32K;
+ c->mask = CLK_OUT_EN_MASK;
+ break;
default:
dev_err(&pdev->dev, "Unknown clk chip\n");
return -EINVAL;
@@ -146,6 +152,7 @@ static const struct platform_device_id bd718x7_clk_id[] = {
{ "bd71847-clk", ROHM_CHIP_TYPE_BD71847 },
{ "bd70528-clk", ROHM_CHIP_TYPE_BD70528 },
{ "bd71828-clk", ROHM_CHIP_TYPE_BD71828 },
+ { "bd71815-clk", ROHM_CHIP_TYPE_BD71815 },
{ },
};
MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
@@ -161,6 +168,6 @@ static struct platform_driver bd71837_clk = {
module_platform_driver(bd71837_clk);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
-MODULE_DESCRIPTION("BD71837/BD71847/BD70528 chip clk driver");
+MODULE_DESCRIPTION("BD718(15/18/28/37/47/50) and BD70528 chip clk driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:bd718xx-clk");
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index ef2a974a2f10..75bc401fdd18 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -31,7 +31,7 @@ struct stm32_timer_cnt {
struct counter_device counter;
struct regmap *regmap;
struct clk *clk;
- u32 ceiling;
+ u32 max_arr;
bool enabled;
struct stm32_timer_regs bak;
};
@@ -44,13 +44,14 @@ struct stm32_timer_cnt {
* @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges
*/
enum stm32_count_function {
- STM32_COUNT_SLAVE_MODE_DISABLED = -1,
+ STM32_COUNT_SLAVE_MODE_DISABLED,
STM32_COUNT_ENCODER_MODE_1,
STM32_COUNT_ENCODER_MODE_2,
STM32_COUNT_ENCODER_MODE_3,
};
static enum counter_count_function stm32_count_functions[] = {
+ [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,
[STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
[STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
[STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
@@ -73,8 +74,10 @@ static int stm32_count_write(struct counter_device *counter,
const unsigned long val)
{
struct stm32_timer_cnt *const priv = counter->priv;
+ u32 ceiling;
- if (val > priv->ceiling)
+ regmap_read(priv->regmap, TIM_ARR, &ceiling);
+ if (val > ceiling)
return -EINVAL;
return regmap_write(priv->regmap, TIM_CNT, val);
@@ -90,6 +93,9 @@ static int stm32_count_function_get(struct counter_device *counter,
regmap_read(priv->regmap, TIM_SMCR, &smcr);
switch (smcr & TIM_SMCR_SMS) {
+ case 0:
+ *function = STM32_COUNT_SLAVE_MODE_DISABLED;
+ return 0;
case 1:
*function = STM32_COUNT_ENCODER_MODE_1;
return 0;
@@ -99,9 +105,9 @@ static int stm32_count_function_get(struct counter_device *counter,
case 3:
*function = STM32_COUNT_ENCODER_MODE_3;
return 0;
+ default:
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int stm32_count_function_set(struct counter_device *counter,
@@ -112,6 +118,9 @@ static int stm32_count_function_set(struct counter_device *counter,
u32 cr1, sms;
switch (function) {
+ case STM32_COUNT_SLAVE_MODE_DISABLED:
+ sms = 0;
+ break;
case STM32_COUNT_ENCODER_MODE_1:
sms = 1;
break;
@@ -122,8 +131,7 @@ static int stm32_count_function_set(struct counter_device *counter,
sms = 3;
break;
default:
- sms = 0;
- break;
+ return -EINVAL;
}
/* Store enable status */
@@ -131,10 +139,6 @@ static int stm32_count_function_set(struct counter_device *counter,
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
- /* TIMx_ARR register shouldn't be buffered (ARPE=0) */
- regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
- regmap_write(priv->regmap, TIM_ARR, priv->ceiling);
-
regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
/* Make sure that registers are updated */
@@ -185,11 +189,13 @@ static ssize_t stm32_count_ceiling_write(struct counter_device *counter,
if (ret)
return ret;
+ if (ceiling > priv->max_arr)
+ return -ERANGE;
+
/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
regmap_write(priv->regmap, TIM_ARR, ceiling);
- priv->ceiling = ceiling;
return len;
}
@@ -274,31 +280,36 @@ static int stm32_action_get(struct counter_device *counter,
size_t function;
int err;
- /* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */
- *action = STM32_SYNAPSE_ACTION_NONE;
-
err = stm32_count_function_get(counter, count, &function);
if (err)
- return 0;
+ return err;
switch (function) {
+ case STM32_COUNT_SLAVE_MODE_DISABLED:
+ /* counts on internal clock when CEN=1 */
+ *action = STM32_SYNAPSE_ACTION_NONE;
+ return 0;
case STM32_COUNT_ENCODER_MODE_1:
/* counts up/down on TI1FP1 edge depending on TI2FP2 level */
if (synapse->signal->id == count->synapses[0].signal->id)
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ else
+ *action = STM32_SYNAPSE_ACTION_NONE;
+ return 0;
case STM32_COUNT_ENCODER_MODE_2:
/* counts up/down on TI2FP2 edge depending on TI1FP1 level */
if (synapse->signal->id == count->synapses[1].signal->id)
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ else
+ *action = STM32_SYNAPSE_ACTION_NONE;
+ return 0;
case STM32_COUNT_ENCODER_MODE_3:
/* counts up/down on both TI1FP1 and TI2FP2 edges */
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
- break;
+ return 0;
+ default:
+ return -EINVAL;
}
-
- return 0;
}
static const struct counter_ops stm32_timer_cnt_ops = {
@@ -359,7 +370,7 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
priv->regmap = ddata->regmap;
priv->clk = ddata->clk;
- priv->ceiling = ddata->max_arr;
+ priv->max_arr = ddata->max_arr;
priv->counter.name = dev_name(dev);
priv->counter.parent = dev;
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 3ba2f716fe97..5e07065ec22f 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -103,6 +103,8 @@ static const struct of_device_id whitelist[] __initconst = {
static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "allwinner,sun50i-h6", },
+ { .compatible = "arm,vexpress", },
+
{ .compatible = "calxeda,highbank", },
{ .compatible = "calxeda,ecx-2000", },
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index d3c23447b892..f86859bf76f1 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -317,9 +317,9 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
}
base = ioremap(res->start, resource_size(res));
- if (IS_ERR(base)) {
+ if (!base) {
dev_err(dev, "failed to map resource %pR\n", res);
- ret = PTR_ERR(base);
+ ret = -ENOMEM;
goto release_region;
}
@@ -374,7 +374,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
error:
kfree(data);
unmap_base:
- iounmap(data->base);
+ iounmap(base);
release_region:
release_mem_region(res->start, resource_size(res));
return ret;
diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-842-pseries.c
index 2de5e3672e42..cc8dd3072b8b 100644
--- a/drivers/crypto/nx/nx-842-pseries.c
+++ b/drivers/crypto/nx/nx-842-pseries.c
@@ -1042,7 +1042,7 @@ error:
return ret;
}
-static int nx842_remove(struct vio_dev *viodev)
+static void nx842_remove(struct vio_dev *viodev)
{
struct nx842_devdata *old_devdata;
unsigned long flags;
@@ -1063,8 +1063,6 @@ static int nx842_remove(struct vio_dev *viodev)
if (old_devdata)
kfree(old_devdata->counters);
kfree(old_devdata);
-
- return 0;
}
static const struct vio_device_id nx842_vio_driver_ids[] = {
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index 0d2dc5be7f19..1d0e8a1ba160 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -783,7 +783,7 @@ static int nx_probe(struct vio_dev *viodev, const struct vio_device_id *id)
return nx_register_algs();
}
-static int nx_remove(struct vio_dev *viodev)
+static void nx_remove(struct vio_dev *viodev)
{
dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
viodev->unit_address);
@@ -811,8 +811,6 @@ static int nx_remove(struct vio_dev *viodev)
nx_unregister_skcipher(&nx_ecb_aes_alg, NX_FC_AES,
NX_MODE_AES_ECB);
}
-
- return 0;
}
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index af58ebca2bf6..e3db936becfd 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -21,14 +21,6 @@ config EXTCON_ADC_JACK
help
Say Y here to enable extcon device driver based on ADC values.
-config EXTCON_ARIZONA
- tristate "Wolfson Arizona EXTCON support"
- depends on MFD_ARIZONA && INPUT && SND_SOC
- help
- Say Y here to enable support for external accessory detection
- with Wolfson Arizona devices. These are audio CODECs with
- advanced audio accessory detection support.
-
config EXTCON_AXP288
tristate "X-Power AXP288 EXTCON support"
depends on MFD_AXP20X && USB_SUPPORT && X86 && ACPI
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index fe10a1b7d18b..1b390d934ca9 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -6,7 +6,6 @@
obj-$(CONFIG_EXTCON) += extcon-core.o
extcon-core-objs += extcon.o devres.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
-obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o
obj-$(CONFIG_EXTCON_FSA9480) += extcon-fsa9480.o
obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
deleted file mode 100644
index aae82db542a5..000000000000
--- a/drivers/extcon/extcon-arizona.c
+++ /dev/null
@@ -1,1816 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * extcon-arizona.c - Extcon driver Wolfson Arizona devices
- *
- * Copyright (C) 2012-2014 Wolfson Microelectronics plc
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/property.h>
-#include <linux/regulator/consumer.h>
-#include <linux/extcon-provider.h>
-
-#include <sound/soc.h>
-
-#include <linux/mfd/arizona/core.h>
-#include <linux/mfd/arizona/pdata.h>
-#include <linux/mfd/arizona/registers.h>
-#include <dt-bindings/mfd/arizona.h>
-
-#define ARIZONA_MAX_MICD_RANGE 8
-
-#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
-#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
-#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
-#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
-
-#define ARIZONA_TST_CAP_DEFAULT 0x3
-#define ARIZONA_TST_CAP_CLAMP 0x1
-
-#define ARIZONA_HPDET_MAX 10000
-
-#define HPDET_DEBOUNCE 500
-#define DEFAULT_MICD_TIMEOUT 2000
-
-#define ARIZONA_HPDET_WAIT_COUNT 15
-#define ARIZONA_HPDET_WAIT_DELAY_MS 20
-
-#define QUICK_HEADPHONE_MAX_OHM 3
-#define MICROPHONE_MIN_OHM 1257
-#define MICROPHONE_MAX_OHM 30000
-
-#define MICD_DBTIME_TWO_READINGS 2
-#define MICD_DBTIME_FOUR_READINGS 4
-
-#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
- ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
- ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
- ARIZONA_MICD_LVL_7)
-
-#define MICD_LVL_0_TO_7 (ARIZONA_MICD_LVL_0 | MICD_LVL_1_TO_7)
-
-#define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8)
-
-struct arizona_extcon_info {
- struct device *dev;
- struct arizona *arizona;
- struct mutex lock;
- struct regulator *micvdd;
- struct input_dev *input;
-
- u16 last_jackdet;
-
- int micd_mode;
- const struct arizona_micd_config *micd_modes;
- int micd_num_modes;
-
- const struct arizona_micd_range *micd_ranges;
- int num_micd_ranges;
-
- bool micd_reva;
- bool micd_clamp;
-
- struct delayed_work hpdet_work;
- struct delayed_work micd_detect_work;
- struct delayed_work micd_timeout_work;
-
- bool hpdet_active;
- bool hpdet_done;
- bool hpdet_retried;
-
- int num_hpdet_res;
- unsigned int hpdet_res[3];
-
- bool mic;
- bool detecting;
- int jack_flips;
-
- int hpdet_ip_version;
-
- struct extcon_dev *edev;
-
- struct gpio_desc *micd_pol_gpio;
-};
-
-static const struct arizona_micd_config micd_default_modes[] = {
- { ARIZONA_ACCDET_SRC, 1, 0 },
- { 0, 2, 1 },
-};
-
-static const struct arizona_micd_range micd_default_ranges[] = {
- { .max = 11, .key = BTN_0 },
- { .max = 28, .key = BTN_1 },
- { .max = 54, .key = BTN_2 },
- { .max = 100, .key = BTN_3 },
- { .max = 186, .key = BTN_4 },
- { .max = 430, .key = BTN_5 },
-};
-
-/* The number of levels in arizona_micd_levels valid for button thresholds */
-#define ARIZONA_NUM_MICD_BUTTON_LEVELS 64
-
-static const int arizona_micd_levels[] = {
- 3, 6, 8, 11, 13, 16, 18, 21, 23, 26, 28, 31, 34, 36, 39, 41, 44, 46,
- 49, 52, 54, 57, 60, 62, 65, 67, 70, 73, 75, 78, 81, 83, 89, 94, 100,
- 105, 111, 116, 122, 127, 139, 150, 161, 173, 186, 196, 209, 220, 245,
- 270, 295, 321, 348, 375, 402, 430, 489, 550, 614, 681, 752, 903, 1071,
- 1257, 30000,
-};
-
-static const unsigned int arizona_cable[] = {
- EXTCON_MECHANICAL,
- EXTCON_JACK_MICROPHONE,
- EXTCON_JACK_HEADPHONE,
- EXTCON_JACK_LINE_OUT,
- EXTCON_NONE,
-};
-
-static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
-
-static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
- bool clamp)
-{
- struct arizona *arizona = info->arizona;
- unsigned int mask = 0, val = 0;
- unsigned int cap_sel = 0;
- int ret;
-
- switch (arizona->type) {
- case WM8998:
- case WM1814:
- mask = 0;
- break;
- case WM5110:
- case WM8280:
- mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
- ARIZONA_HP1L_SHRTI;
- if (clamp) {
- val = ARIZONA_HP1L_SHRTO;
- cap_sel = ARIZONA_TST_CAP_CLAMP;
- } else {
- val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
- cap_sel = ARIZONA_TST_CAP_DEFAULT;
- }
-
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_HP_TEST_CTRL_1,
- ARIZONA_HP1_TST_CAP_SEL_MASK,
- cap_sel);
- if (ret != 0)
- dev_warn(arizona->dev,
- "Failed to set TST_CAP_SEL: %d\n", ret);
- break;
- default:
- mask = ARIZONA_RMV_SHRT_HP1L;
- if (clamp)
- val = ARIZONA_RMV_SHRT_HP1L;
- break;
- }
-
- snd_soc_dapm_mutex_lock(arizona->dapm);
-
- arizona->hpdet_clamp = clamp;
-
- /* Keep the HP output stages disabled while doing the clamp */
- if (clamp) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_OUTPUT_ENABLES_1,
- ARIZONA_OUT1L_ENA |
- ARIZONA_OUT1R_ENA, 0);
- if (ret != 0)
- dev_warn(arizona->dev,
- "Failed to disable headphone outputs: %d\n",
- ret);
- }
-
- if (mask) {
- ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
- mask, val);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to do clamp: %d\n",
- ret);
-
- ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
- mask, val);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to do clamp: %d\n",
- ret);
- }
-
- /* Restore the desired state while not doing the clamp */
- if (!clamp) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_OUTPUT_ENABLES_1,
- ARIZONA_OUT1L_ENA |
- ARIZONA_OUT1R_ENA, arizona->hp_ena);
- if (ret != 0)
- dev_warn(arizona->dev,
- "Failed to restore headphone outputs: %d\n",
- ret);
- }
-
- snd_soc_dapm_mutex_unlock(arizona->dapm);
-}
-
-static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
-{
- struct arizona *arizona = info->arizona;
-
- mode %= info->micd_num_modes;
-
- gpiod_set_value_cansleep(info->micd_pol_gpio,
- info->micd_modes[mode].gpio);
-
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_BIAS_SRC_MASK,
- info->micd_modes[mode].bias <<
- ARIZONA_MICD_BIAS_SRC_SHIFT);
- regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
-
- info->micd_mode = mode;
-
- dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
-}
-
-static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
-{
- switch (info->micd_modes[0].bias) {
- case 1:
- return "MICBIAS1";
- case 2:
- return "MICBIAS2";
- case 3:
- return "MICBIAS3";
- default:
- return "MICVDD";
- }
-}
-
-static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- const char *widget = arizona_extcon_get_micbias(info);
- struct snd_soc_dapm_context *dapm = arizona->dapm;
- struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
- int ret;
-
- ret = snd_soc_component_force_enable_pin(component, widget);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to enable %s: %d\n",
- widget, ret);
-
- snd_soc_dapm_sync(dapm);
-
- if (!arizona->pdata.micd_force_micbias) {
- ret = snd_soc_component_disable_pin(component, widget);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to disable %s: %d\n",
- widget, ret);
-
- snd_soc_dapm_sync(dapm);
- }
-}
-
-static void arizona_start_mic(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- bool change;
- int ret;
- unsigned int mode;
-
- /* Microphone detection can't use idle mode */
- pm_runtime_get(info->dev);
-
- if (info->detecting) {
- ret = regulator_allow_bypass(info->micvdd, false);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to regulate MICVDD: %d\n",
- ret);
- }
- }
-
- ret = regulator_enable(info->micvdd);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
- ret);
- }
-
- if (info->micd_reva) {
- const struct reg_sequence reva[] = {
- { 0x80, 0x3 },
- { 0x294, 0x0 },
- { 0x80, 0x0 },
- };
-
- regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
- }
-
- if (info->detecting && arizona->pdata.micd_software_compare)
- mode = ARIZONA_ACCDET_MODE_ADC;
- else
- mode = ARIZONA_ACCDET_MODE_MIC;
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_MODE_MASK, mode);
-
- arizona_extcon_pulse_micbias(info);
-
- ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
- &change);
- if (ret < 0) {
- dev_err(arizona->dev, "Failed to enable micd: %d\n", ret);
- } else if (!change) {
- regulator_disable(info->micvdd);
- pm_runtime_put_autosuspend(info->dev);
- }
-}
-
-static void arizona_stop_mic(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- const char *widget = arizona_extcon_get_micbias(info);
- struct snd_soc_dapm_context *dapm = arizona->dapm;
- struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
- bool change = false;
- int ret;
-
- ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_ENA, 0,
- &change);
- if (ret < 0)
- dev_err(arizona->dev, "Failed to disable micd: %d\n", ret);
-
- ret = snd_soc_component_disable_pin(component, widget);
- if (ret != 0)
- dev_warn(arizona->dev,
- "Failed to disable %s: %d\n",
- widget, ret);
-
- snd_soc_dapm_sync(dapm);
-
- if (info->micd_reva) {
- const struct reg_sequence reva[] = {
- { 0x80, 0x3 },
- { 0x294, 0x2 },
- { 0x80, 0x0 },
- };
-
- regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
- }
-
- ret = regulator_allow_bypass(info->micvdd, true);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
- ret);
- }
-
- if (change) {
- regulator_disable(info->micvdd);
- pm_runtime_mark_last_busy(info->dev);
- pm_runtime_put_autosuspend(info->dev);
- }
-}
-
-static struct {
- unsigned int threshold;
- unsigned int factor_a;
- unsigned int factor_b;
-} arizona_hpdet_b_ranges[] = {
- { 100, 5528, 362464 },
- { 169, 11084, 6186851 },
- { 169, 11065, 65460395 },
-};
-
-#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
-
-static struct {
- int min;
- int max;
-} arizona_hpdet_c_ranges[] = {
- { 0, 30 },
- { 8, 100 },
- { 100, 1000 },
- { 1000, 10000 },
-};
-
-static int arizona_hpdet_read(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- unsigned int val, range;
- int ret;
-
- ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
- ret);
- return ret;
- }
-
- switch (info->hpdet_ip_version) {
- case 0:
- if (!(val & ARIZONA_HP_DONE)) {
- dev_err(arizona->dev, "HPDET did not complete: %x\n",
- val);
- return -EAGAIN;
- }
-
- val &= ARIZONA_HP_LVL_MASK;
- break;
-
- case 1:
- if (!(val & ARIZONA_HP_DONE_B)) {
- dev_err(arizona->dev, "HPDET did not complete: %x\n",
- val);
- return -EAGAIN;
- }
-
- ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to read HP value: %d\n",
- ret);
- return -EAGAIN;
- }
-
- regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
- &range);
- range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
- >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
-
- if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
- (val < arizona_hpdet_b_ranges[range].threshold ||
- val >= ARIZONA_HPDET_B_RANGE_MAX)) {
- range++;
- dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
- range);
- regmap_update_bits(arizona->regmap,
- ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_IMPEDANCE_RANGE_MASK,
- range <<
- ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
- return -EAGAIN;
- }
-
- /* If we go out of range report top of range */
- if (val < arizona_hpdet_b_ranges[range].threshold ||
- val >= ARIZONA_HPDET_B_RANGE_MAX) {
- dev_dbg(arizona->dev, "Measurement out of range\n");
- return ARIZONA_HPDET_MAX;
- }
-
- dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
- val, range);
-
- val = arizona_hpdet_b_ranges[range].factor_b
- / ((val * 100) -
- arizona_hpdet_b_ranges[range].factor_a);
- break;
-
- case 2:
- if (!(val & ARIZONA_HP_DONE_B)) {
- dev_err(arizona->dev, "HPDET did not complete: %x\n",
- val);
- return -EAGAIN;
- }
-
- val &= ARIZONA_HP_LVL_B_MASK;
- /* Convert to ohms, the value is in 0.5 ohm increments */
- val /= 2;
-
- regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
- &range);
- range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
- >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
-
- /* Skip up a range, or report? */
- if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
- (val >= arizona_hpdet_c_ranges[range].max)) {
- range++;
- dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
- arizona_hpdet_c_ranges[range].min,
- arizona_hpdet_c_ranges[range].max);
- regmap_update_bits(arizona->regmap,
- ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_IMPEDANCE_RANGE_MASK,
- range <<
- ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
- return -EAGAIN;
- }
-
- if (range && (val < arizona_hpdet_c_ranges[range].min)) {
- dev_dbg(arizona->dev, "Reporting range boundary %d\n",
- arizona_hpdet_c_ranges[range].min);
- val = arizona_hpdet_c_ranges[range].min;
- }
- break;
-
- default:
- dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
- info->hpdet_ip_version);
- return -EINVAL;
- }
-
- dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
- return val;
-}
-
-static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
- bool *mic)
-{
- struct arizona *arizona = info->arizona;
- int id_gpio = arizona->pdata.hpdet_id_gpio;
-
- if (!arizona->pdata.hpdet_acc_id)
- return 0;
-
- /*
- * If we're using HPDET for accessory identification we need
- * to take multiple measurements, step through them in sequence.
- */
- info->hpdet_res[info->num_hpdet_res++] = *reading;
-
- /* Only check the mic directly if we didn't already ID it */
- if (id_gpio && info->num_hpdet_res == 1) {
- dev_dbg(arizona->dev, "Measuring mic\n");
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_MODE_MASK |
- ARIZONA_ACCDET_SRC,
- ARIZONA_ACCDET_MODE_HPR |
- info->micd_modes[0].src);
-
- gpio_set_value_cansleep(id_gpio, 1);
-
- regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_POLL, ARIZONA_HP_POLL);
- return -EAGAIN;
- }
-
- /* OK, got both. Now, compare... */
- dev_dbg(arizona->dev, "HPDET measured %d %d\n",
- info->hpdet_res[0], info->hpdet_res[1]);
-
- /* Take the headphone impedance for the main report */
- *reading = info->hpdet_res[0];
-
- /* Sometimes we get false readings due to slow insert */
- if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
- dev_dbg(arizona->dev, "Retrying high impedance\n");
- info->num_hpdet_res = 0;
- info->hpdet_retried = true;
- arizona_start_hpdet_acc_id(info);
- pm_runtime_put(info->dev);
- return -EAGAIN;
- }
-
- /*
- * If we measure the mic as high impedance
- */
- if (!id_gpio || info->hpdet_res[1] > 50) {
- dev_dbg(arizona->dev, "Detected mic\n");
- *mic = true;
- info->detecting = true;
- } else {
- dev_dbg(arizona->dev, "Detected headphone\n");
- }
-
- /* Make sure everything is reset back to the real polarity */
- regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_SRC, info->micd_modes[0].src);
-
- return 0;
-}
-
-static irqreturn_t arizona_hpdet_irq(int irq, void *data)
-{
- struct arizona_extcon_info *info = data;
- struct arizona *arizona = info->arizona;
- int id_gpio = arizona->pdata.hpdet_id_gpio;
- unsigned int report = EXTCON_JACK_HEADPHONE;
- int ret, reading;
- bool mic = false;
-
- mutex_lock(&info->lock);
-
- /* If we got a spurious IRQ for some reason then ignore it */
- if (!info->hpdet_active) {
- dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
- mutex_unlock(&info->lock);
- return IRQ_NONE;
- }
-
- /* If the cable was removed while measuring ignore the result */
- ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
- if (ret < 0) {
- dev_err(arizona->dev, "Failed to check cable state: %d\n",
- ret);
- goto out;
- } else if (!ret) {
- dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
- goto done;
- }
-
- ret = arizona_hpdet_read(info);
- if (ret == -EAGAIN)
- goto out;
- else if (ret < 0)
- goto done;
- reading = ret;
-
- /* Reset back to starting range */
- regmap_update_bits(arizona->regmap,
- ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
- 0);
-
- ret = arizona_hpdet_do_id(info, &reading, &mic);
- if (ret == -EAGAIN)
- goto out;
- else if (ret < 0)
- goto done;
-
- /* Report high impedence cables as line outputs */
- if (reading >= 5000)
- report = EXTCON_JACK_LINE_OUT;
- else
- report = EXTCON_JACK_HEADPHONE;
-
- ret = extcon_set_state_sync(info->edev, report, true);
- if (ret != 0)
- dev_err(arizona->dev, "Failed to report HP/line: %d\n",
- ret);
-
-done:
- /* Reset back to starting range */
- regmap_update_bits(arizona->regmap,
- ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
- 0);
-
- arizona_extcon_hp_clamp(info, false);
-
- if (id_gpio)
- gpio_set_value_cansleep(id_gpio, 0);
-
- /* If we have a mic then reenable MICDET */
- if (mic || info->mic)
- arizona_start_mic(info);
-
- if (info->hpdet_active) {
- pm_runtime_put_autosuspend(info->dev);
- info->hpdet_active = false;
- }
-
- info->hpdet_done = true;
-
-out:
- mutex_unlock(&info->lock);
-
- return IRQ_HANDLED;
-}
-
-static void arizona_identify_headphone(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- int ret;
-
- if (info->hpdet_done)
- return;
-
- dev_dbg(arizona->dev, "Starting HPDET\n");
-
- /* Make sure we keep the device enabled during the measurement */
- pm_runtime_get(info->dev);
-
- info->hpdet_active = true;
-
- arizona_stop_mic(info);
-
- arizona_extcon_hp_clamp(info, true);
-
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_MODE_MASK,
- arizona->pdata.hpdet_channel);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
- goto err;
- }
-
- ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_POLL, ARIZONA_HP_POLL);
- if (ret != 0) {
- dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
- ret);
- goto err;
- }
-
- return;
-
-err:
- arizona_extcon_hp_clamp(info, false);
- pm_runtime_put_autosuspend(info->dev);
-
- /* Just report headphone */
- ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
- if (ret != 0)
- dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
-
- if (info->mic)
- arizona_start_mic(info);
-
- info->hpdet_active = false;
-}
-
-static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- int hp_reading = 32;
- bool mic;
- int ret;
-
- dev_dbg(arizona->dev, "Starting identification via HPDET\n");
-
- /* Make sure we keep the device enabled during the measurement */
- pm_runtime_get_sync(info->dev);
-
- info->hpdet_active = true;
-
- arizona_extcon_hp_clamp(info, true);
-
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_ACCESSORY_DETECT_MODE_1,
- ARIZONA_ACCDET_SRC | ARIZONA_ACCDET_MODE_MASK,
- info->micd_modes[0].src |
- arizona->pdata.hpdet_channel);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to set HPDET mode: %d\n", ret);
- goto err;
- }
-
- if (arizona->pdata.hpdet_acc_id_line) {
- ret = regmap_update_bits(arizona->regmap,
- ARIZONA_HEADPHONE_DETECT_1,
- ARIZONA_HP_POLL, ARIZONA_HP_POLL);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Can't start HPDETL measurement: %d\n",
- ret);
- goto err;
- }
- } else {
- arizona_hpdet_do_id(info, &hp_reading, &mic);
- }
-
- return;
-
-err:
- /* Just report headphone */
- ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
- if (ret != 0)
- dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
-
- info->hpdet_active = false;
-}
-
-static void arizona_micd_timeout_work(struct work_struct *work)
-{
- struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- micd_timeout_work.work);
-
- mutex_lock(&info->lock);
-
- dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
-
- info->detecting = false;
-
- arizona_identify_headphone(info);
-
- mutex_unlock(&info->lock);
-}
-
-static int arizona_micd_adc_read(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- unsigned int val;
- int ret;
-
- /* Must disable MICD before we read the ADCVAL */
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_ENA, 0);
-
- ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to read MICDET_ADCVAL: %d\n", ret);
- return ret;
- }
-
- dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
-
- val &= ARIZONA_MICDET_ADCVAL_MASK;
- if (val < ARRAY_SIZE(arizona_micd_levels))
- val = arizona_micd_levels[val];
- else
- val = INT_MAX;
-
- if (val <= QUICK_HEADPHONE_MAX_OHM)
- val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
- else if (val <= MICROPHONE_MIN_OHM)
- val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
- else if (val <= MICROPHONE_MAX_OHM)
- val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
- else
- val = ARIZONA_MICD_LVL_8;
-
- return val;
-}
-
-static int arizona_micd_read(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- unsigned int val = 0;
- int ret, i;
-
- for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
- ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to read MICDET: %d\n", ret);
- return ret;
- }
-
- dev_dbg(arizona->dev, "MICDET: %x\n", val);
-
- if (!(val & ARIZONA_MICD_VALID)) {
- dev_warn(arizona->dev,
- "Microphone detection state invalid\n");
- return -EINVAL;
- }
- }
-
- if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
- dev_err(arizona->dev, "Failed to get valid MICDET value\n");
- return -EINVAL;
- }
-
- return val;
-}
-
-static int arizona_micdet_reading(void *priv)
-{
- struct arizona_extcon_info *info = priv;
- struct arizona *arizona = info->arizona;
- int ret, val;
-
- if (info->detecting && arizona->pdata.micd_software_compare)
- ret = arizona_micd_adc_read(info);
- else
- ret = arizona_micd_read(info);
- if (ret < 0)
- return ret;
-
- val = ret;
-
- /* Due to jack detect this should never happen */
- if (!(val & ARIZONA_MICD_STS)) {
- dev_warn(arizona->dev, "Detected open circuit\n");
- info->mic = false;
- info->detecting = false;
- arizona_identify_headphone(info);
- return 0;
- }
-
- /* If we got a high impedence we should have a headset, report it. */
- if (val & ARIZONA_MICD_LVL_8) {
- info->mic = true;
- info->detecting = false;
-
- arizona_identify_headphone(info);
-
- ret = extcon_set_state_sync(info->edev,
- EXTCON_JACK_MICROPHONE, true);
- if (ret != 0)
- dev_err(arizona->dev, "Headset report failed: %d\n",
- ret);
-
- /* Don't need to regulate for button detection */
- ret = regulator_allow_bypass(info->micvdd, true);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
- ret);
- }
-
- return 0;
- }
-
- /* If we detected a lower impedence during initial startup
- * then we probably have the wrong polarity, flip it. Don't
- * do this for the lowest impedences to speed up detection of
- * plain headphones. If both polarities report a low
- * impedence then give up and report headphones.
- */
- if (val & MICD_LVL_1_TO_7) {
- if (info->jack_flips >= info->micd_num_modes * 10) {
- dev_dbg(arizona->dev, "Detected HP/line\n");
-
- info->detecting = false;
-
- arizona_identify_headphone(info);
- } else {
- info->micd_mode++;
- if (info->micd_mode == info->micd_num_modes)
- info->micd_mode = 0;
- arizona_extcon_set_mode(info, info->micd_mode);
-
- info->jack_flips++;
-
- if (arizona->pdata.micd_software_compare)
- regmap_update_bits(arizona->regmap,
- ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_ENA,
- ARIZONA_MICD_ENA);
-
- queue_delayed_work(system_power_efficient_wq,
- &info->micd_timeout_work,
- msecs_to_jiffies(arizona->pdata.micd_timeout));
- }
-
- return 0;
- }
-
- /*
- * If we're still detecting and we detect a short then we've
- * got a headphone.
- */
- dev_dbg(arizona->dev, "Headphone detected\n");
- info->detecting = false;
-
- arizona_identify_headphone(info);
-
- return 0;
-}
-
-static int arizona_button_reading(void *priv)
-{
- struct arizona_extcon_info *info = priv;
- struct arizona *arizona = info->arizona;
- int val, key, lvl, i;
-
- val = arizona_micd_read(info);
- if (val < 0)
- return val;
-
- /*
- * If we're still detecting and we detect a short then we've
- * got a headphone. Otherwise it's a button press.
- */
- if (val & MICD_LVL_0_TO_7) {
- if (info->mic) {
- dev_dbg(arizona->dev, "Mic button detected\n");
-
- lvl = val & ARIZONA_MICD_LVL_MASK;
- lvl >>= ARIZONA_MICD_LVL_SHIFT;
-
- for (i = 0; i < info->num_micd_ranges; i++)
- input_report_key(info->input,
- info->micd_ranges[i].key, 0);
-
- if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
- key = info->micd_ranges[ffs(lvl) - 1].key;
- input_report_key(info->input, key, 1);
- input_sync(info->input);
- } else {
- dev_err(arizona->dev, "Button out of range\n");
- }
- } else {
- dev_warn(arizona->dev, "Button with no mic: %x\n",
- val);
- }
- } else {
- dev_dbg(arizona->dev, "Mic button released\n");
- for (i = 0; i < info->num_micd_ranges; i++)
- input_report_key(info->input,
- info->micd_ranges[i].key, 0);
- input_sync(info->input);
- arizona_extcon_pulse_micbias(info);
- }
-
- return 0;
-}
-
-static void arizona_micd_detect(struct work_struct *work)
-{
- struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- micd_detect_work.work);
- struct arizona *arizona = info->arizona;
- int ret;
-
- cancel_delayed_work_sync(&info->micd_timeout_work);
-
- mutex_lock(&info->lock);
-
- /* If the cable was removed while measuring ignore the result */
- ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
- if (ret < 0) {
- dev_err(arizona->dev, "Failed to check cable state: %d\n",
- ret);
- mutex_unlock(&info->lock);
- return;
- } else if (!ret) {
- dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
- mutex_unlock(&info->lock);
- return;
- }
-
- if (info->detecting)
- arizona_micdet_reading(info);
- else
- arizona_button_reading(info);
-
- pm_runtime_mark_last_busy(info->dev);
- mutex_unlock(&info->lock);
-}
-
-static irqreturn_t arizona_micdet(int irq, void *data)
-{
- struct arizona_extcon_info *info = data;
- struct arizona *arizona = info->arizona;
- int debounce = arizona->pdata.micd_detect_debounce;
-
- cancel_delayed_work_sync(&info->micd_detect_work);
- cancel_delayed_work_sync(&info->micd_timeout_work);
-
- mutex_lock(&info->lock);
- if (!info->detecting)
- debounce = 0;
- mutex_unlock(&info->lock);
-
- if (debounce)
- queue_delayed_work(system_power_efficient_wq,
- &info->micd_detect_work,
- msecs_to_jiffies(debounce));
- else
- arizona_micd_detect(&info->micd_detect_work.work);
-
- return IRQ_HANDLED;
-}
-
-static void arizona_hpdet_work(struct work_struct *work)
-{
- struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- hpdet_work.work);
-
- mutex_lock(&info->lock);
- arizona_start_hpdet_acc_id(info);
- mutex_unlock(&info->lock);
-}
-
-static int arizona_hpdet_wait(struct arizona_extcon_info *info)
-{
- struct arizona *arizona = info->arizona;
- unsigned int val;
- int i, ret;
-
- for (i = 0; i < ARIZONA_HPDET_WAIT_COUNT; i++) {
- ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2,
- &val);
- if (ret) {
- dev_err(arizona->dev,
- "Failed to read HPDET state: %d\n", ret);
- return ret;
- }
-
- switch (info->hpdet_ip_version) {
- case 0:
- if (val & ARIZONA_HP_DONE)
- return 0;
- break;
- default:
- if (val & ARIZONA_HP_DONE_B)
- return 0;
- break;
- }
-
- msleep(ARIZONA_HPDET_WAIT_DELAY_MS);
- }
-
- dev_warn(arizona->dev, "HPDET did not appear to complete\n");
-
- return -ETIMEDOUT;
-}
-
-static irqreturn_t arizona_jackdet(int irq, void *data)
-{
- struct arizona_extcon_info *info = data;
- struct arizona *arizona = info->arizona;
- unsigned int val, present, mask;
- bool cancelled_hp, cancelled_mic;
- int ret, i;
-
- cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work);
- cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work);
-
- pm_runtime_get_sync(info->dev);
-
- mutex_lock(&info->lock);
-
- if (info->micd_clamp) {
- mask = ARIZONA_MICD_CLAMP_STS;
- present = 0;
- } else {
- mask = ARIZONA_JD1_STS;
- if (arizona->pdata.jd_invert)
- present = 0;
- else
- present = ARIZONA_JD1_STS;
- }
-
- ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
- ret);
- mutex_unlock(&info->lock);
- pm_runtime_put_autosuspend(info->dev);
- return IRQ_NONE;
- }
-
- val &= mask;
- if (val == info->last_jackdet) {
- dev_dbg(arizona->dev, "Suppressing duplicate JACKDET\n");
- if (cancelled_hp)
- queue_delayed_work(system_power_efficient_wq,
- &info->hpdet_work,
- msecs_to_jiffies(HPDET_DEBOUNCE));
-
- if (cancelled_mic) {
- int micd_timeout = arizona->pdata.micd_timeout;
-
- queue_delayed_work(system_power_efficient_wq,
- &info->micd_timeout_work,
- msecs_to_jiffies(micd_timeout));
- }
-
- goto out;
- }
- info->last_jackdet = val;
-
- if (info->last_jackdet == present) {
- dev_dbg(arizona->dev, "Detected jack\n");
- ret = extcon_set_state_sync(info->edev,
- EXTCON_MECHANICAL, true);
-
- if (ret != 0)
- dev_err(arizona->dev, "Mechanical report failed: %d\n",
- ret);
-
- info->detecting = true;
- info->mic = false;
- info->jack_flips = 0;
-
- if (!arizona->pdata.hpdet_acc_id) {
- arizona_start_mic(info);
- } else {
- queue_delayed_work(system_power_efficient_wq,
- &info->hpdet_work,
- msecs_to_jiffies(HPDET_DEBOUNCE));
- }
-
- if (info->micd_clamp || !arizona->pdata.jd_invert)
- regmap_update_bits(arizona->regmap,
- ARIZONA_JACK_DETECT_DEBOUNCE,
- ARIZONA_MICD_CLAMP_DB |
- ARIZONA_JD1_DB, 0);
- } else {
- dev_dbg(arizona->dev, "Detected jack removal\n");
-
- arizona_stop_mic(info);
-
- info->num_hpdet_res = 0;
- for (i = 0; i < ARRAY_SIZE(info->hpdet_res); i++)
- info->hpdet_res[i] = 0;
- info->mic = false;
- info->hpdet_done = false;
- info->hpdet_retried = false;
-
- for (i = 0; i < info->num_micd_ranges; i++)
- input_report_key(info->input,
- info->micd_ranges[i].key, 0);
- input_sync(info->input);
-
- for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) {
- ret = extcon_set_state_sync(info->edev,
- arizona_cable[i], false);
- if (ret != 0)
- dev_err(arizona->dev,
- "Removal report failed: %d\n", ret);
- }
-
- /*
- * If the jack was removed during a headphone detection we
- * need to wait for the headphone detection to finish, as
- * it can not be aborted. We don't want to be able to start
- * a new headphone detection from a fresh insert until this
- * one is finished.
- */
- arizona_hpdet_wait(info);
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_JACK_DETECT_DEBOUNCE,
- ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB,
- ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
- }
-
-out:
- /* Clear trig_sts to make sure DCVDD is not forced up */
- regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
- ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
- ARIZONA_MICD_CLAMP_RISE_TRIG_STS |
- ARIZONA_JD1_FALL_TRIG_STS |
- ARIZONA_JD1_RISE_TRIG_STS);
-
- mutex_unlock(&info->lock);
-
- pm_runtime_mark_last_busy(info->dev);
- pm_runtime_put_autosuspend(info->dev);
-
- return IRQ_HANDLED;
-}
-
-/* Map a level onto a slot in the register bank */
-static void arizona_micd_set_level(struct arizona *arizona, int index,
- unsigned int level)
-{
- int reg;
- unsigned int mask;
-
- reg = ARIZONA_MIC_DETECT_LEVEL_4 - (index / 2);
-
- if (!(index % 2)) {
- mask = 0x3f00;
- level <<= 8;
- } else {
- mask = 0x3f;
- }
-
- /* Program the level itself */
- regmap_update_bits(arizona->regmap, reg, mask, level);
-}
-
-static int arizona_extcon_get_micd_configs(struct device *dev,
- struct arizona *arizona)
-{
- const char * const prop = "wlf,micd-configs";
- const int entries_per_config = 3;
- struct arizona_micd_config *micd_configs;
- int nconfs, ret;
- int i, j;
- u32 *vals;
-
- nconfs = device_property_count_u32(arizona->dev, prop);
- if (nconfs <= 0)
- return 0;
-
- vals = kcalloc(nconfs, sizeof(u32), GFP_KERNEL);
- if (!vals)
- return -ENOMEM;
-
- ret = device_property_read_u32_array(arizona->dev, prop, vals, nconfs);
- if (ret < 0)
- goto out;
-
- nconfs /= entries_per_config;
- micd_configs = devm_kcalloc(dev, nconfs, sizeof(*micd_configs),
- GFP_KERNEL);
- if (!micd_configs) {
- ret = -ENOMEM;
- goto out;
- }
-
- for (i = 0, j = 0; i < nconfs; ++i) {
- micd_configs[i].src = vals[j++] ? ARIZONA_ACCDET_SRC : 0;
- micd_configs[i].bias = vals[j++];
- micd_configs[i].gpio = vals[j++];
- }
-
- arizona->pdata.micd_configs = micd_configs;
- arizona->pdata.num_micd_configs = nconfs;
-
-out:
- kfree(vals);
- return ret;
-}
-
-static int arizona_extcon_device_get_pdata(struct device *dev,
- struct arizona *arizona)
-{
- struct arizona_pdata *pdata = &arizona->pdata;
- unsigned int val = ARIZONA_ACCDET_MODE_HPL;
- int ret;
-
- device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
- switch (val) {
- case ARIZONA_ACCDET_MODE_HPL:
- case ARIZONA_ACCDET_MODE_HPR:
- pdata->hpdet_channel = val;
- break;
- default:
- dev_err(arizona->dev,
- "Wrong wlf,hpdet-channel DT value %d\n", val);
- pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
- }
-
- device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
- &pdata->micd_detect_debounce);
-
- device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
- &pdata->micd_bias_start_time);
-
- device_property_read_u32(arizona->dev, "wlf,micd-rate",
- &pdata->micd_rate);
-
- device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
- &pdata->micd_dbtime);
-
- device_property_read_u32(arizona->dev, "wlf,micd-timeout-ms",
- &pdata->micd_timeout);
-
- pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
- "wlf,micd-force-micbias");
-
- pdata->micd_software_compare = device_property_read_bool(arizona->dev,
- "wlf,micd-software-compare");
-
- pdata->jd_invert = device_property_read_bool(arizona->dev,
- "wlf,jd-invert");
-
- device_property_read_u32(arizona->dev, "wlf,gpsw", &pdata->gpsw);
-
- pdata->jd_gpio5 = device_property_read_bool(arizona->dev,
- "wlf,use-jd2");
- pdata->jd_gpio5_nopull = device_property_read_bool(arizona->dev,
- "wlf,use-jd2-nopull");
-
- ret = arizona_extcon_get_micd_configs(dev, arizona);
- if (ret < 0)
- dev_err(arizona->dev, "Failed to read micd configs: %d\n", ret);
-
- return 0;
-}
-
-static int arizona_extcon_probe(struct platform_device *pdev)
-{
- struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
- struct arizona_pdata *pdata = &arizona->pdata;
- struct arizona_extcon_info *info;
- unsigned int val;
- unsigned int clamp_mode;
- int jack_irq_fall, jack_irq_rise;
- int ret, mode, i, j;
-
- if (!arizona->dapm || !arizona->dapm->card)
- return -EPROBE_DEFER;
-
- info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- if (!dev_get_platdata(arizona->dev))
- arizona_extcon_device_get_pdata(&pdev->dev, arizona);
-
- info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
- if (IS_ERR(info->micvdd)) {
- ret = PTR_ERR(info->micvdd);
- dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
- return ret;
- }
-
- mutex_init(&info->lock);
- info->arizona = arizona;
- info->dev = &pdev->dev;
- info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS);
- INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work);
- INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect);
- INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work);
- platform_set_drvdata(pdev, info);
-
- switch (arizona->type) {
- case WM5102:
- switch (arizona->rev) {
- case 0:
- info->micd_reva = true;
- break;
- default:
- info->micd_clamp = true;
- info->hpdet_ip_version = 1;
- break;
- }
- break;
- case WM5110:
- case WM8280:
- switch (arizona->rev) {
- case 0 ... 2:
- break;
- default:
- info->micd_clamp = true;
- info->hpdet_ip_version = 2;
- break;
- }
- break;
- case WM8998:
- case WM1814:
- info->micd_clamp = true;
- info->hpdet_ip_version = 2;
- break;
- default:
- break;
- }
-
- info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable);
- if (IS_ERR(info->edev)) {
- dev_err(&pdev->dev, "failed to allocate extcon device\n");
- return -ENOMEM;
- }
-
- ret = devm_extcon_dev_register(&pdev->dev, info->edev);
- if (ret < 0) {
- dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
- ret);
- return ret;
- }
-
- info->input = devm_input_allocate_device(&pdev->dev);
- if (!info->input) {
- dev_err(arizona->dev, "Can't allocate input dev\n");
- ret = -ENOMEM;
- return ret;
- }
-
- info->input->name = "Headset";
- info->input->phys = "arizona/extcon";
-
- if (!pdata->micd_timeout)
- pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;
-
- if (pdata->num_micd_configs) {
- info->micd_modes = pdata->micd_configs;
- info->micd_num_modes = pdata->num_micd_configs;
- } else {
- info->micd_modes = micd_default_modes;
- info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
- }
-
- if (arizona->pdata.gpsw > 0)
- regmap_update_bits(arizona->regmap, ARIZONA_GP_SWITCH_1,
- ARIZONA_SW1_MODE_MASK, arizona->pdata.gpsw);
-
- if (pdata->micd_pol_gpio > 0) {
- if (info->micd_modes[0].gpio)
- mode = GPIOF_OUT_INIT_HIGH;
- else
- mode = GPIOF_OUT_INIT_LOW;
-
- ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio,
- mode, "MICD polarity");
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
- pdata->micd_pol_gpio, ret);
- return ret;
- }
-
- info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
- } else {
- if (info->micd_modes[0].gpio)
- mode = GPIOD_OUT_HIGH;
- else
- mode = GPIOD_OUT_LOW;
-
- /* We can't use devm here because we need to do the get
- * against the MFD device, as that is where the of_node
- * will reside, but if we devm against that the GPIO
- * will not be freed if the extcon driver is unloaded.
- */
- info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
- "wlf,micd-pol",
- GPIOD_OUT_LOW);
- if (IS_ERR(info->micd_pol_gpio)) {
- ret = PTR_ERR(info->micd_pol_gpio);
- dev_err(arizona->dev,
- "Failed to get microphone polarity GPIO: %d\n",
- ret);
- return ret;
- }
- }
-
- if (arizona->pdata.hpdet_id_gpio > 0) {
- ret = devm_gpio_request_one(&pdev->dev,
- arizona->pdata.hpdet_id_gpio,
- GPIOF_OUT_INIT_LOW,
- "HPDET");
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
- arizona->pdata.hpdet_id_gpio, ret);
- goto err_gpio;
- }
- }
-
- if (arizona->pdata.micd_bias_start_time)
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_BIAS_STARTTIME_MASK,
- arizona->pdata.micd_bias_start_time
- << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
-
- if (arizona->pdata.micd_rate)
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_RATE_MASK,
- arizona->pdata.micd_rate
- << ARIZONA_MICD_RATE_SHIFT);
-
- switch (arizona->pdata.micd_dbtime) {
- case MICD_DBTIME_FOUR_READINGS:
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_DBTIME_MASK,
- ARIZONA_MICD_DBTIME);
- break;
- case MICD_DBTIME_TWO_READINGS:
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_DBTIME_MASK, 0);
- break;
- default:
- break;
- }
-
- BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) <
- ARIZONA_NUM_MICD_BUTTON_LEVELS);
-
- if (arizona->pdata.num_micd_ranges) {
- info->micd_ranges = pdata->micd_ranges;
- info->num_micd_ranges = pdata->num_micd_ranges;
- } else {
- info->micd_ranges = micd_default_ranges;
- info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges);
- }
-
- if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) {
- dev_err(arizona->dev, "Too many MICD ranges: %d\n",
- arizona->pdata.num_micd_ranges);
- }
-
- if (info->num_micd_ranges > 1) {
- for (i = 1; i < info->num_micd_ranges; i++) {
- if (info->micd_ranges[i - 1].max >
- info->micd_ranges[i].max) {
- dev_err(arizona->dev,
- "MICD ranges must be sorted\n");
- ret = -EINVAL;
- goto err_gpio;
- }
- }
- }
-
- /* Disable all buttons by default */
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
- ARIZONA_MICD_LVL_SEL_MASK, 0x81);
-
- /* Set up all the buttons the user specified */
- for (i = 0; i < info->num_micd_ranges; i++) {
- for (j = 0; j < ARIZONA_NUM_MICD_BUTTON_LEVELS; j++)
- if (arizona_micd_levels[j] >= info->micd_ranges[i].max)
- break;
-
- if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) {
- dev_err(arizona->dev, "Unsupported MICD level %d\n",
- info->micd_ranges[i].max);
- ret = -EINVAL;
- goto err_gpio;
- }
-
- dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
- arizona_micd_levels[j], i);
-
- arizona_micd_set_level(arizona, i, j);
- input_set_capability(info->input, EV_KEY,
- info->micd_ranges[i].key);
-
- /* Enable reporting of that range */
- regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2,
- 1 << i, 1 << i);
- }
-
- /* Set all the remaining keys to a maximum */
- for (; i < ARIZONA_MAX_MICD_RANGE; i++)
- arizona_micd_set_level(arizona, i, 0x3f);
-
- /*
- * If we have a clamp use it, activating in conjunction with
- * GPIO5 if that is connected for jack detect operation.
- */
- if (info->micd_clamp) {
- if (arizona->pdata.jd_gpio5) {
- /* Put the GPIO into input mode with optional pull */
- val = 0xc101;
- if (arizona->pdata.jd_gpio5_nopull)
- val &= ~ARIZONA_GPN_PU;
-
- regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
- val);
-
- if (arizona->pdata.jd_invert)
- clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
- else
- clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
- } else {
- if (arizona->pdata.jd_invert)
- clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
- else
- clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
- }
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_MICD_CLAMP_CONTROL,
- ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_JACK_DETECT_DEBOUNCE,
- ARIZONA_MICD_CLAMP_DB,
- ARIZONA_MICD_CLAMP_DB);
- }
-
- arizona_extcon_set_mode(info, 0);
-
- pm_runtime_enable(&pdev->dev);
- pm_runtime_idle(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
- if (info->micd_clamp) {
- jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
- jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
- } else {
- jack_irq_rise = ARIZONA_IRQ_JD_RISE;
- jack_irq_fall = ARIZONA_IRQ_JD_FALL;
- }
-
- ret = arizona_request_irq(arizona, jack_irq_rise,
- "JACKDET rise", arizona_jackdet, info);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
- ret);
- goto err_pm;
- }
-
- ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
- ret);
- goto err_rise;
- }
-
- ret = arizona_request_irq(arizona, jack_irq_fall,
- "JACKDET fall", arizona_jackdet, info);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
- goto err_rise_wake;
- }
-
- ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
- ret);
- goto err_fall;
- }
-
- ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
- "MICDET", arizona_micdet, info);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
- goto err_fall_wake;
- }
-
- ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
- "HPDET", arizona_hpdet_irq, info);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
- goto err_micdet;
- }
-
- arizona_clk32k_enable(arizona);
- regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
- ARIZONA_JD1_DB, ARIZONA_JD1_DB);
- regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
- ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
-
- ret = regulator_allow_bypass(info->micvdd, true);
- if (ret != 0)
- dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
- ret);
-
- ret = input_register_device(info->input);
- if (ret) {
- dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
- goto err_hpdet;
- }
-
- pm_runtime_put(&pdev->dev);
-
- return 0;
-
-err_hpdet:
- arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
-err_micdet:
- arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
-err_fall_wake:
- arizona_set_irq_wake(arizona, jack_irq_fall, 0);
-err_fall:
- arizona_free_irq(arizona, jack_irq_fall, info);
-err_rise_wake:
- arizona_set_irq_wake(arizona, jack_irq_rise, 0);
-err_rise:
- arizona_free_irq(arizona, jack_irq_rise, info);
-err_pm:
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-err_gpio:
- gpiod_put(info->micd_pol_gpio);
- return ret;
-}
-
-static int arizona_extcon_remove(struct platform_device *pdev)
-{
- struct arizona_extcon_info *info = platform_get_drvdata(pdev);
- struct arizona *arizona = info->arizona;
- int jack_irq_rise, jack_irq_fall;
- bool change;
- int ret;
-
- ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
- ARIZONA_MICD_ENA, 0,
- &change);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n",
- ret);
- } else if (change) {
- regulator_disable(info->micvdd);
- pm_runtime_put(info->dev);
- }
-
- gpiod_put(info->micd_pol_gpio);
-
- pm_runtime_disable(&pdev->dev);
-
- regmap_update_bits(arizona->regmap,
- ARIZONA_MICD_CLAMP_CONTROL,
- ARIZONA_MICD_CLAMP_MODE_MASK, 0);
-
- if (info->micd_clamp) {
- jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
- jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
- } else {
- jack_irq_rise = ARIZONA_IRQ_JD_RISE;
- jack_irq_fall = ARIZONA_IRQ_JD_FALL;
- }
-
- arizona_set_irq_wake(arizona, jack_irq_rise, 0);
- arizona_set_irq_wake(arizona, jack_irq_fall, 0);
- arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
- arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
- arizona_free_irq(arizona, jack_irq_rise, info);
- arizona_free_irq(arizona, jack_irq_fall, info);
- cancel_delayed_work_sync(&info->hpdet_work);
- regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
- ARIZONA_JD1_ENA, 0);
- arizona_clk32k_disable(arizona);
-
- return 0;
-}
-
-static struct platform_driver arizona_extcon_driver = {
- .driver = {
- .name = "arizona-extcon",
- },
- .probe = arizona_extcon_probe,
- .remove = arizona_extcon_remove,
-};
-
-module_platform_driver(arizona_extcon_driver);
-
-MODULE_DESCRIPTION("Arizona Extcon driver");
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:extcon-arizona");
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index df3f9bcab581..4b7ee3fa9224 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -927,7 +927,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
}
/* first try to find a slot in an existing linked list entry */
- for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
+ for (prsv = efi_memreserve_root->next; prsv; ) {
rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
if (index < rsv->size) {
@@ -937,6 +937,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
memunmap(rsv);
return efi_mem_reserve_iomem(addr, size);
}
+ prsv = rsv->next;
memunmap(rsv);
}
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index b69d63143e0d..7bf0a7acae5e 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -24,7 +24,7 @@ efi_status_t check_platform_features(void)
return EFI_SUCCESS;
tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
- if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
+ if (tg < ID_AA64MMFR0_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_TGRAN_SUPPORTED_MAX) {
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
efi_err("This 64 KB granular kernel is not supported by your CPU\n");
else
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index ec2f3985bef3..26e69788f27a 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -96,6 +96,18 @@ static void install_memreserve_table(void)
efi_err("Failed to install memreserve config table!\n");
}
+static u32 get_supported_rt_services(void)
+{
+ const efi_rt_properties_table_t *rt_prop_table;
+ u32 supported = EFI_RT_SUPPORTED_ALL;
+
+ rt_prop_table = get_efi_config_table(EFI_RT_PROPERTIES_TABLE_GUID);
+ if (rt_prop_table)
+ supported &= rt_prop_table->runtime_services_supported;
+
+ return supported;
+}
+
/*
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
* that is described in the PE/COFF header. Most of the code is the same
@@ -250,6 +262,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
(prop_tbl->memory_protection_attribute &
EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
+ /* force efi_novamap if SetVirtualAddressMap() is unsupported */
+ efi_novamap |= !(get_supported_rt_services() &
+ EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP);
+
/* hibernation expects the runtime regions to stay in the same place */
if (!IS_ENABLED(CONFIG_HIBERNATION) && !efi_nokaslr && !flat_va_mapping) {
/*
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 41c1d00bf933..abdc8a6a3963 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -485,6 +485,10 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
}
break;
+ case EFI_UNSUPPORTED:
+ err = -EOPNOTSUPP;
+ status = EFI_NOT_FOUND;
+ break;
case EFI_NOT_FOUND:
break;
default:
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e3607ec4c2e8..d3b3de514f6e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1105,6 +1105,16 @@ config GPIO_BD70528
This driver can also be built as a module. If so, the module
will be called gpio-bd70528.
+config GPIO_BD71815
+ tristate "ROHM BD71815 PMIC GPIO support"
+ depends on MFD_ROHM_BD71828
+ help
+ Support for GPO(s) on ROHM BD71815 PMIC. There are two GPOs
+ available on the ROHM PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called gpio-bd71815.
+
config GPIO_BD71828
tristate "ROHM BD71828 GPIO support"
depends on MFD_ROHM_BD71828
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c58a90a3c3b1..4c12f31db31f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
+obj-$(CONFIG_GPIO_BD71815) += gpio-bd71815.o
obj-$(CONFIG_GPIO_BD71828) += gpio-bd71828.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
diff --git a/drivers/gpio/gpio-bd71815.c b/drivers/gpio/gpio-bd71815.c
new file mode 100644
index 000000000000..08ff2857256f
--- /dev/null
+++ b/drivers/gpio/gpio-bd71815.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support to GPOs on ROHM BD71815
+ * Copyright 2021 ROHM Semiconductors.
+ * Author: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
+ *
+ * Copyright 2014 Embest Technology Co. Ltd. Inc.
+ * Author: yanglsh@embest-tech.com
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+/* For the BD71815 register definitions */
+#include <linux/mfd/rohm-bd71815.h>
+
+struct bd71815_gpio {
+ /* chip.parent points the MFD which provides DT node and regmap */
+ struct gpio_chip chip;
+ /* dev points to the platform device for devm and prints */
+ struct device *dev;
+ struct regmap *regmap;
+};
+
+static int bd71815gpo_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
+ int ret, val;
+
+ ret = regmap_read(bd71815->regmap, BD71815_REG_GPO, &val);
+ if (ret)
+ return ret;
+
+ return (val >> offset) & 1;
+}
+
+static void bd71815gpo_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct bd71815_gpio *bd71815 = gpiochip_get_data(chip);
+ int ret, bit;
+
+ bit = BIT(offset);
+
+ if (value)
+ ret = regmap_set_bits(bd71815->regmap, BD71815_REG_GPO, bit);
+ else
+ ret = regmap_clear_bits(bd71815->regmap, BD71815_REG_GPO, bit);
+
+ if (ret)
+ dev_warn(bd71815->dev, "failed to toggle GPO\n");
+}
+
+static int bd71815_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ struct bd71815_gpio *bdgpio = gpiochip_get_data(chip);
+
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ return regmap_update_bits(bdgpio->regmap,
+ BD71815_REG_GPO,
+ BD71815_GPIO_DRIVE_MASK << offset,
+ BD71815_GPIO_OPEN_DRAIN << offset);
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return regmap_update_bits(bdgpio->regmap,
+ BD71815_REG_GPO,
+ BD71815_GPIO_DRIVE_MASK << offset,
+ BD71815_GPIO_CMOS << offset);
+ default:
+ break;
+ }
+ return -ENOTSUPP;
+}
+
+/* BD71815 GPIO is actually GPO */
+static int bd71815gpo_direction_get(struct gpio_chip *gc, unsigned int offset)
+{
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+/* Template for GPIO chip */
+static const struct gpio_chip bd71815gpo_chip = {
+ .label = "bd71815",
+ .owner = THIS_MODULE,
+ .get = bd71815gpo_get,
+ .get_direction = bd71815gpo_direction_get,
+ .set = bd71815gpo_set,
+ .set_config = bd71815_gpio_set_config,
+ .can_sleep = true,
+};
+
+#define BD71815_TWO_GPIOS GENMASK(1, 0)
+#define BD71815_ONE_GPIO BIT(0)
+
+/*
+ * Sigh. The BD71815 and BD71817 were originally designed to support two GPO
+ * pins. At some point it was noticed the second GPO pin which is the E5 pin
+ * located at the center of IC is hard to use on PCB (due to the location). It
+ * was decided to not promote this second GPO and the pin is marked as GND in
+ * the datasheet. The functionality is still there though! I guess driving a GPO
+ * connected to the ground is a bad idea. Thus we do not support it by default.
+ * OTOH - the original driver written by colleagues at Embest did support
+ * controlling this second GPO. It is thus possible this is used in some of the
+ * products.
+ *
+ * This driver does not by default support configuring this second GPO
+ * but allows using it by providing the DT property
+ * "rohm,enable-hidden-gpo".
+ */
+static int bd71815_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ if (ngpios != 2)
+ return 0;
+
+ if (gc->parent && device_property_present(gc->parent,
+ "rohm,enable-hidden-gpo"))
+ *valid_mask = BD71815_TWO_GPIOS;
+ else
+ *valid_mask = BD71815_ONE_GPIO;
+
+ return 0;
+}
+
+static int gpo_bd71815_probe(struct platform_device *pdev)
+{
+ struct bd71815_gpio *g;
+ struct device *parent, *dev;
+
+ /*
+ * Bind devm lifetime to this platform device => use dev for devm.
+ * also the prints should originate from this device.
+ */
+ dev = &pdev->dev;
+ /* The device-tree and regmap come from MFD => use parent for that */
+ parent = dev->parent;
+
+ g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
+ if (!g)
+ return -ENOMEM;
+
+ g->chip = bd71815gpo_chip;
+
+ /*
+ * FIXME: As writing of this the sysfs interface for GPIO control does
+ * not respect the valid_mask. Do not trust it but rather set the ngpios
+ * to 1 if "rohm,enable-hidden-gpo" is not given.
+ *
+ * This check can be removed later if the sysfs export is fixed and
+ * if the fix is backported.
+ *
+ * For now it is safest to just set the ngpios though.
+ */
+ if (device_property_present(parent, "rohm,enable-hidden-gpo"))
+ g->chip.ngpio = 2;
+ else
+ g->chip.ngpio = 1;
+
+ g->chip.init_valid_mask = bd71815_init_valid_mask;
+ g->chip.base = -1;
+ g->chip.parent = parent;
+ g->regmap = dev_get_regmap(parent, NULL);
+ g->dev = dev;
+
+ return devm_gpiochip_add_data(dev, &g->chip, g);
+}
+
+static struct platform_driver gpo_bd71815_driver = {
+ .driver = {
+ .name = "bd71815-gpo",
+ },
+ .probe = gpo_bd71815_probe,
+};
+module_platform_driver(gpo_bd71815_driver);
+
+MODULE_ALIAS("platform:bd71815-gpo");
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_AUTHOR("Peter Yang <yanglsh@embest-tech.com>");
+MODULE_DESCRIPTION("GPO interface for BD71815");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 5ea09fd01544..c91d05651596 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -113,8 +113,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);
#ifdef CONFIG_GPIO_PCA953X_IRQ
#include <linux/dmi.h>
-#include <linux/gpio.h>
-#include <linux/list.h>
+
+static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true };
+
+static const struct acpi_gpio_mapping pca953x_acpi_irq_gpios[] = {
+ { "irq-gpios", &pca953x_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER },
+ { }
+};
+
+static int pca953x_acpi_get_irq(struct device *dev)
+{
+ int ret;
+
+ ret = devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_irq_gpios);
+ if (ret)
+ dev_warn(dev, "can't add GPIO ACPI mapping\n");
+
+ ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0);
+ if (ret < 0)
+ return ret;
+
+ dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret);
+ return ret;
+}
static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
{
@@ -133,59 +154,6 @@ static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
},
{}
};
-
-#ifdef CONFIG_ACPI
-static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
-{
- struct acpi_resource_gpio *agpio;
- int *pin = data;
-
- if (acpi_gpio_get_irq_resource(ares, &agpio))
- *pin = agpio->pin_table[0];
- return 1;
-}
-
-static int pca953x_acpi_find_pin(struct device *dev)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
- int pin = -ENOENT, ret;
- LIST_HEAD(r);
-
- ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
- acpi_dev_free_resource_list(&r);
- if (ret < 0)
- return ret;
-
- return pin;
-}
-#else
-static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
-#endif
-
-static int pca953x_acpi_get_irq(struct device *dev)
-{
- int pin, ret;
-
- pin = pca953x_acpi_find_pin(dev);
- if (pin < 0)
- return pin;
-
- dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);
-
- if (!gpio_is_valid(pin))
- return -EINVAL;
-
- ret = gpio_request(pin, "pca953x interrupt");
- if (ret)
- return ret;
-
- ret = gpio_to_irq(pin);
-
- /* When pin is used as an IRQ, no need to keep it requested */
- gpio_free(pin);
-
- return ret;
-}
#endif
static const struct acpi_device_id pca953x_acpi_ids[] = {
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index e37a57d0a2f0..1aacd2a5a1fd 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -174,7 +174,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
int ret, value;
ret = request_threaded_irq(event->irq, NULL, event->handler,
- event->irqflags, "ACPI:Event", event);
+ event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
if (ret) {
dev_err(acpi_gpio->chip->parent,
"Failed to setup interrupt handler for %d\n",
@@ -677,6 +677,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (!lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
+ struct gpio_desc *desc;
u16 pin_index;
if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
@@ -689,8 +690,12 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (pin_index >= agpio->pin_table_length)
return 1;
- lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
+ if (lookup->info.quirks & ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER)
+ desc = gpio_to_desc(agpio->pin_table[pin_index]);
+ else
+ desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]);
+ lookup->desc = desc;
lookup->info.pin_config = agpio->pin_config;
lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint;
@@ -940,8 +945,9 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
}
/**
- * acpi_dev_gpio_irq_get() - Find GpioInt and translate it to Linux IRQ number
+ * acpi_dev_gpio_irq_get_by() - Find GpioInt and translate it to Linux IRQ number
* @adev: pointer to a ACPI device to get IRQ from
+ * @name: optional name of GpioInt resource
* @index: index of GpioInt resource (starting from %0)
*
* If the device has one or more GpioInt resources, this function can be
@@ -951,9 +957,12 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
* The function is idempotent, though each time it runs it will configure GPIO
* pin direction according to the flags in GpioInt resource.
*
+ * The function takes optional @name parameter. If the resource has a property
+ * name, then only those will be taken into account.
+ *
* Return: Linux IRQ number (> %0) on success, negative errno on failure.
*/
-int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
+int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)
{
int idx, i;
unsigned int irq_flags;
@@ -963,7 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
struct acpi_gpio_info info;
struct gpio_desc *desc;
- desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
+ desc = acpi_get_gpiod_by_index(adev, name, i, &info);
/* Ignore -EPROBE_DEFER, it only matters if idx matches */
if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
@@ -1008,7 +1017,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
}
return -ENOENT;
}
-EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
+EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);
static acpi_status
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index adf55db080d8..6367646dce83 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -367,22 +367,18 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
*
* Looks for device property "gpio-line-names" and if it exists assigns
* GPIO line names for the chip. The memory allocated for the assigned
- * names belong to the underlying software node and should not be released
+ * names belong to the underlying firmware node and should not be released
* by the caller.
*/
static int devprop_gpiochip_set_names(struct gpio_chip *chip)
{
struct gpio_device *gdev = chip->gpiodev;
- struct device *dev = chip->parent;
+ struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
const char **names;
int ret, i;
int count;
- /* GPIO chip may not have a parent device whose properties we inspect. */
- if (!dev)
- return 0;
-
- count = device_property_string_array_count(dev, "gpio-line-names");
+ count = fwnode_property_string_array_count(fwnode, "gpio-line-names");
if (count < 0)
return 0;
@@ -396,7 +392,7 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
if (!names)
return -ENOMEM;
- ret = device_property_read_string_array(dev, "gpio-line-names",
+ ret = fwnode_property_read_string_array(fwnode, "gpio-line-names",
names, count);
if (ret < 0) {
dev_warn(&gdev->dev, "failed to read GPIO line names\n");
@@ -474,9 +470,13 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
static void gpiodevice_release(struct device *dev)
{
- struct gpio_device *gdev = dev_get_drvdata(dev);
+ struct gpio_device *gdev = container_of(dev, struct gpio_device, dev);
+ unsigned long flags;
+ spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
ida_free(&gpio_ida, gdev->id);
kfree_const(gdev->label);
kfree(gdev->descs);
@@ -571,6 +571,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
+ struct fwnode_handle *fwnode = gc->parent ? dev_fwnode(gc->parent) : NULL;
unsigned long flags;
int ret = 0;
unsigned i;
@@ -594,6 +595,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
of_gpio_dev_init(gc, gdev);
+ /*
+ * Assign fwnode depending on the result of the previous calls,
+ * if none of them succeed, assign it to the parent's one.
+ */
+ gdev->dev.fwnode = dev_fwnode(&gdev->dev) ?: fwnode;
+
gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL);
if (gdev->id < 0) {
ret = gdev->id;
@@ -605,7 +612,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
goto err_free_ida;
device_initialize(&gdev->dev);
- dev_set_drvdata(&gdev->dev, gdev);
if (gc->parent && gc->parent->driver)
gdev->owner = gc->parent->driver->owner;
else if (gc->owner)
@@ -4257,7 +4263,8 @@ static int __init gpiolib_dev_init(void)
return ret;
}
- if (driver_register(&gpio_stub_drv) < 0) {
+ ret = driver_register(&gpio_stub_drv);
+ if (ret < 0) {
pr_err("gpiolib: could not register GPIO stub driver\n");
bus_unregister(&gpio_bus_type);
return ret;
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index e392a90ca687..85b79a7fee63 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -228,6 +228,7 @@ source "drivers/gpu/drm/arm/Kconfig"
config DRM_RADEON
tristate "ATI Radeon"
depends on DRM && PCI && MMU
+ depends on AGP || !AGP
select FW_LOADER
select DRM_KMS_HELPER
select DRM_TTM
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index b6879d97c9c9..49267eb64302 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -180,6 +180,7 @@ extern uint amdgpu_smu_memory_pool_size;
extern uint amdgpu_dc_feature_mask;
extern uint amdgpu_dc_debug_mask;
extern uint amdgpu_dm_abm_level;
+extern int amdgpu_backlight;
extern struct amdgpu_mgpu_info mgpu_info;
extern int amdgpu_ras_enable;
extern uint amdgpu_ras_mask;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 36a741d63ddc..2e9b16fb3fcd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -903,7 +903,7 @@ void amdgpu_acpi_fini(struct amdgpu_device *adev)
*/
bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
{
-#if defined(CONFIG_AMD_PMC)
+#if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE)
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
if (adev->flags & AMD_IS_APU)
return true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 4575192d9b08..b26e2fd1c538 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -781,6 +781,10 @@ uint amdgpu_dm_abm_level;
MODULE_PARM_DESC(abmlevel, "ABM level (0 = off (default), 1-4 = backlight reduction level) ");
module_param_named(abmlevel, amdgpu_dm_abm_level, uint, 0444);
+int amdgpu_backlight = -1;
+MODULE_PARM_DESC(backlight, "Backlight control (0 = pwm, 1 = aux, -1 auto (default))");
+module_param_named(backlight, amdgpu_backlight, bint, 0444);
+
/**
* DOC: tmz (int)
* Trusted Memory Zone (TMZ) is a method to protect data being written
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 51cd49c6f38f..24010cacf7d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -146,7 +146,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
size = mode_cmd->pitches[0] * height;
aligned_size = ALIGN(size, PAGE_SIZE);
ret = amdgpu_gem_object_create(adev, aligned_size, 0, domain, flags,
- ttm_bo_type_kernel, NULL, &gobj);
+ ttm_bo_type_device, NULL, &gobj);
if (ret) {
pr_err("failed to allocate framebuffer (%d)\n", aligned_size);
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 3e1fd1e7d09f..573cf17262da 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2267,6 +2267,11 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->ext_caps->bits.hdr_aux_backlight_control == 1)
caps->aux_support = true;
+ if (amdgpu_backlight == 0)
+ caps->aux_support = false;
+ else if (amdgpu_backlight == 1)
+ caps->aux_support = true;
+
/* From the specification (CTA-861-G), for calculating the maximum
* luminance we need to use:
* Luminance = 50*2**(CV/32)
@@ -3185,19 +3190,6 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
#endif
}
-static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness)
-{
- bool rc;
-
- if (!link)
- return 1;
-
- rc = dc_link_set_backlight_level_nits(link, true, brightness,
- AUX_BL_DEFAULT_TRANSITION_TIME_MS);
-
- return rc ? 0 : 1;
-}
-
static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
unsigned *min, unsigned *max)
{
@@ -3260,9 +3252,10 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
brightness = convert_brightness_from_user(&caps, bd->props.brightness);
// Change brightness based on AUX property
if (caps.aux_support)
- return set_backlight_via_aux(link, brightness);
-
- rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0);
+ rc = dc_link_set_backlight_level_nits(link, true, brightness,
+ AUX_BL_DEFAULT_TRANSITION_TIME_MS);
+ else
+ rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0);
return rc ? 0 : 1;
}
@@ -3270,11 +3263,27 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
{
struct amdgpu_display_manager *dm = bl_get_data(bd);
- int ret = dc_link_get_backlight_level(dm->backlight_link);
+ struct amdgpu_dm_backlight_caps caps;
+
+ amdgpu_dm_update_backlight_caps(dm);
+ caps = dm->backlight_caps;
+
+ if (caps.aux_support) {
+ struct dc_link *link = (struct dc_link *)dm->backlight_link;
+ u32 avg, peak;
+ bool rc;
- if (ret == DC_ERROR_UNEXPECTED)
- return bd->props.brightness;
- return convert_brightness_to_user(&dm->backlight_caps, ret);
+ rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
+ if (!rc)
+ return bd->props.brightness;
+ return convert_brightness_to_user(&caps, avg);
+ } else {
+ int ret = dc_link_get_backlight_level(dm->backlight_link);
+
+ if (ret == DC_ERROR_UNEXPECTED)
+ return bd->props.brightness;
+ return convert_brightness_to_user(&caps, ret);
+ }
}
static const struct backlight_ops amdgpu_dm_backlight_ops = {
@@ -4716,6 +4725,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
dc_plane_state->global_alpha_value = plane_info.global_alpha_value;
dc_plane_state->dcc = plane_info.dcc;
dc_plane_state->layer_index = plane_info.layer_index; // Always returns 0
+ dc_plane_state->flip_int_enabled = true;
/*
* Always set input transfer function, since plane state is refreshed
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index fa5059f71727..bd0101013ec8 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -2602,7 +2602,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
if (pipe_ctx->plane_state == NULL)
frame_ramp = 0;
} else {
- ASSERT(false);
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 4eee3a55fa30..18ed0d3f247e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -887,6 +887,7 @@ struct dc_plane_state {
int layer_index;
union surface_update_flags update_flags;
+ bool flip_int_enabled;
/* private to DC core */
struct dc_plane_status status;
struct dc_context *ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
index 9e796dfeac20..714c71a5fbde 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
@@ -1257,6 +1257,16 @@ void hubp1_soft_reset(struct hubp *hubp, bool reset)
REG_UPDATE(DCHUBP_CNTL, HUBP_DISABLE, reset ? 1 : 0);
}
+void hubp1_set_flip_int(struct hubp *hubp)
+{
+ struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
+
+ REG_UPDATE(DCSURF_SURFACE_FLIP_INTERRUPT,
+ SURFACE_FLIP_INT_MASK, 1);
+
+ return;
+}
+
void hubp1_init(struct hubp *hubp)
{
//do nothing
@@ -1290,6 +1300,7 @@ static const struct hubp_funcs dcn10_hubp_funcs = {
.dmdata_load = NULL,
.hubp_soft_reset = hubp1_soft_reset,
.hubp_in_blank = hubp1_in_blank,
+ .hubp_set_flip_int = hubp1_set_flip_int,
};
/*****************************************/
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
index a9a6ed7f4f99..e2f2f6995935 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
@@ -74,6 +74,7 @@
SRI(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id),\
SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id),\
SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\
+ SRI(DCSURF_SURFACE_FLIP_INTERRUPT, HUBPREQ, id),\
SRI(HUBPRET_CONTROL, HUBPRET, id),\
SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\
SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\
@@ -183,6 +184,7 @@
uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; \
uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; \
uint32_t DCSURF_SURFACE_CONTROL; \
+ uint32_t DCSURF_SURFACE_FLIP_INTERRUPT; \
uint32_t HUBPRET_CONTROL; \
uint32_t DCN_EXPANSION_MODE; \
uint32_t DCHUBP_REQ_SIZE_CONFIG; \
@@ -332,6 +334,7 @@
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_META_SURFACE_TMZ_C, mask_sh),\
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_EN, mask_sh),\
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\
@@ -531,6 +534,7 @@
type PRIMARY_SURFACE_DCC_IND_64B_BLK;\
type SECONDARY_SURFACE_DCC_EN;\
type SECONDARY_SURFACE_DCC_IND_64B_BLK;\
+ type SURFACE_FLIP_INT_MASK;\
type DET_BUF_PLANE1_BASE_ADDRESS;\
type CROSSBAR_SRC_CB_B;\
type CROSSBAR_SRC_CR_R;\
@@ -777,4 +781,6 @@ void hubp1_read_state_common(struct hubp *hubp);
bool hubp1_in_blank(struct hubp *hubp);
void hubp1_soft_reset(struct hubp *hubp, bool reset);
+void hubp1_set_flip_int(struct hubp *hubp);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 89912bb5014f..9ba5c624770d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -2196,6 +2196,13 @@ static void dcn10_enable_plane(
if (dc->debug.sanity_checks) {
hws->funcs.verify_allow_pstate_change_high(dc);
}
+
+ if (!pipe_ctx->top_pipe
+ && pipe_ctx->plane_state
+ && pipe_ctx->plane_state->flip_int_enabled
+ && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
+ pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
+
}
void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
index 0df0da2e6a4d..bec7059f6d5d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
@@ -1597,6 +1597,7 @@ static struct hubp_funcs dcn20_hubp_funcs = {
.validate_dml_output = hubp2_validate_dml_output,
.hubp_in_blank = hubp1_in_blank,
.hubp_soft_reset = hubp1_soft_reset,
+ .hubp_set_flip_int = hubp1_set_flip_int,
};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index 0726fb435e2a..aece1103331d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1146,6 +1146,12 @@ void dcn20_enable_plane(
pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
}
+ if (!pipe_ctx->top_pipe
+ && pipe_ctx->plane_state
+ && pipe_ctx->plane_state->flip_int_enabled
+ && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
+ pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
+
// if (dc->debug.sanity_checks) {
// dcn10_verify_allow_pstate_change_high(dc);
// }
@@ -1501,38 +1507,8 @@ static void dcn20_update_dchubp_dpp(
if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
|| pipe_ctx->stream->update_flags.bits.gamut_remap
|| pipe_ctx->stream->update_flags.bits.out_csc) {
- struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
-
- if (mpc->funcs->set_gamut_remap) {
- int i;
- int mpcc_id = hubp->inst;
- struct mpc_grph_gamut_adjustment adjust;
- bool enable_remap_dpp = false;
-
- memset(&adjust, 0, sizeof(adjust));
- adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
-
- /* save the enablement of gamut remap for dpp */
- enable_remap_dpp = pipe_ctx->stream->gamut_remap_matrix.enable_remap;
-
- /* force bypass gamut remap for dpp/cm */
- pipe_ctx->stream->gamut_remap_matrix.enable_remap = false;
- dc->hwss.program_gamut_remap(pipe_ctx);
-
- /* restore gamut remap flag and use this remap into mpc */
- pipe_ctx->stream->gamut_remap_matrix.enable_remap = enable_remap_dpp;
-
- /* build remap matrix for top plane if enabled */
- if (enable_remap_dpp && pipe_ctx->top_pipe == NULL) {
- adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
- for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
- adjust.temperature_matrix[i] =
- pipe_ctx->stream->gamut_remap_matrix.matrix[i];
- }
- mpc->funcs->set_gamut_remap(mpc, mpcc_id, &adjust);
- } else
- /* dpp/cm gamut remap*/
- dc->hwss.program_gamut_remap(pipe_ctx);
+ /* dpp/cm gamut remap*/
+ dc->hwss.program_gamut_remap(pipe_ctx);
/*call the dcn2 method which uses mpc csc*/
dc->hwss.program_output_csc(dc,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
index f9045852728f..b0c9180b808f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -838,6 +838,7 @@ static struct hubp_funcs dcn21_hubp_funcs = {
.hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
.hubp_init = hubp21_init,
.validate_dml_output = hubp21_validate_dml_output,
+ .hubp_set_flip_int = hubp1_set_flip_int,
};
bool hubp21_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index 072f8c880924..4a3df13c9e49 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -296,7 +296,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
.num_banks = 8,
.num_chans = 4,
.vmm_page_size_bytes = 4096,
- .dram_clock_change_latency_us = 11.72,
+ .dram_clock_change_latency_us = 23.84,
.return_bus_width_bytes = 64,
.dispclk_dppclk_vco_speed_mhz = 3600,
.xfc_bus_transport_time_us = 4,
@@ -1062,8 +1062,6 @@ static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s
{
int i;
- DC_FP_START();
-
if (dc->bb_overrides.sr_exit_time_ns) {
for (i = 0; i < WM_SET_COUNT; i++) {
dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
@@ -1088,8 +1086,6 @@ static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s
dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
}
}
-
- DC_FP_END();
}
void dcn21_calculate_wm(
@@ -1339,7 +1335,7 @@ static noinline bool dcn21_validate_bandwidth_fp(struct dc *dc,
int vlevel = 0;
int pipe_split_from[MAX_PIPES];
int pipe_cnt = 0;
- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+ display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
DC_LOGGER_INIT(dc->ctx->logger);
BW_VAL_TRACE_COUNT();
@@ -1599,6 +1595,11 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
dcn2_1_soc.num_chans = bw_params->num_channels;
ASSERT(clk_table->num_entries);
+ /* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */
+ for (i = 0; i < dcn2_1_soc.num_states + 1; i++) {
+ clock_limits[i] = dcn2_1_soc.clock_limits[i];
+ }
+
for (i = 0; i < clk_table->num_entries; i++) {
/* loop backwards*/
for (closest_clk_lvl = 0, j = dcn2_1_soc.num_states - 1; j >= 0; j--) {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index 41a1d0e9b7e2..e0df9b0065f9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -113,6 +113,7 @@ bool cm3_helper_translate_curve_to_hw_format(
struct pwl_result_data *rgb_resulted;
struct pwl_result_data *rgb;
struct pwl_result_data *rgb_plus_1;
+ struct pwl_result_data *rgb_minus_1;
struct fixed31_32 end_value;
int32_t region_start, region_end;
@@ -140,7 +141,7 @@ bool cm3_helper_translate_curve_to_hw_format(
region_start = -MAX_LOW_POINT;
region_end = NUMBER_REGIONS - MAX_LOW_POINT;
} else {
- /* 10 segments
+ /* 11 segments
* segment is from 2^-10 to 2^0
* There are less than 256 points, for optimization
*/
@@ -154,9 +155,10 @@ bool cm3_helper_translate_curve_to_hw_format(
seg_distr[7] = 4;
seg_distr[8] = 4;
seg_distr[9] = 4;
+ seg_distr[10] = 1;
region_start = -10;
- region_end = 0;
+ region_end = 1;
}
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
@@ -189,6 +191,10 @@ bool cm3_helper_translate_curve_to_hw_format(
rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
+ rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
+ rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
+ rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
+
// All 3 color channels have same x
corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
dc_fixpt_from_int(region_start));
@@ -259,15 +265,18 @@ bool cm3_helper_translate_curve_to_hw_format(
rgb = rgb_resulted;
rgb_plus_1 = rgb_resulted + 1;
+ rgb_minus_1 = rgb;
i = 1;
while (i != hw_points + 1) {
- if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
- rgb_plus_1->red = rgb->red;
- if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
- rgb_plus_1->green = rgb->green;
- if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
- rgb_plus_1->blue = rgb->blue;
+ if (i >= hw_points - 1) {
+ if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
+ rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
+ if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
+ rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
+ if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
+ rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
+ }
rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
@@ -283,6 +292,7 @@ bool cm3_helper_translate_curve_to_hw_format(
}
++rgb_plus_1;
+ rgb_minus_1 = rgb;
++rgb;
++i;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
index 88ffa9ff1ed1..f24612523248 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c
@@ -511,6 +511,7 @@ static struct hubp_funcs dcn30_hubp_funcs = {
.hubp_init = hubp3_init,
.hubp_in_blank = hubp1_in_blank,
.hubp_soft_reset = hubp1_soft_reset,
+ .hubp_set_flip_int = hubp1_set_flip_int,
};
bool hubp3_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index 8d0f663489ac..fb7f1dea3c46 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -2508,6 +2508,19 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
};
+#define CTX ctx
+
+#define REG(reg_name) \
+ (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
+
+static uint32_t read_pipe_fuses(struct dc_context *ctx)
+{
+ uint32_t value = REG_READ(CC_DC_PIPE_DIS);
+ /* Support for max 6 pipes */
+ value = value & 0x3f;
+ return value;
+}
+
static bool dcn30_resource_construct(
uint8_t num_virtual_links,
struct dc *dc,
@@ -2517,6 +2530,15 @@ static bool dcn30_resource_construct(
struct dc_context *ctx = dc->ctx;
struct irq_service_init_data init_data;
struct ddc_service_init_data ddc_init_data;
+ uint32_t pipe_fuses = read_pipe_fuses(ctx);
+ uint32_t num_pipes = 0;
+
+ if (!(pipe_fuses == 0 || pipe_fuses == 0x3e)) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: Unexpected fuse recipe for navi2x !\n");
+ /* fault to single pipe */
+ pipe_fuses = 0x3e;
+ }
DC_FP_START();
@@ -2650,6 +2672,15 @@ static bool dcn30_resource_construct(
/* PP Lib and SMU interfaces */
init_soc_bounding_box(dc, pool);
+ num_pipes = dcn3_0_ip.max_num_dpp;
+
+ for (i = 0; i < dcn3_0_ip.max_num_dpp; i++)
+ if (pipe_fuses & 1 << i)
+ num_pipes--;
+
+ dcn3_0_ip.max_num_dpp = num_pipes;
+ dcn3_0_ip.max_num_otg = num_pipes;
+
dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30);
/* IRQ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
index 5d4b2c60192e..c494235016e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -1619,12 +1619,106 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
}
+static void calculate_wm_set_for_vlevel(
+ int vlevel,
+ struct wm_range_table_entry *table_entry,
+ struct dcn_watermarks *wm_set,
+ struct display_mode_lib *dml,
+ display_e2e_pipe_params_st *pipes,
+ int pipe_cnt)
+{
+ double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
+
+ ASSERT(vlevel < dml->soc.num_states);
+ /* only pipe 0 is read for voltage and dcf/soc clocks */
+ pipes[0].clks_cfg.voltage = vlevel;
+ pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
+ pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
+
+ dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
+ dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
+ dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
+
+ wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
+ wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
+ wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
+ wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
+ wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
+ wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
+ wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
+ wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
+ dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
+
+}
+
+static void dcn301_calculate_wm_and_dlg(
+ struct dc *dc, struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ int pipe_cnt,
+ int vlevel_req)
+{
+ int i, pipe_idx;
+ int vlevel, vlevel_max;
+ struct wm_range_table_entry *table_entry;
+ struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
+
+ ASSERT(bw_params);
+
+ vlevel_max = bw_params->clk_table.num_entries - 1;
+
+ /* WM Set D */
+ table_entry = &bw_params->wm_table.entries[WM_D];
+ if (table_entry->wm_type == WM_TYPE_RETRAINING)
+ vlevel = 0;
+ else
+ vlevel = vlevel_max;
+ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
+ &context->bw_ctx.dml, pipes, pipe_cnt);
+ /* WM Set C */
+ table_entry = &bw_params->wm_table.entries[WM_C];
+ vlevel = min(max(vlevel_req, 2), vlevel_max);
+ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
+ &context->bw_ctx.dml, pipes, pipe_cnt);
+ /* WM Set B */
+ table_entry = &bw_params->wm_table.entries[WM_B];
+ vlevel = min(max(vlevel_req, 1), vlevel_max);
+ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
+ &context->bw_ctx.dml, pipes, pipe_cnt);
+
+ /* WM Set A */
+ table_entry = &bw_params->wm_table.entries[WM_A];
+ vlevel = min(vlevel_req, vlevel_max);
+ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
+ &context->bw_ctx.dml, pipes, pipe_cnt);
+
+ for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!context->res_ctx.pipe_ctx[i].stream)
+ continue;
+
+ pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
+ pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
+
+ if (dc->config.forced_clocks) {
+ pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
+ pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
+ }
+ if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
+ pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
+ if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
+ pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
+
+ pipe_idx++;
+ }
+
+ dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
+}
+
static struct resource_funcs dcn301_res_pool_funcs = {
.destroy = dcn301_destroy_resource_pool,
.link_enc_create = dcn301_link_encoder_create,
.panel_cntl_create = dcn301_panel_cntl_create,
.validate_bandwidth = dcn30_validate_bandwidth,
- .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,
+ .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg,
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index 22f3f643ed1b..346dcd87dc10 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -191,6 +191,8 @@ struct hubp_funcs {
bool (*hubp_in_blank)(struct hubp *hubp);
void (*hubp_soft_reset)(struct hubp *hubp, bool reset);
+ void (*hubp_set_flip_int)(struct hubp *hubp);
+
};
#endif
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index c57dc9ae81f2..a2681fe875ed 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -5216,10 +5216,10 @@ static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
for (j = 0; j < dep_sclk_table->count; j++) {
valid_entry = false;
for (k = 0; k < watermarks->num_wm_sets; k++) {
- if (dep_sclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz &&
- dep_sclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz &&
- dep_mclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz &&
- dep_mclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz) {
+ if (dep_sclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz / 10 &&
+ dep_sclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz / 10 &&
+ dep_mclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz / 10 &&
+ dep_mclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz / 10) {
valid_entry = true;
table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
break;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
index 29c99642d22d..22b636e2b89b 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
@@ -1505,6 +1505,48 @@ static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
return 0;
}
+static int vega10_override_pcie_parameters(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+ struct vega10_hwmgr *data =
+ (struct vega10_hwmgr *)(hwmgr->backend);
+ uint32_t pcie_gen = 0, pcie_width = 0;
+ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+ int i;
+
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+ pcie_gen = 3;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+ pcie_gen = 2;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
+ pcie_gen = 1;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
+ pcie_gen = 0;
+
+ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+ pcie_width = 6;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
+ pcie_width = 5;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
+ pcie_width = 4;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
+ pcie_width = 3;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
+ pcie_width = 2;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
+ pcie_width = 1;
+
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+ if (pp_table->PcieGenSpeed[i] > pcie_gen)
+ pp_table->PcieGenSpeed[i] = pcie_gen;
+
+ if (pp_table->PcieLaneCount[i] > pcie_width)
+ pp_table->PcieLaneCount[i] = pcie_width;
+ }
+
+ return 0;
+}
+
static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
{
int result = -1;
@@ -2556,6 +2598,11 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
"Failed to initialize Link Level!",
return result);
+ result = vega10_override_pcie_parameters(hwmgr);
+ PP_ASSERT_WITH_CODE(!result,
+ "Failed to override pcie parameters!",
+ return result);
+
result = vega10_populate_all_graphic_levels(hwmgr);
PP_ASSERT_WITH_CODE(!result,
"Failed to initialize Graphics Level!",
@@ -2922,6 +2969,7 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
return 0;
}
+
static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
{
struct vega10_hwmgr *data = hwmgr->backend;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
index c0753029a8e2..43e01d880f7c 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
@@ -481,6 +481,67 @@ static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state)
dpm_state->hard_max_level = 0xffff;
}
+static int vega12_override_pcie_parameters(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+ struct vega12_hwmgr *data =
+ (struct vega12_hwmgr *)(hwmgr->backend);
+ uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
+ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+ int i;
+ int ret;
+
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+ pcie_gen = 3;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+ pcie_gen = 2;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
+ pcie_gen = 1;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
+ pcie_gen = 0;
+
+ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+ pcie_width = 6;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
+ pcie_width = 5;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
+ pcie_width = 4;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
+ pcie_width = 3;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
+ pcie_width = 2;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
+ pcie_width = 1;
+
+ /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
+ * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
+ * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
+ */
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+ pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
+ pp_table->PcieGenSpeed[i];
+ pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
+ pp_table->PcieLaneCount[i];
+
+ if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
+ pp_table->PcieLaneCount[i]) {
+ smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
+ ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
+ NULL);
+ PP_ASSERT_WITH_CODE(!ret,
+ "[OverridePcieParameters] Attempt to override pcie params failed!",
+ return ret);
+ }
+
+ /* update the pptable */
+ pp_table->PcieGenSpeed[i] = pcie_gen_arg;
+ pp_table->PcieLaneCount[i] = pcie_width_arg;
+ }
+
+ return 0;
+}
+
static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
PPCLK_e clk_id, uint32_t *num_of_levels)
{
@@ -968,6 +1029,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
"Failed to enable all smu features!",
return result);
+ result = vega12_override_pcie_parameters(hwmgr);
+ PP_ASSERT_WITH_CODE(!result,
+ "[EnableDPMTasks] Failed to override pcie parameters!",
+ return result);
+
tmp_result = vega12_power_control_set_level(hwmgr);
PP_ASSERT_WITH_CODE(!tmp_result,
"Failed to power control set level!",
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
index 87811b005b85..f19964c69a00 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
@@ -831,7 +831,9 @@ static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
struct vega20_hwmgr *data =
(struct vega20_hwmgr *)(hwmgr->backend);
- uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
+ uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
+ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+ int i;
int ret;
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
@@ -860,17 +862,27 @@ static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
* Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
*/
- smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
- ret = smum_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
- NULL);
- PP_ASSERT_WITH_CODE(!ret,
- "[OverridePcieParameters] Attempt to override pcie params failed!",
- return ret);
+ for (i = 0; i < NUM_LINK_LEVELS; i++) {
+ pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
+ pp_table->PcieGenSpeed[i];
+ pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
+ pp_table->PcieLaneCount[i];
+
+ if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
+ pp_table->PcieLaneCount[i]) {
+ smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
+ ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
+ NULL);
+ PP_ASSERT_WITH_CODE(!ret,
+ "[OverridePcieParameters] Attempt to override pcie params failed!",
+ return ret);
+ }
- data->pcie_parameters_override = true;
- data->pcie_gen_level1 = pcie_gen;
- data->pcie_width_level1 = pcie_width;
+ /* update the pptable */
+ pp_table->PcieGenSpeed[i] = pcie_gen_arg;
+ pp_table->PcieLaneCount[i] = pcie_width_arg;
+ }
return 0;
}
@@ -3319,9 +3331,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
data->od8_settings.od8_settings_array;
OverDriveTable_t *od_table =
&(data->smc_state_table.overdrive_table);
- struct phm_ppt_v3_information *pptable_information =
- (struct phm_ppt_v3_information *)hwmgr->pptable;
- PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
+ PPTable_t *pptable = &(data->smc_state_table.pp_table);
struct pp_clock_levels_with_latency clocks;
struct vega20_single_dpm_table *fclk_dpm_table =
&(data->dpm_table.fclk_table);
@@ -3420,13 +3430,9 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
current_lane_width =
vega20_get_current_pcie_link_width_level(hwmgr);
for (i = 0; i < NUM_LINK_LEVELS; i++) {
- if (i == 1 && data->pcie_parameters_override) {
- gen_speed = data->pcie_gen_level1;
- lane_width = data->pcie_width_level1;
- } else {
- gen_speed = pptable->PcieGenSpeed[i];
- lane_width = pptable->PcieLaneCount[i];
- }
+ gen_speed = pptable->PcieGenSpeed[i];
+ lane_width = pptable->PcieLaneCount[i];
+
size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
(gen_speed == 0) ? "2.5GT/s," :
(gen_speed == 1) ? "5.0GT/s," :
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b9a616737c0e..f6baa2046124 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2048,7 +2048,7 @@ static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
if (shadow)
vfree(shadow);
- else
+ else if (fb_helper->buffer)
drm_client_buffer_vunmap(fb_helper->buffer);
drm_client_framebuffer_delete(fb_helper->buffer);
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 9825c378dfa6..6d625cee7a6a 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -357,13 +357,14 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
if (--shmem->vmap_use_count > 0)
return;
- if (obj->import_attach)
+ if (obj->import_attach) {
dma_buf_vunmap(obj->import_attach->dmabuf, map);
- else
+ } else {
vunmap(shmem->vaddr);
+ drm_gem_shmem_put_pages(shmem);
+ }
shmem->vaddr = NULL;
- drm_gem_shmem_put_pages(shmem);
}
/*
@@ -525,14 +526,28 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
loff_t num_pages = obj->size >> PAGE_SHIFT;
+ vm_fault_t ret;
struct page *page;
+ pgoff_t page_offset;
- if (vmf->pgoff >= num_pages || WARN_ON_ONCE(!shmem->pages))
- return VM_FAULT_SIGBUS;
+ /* We don't use vmf->pgoff since that has the fake offset */
+ page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
- page = shmem->pages[vmf->pgoff];
+ mutex_lock(&shmem->pages_lock);
- return vmf_insert_page(vma, vmf->address, page);
+ if (page_offset >= num_pages ||
+ WARN_ON_ONCE(!shmem->pages) ||
+ shmem->madv < 0) {
+ ret = VM_FAULT_SIGBUS;
+ } else {
+ page = shmem->pages[page_offset];
+
+ ret = vmf_insert_page(vma, vmf->address, page);
+ }
+
+ mutex_unlock(&shmem->pages_lock);
+
+ return ret;
}
static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
@@ -581,9 +596,6 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
struct drm_gem_shmem_object *shmem;
int ret;
- /* Remove the fake offset */
- vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
-
if (obj->import_attach) {
/* Drop the reference drm_gem_mmap_obj() acquired.*/
drm_gem_object_put(obj);
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index f86448ab1fe0..dc734d4828a1 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -99,6 +99,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
return -EFAULT;
+ memset(&v, 0, sizeof(v));
+
v = (struct drm_version) {
.name_len = v32.name_len,
.name = compat_ptr(v32.name),
@@ -137,6 +139,9 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
return -EFAULT;
+
+ memset(&uq, 0, sizeof(uq));
+
uq = (struct drm_unique){
.unique_len = uq32.unique_len,
.unique = compat_ptr(uq32.unique),
@@ -265,6 +270,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
if (copy_from_user(&c32, argp, sizeof(c32)))
return -EFAULT;
+ memset(&client, 0, sizeof(client));
+
client.idx = c32.idx;
err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
@@ -852,6 +859,8 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
if (copy_from_user(&req32, argp, sizeof(req32)))
return -EFAULT;
+ memset(&req, 0, sizeof(req));
+
req.request.type = req32.request.type;
req.request.sequence = req32.request.sequence;
req.request.signal = req32.request.signal;
@@ -889,6 +898,8 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
struct drm_mode_fb_cmd2 req64;
int err;
+ memset(&req64, 0, sizeof(req64));
+
if (copy_from_user(&req64, argp,
offsetof(drm_mode_fb_cmd232_t, modifier)))
return -EFAULT;
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index fb1b1d096975..9cf555d6842b 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -713,9 +713,12 @@ static int engine_setup_common(struct intel_engine_cs *engine)
goto err_status;
}
+ err = intel_engine_init_cmd_parser(engine);
+ if (err)
+ goto err_cmd_parser;
+
intel_engine_init_active(engine, ENGINE_PHYSICAL);
intel_engine_init_execlists(engine);
- intel_engine_init_cmd_parser(engine);
intel_engine_init__pm(engine);
intel_engine_init_retire(engine);
@@ -732,6 +735,8 @@ static int engine_setup_common(struct intel_engine_cs *engine)
return 0;
+err_cmd_parser:
+ intel_breadcrumbs_free(engine->breadcrumbs);
err_status:
cleanup_status_page(engine);
return err;
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index ced9a96d7c34..5f86f5b2caf6 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -940,7 +940,7 @@ static void fini_hash_table(struct intel_engine_cs *engine)
* struct intel_engine_cs based on whether the platform requires software
* command parsing.
*/
-void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
+int intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
{
const struct drm_i915_cmd_table *cmd_tables;
int cmd_table_count;
@@ -948,7 +948,7 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
if (!IS_GEN(engine->i915, 7) && !(IS_GEN(engine->i915, 9) &&
engine->class == COPY_ENGINE_CLASS))
- return;
+ return 0;
switch (engine->class) {
case RENDER_CLASS:
@@ -1013,19 +1013,19 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
break;
default:
MISSING_CASE(engine->class);
- return;
+ goto out;
}
if (!validate_cmds_sorted(engine, cmd_tables, cmd_table_count)) {
drm_err(&engine->i915->drm,
"%s: command descriptions are not sorted\n",
engine->name);
- return;
+ goto out;
}
if (!validate_regs_sorted(engine)) {
drm_err(&engine->i915->drm,
"%s: registers are not sorted\n", engine->name);
- return;
+ goto out;
}
ret = init_hash_table(engine, cmd_tables, cmd_table_count);
@@ -1033,10 +1033,17 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine)
drm_err(&engine->i915->drm,
"%s: initialised failed!\n", engine->name);
fini_hash_table(engine);
- return;
+ goto out;
}
engine->flags |= I915_ENGINE_USING_CMD_PARSER;
+
+out:
+ if (intel_engine_requires_cmd_parser(engine) &&
+ !intel_engine_using_cmd_parser(engine))
+ return -EINVAL;
+
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 26d69d06aa6d..cb62ddba2035 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1952,7 +1952,7 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
/* i915_cmd_parser.c */
int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv);
-void intel_engine_init_cmd_parser(struct intel_engine_cs *engine);
+int intel_engine_init_cmd_parser(struct intel_engine_cs *engine);
void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine);
int intel_engine_cmd_parser(struct intel_engine_cs *engine,
struct i915_vma *batch,
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 112ba5f2ce90..e62ad69606f6 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -603,7 +603,6 @@ static int append_oa_sample(struct i915_perf_stream *stream,
{
int report_size = stream->oa_buffer.format_size;
struct drm_i915_perf_record_header header;
- u32 sample_flags = stream->sample_flags;
header.type = DRM_I915_PERF_RECORD_SAMPLE;
header.pad = 0;
@@ -617,10 +616,8 @@ static int append_oa_sample(struct i915_perf_stream *stream,
return -EFAULT;
buf += sizeof(header);
- if (sample_flags & SAMPLE_OA_REPORT) {
- if (copy_to_user(buf, report, report_size))
- return -EFAULT;
- }
+ if (copy_to_user(buf, report, report_size))
+ return -EFAULT;
(*offset) += header.size;
@@ -2682,7 +2679,7 @@ static void i915_oa_stream_enable(struct i915_perf_stream *stream)
stream->perf->ops.oa_enable(stream);
- if (stream->periodic)
+ if (stream->sample_flags & SAMPLE_OA_REPORT)
hrtimer_start(&stream->poll_check_timer,
ns_to_ktime(stream->poll_oa_period),
HRTIMER_MODE_REL_PINNED);
@@ -2745,7 +2742,7 @@ static void i915_oa_stream_disable(struct i915_perf_stream *stream)
{
stream->perf->ops.oa_disable(stream);
- if (stream->periodic)
+ if (stream->sample_flags & SAMPLE_OA_REPORT)
hrtimer_cancel(&stream->poll_check_timer);
}
@@ -3028,7 +3025,7 @@ static ssize_t i915_perf_read(struct file *file,
* disabled stream as an error. In particular it might otherwise lead
* to a deadlock for blocking file descriptors...
*/
- if (!stream->enabled)
+ if (!stream->enabled || !(stream->sample_flags & SAMPLE_OA_REPORT))
return -EIO;
if (!(file->f_flags & O_NONBLOCK)) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7146cd0f3256..aaf1f0045b16 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3316,7 +3316,18 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000)
#define ILK_FBCQ_DIS (1 << 22)
-#define ILK_PABSTRETCH_DIS (1 << 21)
+#define ILK_PABSTRETCH_DIS REG_BIT(21)
+#define ILK_SABSTRETCH_DIS REG_BIT(20)
+#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20)
+#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0)
+#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1)
+#define IVB_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 2)
+#define IVB_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 3)
+#define IVB_SPR_STRETCH_MAX_MASK REG_GENMASK(19, 18)
+#define IVB_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 0)
+#define IVB_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 1)
+#define IVB_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 2)
+#define IVB_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 3)
/*
@@ -8039,6 +8050,16 @@ enum {
#define _CHICKEN_PIPESL_1_A 0x420b0
#define _CHICKEN_PIPESL_1_B 0x420b4
+#define HSW_PRI_STRETCH_MAX_MASK REG_GENMASK(28, 27)
+#define HSW_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 0)
+#define HSW_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 1)
+#define HSW_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 2)
+#define HSW_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 3)
+#define HSW_SPR_STRETCH_MAX_MASK REG_GENMASK(26, 25)
+#define HSW_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 0)
+#define HSW_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 1)
+#define HSW_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 2)
+#define HSW_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 3)
#define HSW_FBCQ_DIS (1 << 22)
#define BDW_DPRS_MASK_VBLANK_SRD (1 << 0)
#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0c3e63f27c29..97b57acc02e2 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -7245,11 +7245,16 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1,
intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
- /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
for_each_pipe(dev_priv, pipe) {
+ /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe)) |
BDW_DPRS_MASK_VBLANK_SRD);
+
+ /* Undocumented but fixes async flip + VT-d corruption */
+ if (intel_vtd_active())
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
+ HSW_PRI_STRETCH_MAX_MASK, HSW_PRI_STRETCH_MAX_X1);
}
/* WaVSRefCountFullforceMissDisable:bdw */
@@ -7285,11 +7290,20 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
{
+ enum pipe pipe;
+
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A),
intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A)) |
HSW_FBCQ_DIS);
+ for_each_pipe(dev_priv, pipe) {
+ /* Undocumented but fixes async flip + VT-d corruption */
+ if (intel_vtd_active())
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
+ HSW_PRI_STRETCH_MAX_MASK, HSW_PRI_STRETCH_MAX_X1);
+ }
+
/* This is required by WaCatErrorRejectionIssue:hsw */
intel_uncore_write(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
intel_uncore_read(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 42c5d3246cfc..453d8b4c5763 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -482,6 +482,16 @@ static int meson_probe_remote(struct platform_device *pdev,
return count;
}
+static void meson_drv_shutdown(struct platform_device *pdev)
+{
+ struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
+ struct drm_device *drm = priv->drm;
+
+ DRM_DEBUG_DRIVER("\n");
+ drm_kms_helper_poll_fini(drm);
+ drm_atomic_helper_shutdown(drm);
+}
+
static int meson_drv_probe(struct platform_device *pdev)
{
struct component_match *match = NULL;
@@ -553,6 +563,7 @@ static const struct dev_pm_ops meson_drv_pm_ops = {
static struct platform_driver meson_drm_platform_driver = {
.probe = meson_drv_probe,
+ .shutdown = meson_drv_shutdown,
.driver = {
.name = "meson-drm",
.of_match_table = dt_match,
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2375711877cf..f2720a006199 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -551,12 +551,17 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)
if (!ttm_dma)
return;
+ if (!ttm_dma->pages) {
+ NV_DEBUG(drm, "ttm_dma 0x%p: pages NULL\n", ttm_dma);
+ return;
+ }
/* Don't waste time looping if the object is coherent */
if (nvbo->force_coherent)
return;
- for (i = 0; i < ttm_dma->num_pages; ++i) {
+ i = 0;
+ while (i < ttm_dma->num_pages) {
struct page *p = ttm_dma->pages[i];
size_t num_pages = 1;
@@ -582,12 +587,17 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
if (!ttm_dma)
return;
+ if (!ttm_dma->pages) {
+ NV_DEBUG(drm, "ttm_dma 0x%p: pages NULL\n", ttm_dma);
+ return;
+ }
/* Don't waste time looping if the object is coherent */
if (nvbo->force_coherent)
return;
- for (i = 0; i < ttm_dma->num_pages; ++i) {
+ i = 0;
+ while (i < ttm_dma->num_pages) {
struct page *p = ttm_dma->pages[i];
size_t num_pages = 1;
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 8e11612f5fe1..b31d750c425a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -2149,11 +2149,12 @@ static int dsi_vc_send_short(struct dsi_data *dsi, int vc,
const struct mipi_dsi_msg *msg)
{
struct mipi_dsi_packet pkt;
+ int ret;
u32 r;
- r = mipi_dsi_create_packet(&pkt, msg);
- if (r < 0)
- return r;
+ ret = mipi_dsi_create_packet(&pkt, msg);
+ if (ret < 0)
+ return ret;
WARN_ON(!dsi_bus_is_locked(dsi));
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 012bce0cdb65..10738e04c09b 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -328,6 +328,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
head.id = i;
head.flags = 0;
+ head.surface_id = 0;
oldcount = qdev->monitors_config->count;
if (crtc->state->active) {
struct drm_display_mode *mode = &crtc->mode;
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index 0fcfc952d5e9..b372455e2729 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -321,7 +321,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
int type, struct qxl_release **release,
struct qxl_bo **rbo)
{
- struct qxl_bo *bo;
+ struct qxl_bo *bo, *free_bo = NULL;
int idr_ret;
int ret = 0;
union qxl_release_info *info;
@@ -347,7 +347,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
mutex_lock(&qdev->release_mutex);
if (qdev->current_release_bo_offset[cur_idx] + 1 >= releases_per_bo[cur_idx]) {
- qxl_bo_unref(&qdev->current_release_bo[cur_idx]);
+ free_bo = qdev->current_release_bo[cur_idx];
qdev->current_release_bo_offset[cur_idx] = 0;
qdev->current_release_bo[cur_idx] = NULL;
}
@@ -355,6 +355,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
ret = qxl_release_bo_alloc(qdev, &qdev->current_release_bo[cur_idx]);
if (ret) {
mutex_unlock(&qdev->release_mutex);
+ if (free_bo) {
+ qxl_bo_unpin(free_bo);
+ qxl_bo_unref(&free_bo);
+ }
qxl_release_free(qdev, *release);
return ret;
}
@@ -370,6 +374,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
*rbo = bo;
mutex_unlock(&qdev->release_mutex);
+ if (free_bo) {
+ qxl_bo_unpin(free_bo);
+ qxl_bo_unref(&free_bo);
+ }
ret = qxl_release_list_add(*release, bo);
qxl_bo_unref(&bo);
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index f09989bdce98..3effc8c71494 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -574,6 +574,8 @@ struct radeon_gem {
struct list_head objects;
};
+extern const struct drm_gem_object_funcs radeon_gem_object_funcs;
+
int radeon_gem_init(struct radeon_device *rdev);
void radeon_gem_fini(struct radeon_device *rdev);
int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 941826923247..db14a82a2e4b 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -43,7 +43,7 @@ struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj);
int radeon_gem_prime_pin(struct drm_gem_object *obj);
void radeon_gem_prime_unpin(struct drm_gem_object *obj);
-static const struct drm_gem_object_funcs radeon_gem_object_funcs;
+const struct drm_gem_object_funcs radeon_gem_object_funcs;
static void radeon_gem_object_free(struct drm_gem_object *gobj)
{
@@ -227,7 +227,7 @@ static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r)
return r;
}
-static const struct drm_gem_object_funcs radeon_gem_object_funcs = {
+const struct drm_gem_object_funcs radeon_gem_object_funcs = {
.free = radeon_gem_object_free,
.open = radeon_gem_object_open,
.close = radeon_gem_object_close,
diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c
index ab29eb9e8667..42a87948e28c 100644
--- a/drivers/gpu/drm/radeon/radeon_prime.c
+++ b/drivers/gpu/drm/radeon/radeon_prime.c
@@ -56,6 +56,8 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
if (ret)
return ERR_PTR(ret);
+ bo->tbo.base.funcs = &radeon_gem_object_funcs;
+
mutex_lock(&rdev->gem.mutex);
list_add_tail(&bo->list, &rdev->gem.objects);
mutex_unlock(&rdev->gem.mutex);
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index 33f65f4626e5..23866a54e3f9 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -83,6 +83,7 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
struct gm12u320_device {
struct drm_device dev;
+ struct device *dmadev;
struct drm_simple_display_pipe pipe;
struct drm_connector conn;
unsigned char *cmd_buf;
@@ -601,6 +602,22 @@ static const uint64_t gm12u320_pipe_modifiers[] = {
DRM_FORMAT_MOD_INVALID
};
+/*
+ * FIXME: Dma-buf sharing requires DMA support by the importing device.
+ * This function is a workaround to make USB devices work as well.
+ * See todo.rst for how to fix the issue in the dma-buf framework.
+ */
+static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *dma_buf)
+{
+ struct gm12u320_device *gm12u320 = to_gm12u320(dev);
+
+ if (!gm12u320->dmadev)
+ return ERR_PTR(-ENODEV);
+
+ return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
+}
+
DEFINE_DRM_GEM_FOPS(gm12u320_fops);
static const struct drm_driver gm12u320_drm_driver = {
@@ -614,6 +631,7 @@ static const struct drm_driver gm12u320_drm_driver = {
.fops = &gm12u320_fops,
DRM_GEM_SHMEM_DRIVER_OPS,
+ .gem_prime_import = gm12u320_gem_prime_import,
};
static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
@@ -640,15 +658,18 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
struct gm12u320_device, dev);
if (IS_ERR(gm12u320))
return PTR_ERR(gm12u320);
+ dev = &gm12u320->dev;
+
+ gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
+ if (!gm12u320->dmadev)
+ drm_warn(dev, "buffer sharing not supported"); /* not an error */
INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
mutex_init(&gm12u320->fb_update.lock);
- dev = &gm12u320->dev;
-
ret = drmm_mode_config_init(dev);
if (ret)
- return ret;
+ goto err_put_device;
dev->mode_config.min_width = GM12U320_USER_WIDTH;
dev->mode_config.max_width = GM12U320_USER_WIDTH;
@@ -658,15 +679,15 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
ret = gm12u320_usb_alloc(gm12u320);
if (ret)
- return ret;
+ goto err_put_device;
ret = gm12u320_set_ecomode(gm12u320);
if (ret)
- return ret;
+ goto err_put_device;
ret = gm12u320_conn_init(gm12u320);
if (ret)
- return ret;
+ goto err_put_device;
ret = drm_simple_display_pipe_init(&gm12u320->dev,
&gm12u320->pipe,
@@ -676,24 +697,31 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
gm12u320_pipe_modifiers,
&gm12u320->conn);
if (ret)
- return ret;
+ goto err_put_device;
drm_mode_config_reset(dev);
usb_set_intfdata(interface, dev);
ret = drm_dev_register(dev, 0);
if (ret)
- return ret;
+ goto err_put_device;
drm_fbdev_generic_setup(dev, 0);
return 0;
+
+err_put_device:
+ put_device(gm12u320->dmadev);
+ return ret;
}
static void gm12u320_usb_disconnect(struct usb_interface *interface)
{
struct drm_device *dev = usb_get_intfdata(interface);
+ struct gm12u320_device *gm12u320 = to_gm12u320(dev);
+ put_device(gm12u320->dmadev);
+ gm12u320->dmadev = NULL;
drm_dev_unplug(dev);
drm_atomic_helper_shutdown(dev);
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 20a25660b35b..101a68dc615b 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -136,7 +136,8 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,
struct ttm_bo_device *bdev = bo->bdev;
struct ttm_resource_manager *man;
- dma_resv_assert_held(bo->base.resv);
+ if (!bo->deleted)
+ dma_resv_assert_held(bo->base.resv);
if (bo->pin_count) {
ttm_bo_del_from_lru(bo);
@@ -508,8 +509,11 @@ static void ttm_bo_release(struct kref *kref)
* Make pinned bos immediately available to
* shrinkers, now that they are queued for
* destruction.
+ *
+ * FIXME: QXL is triggering this. Can be removed when the
+ * driver is fixed.
*/
- if (WARN_ON(bo->pin_count)) {
+ if (WARN_ON_ONCE(bo->pin_count)) {
bo->pin_count = 0;
ttm_bo_move_to_lru_tail(bo, &bo->mem, NULL);
}
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 6e27cb1bf48b..4eb6efb8b8c0 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -268,13 +268,13 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,
/* Remove a pool_type from the global shrinker list and free all pages */
static void ttm_pool_type_fini(struct ttm_pool_type *pt)
{
- struct page *p, *tmp;
+ struct page *p;
mutex_lock(&shrinker_lock);
list_del(&pt->shrinker_list);
mutex_unlock(&shrinker_lock);
- list_for_each_entry_safe(p, tmp, &pt->pages, lru)
+ while ((p = ttm_pool_type_take(pt)))
ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
}
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 9269092697d8..5703277c6f52 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -32,6 +32,22 @@ static int udl_usb_resume(struct usb_interface *interface)
return drm_mode_config_helper_resume(dev);
}
+/*
+ * FIXME: Dma-buf sharing requires DMA support by the importing device.
+ * This function is a workaround to make USB devices work as well.
+ * See todo.rst for how to fix the issue in the dma-buf framework.
+ */
+static struct drm_gem_object *udl_driver_gem_prime_import(struct drm_device *dev,
+ struct dma_buf *dma_buf)
+{
+ struct udl_device *udl = to_udl(dev);
+
+ if (!udl->dmadev)
+ return ERR_PTR(-ENODEV);
+
+ return drm_gem_prime_import_dev(dev, dma_buf, udl->dmadev);
+}
+
DEFINE_DRM_GEM_FOPS(udl_driver_fops);
static const struct drm_driver driver = {
@@ -40,6 +56,7 @@ static const struct drm_driver driver = {
/* GEM hooks */
.fops = &udl_driver_fops,
DRM_GEM_SHMEM_DRIVER_OPS,
+ .gem_prime_import = udl_driver_gem_prime_import,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 875e73551ae9..cc16a13316e4 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -50,6 +50,7 @@ struct urb_list {
struct udl_device {
struct drm_device drm;
struct device *dev;
+ struct device *dmadev;
struct drm_simple_display_pipe display_pipe;
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 0e2a376cb075..853f147036f6 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -315,6 +315,10 @@ int udl_init(struct udl_device *udl)
DRM_DEBUG("\n");
+ udl->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
+ if (!udl->dmadev)
+ drm_warn(dev, "buffer sharing not supported"); /* not an error */
+
mutex_init(&udl->gem_lock);
if (!udl_parse_vendor_descriptor(udl)) {
@@ -343,12 +347,18 @@ int udl_init(struct udl_device *udl)
err:
if (udl->urbs.count)
udl_free_urb_list(dev);
+ put_device(udl->dmadev);
DRM_ERROR("%d\n", ret);
return ret;
}
int udl_drop_usb(struct drm_device *dev)
{
+ struct udl_device *udl = to_udl(dev);
+
udl_free_urb_list(dev);
+ put_device(udl->dmadev);
+ udl->dmadev = NULL;
+
return 0;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
index 0a900afc66ff..45c9c6a7f1d6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
@@ -500,8 +500,6 @@ vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf,
vm_fault_t ret;
pgoff_t fault_page_size;
bool write = vmf->flags & FAULT_FLAG_WRITE;
- bool is_cow_mapping =
- (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
switch (pe_size) {
case PE_SIZE_PMD:
@@ -518,7 +516,7 @@ vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf,
}
/* Always do write dirty-tracking and COW on PTE level. */
- if (write && (READ_ONCE(vbo->dirty) || is_cow_mapping))
+ if (write && (READ_ONCE(vbo->dirty) || is_cow_mapping(vma->vm_flags)))
return VM_FAULT_FALLBACK;
ret = ttm_bo_vm_reserve(bo, vmf);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
index 3c03b1746661..cb9975889e2f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
@@ -49,7 +49,7 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &vmw_vm_ops;
/* Use VM_PFNMAP rather than VM_MIXEDMAP if not a COW mapping */
- if ((vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) != VM_MAYWRITE)
+ if (!is_cow_mapping(vma->vm_flags))
vma->vm_flags = (vma->vm_flags & ~VM_MIXEDMAP) | VM_PFNMAP;
return 0;
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index bf7d22fa4be2..e0667c4b3c08 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -266,6 +266,8 @@ config ADI_AXI_ADC
select IIO_BUFFER
select IIO_BUFFER_HW_CONSUMER
select IIO_BUFFER_DMAENGINE
+ depends on HAS_IOMEM
+ depends on OF
help
Say yes here to build support for Analog Devices Generic
AXI ADC IP core. The IP core is used for interfacing with
@@ -923,6 +925,7 @@ config STM32_ADC_CORE
depends on ARCH_STM32 || COMPILE_TEST
depends on OF
depends on REGULATOR
+ depends on HAS_IOMEM
select IIO_BUFFER
select MFD_STM32_TIMERS
select IIO_STM32_TIMER_TRIGGER
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 6f9a3e2d5533..7b5212ba5501 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -918,7 +918,7 @@ static int ab8500_gpadc_read_raw(struct iio_dev *indio_dev,
return processed;
/* Return millivolt or milliamps or millicentigrades */
- *val = processed * 1000;
+ *val = processed;
return IIO_VAL_INT;
}
diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c
index 5d597e5050f6..1b4b3203e428 100644
--- a/drivers/iio/adc/ad7949.c
+++ b/drivers/iio/adc/ad7949.c
@@ -91,7 +91,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
int ret;
int i;
int bits_per_word = ad7949_adc->resolution;
- int mask = GENMASK(ad7949_adc->resolution, 0);
+ int mask = GENMASK(ad7949_adc->resolution - 1, 0);
struct spi_message msg;
struct spi_transfer tx[] = {
{
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index 05ff948372b3..07b1a99381d9 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -597,7 +597,7 @@ static const struct vadc_channels vadc_chans[] = {
VADC_CHAN_NO_SCALE(P_MUX16_1_3, 1)
VADC_CHAN_NO_SCALE(LR_MUX1_BAT_THERM, 0)
- VADC_CHAN_NO_SCALE(LR_MUX2_BAT_ID, 0)
+ VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_DEFAULT)
VADC_CHAN_NO_SCALE(LR_MUX3_XO_THERM, 0)
VADC_CHAN_NO_SCALE(LR_MUX4_AMUX_THM1, 0)
VADC_CHAN_NO_SCALE(LR_MUX5_AMUX_THM2, 0)
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index dfa31a23500f..ac90be03332a 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -551,6 +551,8 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
MPU3050_FIFO_R,
&fifo_values[offset],
toread);
+ if (ret)
+ goto out_trigger_unlock;
dev_dbg(mpu3050->dev,
"%04x %04x %04x %04x %04x\n",
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index 52f605114ef7..d62705448ae2 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -15,7 +15,10 @@
struct hid_humidity_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info humidity_attr;
- s32 humidity_data;
+ struct {
+ s32 humidity_data;
+ u64 timestamp __aligned(8);
+ } scan;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
@@ -125,9 +128,8 @@ static int humidity_proc_event(struct hid_sensor_hub_device *hsdev,
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
if (atomic_read(&humid_st->common_attributes.data_ready))
- iio_push_to_buffers_with_timestamp(indio_dev,
- &humid_st->humidity_data,
- iio_get_time_ns(indio_dev));
+ iio_push_to_buffers_with_timestamp(indio_dev, &humid_st->scan,
+ iio_get_time_ns(indio_dev));
return 0;
}
@@ -142,7 +144,7 @@ static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev,
switch (usage_id) {
case HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY:
- humid_st->humidity_data = *(s32 *)raw_data;
+ humid_st->scan.humidity_data = *(s32 *)raw_data;
return 0;
default:
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index 54af2ed664f6..785a4ce606d8 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -462,8 +462,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
if (ret)
goto err_ret;
- ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
- if (ret != 1) {
+ if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) {
ret = -EINVAL;
goto err_ret;
}
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 330cf359e0b8..e9e00ce0c6d4 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -23,6 +23,9 @@ struct prox_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info prox_attr;
u32 human_presence;
+ int scale_pre_decml;
+ int scale_post_decml;
+ int scale_precision;
};
/* Channel definitions */
@@ -93,8 +96,9 @@ static int prox_read_raw(struct iio_dev *indio_dev,
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
- *val = prox_state->prox_attr.units;
- ret_type = IIO_VAL_INT;
+ *val = prox_state->scale_pre_decml;
+ *val2 = prox_state->scale_post_decml;
+ ret_type = prox_state->scale_precision;
break;
case IIO_CHAN_INFO_OFFSET:
*val = hid_sensor_convert_exponent(
@@ -234,6 +238,11 @@ static int prox_parse_report(struct platform_device *pdev,
HID_USAGE_SENSOR_HUMAN_PRESENCE,
&st->common_attributes.sensitivity);
+ st->scale_precision = hid_sensor_format_scale(
+ hsdev->usage,
+ &st->prox_attr,
+ &st->scale_pre_decml, &st->scale_post_decml);
+
return ret;
}
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 81688f1b932f..da9a247097fa 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -15,7 +15,10 @@
struct temperature_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info temperature_attr;
- s32 temperature_data;
+ struct {
+ s32 temperature_data;
+ u64 timestamp __aligned(8);
+ } scan;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
@@ -32,7 +35,7 @@ static const struct iio_chan_spec temperature_channels[] = {
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
},
- IIO_CHAN_SOFT_TIMESTAMP(3),
+ IIO_CHAN_SOFT_TIMESTAMP(1),
};
/* Adjust channel real bits based on report descriptor */
@@ -123,9 +126,8 @@ static int temperature_proc_event(struct hid_sensor_hub_device *hsdev,
struct temperature_state *temp_st = iio_priv(indio_dev);
if (atomic_read(&temp_st->common_attributes.data_ready))
- iio_push_to_buffers_with_timestamp(indio_dev,
- &temp_st->temperature_data,
- iio_get_time_ns(indio_dev));
+ iio_push_to_buffers_with_timestamp(indio_dev, &temp_st->scan,
+ iio_get_time_ns(indio_dev));
return 0;
}
@@ -140,7 +142,7 @@ static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev,
switch (usage_id) {
case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE:
- temp_st->temperature_data = *(s32 *)raw_data;
+ temp_st->scan.temperature_data = *(s32 *)raw_data;
return 0;
default:
return -EINVAL;
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 430dc6975004..da8963a9f044 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -26,7 +26,6 @@
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Joystick device interfaces");
-MODULE_SUPPORTED_DEVICE("input/js");
MODULE_LICENSE("GPL");
#define JOYDEV_MINOR_BASE 0
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index ad1b6c90bc4d..7237dc440b98 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -94,6 +94,17 @@ config INPUT_ARIZONA_HAPTICS
To compile this driver as a module, choose M here: the
module will be called arizona-haptics.
+config INPUT_ATC260X_ONKEY
+ tristate "Actions Semi ATC260x PMIC ONKEY"
+ depends on MFD_ATC260X
+ help
+ Support the ONKEY of ATC260x PMICs as an input device reporting
+ power button status. ONKEY can be used to wakeup from low power
+ modes and force a reset on long press.
+
+ To compile this driver as a module, choose M here: the
+ module will be called atc260x-onkey.
+
config INPUT_ATMEL_CAPTOUCH
tristate "Atmel Capacitive Touch Button Driver"
depends on OF || COMPILE_TEST
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 7f202ba8f775..46db664a8bc4 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_ARIEL_PWRBUTTON) += ariel-pwrbutton.o
obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o
+obj-$(CONFIG_INPUT_ATC260X_ONKEY) += atc260x-onkey.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o
@@ -86,4 +87,3 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
-
diff --git a/drivers/input/misc/atc260x-onkey.c b/drivers/input/misc/atc260x-onkey.c
new file mode 100644
index 000000000000..999aabf9dcbd
--- /dev/null
+++ b/drivers/input/misc/atc260x-onkey.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Onkey driver for Actions Semi ATC260x PMICs.
+ *
+ * Copyright (c) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/atc260x/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* <2s for short press, >2s for long press */
+#define KEY_PRESS_TIME_SEC 2
+
+/* Driver internals */
+enum atc260x_onkey_reset_status {
+ KEY_RESET_HW_DEFAULT,
+ KEY_RESET_DISABLED,
+ KEY_RESET_USER_SEL,
+};
+
+struct atc260x_onkey_params {
+ u32 reg_int_ctl;
+ u32 kdwn_state_bm;
+ u32 long_int_pnd_bm;
+ u32 short_int_pnd_bm;
+ u32 kdwn_int_pnd_bm;
+ u32 press_int_en_bm;
+ u32 kdwn_int_en_bm;
+ u32 press_time_bm;
+ u32 reset_en_bm;
+ u32 reset_time_bm;
+};
+
+struct atc260x_onkey {
+ struct atc260x *atc260x;
+ const struct atc260x_onkey_params *params;
+ struct input_dev *input_dev;
+ struct delayed_work work;
+ int irq;
+};
+
+static const struct atc260x_onkey_params atc2603c_onkey_params = {
+ .reg_int_ctl = ATC2603C_PMU_SYS_CTL2,
+ .long_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_LONG_PRESS,
+ .short_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_SHORT_PRESS,
+ .kdwn_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_PD,
+ .press_int_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_INT_EN,
+ .kdwn_int_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN,
+ .kdwn_state_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS,
+ .press_time_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
+ .reset_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_RESET_EN,
+ .reset_time_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
+};
+
+static const struct atc260x_onkey_params atc2609a_onkey_params = {
+ .reg_int_ctl = ATC2609A_PMU_SYS_CTL2,
+ .long_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_LONG_PRESS,
+ .short_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_SHORT_PRESS,
+ .kdwn_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_PD,
+ .press_int_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_LSP_INT_EN,
+ .kdwn_int_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN,
+ .kdwn_state_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS,
+ .press_time_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
+ .reset_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_EN,
+ .reset_time_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
+};
+
+static int atc2603x_onkey_hw_init(struct atc260x_onkey *onkey,
+ enum atc260x_onkey_reset_status reset_status,
+ u32 reset_time, u32 press_time)
+{
+ u32 reg_bm, reg_val;
+
+ reg_bm = onkey->params->long_int_pnd_bm |
+ onkey->params->short_int_pnd_bm |
+ onkey->params->kdwn_int_pnd_bm |
+ onkey->params->press_int_en_bm |
+ onkey->params->kdwn_int_en_bm;
+
+ reg_val = reg_bm | press_time;
+ reg_bm |= onkey->params->press_time_bm;
+
+ if (reset_status == KEY_RESET_DISABLED) {
+ reg_bm |= onkey->params->reset_en_bm;
+ } else if (reset_status == KEY_RESET_USER_SEL) {
+ reg_bm |= onkey->params->reset_en_bm |
+ onkey->params->reset_time_bm;
+ reg_val |= onkey->params->reset_en_bm | reset_time;
+ }
+
+ return regmap_update_bits(onkey->atc260x->regmap,
+ onkey->params->reg_int_ctl, reg_bm, reg_val);
+}
+
+static void atc260x_onkey_query(struct atc260x_onkey *onkey)
+{
+ u32 reg_bits;
+ int ret, key_down;
+
+ ret = regmap_read(onkey->atc260x->regmap,
+ onkey->params->reg_int_ctl, &key_down);
+ if (ret) {
+ key_down = 1;
+ dev_err(onkey->atc260x->dev,
+ "Failed to read onkey status: %d\n", ret);
+ } else {
+ key_down &= onkey->params->kdwn_state_bm;
+ }
+
+ /*
+ * The hardware generates interrupt only when the onkey pin is
+ * asserted. Hence, the deassertion of the pin is simulated through
+ * work queue.
+ */
+ if (key_down) {
+ schedule_delayed_work(&onkey->work, msecs_to_jiffies(200));
+ return;
+ }
+
+ /*
+ * The key-down status bit is cleared when the On/Off button
+ * is released.
+ */
+ input_report_key(onkey->input_dev, KEY_POWER, 0);
+ input_sync(onkey->input_dev);
+
+ reg_bits = onkey->params->long_int_pnd_bm |
+ onkey->params->short_int_pnd_bm |
+ onkey->params->kdwn_int_pnd_bm |
+ onkey->params->press_int_en_bm |
+ onkey->params->kdwn_int_en_bm;
+
+ /* Clear key press pending events and enable key press interrupts. */
+ regmap_update_bits(onkey->atc260x->regmap, onkey->params->reg_int_ctl,
+ reg_bits, reg_bits);
+}
+
+static void atc260x_onkey_work(struct work_struct *work)
+{
+ struct atc260x_onkey *onkey = container_of(work, struct atc260x_onkey,
+ work.work);
+ atc260x_onkey_query(onkey);
+}
+
+static irqreturn_t atc260x_onkey_irq(int irq, void *data)
+{
+ struct atc260x_onkey *onkey = data;
+ int ret;
+
+ /* Disable key press interrupts. */
+ ret = regmap_update_bits(onkey->atc260x->regmap,
+ onkey->params->reg_int_ctl,
+ onkey->params->press_int_en_bm |
+ onkey->params->kdwn_int_en_bm, 0);
+ if (ret)
+ dev_err(onkey->atc260x->dev,
+ "Failed to disable interrupts: %d\n", ret);
+
+ input_report_key(onkey->input_dev, KEY_POWER, 1);
+ input_sync(onkey->input_dev);
+
+ atc260x_onkey_query(onkey);
+
+ return IRQ_HANDLED;
+}
+
+static int atc260x_onkey_open(struct input_dev *dev)
+{
+ struct atc260x_onkey *onkey = input_get_drvdata(dev);
+
+ enable_irq(onkey->irq);
+
+ return 0;
+}
+
+static void atc260x_onkey_close(struct input_dev *dev)
+{
+ struct atc260x_onkey *onkey = input_get_drvdata(dev);
+
+ disable_irq(onkey->irq);
+ cancel_delayed_work_sync(&onkey->work);
+}
+
+static int atc260x_onkey_probe(struct platform_device *pdev)
+{
+ struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent);
+ struct atc260x_onkey *onkey;
+ struct input_dev *input_dev;
+ enum atc260x_onkey_reset_status reset_status;
+ u32 press_time = KEY_PRESS_TIME_SEC, reset_time = 0;
+ int val, error;
+
+ onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
+ if (!onkey)
+ return -ENOMEM;
+
+ error = device_property_read_u32(pdev->dev.parent,
+ "reset-time-sec", &val);
+ if (error) {
+ reset_status = KEY_RESET_HW_DEFAULT;
+ } else if (val) {
+ if (val < 6 || val > 12) {
+ dev_err(&pdev->dev, "reset-time-sec out of range\n");
+ return -EINVAL;
+ }
+
+ reset_status = KEY_RESET_USER_SEL;
+ reset_time = (val - 6) / 2;
+ } else {
+ reset_status = KEY_RESET_DISABLED;
+ dev_dbg(&pdev->dev, "Disabled reset on long-press\n");
+ }
+
+ switch (atc260x->ic_type) {
+ case ATC2603C:
+ onkey->params = &atc2603c_onkey_params;
+ press_time = FIELD_PREP(ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
+ press_time);
+ reset_time = FIELD_PREP(ATC2603C_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
+ reset_time);
+ break;
+ case ATC2609A:
+ onkey->params = &atc2609a_onkey_params;
+ press_time = FIELD_PREP(ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
+ press_time);
+ reset_time = FIELD_PREP(ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
+ reset_time);
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "OnKey not supported for ATC260x PMIC type: %u\n",
+ atc260x->ic_type);
+ return -EINVAL;
+ }
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev) {
+ dev_err(&pdev->dev, "Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ onkey->input_dev = input_dev;
+ onkey->atc260x = atc260x;
+
+ input_dev->name = "atc260x-onkey";
+ input_dev->phys = "atc260x-onkey/input0";
+ input_dev->open = atc260x_onkey_open;
+ input_dev->close = atc260x_onkey_close;
+
+ input_set_capability(input_dev, EV_KEY, KEY_POWER);
+ input_set_drvdata(input_dev, onkey);
+
+ INIT_DELAYED_WORK(&onkey->work, atc260x_onkey_work);
+
+ onkey->irq = platform_get_irq(pdev, 0);
+ if (onkey->irq < 0)
+ return onkey->irq;
+
+ error = devm_request_threaded_irq(&pdev->dev, onkey->irq, NULL,
+ atc260x_onkey_irq, IRQF_ONESHOT,
+ dev_name(&pdev->dev), onkey);
+ if (error) {
+ dev_err(&pdev->dev,
+ "Failed to register IRQ %d: %d\n", onkey->irq, error);
+ return error;
+ }
+
+ /* Keep IRQ disabled until atc260x_onkey_open() is called. */
+ disable_irq(onkey->irq);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(&pdev->dev,
+ "Failed to register input device: %d\n", error);
+ return error;
+ }
+
+ error = atc2603x_onkey_hw_init(onkey, reset_status,
+ reset_time, press_time);
+ if (error)
+ return error;
+
+ device_init_wakeup(&pdev->dev, true);
+
+ return 0;
+}
+
+static struct platform_driver atc260x_onkey_driver = {
+ .probe = atc260x_onkey_probe,
+ .driver = {
+ .name = "atc260x-onkey",
+ },
+};
+
+module_platform_driver(atc260x_onkey_driver);
+
+MODULE_DESCRIPTION("Onkey driver for ATC260x PMICs");
+MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 9126efcbaf2c..321f5906e6ed 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2714,7 +2714,6 @@ static int __init early_amd_iommu_init(void)
struct acpi_table_header *ivrs_base;
int i, remap_cache_sz, ret;
acpi_status status;
- u32 pci_id;
if (!amd_iommu_detected)
return -ENODEV;
@@ -2804,16 +2803,6 @@ static int __init early_amd_iommu_init(void)
if (ret)
goto out;
- /* Disable IOMMU if there's Stoney Ridge graphics */
- for (i = 0; i < 32; i++) {
- pci_id = read_pci_config(0, i, 0, 0);
- if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
- pr_info("Disable IOMMU on Stoney Ridge\n");
- amd_iommu_disabled = true;
- break;
- }
- }
-
/* Disable any previously enabled IOMMUs */
if (!is_kdump_kernel() || amd_iommu_disabled)
disable_iommus();
@@ -2880,6 +2869,7 @@ static bool detect_ivrs(void)
{
struct acpi_table_header *ivrs_base;
acpi_status status;
+ int i;
status = acpi_get_table("IVRS", 0, &ivrs_base);
if (status == AE_NOT_FOUND)
@@ -2892,6 +2882,17 @@ static bool detect_ivrs(void)
acpi_put_table(ivrs_base);
+ /* Don't use IOMMU if there is Stoney Ridge graphics */
+ for (i = 0; i < 32; i++) {
+ u32 pci_id;
+
+ pci_id = read_pci_config(0, i, 0, 0);
+ if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
+ pr_info("Disable IOMMU on Stoney Ridge\n");
+ return false;
+ }
+ }
+
/* Make sure ACS will be enabled during PCI probe */
pci_request_acs();
@@ -2918,12 +2919,12 @@ static int __init state_next(void)
}
break;
case IOMMU_IVRS_DETECTED:
- ret = early_amd_iommu_init();
- init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
- if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
- pr_info("AMD IOMMU disabled\n");
+ if (amd_iommu_disabled) {
init_state = IOMMU_CMDLINE_DISABLED;
ret = -EINVAL;
+ } else {
+ ret = early_amd_iommu_init();
+ init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
}
break;
case IOMMU_ACPI_FINISHED:
@@ -3001,8 +3002,11 @@ int __init amd_iommu_prepare(void)
amd_iommu_irq_remap = true;
ret = iommu_go_to_state(IOMMU_ACPI_FINISHED);
- if (ret)
+ if (ret) {
+ amd_iommu_irq_remap = false;
return ret;
+ }
+
return amd_iommu_irq_remap ? 0 : -ENODEV;
}
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 97eb62f667d2..602aab98c079 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -849,12 +849,11 @@ static struct iommu_device *tegra_smmu_probe_device(struct device *dev)
smmu = tegra_smmu_find(args.np);
if (smmu) {
err = tegra_smmu_configure(smmu, dev, &args);
- of_node_put(args.np);
- if (err < 0)
+ if (err < 0) {
+ of_node_put(args.np);
return ERR_PTR(err);
-
- break;
+ }
}
of_node_put(args.np);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index e74fa206240a..15536e321df5 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -8,7 +8,6 @@ config IRQCHIP
config ARM_GIC
bool
select IRQ_DOMAIN_HIERARCHY
- select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_IRQ_EFFECTIVE_AFF_MASK
config ARM_GIC_PM
@@ -33,7 +32,6 @@ config GIC_NON_BANKED
config ARM_GIC_V3
bool
- select GENERIC_IRQ_MULTI_HANDLER
select IRQ_DOMAIN_HIERARCHY
select PARTITION_PERCPU
select GENERIC_IRQ_EFFECTIVE_AFF_MASK
@@ -64,7 +62,6 @@ config ARM_NVIC
config ARM_VIC
bool
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
config ARM_VIC_NR
int
@@ -99,14 +96,12 @@ config ATMEL_AIC_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
config ATMEL_AIC5_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
config I8259
@@ -153,7 +148,6 @@ config DW_APB_ICTL
config FARADAY_FTINTC010
bool
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
config HISILICON_IRQ_MBIGEN
@@ -169,7 +163,6 @@ config IMGPDC_IRQ
config IXP4XX_IRQ
bool
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
config MADERA_IRQ
@@ -186,7 +179,6 @@ config CLPS711X_IRQCHIP
bool
depends on ARCH_CLPS711X
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
default y
@@ -205,7 +197,6 @@ config OMAP_IRQCHIP
config ORION_IRQCHIP
bool
select IRQ_DOMAIN
- select GENERIC_IRQ_MULTI_HANDLER
config PIC32_EVIC
bool
diff --git a/drivers/irqchip/irq-ingenic-tcu.c b/drivers/irqchip/irq-ingenic-tcu.c
index 7a7222d4c19c..b938d1d04d96 100644
--- a/drivers/irqchip/irq-ingenic-tcu.c
+++ b/drivers/irqchip/irq-ingenic-tcu.c
@@ -179,5 +179,6 @@ err_free_tcu:
}
IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
+IRQCHIP_DECLARE(jz4760_tcu_irq, "ingenic,jz4760-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
IRQCHIP_DECLARE(x1000_tcu_irq, "ingenic,x1000-tcu", ingenic_tcu_irq_init);
diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c
index b61a8901ef72..ea36bb00be80 100644
--- a/drivers/irqchip/irq-ingenic.c
+++ b/drivers/irqchip/irq-ingenic.c
@@ -155,6 +155,7 @@ static int __init intc_2chip_of_init(struct device_node *node,
{
return ingenic_intc_of_init(node, 2);
}
+IRQCHIP_DECLARE(jz4760_intc, "ingenic,jz4760-intc", intc_2chip_of_init);
IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c
index d2ab6ab080ac..f62db7e520b5 100644
--- a/drivers/leds/trigger/ledtrig-tty.c
+++ b/drivers/leds/trigger/ledtrig-tty.c
@@ -51,10 +51,8 @@ static ssize_t ttyname_store(struct device *dev,
if (size) {
ttyname = kmemdup_nul(buf, size, GFP_KERNEL);
- if (!ttyname) {
- ret = -ENOMEM;
- goto out_unlock;
- }
+ if (!ttyname)
+ return -ENOMEM;
} else {
ttyname = NULL;
}
@@ -69,7 +67,6 @@ static ssize_t ttyname_store(struct device *dev,
trigger_data->ttyname = ttyname;
-out_unlock:
mutex_unlock(&trigger_data->mutex);
if (ttyname && !running)
@@ -125,12 +122,12 @@ static void ledtrig_tty_work(struct work_struct *work)
if (icount.rx != trigger_data->rx ||
icount.tx != trigger_data->tx) {
- led_set_brightness(trigger_data->led_cdev, LED_ON);
+ led_set_brightness_sync(trigger_data->led_cdev, LED_ON);
trigger_data->rx = icount.rx;
trigger_data->tx = icount.tx;
} else {
- led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ led_set_brightness_sync(trigger_data->led_cdev, LED_OFF);
}
out:
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 71691f32959b..03e1fe4de53d 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -965,7 +965,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
q->limits.max_hw_sectors = UINT_MAX;
q->limits.max_sectors = UINT_MAX;
q->limits.max_segment_size = UINT_MAX;
- q->limits.max_segments = BIO_MAX_PAGES;
+ q->limits.max_segments = BIO_MAX_VECS;
blk_queue_max_discard_sectors(q, UINT_MAX);
q->limits.discard_granularity = 512;
q->limits.io_min = block_size;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 11c105ecd165..b0ab080f2567 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -229,7 +229,7 @@ static DEFINE_SPINLOCK(dm_crypt_clients_lock);
static unsigned dm_crypt_clients_n = 0;
static volatile unsigned long dm_crypt_pages_per_client;
#define DM_CRYPT_MEMORY_PERCENT 2
-#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_PAGES * 16)
+#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_VECS * 16)
static void clone_init(struct dm_crypt_io *, struct bio *);
static void kcryptd_queue_crypt(struct dm_crypt_io *io);
@@ -3246,7 +3246,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ALIGN(sizeof(struct dm_crypt_io) + cc->dmreq_start + additional_req_size,
ARCH_KMALLOC_MINALIGN);
- ret = mempool_init(&cc->page_pool, BIO_MAX_PAGES, crypt_page_alloc, crypt_page_free, cc);
+ ret = mempool_init(&cc->page_pool, BIO_MAX_VECS, crypt_page_alloc, crypt_page_free, cc);
if (ret) {
ti->error = "Cannot allocate page mempool";
goto bad;
@@ -3373,9 +3373,9 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
/*
* Check if bio is too large, split as needed.
*/
- if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_PAGES << PAGE_SHIFT)) &&
+ if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_VECS << PAGE_SHIFT)) &&
(bio_data_dir(bio) == WRITE || cc->on_disk_tag_size))
- dm_accept_partial_bio(bio, ((BIO_MAX_PAGES << PAGE_SHIFT) >> SECTOR_SHIFT));
+ dm_accept_partial_bio(bio, ((BIO_MAX_VECS << PAGE_SHIFT) >> SECTOR_SHIFT));
/*
* Ensure that bio is a multiple of internal sector encryption size
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 844c4be11768..4f72b6f66c3a 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -1892,10 +1892,10 @@ restart:
list_add(&g->lru, &wbl.list);
wbl.size++;
g->write_in_progress = true;
- g->wc_list_contiguous = BIO_MAX_PAGES;
+ g->wc_list_contiguous = BIO_MAX_VECS;
f = g;
e->wc_list_contiguous++;
- if (unlikely(e->wc_list_contiguous == BIO_MAX_PAGES)) {
+ if (unlikely(e->wc_list_contiguous == BIO_MAX_VECS)) {
if (unlikely(wc->writeback_all)) {
next_node = rb_next(&f->rb_node);
if (likely(next_node))
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 4337ae0e6af2..0b5dcaabbc15 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -735,7 +735,7 @@ static void r5l_submit_current_io(struct r5l_log *log)
static struct bio *r5l_bio_alloc(struct r5l_log *log)
{
- struct bio *bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, &log->bs);
+ struct bio *bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_VECS, &log->bs);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
bio_set_dev(bio, log->rdev->bdev);
@@ -1634,7 +1634,7 @@ static int r5l_recovery_allocate_ra_pool(struct r5l_log *log,
{
struct page *page;
- ctx->ra_bio = bio_alloc_bioset(GFP_KERNEL, BIO_MAX_PAGES, &log->bs);
+ ctx->ra_bio = bio_alloc_bioset(GFP_KERNEL, BIO_MAX_VECS, &log->bs);
if (!ctx->ra_bio)
return -ENOMEM;
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c
index e8c118e05dfd..3ddc2aa0b530 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -496,7 +496,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
if (!bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0)) {
struct bio *prev = bio;
- bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES,
+ bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_VECS,
&ppl_conf->bs);
bio->bi_opf = prev->bi_opf;
bio->bi_write_hint = prev->bi_write_hint;
diff --git a/drivers/media/firewire/firedtv-fw.c b/drivers/media/firewire/firedtv-fw.c
index 8a8585261bb8..5f6e97a8d1c0 100644
--- a/drivers/media/firewire/firedtv-fw.c
+++ b/drivers/media/firewire/firedtv-fw.c
@@ -430,4 +430,3 @@ MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
MODULE_DESCRIPTION("FireDTV DVB Driver");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
index 692b95a685d1..9a82e68303b6 100644
--- a/drivers/media/pci/cx18/cx18-alsa-main.c
+++ b/drivers/media/pci/cx18/cx18-alsa-main.c
@@ -41,7 +41,6 @@ MODULE_PARM_DESC(debug,
MODULE_AUTHOR("Andy Walls");
MODULE_DESCRIPTION("CX23418 ALSA Interface");
-MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
MODULE_LICENSE("GPL");
MODULE_VERSION(CX18_VERSION);
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
index 95aed00f353b..f2440eb38820 100644
--- a/drivers/media/pci/cx18/cx18-driver.c
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -232,7 +232,6 @@ MODULE_PARM_DESC(cx18_first_minor,
MODULE_AUTHOR("Hans Verkuil");
MODULE_DESCRIPTION("CX23418 driver");
-MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
MODULE_LICENSE("GPL");
MODULE_VERSION(CX18_VERSION);
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index 608fbaf0f659..8797d85a6b0a 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -104,7 +104,6 @@ MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
MODULE_AUTHOR("Hiep Huynh");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); /* "{{Conexant,23881}," */
static unsigned int debug;
module_param(debug, int, 0644);
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 95e0cbb1277d..c83814c052d3 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -98,7 +98,6 @@ MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(CX88_VERSION);
-MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}");
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
index 39029b8e12c9..4cefdb2e4d40 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-main.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -38,7 +38,6 @@ MODULE_PARM_DESC(index,
MODULE_AUTHOR("Andy Walls");
MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface");
-MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder");
MODULE_LICENSE("GPL");
MODULE_VERSION(IVTV_VERSION);
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
index 6e448cb3b51c..942b8c266f50 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.c
+++ b/drivers/media/pci/ivtv/ivtv-driver.c
@@ -275,9 +275,6 @@ MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first car
MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
MODULE_DESCRIPTION("CX23415/CX23416 driver");
-MODULE_SUPPORTED_DEVICE
- ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n"
- "\t\t\tYuan MPG series and similar)");
MODULE_LICENSE("GPL");
MODULE_VERSION(IVTV_VERSION);
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 336df65c8af1..524912f20d9f 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -1269,6 +1269,5 @@ late_initcall_sync(sta2x11_vip_init_module);
MODULE_DESCRIPTION("STA2X11 Video Input Port driver");
MODULE_AUTHOR("Wind River");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("sta2x11 video input");
MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, sta2x11_vip_pci_tbl);
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index 0514be6153df..e392b3efe363 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -1363,4 +1363,3 @@ module_platform_driver(atmel_isi_driver);
MODULE_AUTHOR("Josh Wu <josh.wu@atmel.com>");
MODULE_DESCRIPTION("The V4L2 driver for Atmel Linux");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("video");
diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
index 0b78fecfd2a8..61d9885765f4 100644
--- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c
+++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
@@ -330,4 +330,3 @@ module_platform_driver(atmel_isc_driver);
MODULE_AUTHOR("Songjun Wu");
MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("video");
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
index 9c94a8b58b7c..baac86f3d153 100644
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -44,10 +44,6 @@
MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Video");
-
-
-
struct cafe_camera {
int registered; /* Fully initialized? */
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index aa5f45749543..a60c302ef267 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -1288,7 +1288,6 @@ static void rkisp1_params_config_parameter(struct rkisp1_params *params)
memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight));
rkisp1_hst_config(params, &hst);
rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP,
- ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK |
rkisp1_hst_params_default_config.mode);
/* set the range */
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index bbcc2254fa2e..d9b4ad0abf0c 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -2149,4 +2149,3 @@ MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@st.com>");
MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface driver");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("video");
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 86d5e3f4b1ff..06f74d410973 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -245,7 +245,7 @@ static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
brx = &vsp1->bru->entity;
else if (pipe->brx && !drm_pipe->force_brx_release)
brx = pipe->brx;
- else if (!vsp1->bru->entity.pipe)
+ else if (vsp1_feature(vsp1, VSP1_HAS_BRU) && !vsp1->bru->entity.pipe)
brx = &vsp1->bru->entity;
else
brx = &vsp1->brs->entity;
@@ -462,9 +462,9 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1,
* make sure it is present in the pipeline's list of entities if it
* wasn't already.
*/
- if (!use_uif) {
+ if (drm_pipe->uif && !use_uif) {
drm_pipe->uif->pipe = NULL;
- } else if (!drm_pipe->uif->pipe) {
+ } else if (drm_pipe->uif && !drm_pipe->uif->pipe) {
drm_pipe->uif->pipe = pipe;
list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
}
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 5bb2932ab119..ff6a8fc4c38e 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -5,6 +5,7 @@ obj-y += keymaps/
obj-$(CONFIG_RC_CORE) += rc-core.o
rc-core-y := rc-main.o rc-ir-raw.o
rc-core-$(CONFIG_LIRC) += lirc_dev.o
+rc-core-$(CONFIG_MEDIA_CEC_RC) += keymaps/rc-cec.o
rc-core-$(CONFIG_BPF_LIRC_MODE2) += bpf-lirc.o
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index b252a1d2ebd6..cc6662e1903f 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-behold.o \
rc-behold-columbus.o \
rc-budget-ci-old.o \
- rc-cec.o \
rc-cinergy-1400.o \
rc-cinergy.o \
rc-d680-dmb.o \
diff --git a/drivers/media/rc/keymaps/rc-cec.c b/drivers/media/rc/keymaps/rc-cec.c
index 3e3bd11092b4..068e22aeac8c 100644
--- a/drivers/media/rc/keymaps/rc-cec.c
+++ b/drivers/media/rc/keymaps/rc-cec.c
@@ -1,6 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* Keytable for the CEC remote control
*
+ * This keymap is unusual in that it can't be built as a module,
+ * instead it is registered directly in rc-main.c if CONFIG_MEDIA_CEC_RC
+ * is set. This is because it can be called from drm_dp_cec_set_edid() via
+ * cec_register_adapter() in an asynchronous context, and it is not
+ * allowed to use request_module() to load rc-cec.ko in that case.
+ *
+ * Since this keymap is only used if CONFIG_MEDIA_CEC_RC is set, we
+ * just compile this keymap into the rc-core module and never as a
+ * separate module.
+ *
* Copyright (c) 2015 by Kamil Debski
*/
@@ -152,7 +162,7 @@ static struct rc_map_table cec[] = {
/* 0x77-0xff: Reserved */
};
-static struct rc_map_list cec_map = {
+struct rc_map_list cec_map = {
.map = {
.scan = cec,
.size = ARRAY_SIZE(cec),
@@ -160,19 +170,3 @@ static struct rc_map_list cec_map = {
.name = RC_MAP_CEC,
}
};
-
-static int __init init_rc_map_cec(void)
-{
- return rc_map_register(&cec_map);
-}
-
-static void __exit exit_rc_map_cec(void)
-{
- rc_map_unregister(&cec_map);
-}
-
-module_init(init_rc_map_cec);
-module_exit(exit_rc_map_cec);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kamil Debski");
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 1fd62c1dac76..8e88dc8ea6c5 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -2069,6 +2069,9 @@ static int __init rc_core_init(void)
led_trigger_register_simple("rc-feedback", &led_feedback);
rc_map_register(&empty_map);
+#ifdef CONFIG_MEDIA_CEC_RC
+ rc_map_register(&cec_map);
+#endif
return 0;
}
@@ -2078,6 +2081,9 @@ static void __exit rc_core_exit(void)
lirc_dev_exit();
class_unregister(&rc_class);
led_trigger_unregister_simple(led_feedback);
+#ifdef CONFIG_MEDIA_CEC_RC
+ rc_map_unregister(&cec_map);
+#endif
rc_map_unregister(&empty_map);
}
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index e488e7870f42..69d5c628a797 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -56,7 +56,6 @@ MODULE_PARM_DESC(flicker_mode, "Flicker frequency (0 (disabled), " __stringify(5
MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
-MODULE_SUPPORTED_DEVICE("video");
MODULE_LICENSE("GPL");
MODULE_VERSION(CPIA_VERSION);
diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c
index 3a2df36ef1db..a19a46770c2b 100644
--- a/drivers/media/usb/tm6000/tm6000-alsa.c
+++ b/drivers/media/usb/tm6000/tm6000-alsa.c
@@ -51,7 +51,6 @@ MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},{{Trident,tm6000},{{Trident,tm6010}");
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c
index 293a460f4616..4990fa886d7a 100644
--- a/drivers/media/usb/tm6000/tm6000-dvb.c
+++ b/drivers/media/usb/tm6000/tm6000-dvb.c
@@ -23,8 +23,6 @@ MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV ca
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},{{Trident, tm6000},{{Trident, tm6010}");
-
static int debug;
module_param(debug, int, 0644);
diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c
index b57e94fb1977..333bd305a4f9 100644
--- a/drivers/media/usb/usbtv/usbtv-audio.c
+++ b/drivers/media/usb/usbtv/usbtv-audio.c
@@ -371,7 +371,7 @@ void usbtv_audio_free(struct usbtv *usbtv)
cancel_work_sync(&usbtv->snd_trigger);
if (usbtv->snd && usbtv->udev) {
- snd_card_free(usbtv->snd);
+ snd_card_free_when_closed(usbtv->snd);
usbtv->snd = NULL;
}
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b74efa469e90..7605bed6914e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -967,6 +967,17 @@ config MFD_VIPERBOARD
You need to select the mfd cell drivers separately.
The drivers do not support all features the board exposes.
+config MFD_NTXEC
+ tristate "Netronix embedded controller (EC)"
+ depends on OF || COMPILE_TEST
+ depends on I2C
+ select REGMAP_I2C
+ select MFD_CORE
+ help
+ Say yes here if you want to support the embedded controller found in
+ certain e-book readers designed by the original design manufacturer
+ Netronix.
+
config MFD_RETU
tristate "Nokia Retu and Tahvo multi-function device"
select MFD_CORE
@@ -1975,19 +1986,20 @@ config MFD_ROHM_BD70528
charger.
config MFD_ROHM_BD71828
- tristate "ROHM BD71828 Power Management IC"
+ tristate "ROHM BD71828 and BD71815 Power Management IC"
depends on I2C=y
depends on OF
select REGMAP_I2C
select REGMAP_IRQ
select MFD_CORE
help
- Select this option to get support for the ROHM BD71828 Power
- Management IC. BD71828GW is a single-chip power management IC for
- battery-powered portable devices. The IC integrates 7 buck
- converters, 7 LDOs, and a 1500 mA single-cell linear charger.
- Also included is a Coulomb counter, a real-time clock (RTC), and
- a 32.768 kHz clock gate.
+ Select this option to get support for the ROHM BD71828 and BD71815
+ Power Management ICs. BD71828GW and BD71815AGW are single-chip power
+ management ICs mainly for battery-powered portable devices.
+ The BD71828 integrates 7 buck converters and 7 LDOs. The BD71815
+ has 5 bucks, 7 LDOs, and a boost for driving LEDs. Both ICs provide
+ also a single-cell linear charger, a Coulomb counter, a real-time
+ clock (RTC), GPIOs and a 32.768 kHz clock gate.
config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer"
@@ -2055,6 +2067,24 @@ config MFD_WCD934X
This driver provides common support WCD934x audio codec and its
associated Pin Controller, Soundwire Controller and Audio codec.
+config MFD_ATC260X
+ tristate
+ select MFD_CORE
+ select REGMAP
+ select REGMAP_IRQ
+
+config MFD_ATC260X_I2C
+ tristate "Actions Semi ATC260x PMICs with I2C"
+ select MFD_ATC260X
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Support for the Actions Semi ATC260x PMICs controlled via I2C.
+
+ This driver provides common support for accessing the ATC2603C
+ and ATC2609A chip variants, additional drivers must be enabled
+ in order to use the functionality of the device.
+
config MFD_KHADAS_MCU
tristate "Support for Khadas System control Microcontroller"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 834f5463af28..20b7aeb71d38 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -218,6 +218,7 @@ obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o
obj-$(CONFIG_MFD_INTEL_PMT) += intel_pmt.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
+obj-$(CONFIG_MFD_NTXEC) += ntxec.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_RK808) += rk808.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
@@ -268,3 +269,6 @@ obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
+
+obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
+obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index a9037911162b..22c0e3d87629 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -19,7 +19,6 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/dbx500-prcmu.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -609,14 +608,14 @@ int ab8500_suspend(struct ab8500 *ab8500)
}
static const struct mfd_cell ab8500_bm_devs[] = {
- MFD_CELL_OF("ab8500-charger", NULL, &ab8500_bm_data,
- sizeof(ab8500_bm_data), 0, "stericsson,ab8500-charger"),
- MFD_CELL_OF("ab8500-btemp", NULL, &ab8500_bm_data,
- sizeof(ab8500_bm_data), 0, "stericsson,ab8500-btemp"),
- MFD_CELL_OF("ab8500-fg", NULL, &ab8500_bm_data,
- sizeof(ab8500_bm_data), 0, "stericsson,ab8500-fg"),
- MFD_CELL_OF("ab8500-chargalg", NULL, &ab8500_bm_data,
- sizeof(ab8500_bm_data), 0, "stericsson,ab8500-chargalg"),
+ MFD_CELL_OF("ab8500-charger", NULL, NULL, 0, 0,
+ "stericsson,ab8500-charger"),
+ MFD_CELL_OF("ab8500-btemp", NULL, NULL, 0, 0,
+ "stericsson,ab8500-btemp"),
+ MFD_CELL_OF("ab8500-fg", NULL, NULL, 0, 0,
+ "stericsson,ab8500-fg"),
+ MFD_CELL_OF("ab8500-chargalg", NULL, NULL, 0, 0,
+ "stericsson,ab8500-chargalg"),
};
static const struct mfd_cell ab8500_devs[] = {
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 75f1bc671d59..ce6fe6de34f8 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -881,11 +881,6 @@ static const char * const wm5102_supplies[] = {
static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
- {
- .name = "arizona-extcon",
- .parent_supplies = wm5102_supplies,
- .num_parent_supplies = 1, /* We only need MICVDD */
- },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@@ -898,11 +893,6 @@ static const struct mfd_cell wm5102_devs[] = {
static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
- {
- .name = "arizona-extcon",
- .parent_supplies = wm5102_supplies,
- .num_parent_supplies = 1, /* We only need MICVDD */
- },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@@ -939,11 +929,6 @@ static const char * const wm8997_supplies[] = {
static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
- {
- .name = "arizona-extcon",
- .parent_supplies = wm8997_supplies,
- .num_parent_supplies = 1, /* We only need MICVDD */
- },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
@@ -956,11 +941,6 @@ static const struct mfd_cell wm8997_devs[] = {
static const struct mfd_cell wm8998_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-gpio" },
- {
- .name = "arizona-extcon",
- .parent_supplies = wm5102_supplies,
- .num_parent_supplies = 1, /* We only need MICVDD */
- },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
diff --git a/drivers/mfd/atc260x-core.c b/drivers/mfd/atc260x-core.c
new file mode 100644
index 000000000000..7148ff5b05b1
--- /dev/null
+++ b/drivers/mfd/atc260x-core.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Core support for ATC260x PMICs
+ *
+ * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/atc260x/core.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#define ATC260X_CHIP_REV_MAX 31
+
+struct atc260x_init_regs {
+ unsigned int cmu_devrst;
+ unsigned int cmu_devrst_ints;
+ unsigned int ints_msk;
+ unsigned int pad_en;
+ unsigned int pad_en_extirq;
+};
+
+static void regmap_lock_mutex(void *__mutex)
+{
+ struct mutex *mutex = __mutex;
+
+ /*
+ * Using regmap within an atomic context (e.g. accessing a PMIC when
+ * powering system down) is normally allowed only if the regmap type
+ * is MMIO and the regcache type is either REGCACHE_NONE or
+ * REGCACHE_FLAT. For slow buses like I2C and SPI, the regmap is
+ * internally protected by a mutex which is acquired non-atomically.
+ *
+ * Let's improve this by using a customized locking scheme inspired
+ * from I2C atomic transfer. See i2c_in_atomic_xfer_mode() for a
+ * starting point.
+ */
+ if (system_state > SYSTEM_RUNNING && irqs_disabled())
+ mutex_trylock(mutex);
+ else
+ mutex_lock(mutex);
+}
+
+static void regmap_unlock_mutex(void *__mutex)
+{
+ struct mutex *mutex = __mutex;
+
+ mutex_unlock(mutex);
+}
+
+static const struct regmap_config atc2603c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = ATC2603C_SADDR,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_config atc2609a_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = ATC2609A_SADDR,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_irq atc2603c_regmap_irqs[] = {
+ REGMAP_IRQ_REG(ATC2603C_IRQ_AUDIO, 0, ATC2603C_INTS_MSK_AUDIO),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_OV, 0, ATC2603C_INTS_MSK_OV),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_OC, 0, ATC2603C_INTS_MSK_OC),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_OT, 0, ATC2603C_INTS_MSK_OT),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_UV, 0, ATC2603C_INTS_MSK_UV),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_ALARM, 0, ATC2603C_INTS_MSK_ALARM),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_ONOFF, 0, ATC2603C_INTS_MSK_ONOFF),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_SGPIO, 0, ATC2603C_INTS_MSK_SGPIO),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_IR, 0, ATC2603C_INTS_MSK_IR),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_REMCON, 0, ATC2603C_INTS_MSK_REMCON),
+ REGMAP_IRQ_REG(ATC2603C_IRQ_POWER_IN, 0, ATC2603C_INTS_MSK_POWERIN),
+};
+
+static const struct regmap_irq atc2609a_regmap_irqs[] = {
+ REGMAP_IRQ_REG(ATC2609A_IRQ_AUDIO, 0, ATC2609A_INTS_MSK_AUDIO),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_OV, 0, ATC2609A_INTS_MSK_OV),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_OC, 0, ATC2609A_INTS_MSK_OC),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_OT, 0, ATC2609A_INTS_MSK_OT),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_UV, 0, ATC2609A_INTS_MSK_UV),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_ALARM, 0, ATC2609A_INTS_MSK_ALARM),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_ONOFF, 0, ATC2609A_INTS_MSK_ONOFF),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_WKUP, 0, ATC2609A_INTS_MSK_WKUP),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_IR, 0, ATC2609A_INTS_MSK_IR),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_REMCON, 0, ATC2609A_INTS_MSK_REMCON),
+ REGMAP_IRQ_REG(ATC2609A_IRQ_POWER_IN, 0, ATC2609A_INTS_MSK_POWERIN),
+};
+
+static const struct regmap_irq_chip atc2603c_regmap_irq_chip = {
+ .name = "atc2603c",
+ .irqs = atc2603c_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(atc2603c_regmap_irqs),
+ .num_regs = 1,
+ .status_base = ATC2603C_INTS_PD,
+ .mask_base = ATC2603C_INTS_MSK,
+ .mask_invert = true,
+};
+
+static const struct regmap_irq_chip atc2609a_regmap_irq_chip = {
+ .name = "atc2609a",
+ .irqs = atc2609a_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(atc2609a_regmap_irqs),
+ .num_regs = 1,
+ .status_base = ATC2609A_INTS_PD,
+ .mask_base = ATC2609A_INTS_MSK,
+ .mask_invert = true,
+};
+
+static const struct resource atc2603c_onkey_resources[] = {
+ DEFINE_RES_IRQ(ATC2603C_IRQ_ONOFF),
+};
+
+static const struct resource atc2609a_onkey_resources[] = {
+ DEFINE_RES_IRQ(ATC2609A_IRQ_ONOFF),
+};
+
+static const struct mfd_cell atc2603c_mfd_cells[] = {
+ { .name = "atc260x-regulator" },
+ { .name = "atc260x-pwrc" },
+ {
+ .name = "atc260x-onkey",
+ .num_resources = ARRAY_SIZE(atc2603c_onkey_resources),
+ .resources = atc2603c_onkey_resources,
+ },
+};
+
+static const struct mfd_cell atc2609a_mfd_cells[] = {
+ { .name = "atc260x-regulator" },
+ { .name = "atc260x-pwrc" },
+ {
+ .name = "atc260x-onkey",
+ .num_resources = ARRAY_SIZE(atc2609a_onkey_resources),
+ .resources = atc2609a_onkey_resources,
+ },
+};
+
+static const struct atc260x_init_regs atc2603c_init_regs = {
+ .cmu_devrst = ATC2603C_CMU_DEVRST,
+ .cmu_devrst_ints = ATC2603C_CMU_DEVRST_INTS,
+ .ints_msk = ATC2603C_INTS_MSK,
+ .pad_en = ATC2603C_PAD_EN,
+ .pad_en_extirq = ATC2603C_PAD_EN_EXTIRQ,
+};
+
+static const struct atc260x_init_regs atc2609a_init_regs = {
+ .cmu_devrst = ATC2609A_CMU_DEVRST,
+ .cmu_devrst_ints = ATC2609A_CMU_DEVRST_INTS,
+ .ints_msk = ATC2609A_INTS_MSK,
+ .pad_en = ATC2609A_PAD_EN,
+ .pad_en_extirq = ATC2609A_PAD_EN_EXTIRQ,
+};
+
+static void atc260x_cmu_reset(struct atc260x *atc260x)
+{
+ const struct atc260x_init_regs *regs = atc260x->init_regs;
+
+ /* Assert reset */
+ regmap_update_bits(atc260x->regmap, regs->cmu_devrst,
+ regs->cmu_devrst_ints, ~regs->cmu_devrst_ints);
+
+ /* De-assert reset */
+ regmap_update_bits(atc260x->regmap, regs->cmu_devrst,
+ regs->cmu_devrst_ints, regs->cmu_devrst_ints);
+}
+
+static void atc260x_dev_init(struct atc260x *atc260x)
+{
+ const struct atc260x_init_regs *regs = atc260x->init_regs;
+
+ /* Initialize interrupt block */
+ atc260x_cmu_reset(atc260x);
+
+ /* Disable all interrupt sources */
+ regmap_write(atc260x->regmap, regs->ints_msk, 0);
+
+ /* Enable EXTIRQ pad */
+ regmap_update_bits(atc260x->regmap, regs->pad_en,
+ regs->pad_en_extirq, regs->pad_en_extirq);
+}
+
+/**
+ * atc260x_match_device(): Setup ATC260x variant related fields
+ *
+ * @atc260x: ATC260x device to setup (.dev field must be set)
+ * @regmap_cfg: regmap config associated with this ATC260x device
+ *
+ * This lets the ATC260x core configure the MFD cells and register maps
+ * for later use.
+ */
+int atc260x_match_device(struct atc260x *atc260x, struct regmap_config *regmap_cfg)
+{
+ struct device *dev = atc260x->dev;
+ const void *of_data;
+
+ of_data = of_device_get_match_data(dev);
+ if (!of_data)
+ return -ENODEV;
+
+ atc260x->ic_type = (unsigned long)of_data;
+
+ switch (atc260x->ic_type) {
+ case ATC2603C:
+ *regmap_cfg = atc2603c_regmap_config;
+ atc260x->regmap_irq_chip = &atc2603c_regmap_irq_chip;
+ atc260x->cells = atc2603c_mfd_cells;
+ atc260x->nr_cells = ARRAY_SIZE(atc2603c_mfd_cells);
+ atc260x->type_name = "atc2603c";
+ atc260x->rev_reg = ATC2603C_CHIP_VER;
+ atc260x->init_regs = &atc2603c_init_regs;
+ break;
+ case ATC2609A:
+ *regmap_cfg = atc2609a_regmap_config;
+ atc260x->regmap_irq_chip = &atc2609a_regmap_irq_chip;
+ atc260x->cells = atc2609a_mfd_cells;
+ atc260x->nr_cells = ARRAY_SIZE(atc2609a_mfd_cells);
+ atc260x->type_name = "atc2609a";
+ atc260x->rev_reg = ATC2609A_CHIP_VER;
+ atc260x->init_regs = &atc2609a_init_regs;
+ break;
+ default:
+ dev_err(dev, "Unsupported ATC260x device type: %u\n",
+ atc260x->ic_type);
+ return -EINVAL;
+ }
+
+ atc260x->regmap_mutex = devm_kzalloc(dev, sizeof(*atc260x->regmap_mutex),
+ GFP_KERNEL);
+ if (!atc260x->regmap_mutex)
+ return -ENOMEM;
+
+ mutex_init(atc260x->regmap_mutex);
+
+ regmap_cfg->lock = regmap_lock_mutex,
+ regmap_cfg->unlock = regmap_unlock_mutex,
+ regmap_cfg->lock_arg = atc260x->regmap_mutex;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(atc260x_match_device);
+
+/**
+ * atc260x_device_probe(): Probe a configured ATC260x device
+ *
+ * @atc260x: ATC260x device to probe (must be configured)
+ *
+ * This function lets the ATC260x core register the ATC260x MFD devices
+ * and IRQCHIP. The ATC260x device passed in must be fully configured
+ * with atc260x_match_device, its IRQ set, and regmap created.
+ */
+int atc260x_device_probe(struct atc260x *atc260x)
+{
+ struct device *dev = atc260x->dev;
+ unsigned int chip_rev;
+ int ret;
+
+ if (!atc260x->irq) {
+ dev_err(dev, "No interrupt support\n");
+ return -EINVAL;
+ }
+
+ /* Initialize the hardware */
+ atc260x_dev_init(atc260x);
+
+ ret = regmap_read(atc260x->regmap, atc260x->rev_reg, &chip_rev);
+ if (ret) {
+ dev_err(dev, "Failed to get chip revision\n");
+ return ret;
+ }
+
+ if (chip_rev > ATC260X_CHIP_REV_MAX) {
+ dev_err(dev, "Unknown chip revision: %u\n", chip_rev);
+ return -EINVAL;
+ }
+
+ atc260x->ic_ver = __ffs(chip_rev + 1U);
+
+ dev_info(dev, "Detected chip type %s rev.%c\n",
+ atc260x->type_name, 'A' + atc260x->ic_ver);
+
+ ret = devm_regmap_add_irq_chip(dev, atc260x->regmap, atc260x->irq, IRQF_ONESHOT,
+ -1, atc260x->regmap_irq_chip, &atc260x->irq_data);
+ if (ret) {
+ dev_err(dev, "Failed to add IRQ chip: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+ atc260x->cells, atc260x->nr_cells, NULL, 0,
+ regmap_irq_get_domain(atc260x->irq_data));
+ if (ret) {
+ dev_err(dev, "Failed to add child devices: %d\n", ret);
+ regmap_del_irq_chip(atc260x->irq, atc260x->irq_data);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(atc260x_device_probe);
+
+MODULE_DESCRIPTION("ATC260x PMICs Core support");
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c
new file mode 100644
index 000000000000..362005703367
--- /dev/null
+++ b/drivers/mfd/atc260x-i2c.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * I2C bus interface for ATC260x PMICs
+ *
+ * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/mfd/atc260x/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+static int atc260x_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct atc260x *atc260x;
+ struct regmap_config regmap_cfg;
+ int ret;
+
+ atc260x = devm_kzalloc(&client->dev, sizeof(*atc260x), GFP_KERNEL);
+ if (!atc260x)
+ return -ENOMEM;
+
+ atc260x->dev = &client->dev;
+ atc260x->irq = client->irq;
+
+ ret = atc260x_match_device(atc260x, &regmap_cfg);
+ if (ret)
+ return ret;
+
+ i2c_set_clientdata(client, atc260x);
+
+ atc260x->regmap = devm_regmap_init_i2c(client, &regmap_cfg);
+ if (IS_ERR(atc260x->regmap)) {
+ ret = PTR_ERR(atc260x->regmap);
+ dev_err(&client->dev, "failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ return atc260x_device_probe(atc260x);
+}
+
+const struct of_device_id atc260x_i2c_of_match[] = {
+ { .compatible = "actions,atc2603c", .data = (void *)ATC2603C },
+ { .compatible = "actions,atc2609a", .data = (void *)ATC2609A },
+ { }
+};
+MODULE_DEVICE_TABLE(of, atc260x_i2c_of_match);
+
+static struct i2c_driver atc260x_i2c_driver = {
+ .driver = {
+ .name = "atc260x",
+ .of_match_table = of_match_ptr(atc260x_i2c_of_match),
+ },
+ .probe = atc260x_i2c_probe,
+};
+module_i2c_driver(atc260x_i2c_driver);
+
+MODULE_DESCRIPTION("ATC260x PMICs I2C bus interface");
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c
new file mode 100644
index 000000000000..957de2b03529
--- /dev/null
+++ b/drivers/mfd/ntxec.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The Netronix embedded controller is a microcontroller found in some
+ * e-book readers designed by the original design manufacturer Netronix, Inc.
+ * It contains RTC, battery monitoring, system power management, and PWM
+ * functionality.
+ *
+ * This driver implements register access, version detection, and system
+ * power-off/reset.
+ *
+ * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ntxec.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#define NTXEC_REG_VERSION 0x00
+#define NTXEC_REG_POWEROFF 0x50
+#define NTXEC_REG_POWERKEEP 0x70
+#define NTXEC_REG_RESET 0x90
+
+#define NTXEC_POWEROFF_VALUE 0x0100
+#define NTXEC_POWERKEEP_VALUE 0x0800
+#define NTXEC_RESET_VALUE 0xff00
+
+static struct i2c_client *poweroff_restart_client;
+
+static void ntxec_poweroff(void)
+{
+ int res;
+ u8 buf[3] = { NTXEC_REG_POWEROFF };
+ struct i2c_msg msgs[] = {
+ {
+ .addr = poweroff_restart_client->addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ },
+ };
+
+ put_unaligned_be16(NTXEC_POWEROFF_VALUE, buf + 1);
+
+ res = i2c_transfer(poweroff_restart_client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (res < 0)
+ dev_warn(&poweroff_restart_client->dev,
+ "Failed to power off (err = %d)\n", res);
+
+ /*
+ * The time from the register write until the host CPU is powered off
+ * has been observed to be about 2.5 to 3 seconds. Sleep long enough to
+ * safely avoid returning from the poweroff handler.
+ */
+ msleep(5000);
+}
+
+static int ntxec_restart(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ int res;
+ u8 buf[3] = { NTXEC_REG_RESET };
+ /*
+ * NOTE: The lower half of the reset value is not sent, because sending
+ * it causes an I2C error. (The reset handler in the downstream driver
+ * does send the full two-byte value, but doesn't check the result).
+ */
+ struct i2c_msg msgs[] = {
+ {
+ .addr = poweroff_restart_client->addr,
+ .flags = 0,
+ .len = sizeof(buf) - 1,
+ .buf = buf,
+ },
+ };
+
+ put_unaligned_be16(NTXEC_RESET_VALUE, buf + 1);
+
+ res = i2c_transfer(poweroff_restart_client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (res < 0)
+ dev_warn(&poweroff_restart_client->dev,
+ "Failed to restart (err = %d)\n", res);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ntxec_restart_handler = {
+ .notifier_call = ntxec_restart,
+ .priority = 128,
+};
+
+static const struct regmap_config regmap_config = {
+ .name = "ntxec",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .cache_type = REGCACHE_NONE,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static const struct mfd_cell ntxec_subdevices[] = {
+ { .name = "ntxec-rtc" },
+ { .name = "ntxec-pwm" },
+};
+
+static int ntxec_probe(struct i2c_client *client)
+{
+ struct ntxec *ec;
+ unsigned int version;
+ int res;
+
+ ec = devm_kmalloc(&client->dev, sizeof(*ec), GFP_KERNEL);
+ if (!ec)
+ return -ENOMEM;
+
+ ec->dev = &client->dev;
+
+ ec->regmap = devm_regmap_init_i2c(client, &regmap_config);
+ if (IS_ERR(ec->regmap)) {
+ dev_err(ec->dev, "Failed to set up regmap for device\n");
+ return PTR_ERR(ec->regmap);
+ }
+
+ /* Determine the firmware version */
+ res = regmap_read(ec->regmap, NTXEC_REG_VERSION, &version);
+ if (res < 0) {
+ dev_err(ec->dev, "Failed to read firmware version number\n");
+ return res;
+ }
+
+ /* Bail out if we encounter an unknown firmware version */
+ switch (version) {
+ case NTXEC_VERSION_KOBO_AURA:
+ break;
+ default:
+ dev_err(ec->dev,
+ "Netronix embedded controller version %04x is not supported.\n",
+ version);
+ return -ENODEV;
+ }
+
+ dev_info(ec->dev,
+ "Netronix embedded controller version %04x detected.\n", version);
+
+ if (of_device_is_system_power_controller(ec->dev->of_node)) {
+ /*
+ * Set the 'powerkeep' bit. This is necessary on some boards
+ * in order to keep the system running.
+ */
+ res = regmap_write(ec->regmap, NTXEC_REG_POWERKEEP,
+ NTXEC_POWERKEEP_VALUE);
+ if (res < 0)
+ return res;
+
+ if (poweroff_restart_client)
+ /*
+ * Another instance of the driver already took
+ * poweroff/restart duties.
+ */
+ dev_err(ec->dev, "poweroff_restart_client already assigned\n");
+ else
+ poweroff_restart_client = client;
+
+ if (pm_power_off)
+ /* Another driver already registered a poweroff handler. */
+ dev_err(ec->dev, "pm_power_off already assigned\n");
+ else
+ pm_power_off = ntxec_poweroff;
+
+ res = register_restart_handler(&ntxec_restart_handler);
+ if (res)
+ dev_err(ec->dev,
+ "Failed to register restart handler: %d\n", res);
+ }
+
+ i2c_set_clientdata(client, ec);
+
+ res = devm_mfd_add_devices(ec->dev, PLATFORM_DEVID_NONE, ntxec_subdevices,
+ ARRAY_SIZE(ntxec_subdevices), NULL, 0, NULL);
+ if (res)
+ dev_err(ec->dev, "Failed to add subdevices: %d\n", res);
+
+ return res;
+}
+
+static int ntxec_remove(struct i2c_client *client)
+{
+ if (client == poweroff_restart_client) {
+ poweroff_restart_client = NULL;
+ pm_power_off = NULL;
+ unregister_restart_handler(&ntxec_restart_handler);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id of_ntxec_match_table[] = {
+ { .compatible = "netronix,ntxec", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, of_ntxec_match_table);
+
+static struct i2c_driver ntxec_driver = {
+ .driver = {
+ .name = "ntxec",
+ .of_match_table = of_ntxec_match_table,
+ },
+ .probe_new = ntxec_probe,
+ .remove = ntxec_remove,
+};
+module_i2c_driver(ntxec_driver);
+
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("Core driver for Netronix EC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c
index 210261d026f2..714d9fcbf07b 100644
--- a/drivers/mfd/rohm-bd71828.c
+++ b/drivers/mfd/rohm-bd71828.c
@@ -2,7 +2,7 @@
//
// Copyright (C) 2019 ROHM Semiconductors
//
-// ROHM BD71828 PMIC driver
+// ROHM BD71828/BD71815 PMIC driver
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
@@ -11,7 +11,9 @@
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
+#include <linux/mfd/rohm-bd71815.h>
#include <linux/mfd/rohm-bd71828.h>
+#include <linux/mfd/rohm-generic.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
@@ -29,12 +31,84 @@ static struct gpio_keys_platform_data bd71828_powerkey_data = {
.name = "bd71828-pwrkey",
};
-static const struct resource rtc_irqs[] = {
+static const struct resource bd71815_rtc_irqs[] = {
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC0, "bd71815-rtc-alm-0"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC1, "bd71815-rtc-alm-1"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC2, "bd71815-rtc-alm-2"),
+};
+
+static const struct resource bd71828_rtc_irqs[] = {
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"),
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"),
DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"),
};
+static struct resource bd71815_power_irqs[] = {
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_RMV, "bd71815-dcin-rmv"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-clps-out"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_IN, "bd71815-clps-in"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_RES, "bd71815-dcin-ovp-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_DET, "bd71815-dcin-ovp-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_MON_RES, "bd71815-dcin-mon-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_MON_DET, "bd71815-dcin-mon-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_UV_RES, "bd71815-vsys-uv-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_UV_DET, "bd71815-vsys-uv-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_RES, "bd71815-vsys-low-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_DET, "bd71815-vsys-low-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TEMP, "bd71815-chg-wdg-temp"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TIME, "bd71815-chg-wdg"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RECHARGE_RES, "bd71815-rechg-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RECHARGE_DET, "bd71815-rechg-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RANGED_TEMP_TRANSITION, "bd71815-ranged-temp-transit"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_STATE_TRANSITION, "bd71815-chg-state-change"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_TEMP_NORMAL, "bd71815-bat-temp-normal"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_TEMP_ERANGE, "bd71815-bat-temp-erange"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_REMOVED, "bd71815-bat-rmv"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_DETECTED, "bd71815-bat-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_THERM_REMOVED, "bd71815-therm-rmv"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_THERM_DETECTED, "bd71815-therm-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_DEAD, "bd71815-bat-dead"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_SHORTC_RES, "bd71815-bat-short-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_SHORTC_DET, "bd71815-bat-short-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_LOW_VOLT_RES, "bd71815-bat-low-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_LOW_VOLT_DET, "bd71815-bat-low-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_VOLT_RES, "bd71815-bat-over-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_VOLT_DET, "bd71815-bat-over-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_MON_RES, "bd71815-bat-mon-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_MON_DET, "bd71815-bat-mon-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON1, "bd71815-bat-cc-mon1"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON2, "bd71815-bat-cc-mon2"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON3, "bd71815-bat-cc-mon3"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_1_RES, "bd71815-bat-oc1-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_1_DET, "bd71815-bat-oc1-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_2_RES, "bd71815-bat-oc2-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_2_DET, "bd71815-bat-oc2-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_RES, "bd71815-bat-oc3-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_DET, "bd71815-bat-oc3-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_RES, "bd71815-bat-low-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_DET, "bd71815-bat-low-det"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_RES, "bd71815-bat-hi-res"),
+ DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_DET, "bd71815-bat-hi-det"),
+};
+
+static struct mfd_cell bd71815_mfd_cells[] = {
+ { .name = "bd71815-pmic", },
+ { .name = "bd71815-clk", },
+ { .name = "bd71815-gpo", },
+ {
+ .name = "bd71815-power",
+ .num_resources = ARRAY_SIZE(bd71815_power_irqs),
+ .resources = &bd71815_power_irqs[0],
+ },
+ {
+ .name = "bd71815-rtc",
+ .num_resources = ARRAY_SIZE(bd71815_rtc_irqs),
+ .resources = &bd71815_rtc_irqs[0],
+ },
+};
+
static struct mfd_cell bd71828_mfd_cells[] = {
{ .name = "bd71828-pmic", },
{ .name = "bd71828-gpio", },
@@ -47,8 +121,8 @@ static struct mfd_cell bd71828_mfd_cells[] = {
{ .name = "bd71827-power", },
{
.name = "bd71828-rtc",
- .resources = rtc_irqs,
- .num_resources = ARRAY_SIZE(rtc_irqs),
+ .resources = bd71828_rtc_irqs,
+ .num_resources = ARRAY_SIZE(bd71828_rtc_irqs),
}, {
.name = "gpio-keys",
.platform_data = &bd71828_powerkey_data,
@@ -56,7 +130,35 @@ static struct mfd_cell bd71828_mfd_cells[] = {
},
};
-static const struct regmap_range volatile_ranges[] = {
+static const struct regmap_range bd71815_volatile_ranges[] = {
+ {
+ .range_min = BD71815_REG_SEC,
+ .range_max = BD71815_REG_YEAR,
+ }, {
+ .range_min = BD71815_REG_CONF,
+ .range_max = BD71815_REG_BAT_TEMP,
+ }, {
+ .range_min = BD71815_REG_VM_IBAT_U,
+ .range_max = BD71815_REG_CC_CTRL,
+ }, {
+ .range_min = BD71815_REG_CC_STAT,
+ .range_max = BD71815_REG_CC_CURCD_L,
+ }, {
+ .range_min = BD71815_REG_VM_BTMP_MON,
+ .range_max = BD71815_REG_VM_BTMP_MON,
+ }, {
+ .range_min = BD71815_REG_INT_STAT,
+ .range_max = BD71815_REG_INT_UPDATE,
+ }, {
+ .range_min = BD71815_REG_VM_VSYS_U,
+ .range_max = BD71815_REG_REX_CTRL_1,
+ }, {
+ .range_min = BD71815_REG_FULL_CCNTD_3,
+ .range_max = BD71815_REG_CCNTD_CHG_2,
+ },
+};
+
+static const struct regmap_range bd71828_volatile_ranges[] = {
{
.range_min = BD71828_REG_PS_CTRL_1,
.range_max = BD71828_REG_PS_CTRL_1,
@@ -80,15 +182,28 @@ static const struct regmap_range volatile_ranges[] = {
},
};
-static const struct regmap_access_table volatile_regs = {
- .yes_ranges = &volatile_ranges[0],
- .n_yes_ranges = ARRAY_SIZE(volatile_ranges),
+static const struct regmap_access_table bd71815_volatile_regs = {
+ .yes_ranges = &bd71815_volatile_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(bd71815_volatile_ranges),
+};
+
+static const struct regmap_access_table bd71828_volatile_regs = {
+ .yes_ranges = &bd71828_volatile_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(bd71828_volatile_ranges),
+};
+
+static const struct regmap_config bd71815_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &bd71815_volatile_regs,
+ .max_register = BD71815_MAX_REGISTER - 1,
+ .cache_type = REGCACHE_RBTREE,
};
-static struct regmap_config bd71828_regmap = {
+static const struct regmap_config bd71828_regmap = {
.reg_bits = 8,
.val_bits = 8,
- .volatile_table = &volatile_regs,
+ .volatile_table = &bd71828_volatile_regs,
.max_register = BD71828_MAX_REGISTER,
.cache_type = REGCACHE_RBTREE,
};
@@ -96,7 +211,7 @@ static struct regmap_config bd71828_regmap = {
/*
* Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
* access corect sub-IRQ registers based on bits that are set in main IRQ
- * register.
+ * register. BD71815 and BD71828 have same sub-register-block offests.
*/
static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */
@@ -108,7 +223,7 @@ static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */
static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */
static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */
-static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = {
+static struct regmap_irq_sub_irq_map bd718xx_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
@@ -119,6 +234,88 @@ static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = {
REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
};
+static const struct regmap_irq bd71815_irqs[] = {
+ REGMAP_IRQ_REG(BD71815_INT_BUCK1_OCP, 0, BD71815_INT_BUCK1_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BUCK2_OCP, 0, BD71815_INT_BUCK2_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BUCK3_OCP, 0, BD71815_INT_BUCK3_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BUCK4_OCP, 0, BD71815_INT_BUCK4_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BUCK5_OCP, 0, BD71815_INT_BUCK5_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_LED_OVP, 0, BD71815_INT_LED_OVP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_LED_OCP, 0, BD71815_INT_LED_OCP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_LED_SCP, 0, BD71815_INT_LED_SCP_MASK),
+ /* DCIN1 interrupts */
+ REGMAP_IRQ_REG(BD71815_INT_DCIN_RMV, 1, BD71815_INT_DCIN_RMV_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CLPS_OUT, 1, BD71815_INT_CLPS_OUT_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CLPS_IN, 1, BD71815_INT_CLPS_IN_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_DCIN_OVP_RES, 1, BD71815_INT_DCIN_OVP_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_DCIN_OVP_DET, 1, BD71815_INT_DCIN_OVP_DET_MASK),
+ /* DCIN2 interrupts */
+ REGMAP_IRQ_REG(BD71815_INT_DCIN_MON_RES, 2, BD71815_INT_DCIN_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_DCIN_MON_DET, 2, BD71815_INT_DCIN_MON_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_WDOG, 2, BD71815_INT_WDOG_MASK),
+ /* Vsys */
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_UV_RES, 3, BD71815_INT_VSYS_UV_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_UV_DET, 3, BD71815_INT_VSYS_UV_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_LOW_RES, 3, BD71815_INT_VSYS_LOW_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_LOW_DET, 3, BD71815_INT_VSYS_LOW_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_MON_RES, 3, BD71815_INT_VSYS_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_VSYS_MON_DET, 3, BD71815_INT_VSYS_MON_DET_MASK),
+ /* Charger */
+ REGMAP_IRQ_REG(BD71815_INT_CHG_WDG_TEMP, 4, BD71815_INT_CHG_WDG_TEMP_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CHG_WDG_TIME, 4, BD71815_INT_CHG_WDG_TIME_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CHG_RECHARGE_RES, 4, BD71815_INT_CHG_RECHARGE_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CHG_RECHARGE_DET, 4, BD71815_INT_CHG_RECHARGE_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CHG_RANGED_TEMP_TRANSITION, 4,
+ BD71815_INT_CHG_RANGED_TEMP_TRANSITION_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_CHG_STATE_TRANSITION, 4, BD71815_INT_CHG_STATE_TRANSITION_MASK),
+ /* Battery */
+ REGMAP_IRQ_REG(BD71815_INT_BAT_TEMP_NORMAL, 5, BD71815_INT_BAT_TEMP_NORMAL_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_TEMP_ERANGE, 5, BD71815_INT_BAT_TEMP_ERANGE_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_REMOVED, 5, BD71815_INT_BAT_REMOVED_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_DETECTED, 5, BD71815_INT_BAT_DETECTED_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_THERM_REMOVED, 5, BD71815_INT_THERM_REMOVED_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_THERM_DETECTED, 5, BD71815_INT_THERM_DETECTED_MASK),
+ /* Battery Mon 1 */
+ REGMAP_IRQ_REG(BD71815_INT_BAT_DEAD, 6, BD71815_INT_BAT_DEAD_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_SHORTC_RES, 6, BD71815_INT_BAT_SHORTC_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_SHORTC_DET, 6, BD71815_INT_BAT_SHORTC_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_LOW_VOLT_RES, 6, BD71815_INT_BAT_LOW_VOLT_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_LOW_VOLT_DET, 6, BD71815_INT_BAT_LOW_VOLT_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_VOLT_RES, 6, BD71815_INT_BAT_OVER_VOLT_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_VOLT_DET, 6, BD71815_INT_BAT_OVER_VOLT_DET_MASK),
+ /* Battery Mon 2 */
+ REGMAP_IRQ_REG(BD71815_INT_BAT_MON_RES, 7, BD71815_INT_BAT_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_MON_DET, 7, BD71815_INT_BAT_MON_DET_MASK),
+ /* Battery Mon 3 (Coulomb counter) */
+ REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON1, 8, BD71815_INT_BAT_CC_MON1_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON2, 8, BD71815_INT_BAT_CC_MON2_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON3, 8, BD71815_INT_BAT_CC_MON3_MASK),
+ /* Battery Mon 4 */
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_1_RES, 9, BD71815_INT_BAT_OVER_CURR_1_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_1_DET, 9, BD71815_INT_BAT_OVER_CURR_1_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_2_RES, 9, BD71815_INT_BAT_OVER_CURR_2_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_2_DET, 9, BD71815_INT_BAT_OVER_CURR_2_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_3_RES, 9, BD71815_INT_BAT_OVER_CURR_3_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_3_DET, 9, BD71815_INT_BAT_OVER_CURR_3_DET_MASK),
+ /* Temperature */
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_LOW_RES, 10, BD71815_INT_TEMP_BAT_LOW_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_LOW_DET, 10, BD71815_INT_TEMP_BAT_LOW_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_HI_RES, 10, BD71815_INT_TEMP_BAT_HI_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_HI_DET, 10, BD71815_INT_TEMP_BAT_HI_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_125_RES, 10,
+ BD71815_INT_TEMP_CHIP_OVER_125_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_125_DET, 10,
+ BD71815_INT_TEMP_CHIP_OVER_125_DET_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_VF_RES, 10,
+ BD71815_INT_TEMP_CHIP_OVER_VF_RES_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_VF_DET, 10,
+ BD71815_INT_TEMP_CHIP_OVER_VF_DET_MASK),
+ /* RTC Alarm */
+ REGMAP_IRQ_REG(BD71815_INT_RTC0, 11, BD71815_INT_RTC0_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_RTC1, 11, BD71815_INT_RTC1_MASK),
+ REGMAP_IRQ_REG(BD71815_INT_RTC2, 11, BD71815_INT_RTC2_MASK),
+};
+
static struct regmap_irq bd71828_irqs[] = {
REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK),
REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK),
@@ -134,10 +331,8 @@ static struct regmap_irq bd71828_irqs[] = {
REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK),
REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK),
/* DCIN2 interrupts */
- REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2,
- BD71828_INT_DCIN_MON_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2,
- BD71828_INT_DCIN_MON_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2, BD71828_INT_DCIN_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2, BD71828_INT_DCIN_MON_DET_MASK),
REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK),
REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK),
REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK),
@@ -145,102 +340,59 @@ static struct regmap_irq bd71828_irqs[] = {
REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK),
REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK),
/* Vsys */
- REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3,
- BD71828_INT_VSYS_UV_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3,
- BD71828_INT_VSYS_UV_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3,
- BD71828_INT_VSYS_LOW_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3,
- BD71828_INT_VSYS_LOW_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3,
- BD71828_INT_VSYS_HALL_IN_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3,
- BD71828_INT_VSYS_HALL_TOGGLE_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3,
- BD71828_INT_VSYS_MON_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3,
- BD71828_INT_VSYS_MON_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3, BD71828_INT_VSYS_UV_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3, BD71828_INT_VSYS_UV_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3, BD71828_INT_VSYS_LOW_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3, BD71828_INT_VSYS_LOW_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3, BD71828_INT_VSYS_HALL_IN_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3, BD71828_INT_VSYS_HALL_TOGGLE_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3, BD71828_INT_VSYS_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3, BD71828_INT_VSYS_MON_DET_MASK),
/* Charger */
- REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4,
- BD71828_INT_CHG_DCIN_ILIM_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4,
- BD71828_INT_CHG_TOPOFF_TO_DONE_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4,
- BD71828_INT_CHG_WDG_TEMP_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4,
- BD71828_INT_CHG_WDG_TIME_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4,
- BD71828_INT_CHG_RECHARGE_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4,
- BD71828_INT_CHG_RECHARGE_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4, BD71828_INT_CHG_DCIN_ILIM_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4, BD71828_INT_CHG_TOPOFF_TO_DONE_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4, BD71828_INT_CHG_WDG_TEMP_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4, BD71828_INT_CHG_WDG_TIME_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4, BD71828_INT_CHG_RECHARGE_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4, BD71828_INT_CHG_RECHARGE_DET_MASK),
REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4,
BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK),
- REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4,
- BD71828_INT_CHG_STATE_TRANSITION_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4, BD71828_INT_CHG_STATE_TRANSITION_MASK),
/* Battery */
- REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5,
- BD71828_INT_BAT_TEMP_NORMAL_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5,
- BD71828_INT_BAT_TEMP_ERANGE_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5,
- BD71828_INT_BAT_TEMP_WARN_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5,
- BD71828_INT_BAT_REMOVED_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5,
- BD71828_INT_BAT_DETECTED_MASK),
- REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5,
- BD71828_INT_THERM_REMOVED_MASK),
- REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5,
- BD71828_INT_THERM_DETECTED_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5, BD71828_INT_BAT_TEMP_NORMAL_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5, BD71828_INT_BAT_TEMP_ERANGE_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5, BD71828_INT_BAT_TEMP_WARN_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5, BD71828_INT_BAT_REMOVED_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5, BD71828_INT_BAT_DETECTED_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5, BD71828_INT_THERM_REMOVED_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5, BD71828_INT_THERM_DETECTED_MASK),
/* Battery Mon 1 */
REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6,
- BD71828_INT_BAT_SHORTC_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6,
- BD71828_INT_BAT_SHORTC_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6,
- BD71828_INT_BAT_LOW_VOLT_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6,
- BD71828_INT_BAT_LOW_VOLT_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6,
- BD71828_INT_BAT_OVER_VOLT_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6,
- BD71828_INT_BAT_OVER_VOLT_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6, BD71828_INT_BAT_SHORTC_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6, BD71828_INT_BAT_SHORTC_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6, BD71828_INT_BAT_LOW_VOLT_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6, BD71828_INT_BAT_LOW_VOLT_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6, BD71828_INT_BAT_OVER_VOLT_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6, BD71828_INT_BAT_OVER_VOLT_DET_MASK),
/* Battery Mon 2 */
- REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7,
- BD71828_INT_BAT_MON_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7,
- BD71828_INT_BAT_MON_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7, BD71828_INT_BAT_MON_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7, BD71828_INT_BAT_MON_DET_MASK),
/* Battery Mon 3 (Coulomb counter) */
- REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8,
- BD71828_INT_BAT_CC_MON1_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8,
- BD71828_INT_BAT_CC_MON2_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8,
- BD71828_INT_BAT_CC_MON3_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8, BD71828_INT_BAT_CC_MON1_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8, BD71828_INT_BAT_CC_MON2_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8, BD71828_INT_BAT_CC_MON3_MASK),
/* Battery Mon 4 */
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9,
- BD71828_INT_BAT_OVER_CURR_1_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9,
- BD71828_INT_BAT_OVER_CURR_1_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9,
- BD71828_INT_BAT_OVER_CURR_2_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9,
- BD71828_INT_BAT_OVER_CURR_2_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9,
- BD71828_INT_BAT_OVER_CURR_3_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9,
- BD71828_INT_BAT_OVER_CURR_3_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9, BD71828_INT_BAT_OVER_CURR_1_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9, BD71828_INT_BAT_OVER_CURR_1_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9, BD71828_INT_BAT_OVER_CURR_2_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9, BD71828_INT_BAT_OVER_CURR_2_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9, BD71828_INT_BAT_OVER_CURR_3_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9, BD71828_INT_BAT_OVER_CURR_3_DET_MASK),
/* Temperature */
- REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10,
- BD71828_INT_TEMP_BAT_LOW_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10,
- BD71828_INT_TEMP_BAT_LOW_DET_MASK),
- REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10,
- BD71828_INT_TEMP_BAT_HI_RES_MASK),
- REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10,
- BD71828_INT_TEMP_BAT_HI_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10, BD71828_INT_TEMP_BAT_LOW_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10, BD71828_INT_TEMP_BAT_LOW_DET_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10, BD71828_INT_TEMP_BAT_HI_RES_MASK),
+ REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10, BD71828_INT_TEMP_BAT_HI_DET_MASK),
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10,
BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK),
REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10,
@@ -267,57 +419,133 @@ static struct regmap_irq_chip bd71828_irq_chip = {
.init_ack_masked = true,
.num_regs = 12,
.num_main_regs = 1,
- .sub_reg_offsets = &bd71828_sub_irq_offsets[0],
+ .sub_reg_offsets = &bd718xx_sub_irq_offsets[0],
+ .num_main_status_bits = 8,
+ .irq_reg_stride = 1,
+};
+
+static struct regmap_irq_chip bd71815_irq_chip = {
+ .name = "bd71815_irq",
+ .main_status = BD71815_REG_INT_STAT,
+ .irqs = &bd71815_irqs[0],
+ .num_irqs = ARRAY_SIZE(bd71815_irqs),
+ .status_base = BD71815_REG_INT_STAT_01,
+ .mask_base = BD71815_REG_INT_EN_01,
+ .ack_base = BD71815_REG_INT_STAT_01,
+ .mask_invert = true,
+ .init_ack_masked = true,
+ .num_regs = 12,
+ .num_main_regs = 1,
+ .sub_reg_offsets = &bd718xx_sub_irq_offsets[0],
.num_main_status_bits = 8,
.irq_reg_stride = 1,
};
+static int set_clk_mode(struct device *dev, struct regmap *regmap,
+ int clkmode_reg)
+{
+ int ret;
+ unsigned int open_drain;
+
+ ret = of_property_read_u32(dev->of_node, "rohm,clkout-open-drain", &open_drain);
+ if (ret) {
+ if (ret == -EINVAL)
+ return 0;
+ return ret;
+ }
+ if (open_drain > 1) {
+ dev_err(dev, "bad clk32kout mode configuration");
+ return -EINVAL;
+ }
+
+ if (open_drain)
+ return regmap_update_bits(regmap, clkmode_reg, OUT32K_MODE,
+ OUT32K_MODE_OPEN_DRAIN);
+
+ return regmap_update_bits(regmap, clkmode_reg, OUT32K_MODE,
+ OUT32K_MODE_CMOS);
+}
+
static int bd71828_i2c_probe(struct i2c_client *i2c)
{
- struct rohm_regmap_dev *chip;
struct regmap_irq_chip_data *irq_data;
int ret;
+ struct regmap *regmap;
+ const struct regmap_config *regmap_config;
+ struct regmap_irq_chip *irqchip;
+ unsigned int chip_type;
+ struct mfd_cell *mfd;
+ int cells;
+ int button_irq;
+ int clkmode_reg;
if (!i2c->irq) {
dev_err(&i2c->dev, "No IRQ configured\n");
return -EINVAL;
}
- chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- dev_set_drvdata(&i2c->dev, chip);
+ chip_type = (unsigned int)(uintptr_t)
+ of_device_get_match_data(&i2c->dev);
+ switch (chip_type) {
+ case ROHM_CHIP_TYPE_BD71828:
+ mfd = bd71828_mfd_cells;
+ cells = ARRAY_SIZE(bd71828_mfd_cells);
+ regmap_config = &bd71828_regmap;
+ irqchip = &bd71828_irq_chip;
+ clkmode_reg = BD71828_REG_OUT32K;
+ button_irq = BD71828_INT_SHORTPUSH;
+ break;
+ case ROHM_CHIP_TYPE_BD71815:
+ mfd = bd71815_mfd_cells;
+ cells = ARRAY_SIZE(bd71815_mfd_cells);
+ regmap_config = &bd71815_regmap;
+ irqchip = &bd71815_irq_chip;
+ clkmode_reg = BD71815_REG_OUT32K;
+ /*
+ * If BD71817 support is needed we should be able to handle it
+ * with proper DT configs + BD71815 drivers + power-button.
+ * BD71815 data-sheet does not list the power-button IRQ so we
+ * don't use it.
+ */
+ button_irq = 0;
+ break;
+ default:
+ dev_err(&i2c->dev, "Unknown device type");
+ return -EINVAL;
+ }
- chip->regmap = devm_regmap_init_i2c(i2c, &bd71828_regmap);
- if (IS_ERR(chip->regmap)) {
+ regmap = devm_regmap_init_i2c(i2c, regmap_config);
+ if (IS_ERR(regmap)) {
dev_err(&i2c->dev, "Failed to initialize Regmap\n");
- return PTR_ERR(chip->regmap);
+ return PTR_ERR(regmap);
}
- ret = devm_regmap_add_irq_chip(&i2c->dev, chip->regmap,
- i2c->irq, IRQF_ONESHOT, 0,
- &bd71828_irq_chip, &irq_data);
+ ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, i2c->irq,
+ IRQF_ONESHOT, 0, irqchip, &irq_data);
if (ret) {
dev_err(&i2c->dev, "Failed to add IRQ chip\n");
return ret;
}
dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n",
- bd71828_irq_chip.num_irqs);
+ irqchip->num_irqs);
- ret = regmap_irq_get_virq(irq_data, BD71828_INT_SHORTPUSH);
- if (ret < 0) {
- dev_err(&i2c->dev, "Failed to get the power-key IRQ\n");
- return ret;
+ if (button_irq) {
+ ret = regmap_irq_get_virq(irq_data, button_irq);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to get the power-key IRQ\n");
+ return ret;
+ }
+
+ button.irq = ret;
}
- button.irq = ret;
+ ret = set_clk_mode(&i2c->dev, regmap, clkmode_reg);
+ if (ret)
+ return ret;
- ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
- bd71828_mfd_cells,
- ARRAY_SIZE(bd71828_mfd_cells), NULL, 0,
- regmap_irq_get_domain(irq_data));
+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, mfd, cells,
+ NULL, 0, regmap_irq_get_domain(irq_data));
if (ret)
dev_err(&i2c->dev, "Failed to create subdevices\n");
@@ -325,7 +553,13 @@ static int bd71828_i2c_probe(struct i2c_client *i2c)
}
static const struct of_device_id bd71828_of_match[] = {
- { .compatible = "rohm,bd71828", },
+ {
+ .compatible = "rohm,bd71828",
+ .data = (void *)ROHM_CHIP_TYPE_BD71828,
+ }, {
+ .compatible = "rohm,bd71815",
+ .data = (void *)ROHM_CHIP_TYPE_BD71815,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, bd71828_of_match);
diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c
index c32c1b6c98fa..bfd81f78beae 100644
--- a/drivers/mfd/rohm-bd718x7.c
+++ b/drivers/mfd/rohm-bd718x7.c
@@ -91,9 +91,9 @@ static const struct regmap_config bd718xx_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int bd718xx_init_press_duration(struct bd718xx *bd718xx)
+static int bd718xx_init_press_duration(struct regmap *regmap,
+ struct device *dev)
{
- struct device* dev = bd718xx->chip.dev;
u32 short_press_ms, long_press_ms;
u32 short_press_value, long_press_value;
int ret;
@@ -102,8 +102,7 @@ static int bd718xx_init_press_duration(struct bd718xx *bd718xx)
&short_press_ms);
if (!ret) {
short_press_value = min(15u, (short_press_ms + 250) / 500);
- ret = regmap_update_bits(bd718xx->chip.regmap,
- BD718XX_REG_PWRONCONFIG0,
+ ret = regmap_update_bits(regmap, BD718XX_REG_PWRONCONFIG0,
BD718XX_PWRBTN_PRESS_DURATION_MASK,
short_press_value);
if (ret) {
@@ -116,8 +115,7 @@ static int bd718xx_init_press_duration(struct bd718xx *bd718xx)
&long_press_ms);
if (!ret) {
long_press_value = min(15u, (long_press_ms + 500) / 1000);
- ret = regmap_update_bits(bd718xx->chip.regmap,
- BD718XX_REG_PWRONCONFIG1,
+ ret = regmap_update_bits(regmap, BD718XX_REG_PWRONCONFIG1,
BD718XX_PWRBTN_PRESS_DURATION_MASK,
long_press_value);
if (ret) {
@@ -132,7 +130,8 @@ static int bd718xx_init_press_duration(struct bd718xx *bd718xx)
static int bd718xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct bd718xx *bd718xx;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *irq_data;
int ret;
unsigned int chip_type;
struct mfd_cell *mfd;
@@ -142,13 +141,6 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
dev_err(&i2c->dev, "No IRQ configured\n");
return -EINVAL;
}
-
- bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL);
-
- if (!bd718xx)
- return -ENOMEM;
-
- bd718xx->chip_irq = i2c->irq;
chip_type = (unsigned int)(uintptr_t)
of_device_get_match_data(&i2c->dev);
switch (chip_type) {
@@ -164,29 +156,26 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
dev_err(&i2c->dev, "Unknown device type");
return -EINVAL;
}
- bd718xx->chip.dev = &i2c->dev;
- dev_set_drvdata(&i2c->dev, bd718xx);
- bd718xx->chip.regmap = devm_regmap_init_i2c(i2c,
- &bd718xx_regmap_config);
- if (IS_ERR(bd718xx->chip.regmap)) {
+ regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config);
+ if (IS_ERR(regmap)) {
dev_err(&i2c->dev, "regmap initialization failed\n");
- return PTR_ERR(bd718xx->chip.regmap);
+ return PTR_ERR(regmap);
}
- ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->chip.regmap,
- bd718xx->chip_irq, IRQF_ONESHOT, 0,
- &bd718xx_irq_chip, &bd718xx->irq_data);
+ ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, i2c->irq,
+ IRQF_ONESHOT, 0, &bd718xx_irq_chip,
+ &irq_data);
if (ret) {
dev_err(&i2c->dev, "Failed to add irq_chip\n");
return ret;
}
- ret = bd718xx_init_press_duration(bd718xx);
+ ret = bd718xx_init_press_duration(regmap, &i2c->dev);
if (ret)
return ret;
- ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S);
+ ret = regmap_irq_get_virq(irq_data, BD718XX_INT_PWRBTN_S);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to get the IRQ\n");
@@ -195,9 +184,9 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c,
button.irq = ret;
- ret = devm_mfd_add_devices(bd718xx->chip.dev, PLATFORM_DEVID_AUTO,
+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
mfd, cells, NULL, 0,
- regmap_irq_get_domain(bd718xx->irq_data));
+ regmap_irq_get_domain(irq_data));
if (ret)
dev_err(&i2c->dev, "Failed to create subdevices\n");
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index f12e909034ac..beda610e6b30 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -950,6 +950,11 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
if (!fl->cctx->rpdev)
return -EPIPE;
+ if (handle == FASTRPC_INIT_HANDLE && !kernel) {
+ dev_warn_ratelimited(fl->sctx->dev, "user app trying to send a kernel RPC message (%d)\n", handle);
+ return -EPERM;
+ }
+
ctx = fastrpc_context_alloc(fl, kernel, sc, args);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/misc/habanalabs/common/debugfs.c
index df847a6d19f4..9f19bee7b592 100644
--- a/drivers/misc/habanalabs/common/debugfs.c
+++ b/drivers/misc/habanalabs/common/debugfs.c
@@ -992,7 +992,6 @@ void hl_debugfs_add_device(struct hl_device *hdev)
struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
int count = ARRAY_SIZE(hl_debugfs_list);
struct hl_debugfs_entry *entry;
- struct dentry *ent;
int i;
dev_entry->hdev = hdev;
@@ -1105,13 +1104,11 @@ void hl_debugfs_add_device(struct hl_device *hdev)
&hl_security_violations_fops);
for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
-
- ent = debugfs_create_file(hl_debugfs_list[i].name,
+ debugfs_create_file(hl_debugfs_list[i].name,
0444,
dev_entry->root,
entry,
&hl_debugfs_fops);
- entry->dent = ent;
entry->info_ent = &hl_debugfs_list[i];
entry->dev_entry = dev_entry;
}
diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c
index 15fcb5c31c4b..334009e83823 100644
--- a/drivers/misc/habanalabs/common/device.c
+++ b/drivers/misc/habanalabs/common/device.c
@@ -93,12 +93,19 @@ void hl_hpriv_put(struct hl_fpriv *hpriv)
static int hl_device_release(struct inode *inode, struct file *filp)
{
struct hl_fpriv *hpriv = filp->private_data;
+ struct hl_device *hdev = hpriv->hdev;
+
+ filp->private_data = NULL;
+
+ if (!hdev) {
+ pr_crit("Closing FD after device was removed. Memory leak will occur and it is advised to reboot.\n");
+ put_pid(hpriv->taskpid);
+ return 0;
+ }
hl_cb_mgr_fini(hpriv->hdev, &hpriv->cb_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
- filp->private_data = NULL;
-
hl_hpriv_put(hpriv);
return 0;
@@ -107,15 +114,20 @@ static int hl_device_release(struct inode *inode, struct file *filp)
static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
{
struct hl_fpriv *hpriv = filp->private_data;
- struct hl_device *hdev;
+ struct hl_device *hdev = hpriv->hdev;
filp->private_data = NULL;
- hdev = hpriv->hdev;
+ if (!hdev) {
+ pr_err("Closing FD after device was removed\n");
+ goto out;
+ }
mutex_lock(&hdev->fpriv_list_lock);
list_del(&hpriv->dev_node);
mutex_unlock(&hdev->fpriv_list_lock);
+out:
+ put_pid(hpriv->taskpid);
kfree(hpriv);
@@ -134,8 +146,14 @@ static int hl_device_release_ctrl(struct inode *inode, struct file *filp)
static int hl_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct hl_fpriv *hpriv = filp->private_data;
+ struct hl_device *hdev = hpriv->hdev;
unsigned long vm_pgoff;
+ if (!hdev) {
+ pr_err_ratelimited("Trying to mmap after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
vm_pgoff = vma->vm_pgoff;
vma->vm_pgoff = HL_MMAP_OFFSET_VALUE_GET(vm_pgoff);
@@ -883,6 +901,16 @@ wait_for_processes:
return -EBUSY;
}
+static void device_disable_open_processes(struct hl_device *hdev)
+{
+ struct hl_fpriv *hpriv;
+
+ mutex_lock(&hdev->fpriv_list_lock);
+ list_for_each_entry(hpriv, &hdev->fpriv_list, dev_node)
+ hpriv->hdev = NULL;
+ mutex_unlock(&hdev->fpriv_list_lock);
+}
+
/*
* hl_device_reset - reset the device
*
@@ -1556,8 +1584,10 @@ void hl_device_fini(struct hl_device *hdev)
HL_PENDING_RESET_LONG_SEC);
rc = device_kill_open_processes(hdev, HL_PENDING_RESET_LONG_SEC);
- if (rc)
+ if (rc) {
dev_crit(hdev->dev, "Failed to kill all open processes\n");
+ device_disable_open_processes(hdev);
+ }
hl_cb_pool_fini(hdev);
diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h
index d933878b24d1..4b321e4f8059 100644
--- a/drivers/misc/habanalabs/common/habanalabs.h
+++ b/drivers/misc/habanalabs/common/habanalabs.h
@@ -1465,12 +1465,10 @@ struct hl_info_list {
/**
* struct hl_debugfs_entry - debugfs dentry wrapper.
- * @dent: base debugfs entry structure.
* @info_ent: dentry realted ops.
* @dev_entry: ASIC specific debugfs manager.
*/
struct hl_debugfs_entry {
- struct dentry *dent;
const struct hl_info_list *info_ent;
struct hl_dbg_device_entry *dev_entry;
};
diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
index 03af61cecd37..083a30969c5f 100644
--- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
@@ -5,6 +5,8 @@
* All Rights Reserved.
*/
+#define pr_fmt(fmt) "habanalabs: " fmt
+
#include <uapi/misc/habanalabs.h>
#include "habanalabs.h"
@@ -682,6 +684,11 @@ long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
const struct hl_ioctl_desc *ioctl = NULL;
unsigned int nr = _IOC_NR(cmd);
+ if (!hdev) {
+ pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
ioctl = &hl_ioctls[nr];
} else {
@@ -700,6 +707,11 @@ long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
const struct hl_ioctl_desc *ioctl = NULL;
unsigned int nr = _IOC_NR(cmd);
+ if (!hdev) {
+ pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n");
+ return -ENODEV;
+ }
+
if (nr == _IOC_NR(HL_IOCTL_INFO)) {
ioctl = &hl_ioctls_control[nr];
} else {
diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/misc/habanalabs/common/irq.c
index de53fb5f978a..44a0522b59b9 100644
--- a/drivers/misc/habanalabs/common/irq.c
+++ b/drivers/misc/habanalabs/common/irq.c
@@ -47,7 +47,7 @@ inline u32 hl_cq_inc_ptr(u32 ptr)
* Increment ptr by 1. If it reaches the number of event queue
* entries, set it to 0
*/
-inline u32 hl_eq_inc_ptr(u32 ptr)
+static inline u32 hl_eq_inc_ptr(u32 ptr)
{
ptr++;
if (unlikely(ptr == HL_EQ_LENGTH))
diff --git a/drivers/misc/habanalabs/common/mmu/mmu.c b/drivers/misc/habanalabs/common/mmu/mmu.c
index 71703a32350f..93c9e5f587e1 100644
--- a/drivers/misc/habanalabs/common/mmu/mmu.c
+++ b/drivers/misc/habanalabs/common/mmu/mmu.c
@@ -499,18 +499,32 @@ static void hl_mmu_pa_page_with_offset(struct hl_ctx *ctx, u64 virt_addr,
else /* HL_VA_RANGE_TYPE_DRAM */
p = &prop->dmmu;
- /*
- * find the correct hop shift field in hl_mmu_properties structure
- * in order to determine the right maks for the page offset.
- */
- hop0_shift_off = offsetof(struct hl_mmu_properties, hop0_shift);
- p = (char *)p + hop0_shift_off;
- p = (char *)p + ((hops->used_hops - 1) * sizeof(u64));
- hop_shift = *(u64 *)p;
- offset_mask = (1ull << hop_shift) - 1;
- addr_mask = ~(offset_mask);
- *phys_addr = (tmp_phys_addr & addr_mask) |
- (virt_addr & offset_mask);
+ if ((hops->range_type == HL_VA_RANGE_TYPE_DRAM) &&
+ !is_power_of_2(prop->dram_page_size)) {
+ u32 bit;
+ u64 page_offset_mask;
+ u64 phys_addr_mask;
+
+ bit = __ffs64((u64)prop->dram_page_size);
+ page_offset_mask = ((1ull << bit) - 1);
+ phys_addr_mask = ~page_offset_mask;
+ *phys_addr = (tmp_phys_addr & phys_addr_mask) |
+ (virt_addr & page_offset_mask);
+ } else {
+ /*
+ * find the correct hop shift field in hl_mmu_properties
+ * structure in order to determine the right masks
+ * for the page offset.
+ */
+ hop0_shift_off = offsetof(struct hl_mmu_properties, hop0_shift);
+ p = (char *)p + hop0_shift_off;
+ p = (char *)p + ((hops->used_hops - 1) * sizeof(u64));
+ hop_shift = *(u64 *)p;
+ offset_mask = (1ull << hop_shift) - 1;
+ addr_mask = ~(offset_mask);
+ *phys_addr = (tmp_phys_addr & addr_mask) |
+ (virt_addr & offset_mask);
+ }
}
int hl_mmu_va_to_pa(struct hl_ctx *ctx, u64 virt_addr, u64 *phys_addr)
diff --git a/drivers/misc/ibmvmc.c b/drivers/misc/ibmvmc.c
index 2d778d0f011e..c0fe3295c330 100644
--- a/drivers/misc/ibmvmc.c
+++ b/drivers/misc/ibmvmc.c
@@ -2288,15 +2288,13 @@ crq_failed:
return -EPERM;
}
-static int ibmvmc_remove(struct vio_dev *vdev)
+static void ibmvmc_remove(struct vio_dev *vdev)
{
struct crq_server_adapter *adapter = dev_get_drvdata(&vdev->dev);
dev_info(adapter->dev, "Entering remove for UA 0x%x\n",
vdev->unit_address);
ibmvmc_release_crq_queue(adapter);
-
- return 0;
}
static struct vio_device_id ibmvmc_device_table[] = {
diff --git a/drivers/misc/pvpanic.c b/drivers/misc/pvpanic.c
index 9f350e05ef68..f1655f5ca016 100644
--- a/drivers/misc/pvpanic.c
+++ b/drivers/misc/pvpanic.c
@@ -140,6 +140,7 @@ static const struct of_device_id pvpanic_mmio_match[] = {
{ .compatible = "qemu,pvpanic-mmio", },
{}
};
+MODULE_DEVICE_TABLE(of, pvpanic_mmio_match);
static const struct acpi_device_id pvpanic_device_ids[] = {
{ "QEMU0001", 0 },
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index c2e70b757dd1..4383c262b3f5 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -399,11 +399,6 @@ void mmc_remove_card(struct mmc_card *card)
mmc_remove_card_debugfs(card);
#endif
- if (host->cqe_enabled) {
- host->cqe_ops->cqe_disable(host);
- host->cqe_enabled = false;
- }
-
if (mmc_card_present(card)) {
if (mmc_host_is_spi(card->host)) {
pr_info("%s: SPI card removed\n",
@@ -416,6 +411,10 @@ void mmc_remove_card(struct mmc_card *card)
of_node_put(card->dev.of_node);
}
+ if (host->cqe_enabled) {
+ host->cqe_ops->cqe_disable(host);
+ host->cqe_enabled = false;
+ }
+
put_device(&card->dev);
}
-
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 0d80b72ddde8..8741271d3971 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -423,10 +423,6 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
/* EXT_CSD value is in units of 10ms, but we store in ms */
card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME];
- /* Some eMMC set the value too low so set a minimum */
- if (card->ext_csd.part_time &&
- card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
- card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
/* Sleep / awake timeout in 100ns units */
if (sa_shift > 0 && sa_shift <= 0x17)
@@ -616,6 +612,17 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.data_sector_size = 512;
}
+ /*
+ * GENERIC_CMD6_TIME is to be used "unless a specific timeout is defined
+ * when accessing a specific field", so use it here if there is no
+ * PARTITION_SWITCH_TIME.
+ */
+ if (!card->ext_csd.part_time)
+ card->ext_csd.part_time = card->ext_csd.generic_cmd6_time;
+ /* Some eMMC set the value too low so set a minimum */
+ if (card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
+ card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
+
/* eMMC v5 or later */
if (card->ext_csd.rev >= 7) {
memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION],
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 17dbc81c221e..984d35055156 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1242,7 +1242,11 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (!cmd->busy_timeout)
cmd->busy_timeout = 10 * MSEC_PER_SEC;
- clks = (unsigned long long)cmd->busy_timeout * host->cclk;
+ if (cmd->busy_timeout > host->mmc->max_busy_timeout)
+ clks = (unsigned long long)host->mmc->max_busy_timeout * host->cclk;
+ else
+ clks = (unsigned long long)cmd->busy_timeout * host->cclk;
+
do_div(clks, MSEC_PER_SEC);
writel_relaxed(clks, host->base + MMCIDATATIMER);
}
@@ -2151,6 +2155,10 @@ static int mmci_probe(struct amba_device *dev,
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
}
+ /* Variants with mandatory busy timeout in HW needs R1B responses. */
+ if (variant->busy_timeout)
+ mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+
/* Prepare a CMD12 - needed to clear the DPSM on some variants. */
host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
host->stop_abort.arg = 0;
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index eb7258293256..f9cfb084c029 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -32,7 +32,6 @@
MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets");
-MODULE_SUPPORTED_DEVICE(DRIVER_NAME);
MODULE_LICENSE("GPL");
MODULE_VERSION("2.1");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b09bed554f26..bcd31f458d1a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -94,7 +94,7 @@ config WIREGUARD
select CRYPTO_BLAKE2S_ARM if ARM
select CRYPTO_CURVE25519_NEON if ARM && KERNEL_MODE_NEON
select CRYPTO_CHACHA_MIPS if CPU_MIPS32_R2
- select CRYPTO_POLY1305_MIPS if CPU_MIPS32 || (CPU_MIPS64 && 64BIT)
+ select CRYPTO_POLY1305_MIPS if MIPS
help
WireGuard is a secure, fast, and easy to use replacement for IPSec
that uses modern cryptography and clever networking tricks. It's
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 74cbbb22470b..456315bef3a8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3978,11 +3978,15 @@ static int bond_neigh_init(struct neighbour *n)
rcu_read_lock();
slave = bond_first_slave_rcu(bond);
- if (!slave)
+ if (!slave) {
+ ret = -EINVAL;
goto out;
+ }
slave_ops = slave->dev->netdev_ops;
- if (!slave_ops->ndo_neigh_setup)
+ if (!slave_ops->ndo_neigh_setup) {
+ ret = -EINVAL;
goto out;
+ }
/* TODO: find another way [1] to implement this.
* Passing a zeroed structure is fragile,
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 971ada36e37f..134c05757a3b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -701,7 +701,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
u32 reg;
reg = priv->read(&regs->mcr);
- reg |= FLEXCAN_MCR_HALT;
+ reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT;
priv->write(reg, &regs->mcr);
while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
@@ -1480,10 +1480,13 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_set_bittiming(dev);
+ /* set freeze, halt */
+ err = flexcan_chip_freeze(priv);
+ if (err)
+ goto out_chip_disable;
+
/* MCR
*
- * enable freeze
- * halt now
* only supervisor access
* enable warning int
* enable individual RX masking
@@ -1492,9 +1495,8 @@ static int flexcan_chip_start(struct net_device *dev)
*/
reg_mcr = priv->read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
- reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
- FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
- FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+ reg_mcr |= FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ |
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
/* MCR
*
@@ -1865,10 +1867,14 @@ static int register_flexcandev(struct net_device *dev)
if (err)
goto out_chip_disable;
- /* set freeze, halt and activate FIFO, restrict register access */
+ /* set freeze, halt */
+ err = flexcan_chip_freeze(priv);
+ if (err)
+ goto out_chip_disable;
+
+ /* activate FIFO, restrict register access */
reg = priv->read(&regs->mcr);
- reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
- FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
+ reg |= FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
priv->write(reg, &regs->mcr);
/* Currently we only support newer versions of this core
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
index b7caec769ddb..4147cecfbbd6 100644
--- a/drivers/net/can/m_can/tcan4x5x-core.c
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
@@ -237,14 +237,14 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
if (ret)
return ret;
+ /* Zero out the MCAN buffers */
+ m_can_init_ram(cdev);
+
ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
if (ret)
return ret;
- /* Zero out the MCAN buffers */
- m_can_init_ram(cdev);
-
return ret;
}
diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c
index 0df1cdfa6835..1df3c4b54f03 100644
--- a/drivers/net/can/peak_canfd/peak_pciefd_main.c
+++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c
@@ -21,7 +21,6 @@
MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCIe/M.2 FD family cards");
-MODULE_SUPPORTED_DEVICE("PEAK PCAN PCIe/M.2 FD CAN cards");
MODULE_LICENSE("GPL v2");
#define PCIEFD_DRV_NAME "peak_pciefd"
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
index 6f88c9932920..4ab91759a5c6 100644
--- a/drivers/net/can/sja1000/ems_pci.c
+++ b/drivers/net/can/sja1000/ems_pci.c
@@ -21,7 +21,6 @@
MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>");
MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe/104P CAN cards");
-MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe/104P CAN card");
MODULE_LICENSE("GPL v2");
#define EMS_PCI_V1_MAX_CHAN 2
diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c
index 770304eaef95..e21b169c14c0 100644
--- a/drivers/net/can/sja1000/ems_pcmcia.c
+++ b/drivers/net/can/sja1000/ems_pcmcia.c
@@ -21,7 +21,6 @@
MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>");
MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards");
-MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card");
MODULE_LICENSE("GPL v2");
#define EMS_PCMCIA_MAX_CHAN 2
diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
index 0ea6b711c07b..95fe9ee1ce32 100644
--- a/drivers/net/can/sja1000/kvaser_pci.c
+++ b/drivers/net/can/sja1000/kvaser_pci.c
@@ -33,7 +33,6 @@
MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>");
MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards");
-MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card");
MODULE_LICENSE("GPL v2");
#define MAX_NO_OF_CHANNELS 4 /* max no of channels on a single card */
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index 4713921bd511..84eac8cb8686 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -24,8 +24,6 @@
MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");
-MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards");
-MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");
MODULE_LICENSE("GPL v2");
#define DRV_NAME "peak_pci"
diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c
index cf951a783078..131a084c3535 100644
--- a/drivers/net/can/sja1000/peak_pcmcia.c
+++ b/drivers/net/can/sja1000/peak_pcmcia.c
@@ -22,7 +22,6 @@
MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
MODULE_DESCRIPTION("CAN driver for PEAK-System PCAN-PC Cards");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("PEAK PCAN-PC Card");
/* PEAK-System PCMCIA driver name */
#define PCC_NAME "peak_pcmcia"
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 85679588ef73..5de1ebb0c6f0 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -25,18 +25,6 @@
MODULE_AUTHOR("Pavel Cheblakov <P.B.Cheblakov@inp.nsk.su>");
MODULE_DESCRIPTION("Socket-CAN driver for PLX90xx PCI-bridge cards with "
"the SJA1000 chips");
-MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
- "Adlink PCI-7841/cPCI-7841 SE, "
- "Marathon CAN-bus-PCI, "
- "Marathon CAN-bus-PCIe, "
- "TEWS TECHNOLOGIES TPMC810, "
- "esd CAN-PCI/CPCI/PCI104/200, "
- "esd CAN-PCI/PMC/266, "
- "esd CAN-PCIe/2000, "
- "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
- "IXXAT PC-I 04/PCI, "
- "ELCUS CAN-200-PCI, "
- "ASEM DUAL CAN-RAW")
MODULE_LICENSE("GPL v2");
#define PLX_PCI_MAX_CHAN 2
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 3c5b92911d46..799e9d5d3481 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -335,8 +335,6 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
u8 len;
int i, j;
- netdev_reset_queue(priv->ndev);
-
/* TEF */
tef_ring = priv->tef;
tef_ring->head = 0;
@@ -1249,8 +1247,7 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
static int
mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
- const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
- unsigned int *frame_len_ptr)
+ const struct mcp251xfd_hw_tef_obj *hw_tef_obj)
{
struct net_device_stats *stats = &priv->ndev->stats;
u32 seq, seq_masked, tef_tail_masked;
@@ -1272,8 +1269,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
stats->tx_bytes +=
can_rx_offload_get_echo_skb(&priv->offload,
mcp251xfd_get_tef_tail(priv),
- hw_tef_obj->ts,
- frame_len_ptr);
+ hw_tef_obj->ts, NULL);
stats->tx_packets++;
priv->tef->tail++;
@@ -1331,7 +1327,6 @@ mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
{
struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
- unsigned int total_frame_len = 0;
u8 tef_tail, len, l;
int err, i;
@@ -1353,9 +1348,7 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
}
for (i = 0; i < len; i++) {
- unsigned int frame_len;
-
- err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
+ err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]);
/* -EAGAIN means the Sequence Number in the TEF
* doesn't match our tef_tail. This can happen if we
* read the TEF objects too early. Leave loop let the
@@ -1365,8 +1358,6 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
goto out_netif_wake_queue;
if (err)
return err;
-
- total_frame_len += frame_len;
}
out_netif_wake_queue:
@@ -1397,7 +1388,6 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
return err;
tx_ring->tail += len;
- netdev_completed_queue(priv->ndev, len, total_frame_len);
err = mcp251xfd_check_tef_tail(priv);
if (err)
@@ -2443,7 +2433,6 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
struct mcp251xfd_priv *priv = netdev_priv(ndev);
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
struct mcp251xfd_tx_obj *tx_obj;
- unsigned int frame_len;
u8 tx_head;
int err;
@@ -2462,9 +2451,7 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
if (mcp251xfd_get_tx_free(tx_ring) == 0)
netif_stop_queue(ndev);
- frame_len = can_skb_get_frame_len(skb);
- can_put_echo_skb(skb, ndev, tx_head, frame_len);
- netdev_sent_queue(priv->ndev, frame_len);
+ can_put_echo_skb(skb, ndev, tx_head, 0);
err = mcp251xfd_tx_obj_write(priv, tx_obj);
if (err)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index e6c1e5d33924..e393e8457d77 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -18,8 +18,6 @@
#include "pcan_usb_core.h"
-MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB adapter");
-
/* PCAN-USB Endpoints */
#define PCAN_USB_EP_CMDOUT 1
#define PCAN_USB_EP_CMDIN (PCAN_USB_EP_CMDOUT | USB_DIR_IN)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
index f347ecc79aef..bae078579c0d 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -16,9 +16,6 @@
#include "pcan_usb_core.h"
#include "pcan_usb_pro.h"
-MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB FD adapter");
-MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB Pro FD adapter");
-
#define PCAN_USBPROFD_CHANNEL_COUNT 2
#define PCAN_USBFD_CHANNEL_COUNT 1
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index 275087c39602..18fa180ecc81 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -17,8 +17,6 @@
#include "pcan_usb_core.h"
#include "pcan_usb_pro.h"
-MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB Pro adapter");
-
#define PCAN_USBPRO_CHANNEL_COUNT 2
/* PCAN-USB Pro adapter internal clock (MHz) */
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 5ee8103b8e9c..f277df922fcd 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -406,7 +406,7 @@ static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
/* The watchdog reset does not work on 7278, we need to hit the
* "external" reset line through the reset controller.
*/
- if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev)) {
+ if (priv->type == BCM7278_DEVICE_ID) {
ret = reset_control_assert(priv->rcdev);
if (ret)
return ret;
@@ -1265,7 +1265,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev,
"switch");
- if (PTR_ERR(priv->rcdev) == -EPROBE_DEFER)
+ if (IS_ERR(priv->rcdev))
return PTR_ERR(priv->rcdev);
/* Auto-detection using standard registers will not work, so
@@ -1426,7 +1426,7 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
bcm_sf2_mdio_unregister(priv);
clk_disable_unprepare(priv->clk_mdiv);
clk_disable_unprepare(priv->clk);
- if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev))
+ if (priv->type == BCM7278_DEVICE_ID)
reset_control_assert(priv->rcdev);
return 0;
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index c17de2bcf2fe..f06f5fa2f898 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1624,6 +1624,7 @@ mtk_get_tag_protocol(struct dsa_switch *ds, int port,
}
}
+#ifdef CONFIG_GPIOLIB
static inline u32
mt7530_gpio_to_bit(unsigned int offset)
{
@@ -1726,6 +1727,7 @@ mt7530_setup_gpio(struct mt7530_priv *priv)
return devm_gpiochip_add_data(dev, gc, priv);
}
+#endif /* CONFIG_GPIOLIB */
static int
mt7530_setup(struct dsa_switch *ds)
@@ -1868,11 +1870,13 @@ mt7530_setup(struct dsa_switch *ds)
}
}
+#ifdef CONFIG_GPIOLIB
if (of_property_read_bool(priv->dev->of_node, "gpio-controller")) {
ret = mt7530_setup_gpio(priv);
if (ret)
return ret;
}
+#endif /* CONFIG_GPIOLIB */
mt7530_setup_port5(ds, interface);
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 7692338730df..51ea104c63bb 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -1922,7 +1922,7 @@ out_unlock_ptp:
speed = SPEED_1000;
else if (bmcr & BMCR_SPEED100)
speed = SPEED_100;
- else if (bmcr & BMCR_SPEED10)
+ else
speed = SPEED_10;
sja1105_sgmii_pcs_force_speed(priv, speed);
@@ -3369,14 +3369,14 @@ static int sja1105_port_ucast_bcast_flood(struct sja1105_private *priv, int to,
if (flags.val & BR_FLOOD)
priv->ucast_egress_floods |= BIT(to);
else
- priv->ucast_egress_floods |= BIT(to);
+ priv->ucast_egress_floods &= ~BIT(to);
}
if (flags.mask & BR_BCAST_FLOOD) {
if (flags.val & BR_BCAST_FLOOD)
priv->bcast_egress_floods |= BIT(to);
else
- priv->bcast_egress_floods |= BIT(to);
+ priv->bcast_egress_floods &= ~BIT(to);
}
return sja1105_manage_flood_domains(priv);
diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c
index f025f968f96d..fde6e99274b6 100644
--- a/drivers/net/dsa/xrs700x/xrs700x.c
+++ b/drivers/net/dsa/xrs700x/xrs700x.c
@@ -528,7 +528,10 @@ static int xrs700x_hsr_join(struct dsa_switch *ds, int port,
return -EOPNOTSUPP;
dsa_hsr_foreach_port(dp, ds, hsr) {
- partner = dp;
+ if (dp->index != port) {
+ partner = dp;
+ break;
+ }
}
/* We can't enable redundancy on the switch until both
@@ -582,7 +585,10 @@ static int xrs700x_hsr_leave(struct dsa_switch *ds, int port,
unsigned int val;
dsa_hsr_foreach_port(dp, ds, hsr) {
- partner = dp;
+ if (dp->index != port) {
+ partner = dp;
+ break;
+ }
}
if (!partner)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 9b7f1af5f574..9e02f8864593 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1894,13 +1894,16 @@ static int alx_resume(struct device *dev)
if (!netif_running(alx->dev))
return 0;
- netif_device_attach(alx->dev);
rtnl_lock();
err = __alx_open(alx, true);
rtnl_unlock();
+ if (err)
+ return err;
- return err;
+ netif_device_attach(alx->dev);
+
+ return 0;
}
static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume);
diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c
index 0b70e9e0ddad..98cf82dea3e4 100644
--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
@@ -592,6 +592,9 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight)
bcm4908_enet_intrs_on(enet);
}
+ /* Hardware could disable ring if it run out of descriptors */
+ bcm4908_enet_dma_rx_ring_enable(enet, &enet->rx_ring);
+
return handled;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index a680fd9c68ea..b53a0d87371a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -8556,10 +8556,18 @@ static void bnxt_setup_inta(struct bnxt *bp)
bp->irq_tbl[0].handler = bnxt_inta;
}
+static int bnxt_init_int_mode(struct bnxt *bp);
+
static int bnxt_setup_int_mode(struct bnxt *bp)
{
int rc;
+ if (!bp->irq_tbl) {
+ rc = bnxt_init_int_mode(bp);
+ if (rc || !bp->irq_tbl)
+ return rc ?: -ENODEV;
+ }
+
if (bp->flags & BNXT_FLAG_USING_MSIX)
bnxt_setup_msix(bp);
else
@@ -8744,7 +8752,7 @@ static int bnxt_init_inta(struct bnxt *bp)
static int bnxt_init_int_mode(struct bnxt *bp)
{
- int rc = 0;
+ int rc = -ENODEV;
if (bp->flags & BNXT_FLAG_MSIX_CAP)
rc = bnxt_init_msix(bp);
@@ -9514,7 +9522,8 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
{
struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr;
struct hwrm_func_drv_if_change_input req = {0};
- bool resc_reinit = false, fw_reset = false;
+ bool fw_reset = !bp->irq_tbl;
+ bool resc_reinit = false;
int rc, retry = 0;
u32 flags = 0;
@@ -9557,6 +9566,7 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
+ set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
return -ENODEV;
}
if (resc_reinit || fw_reset) {
@@ -9890,6 +9900,9 @@ static int bnxt_reinit_after_abort(struct bnxt *bp)
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
return -EBUSY;
+ if (bp->dev->reg_state == NETREG_UNREGISTERED)
+ return -ENODEV;
+
rc = bnxt_fw_init_one(bp);
if (!rc) {
bnxt_clear_int_mode(bp);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 472bf8f220bc..15362d016a87 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -3954,6 +3954,13 @@ static int macb_init(struct platform_device *pdev)
return 0;
}
+static const struct macb_usrio_config macb_default_usrio = {
+ .mii = MACB_BIT(MII),
+ .rmii = MACB_BIT(RMII),
+ .rgmii = GEM_BIT(RGMII),
+ .refclk = MACB_BIT(CLKEN),
+};
+
#if defined(CONFIG_OF)
/* 1518 rounded up */
#define AT91ETHER_MAX_RBUFF_SZ 0x600
@@ -4439,13 +4446,6 @@ static int fu540_c000_init(struct platform_device *pdev)
return macb_init(pdev);
}
-static const struct macb_usrio_config macb_default_usrio = {
- .mii = MACB_BIT(MII),
- .rmii = MACB_BIT(RMII),
- .rgmii = GEM_BIT(RGMII),
- .refclk = MACB_BIT(CLKEN),
-};
-
static const struct macb_usrio_config sama7g5_usrio = {
.mii = 0,
.rmii = 1,
@@ -4594,6 +4594,7 @@ static const struct macb_config default_gem_config = {
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
+ .usrio = &macb_default_usrio,
.jumbo_max_len = 10240,
};
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
index 46a809f2aeca..169e10c91378 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
@@ -672,7 +672,7 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap,
if (tx_info->pending_close) {
spin_unlock(&tx_info->lock);
if (!status) {
- /* it's a late success, tcb status is establised,
+ /* it's a late success, tcb status is established,
* mark it close.
*/
chcr_ktls_mark_tcb_close(tx_info);
@@ -930,7 +930,7 @@ chcr_ktls_get_tx_flits(u32 nr_frags, unsigned int key_ctx_len)
}
/*
- * chcr_ktls_check_tcp_options: To check if there is any TCP option availbale
+ * chcr_ktls_check_tcp_options: To check if there is any TCP option available
* other than timestamp.
* @skb - skb contains partial record..
* return: 1 / 0
@@ -1115,7 +1115,7 @@ static int chcr_ktls_xmit_wr_complete(struct sk_buff *skb,
}
if (unlikely(credits < ETHTXQ_STOP_THRES)) {
- /* Credits are below the threshold vaues, stop the queue after
+ /* Credits are below the threshold values, stop the queue after
* injecting the Work Request for this packet.
*/
chcr_eth_txq_stop(q);
@@ -2006,7 +2006,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
/* TCP segments can be in received either complete or partial.
* chcr_end_part_handler will handle cases if complete record or end
- * part of the record is received. Incase of partial end part of record,
+ * part of the record is received. In case of partial end part of record,
* we will send the complete record again.
*/
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 3fdc70dab5c1..252adfa5d837 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -133,6 +133,8 @@ struct board_info {
u32 wake_state;
int ip_summed;
+
+ struct regulator *power_supply;
};
/* debug code */
@@ -1449,7 +1451,7 @@ dm9000_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "failed to request reset gpio %d: %d\n",
reset_gpios, ret);
- return -ENODEV;
+ goto out_regulator_disable;
}
/* According to manual PWRST# Low Period Min 1ms */
@@ -1461,8 +1463,10 @@ dm9000_probe(struct platform_device *pdev)
if (!pdata) {
pdata = dm9000_parse_dt(&pdev->dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
+ if (IS_ERR(pdata)) {
+ ret = PTR_ERR(pdata);
+ goto out_regulator_disable;
+ }
}
/* Init network device */
@@ -1479,6 +1483,8 @@ dm9000_probe(struct platform_device *pdev)
db->dev = &pdev->dev;
db->ndev = ndev;
+ if (!IS_ERR(power))
+ db->power_supply = power;
spin_lock_init(&db->lock);
mutex_init(&db->addr_lock);
@@ -1501,7 +1507,7 @@ dm9000_probe(struct platform_device *pdev)
goto out;
}
- db->irq_wake = platform_get_irq(pdev, 1);
+ db->irq_wake = platform_get_irq_optional(pdev, 1);
if (db->irq_wake >= 0) {
dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
@@ -1703,6 +1709,10 @@ out:
dm9000_release_board(pdev, db);
free_netdev(ndev);
+out_regulator_disable:
+ if (!IS_ERR(power))
+ regulator_disable(power);
+
return ret;
}
@@ -1760,10 +1770,13 @@ static int
dm9000_drv_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
+ struct board_info *dm = to_dm9000_board(ndev);
unregister_netdev(ndev);
- dm9000_release_board(pdev, netdev_priv(ndev));
+ dm9000_release_board(pdev, dm);
free_netdev(ndev); /* free device structure */
+ if (dm->power_supply)
+ regulator_disable(dm->power_supply);
dev_dbg(&pdev->dev, "released and freed device\n");
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index c78d12229730..09471329f3a3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -281,6 +281,8 @@ static int enetc_poll(struct napi_struct *napi, int budget)
int work_done;
int i;
+ enetc_lock_mdio();
+
for (i = 0; i < v->count_tx_rings; i++)
if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
complete = false;
@@ -291,8 +293,10 @@ static int enetc_poll(struct napi_struct *napi, int budget)
if (work_done)
v->rx_napi_work = true;
- if (!complete)
+ if (!complete) {
+ enetc_unlock_mdio();
return budget;
+ }
napi_complete_done(napi, work_done);
@@ -301,8 +305,6 @@ static int enetc_poll(struct napi_struct *napi, int budget)
v->rx_napi_work = false;
- enetc_lock_mdio();
-
/* enable interrupts */
enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE);
@@ -327,8 +329,8 @@ static void enetc_get_tx_tstamp(struct enetc_hw *hw, union enetc_tx_bd *txbd,
{
u32 lo, hi, tstamp_lo;
- lo = enetc_rd(hw, ENETC_SICTR0);
- hi = enetc_rd(hw, ENETC_SICTR1);
+ lo = enetc_rd_hot(hw, ENETC_SICTR0);
+ hi = enetc_rd_hot(hw, ENETC_SICTR1);
tstamp_lo = le32_to_cpu(txbd->wb.tstamp);
if (lo <= tstamp_lo)
hi -= 1;
@@ -342,6 +344,12 @@ static void enetc_tstamp_tx(struct sk_buff *skb, u64 tstamp)
if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
+ /* Ensure skb_mstamp_ns, which might have been populated with
+ * the txtime, is not mistaken for a software timestamp,
+ * because this will prevent the dispatch of our hardware
+ * timestamp to the socket.
+ */
+ skb->tstamp = ktime_set(0, 0);
skb_tstamp_tx(skb, &shhwtstamps);
}
}
@@ -358,9 +366,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
i = tx_ring->next_to_clean;
tx_swbd = &tx_ring->tx_swbd[i];
- enetc_lock_mdio();
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
- enetc_unlock_mdio();
do_tstamp = false;
@@ -403,8 +409,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
tx_swbd = tx_ring->tx_swbd;
}
- enetc_lock_mdio();
-
/* BD iteration loop end */
if (is_eof) {
tx_frm_cnt++;
@@ -415,8 +419,6 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
if (unlikely(!bds_to_clean))
bds_to_clean = enetc_bd_ready_count(tx_ring, i);
-
- enetc_unlock_mdio();
}
tx_ring->next_to_clean = i;
@@ -527,9 +529,8 @@ static void enetc_get_rx_tstamp(struct net_device *ndev,
static void enetc_get_offloads(struct enetc_bdr *rx_ring,
union enetc_rx_bd *rxbd, struct sk_buff *skb)
{
-#ifdef CONFIG_FSL_ENETC_PTP_CLOCK
struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
-#endif
+
/* TODO: hashing */
if (rx_ring->ndev->features & NETIF_F_RXCSUM) {
u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum);
@@ -538,12 +539,31 @@ static void enetc_get_offloads(struct enetc_bdr *rx_ring,
skb->ip_summed = CHECKSUM_COMPLETE;
}
- /* copy VLAN to skb, if one is extracted, for now we assume it's a
- * standard TPID, but HW also supports custom values
- */
- if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN)
- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
- le16_to_cpu(rxbd->r.vlan_opt));
+ if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) {
+ __be16 tpid = 0;
+
+ switch (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_TPID) {
+ case 0:
+ tpid = htons(ETH_P_8021Q);
+ break;
+ case 1:
+ tpid = htons(ETH_P_8021AD);
+ break;
+ case 2:
+ tpid = htons(enetc_port_rd(&priv->si->hw,
+ ENETC_PCVLANR1));
+ break;
+ case 3:
+ tpid = htons(enetc_port_rd(&priv->si->hw,
+ ENETC_PCVLANR2));
+ break;
+ default:
+ break;
+ }
+
+ __vlan_hwaccel_put_tag(skb, tpid, le16_to_cpu(rxbd->r.vlan_opt));
+ }
+
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK
if (priv->active_offloads & ENETC_F_RX_TSTAMP)
enetc_get_rx_tstamp(rx_ring->ndev, rxbd, skb);
@@ -660,8 +680,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
u32 bd_status;
u16 size;
- enetc_lock_mdio();
-
if (cleaned_cnt >= ENETC_RXBD_BUNDLE) {
int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt);
@@ -672,19 +690,15 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
rxbd = enetc_rxbd(rx_ring, i);
bd_status = le32_to_cpu(rxbd->r.lstatus);
- if (!bd_status) {
- enetc_unlock_mdio();
+ if (!bd_status)
break;
- }
enetc_wr_reg_hot(rx_ring->idr, BIT(rx_ring->index));
dma_rmb(); /* for reading other rxbd fields */
size = le16_to_cpu(rxbd->r.buf_len);
skb = enetc_map_rx_buff_to_skb(rx_ring, i, size);
- if (!skb) {
- enetc_unlock_mdio();
+ if (!skb)
break;
- }
enetc_get_offloads(rx_ring, rxbd, skb);
@@ -696,7 +710,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
if (unlikely(bd_status &
ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) {
- enetc_unlock_mdio();
dev_kfree_skb(skb);
while (!(bd_status & ENETC_RXBD_LSTATUS_F)) {
dma_rmb();
@@ -736,8 +749,6 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
enetc_process_skb(rx_ring, skb);
- enetc_unlock_mdio();
-
napi_gro_receive(napi, skb);
rx_frm_cnt++;
@@ -984,7 +995,7 @@ static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
enetc_free_tx_ring(priv->tx_ring[i]);
}
-static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{
int size = cbdr->bd_count * sizeof(struct enetc_cbd);
@@ -1005,7 +1016,7 @@ static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
return 0;
}
-static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
{
int size = cbdr->bd_count * sizeof(struct enetc_cbd);
@@ -1013,7 +1024,7 @@ static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
cbdr->bd_base = NULL;
}
-static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
{
/* set CBDR cache attributes */
enetc_wr(hw, ENETC_SICAR2,
@@ -1033,7 +1044,7 @@ static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
cbdr->cir = hw->reg + ENETC_SICBDRCIR;
}
-static void enetc_clear_cbdr(struct enetc_hw *hw)
+void enetc_clear_cbdr(struct enetc_hw *hw)
{
enetc_wr(hw, ENETC_SICBDRMR, 0);
}
@@ -1058,13 +1069,12 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
return 0;
}
-static int enetc_configure_si(struct enetc_ndev_priv *priv)
+int enetc_configure_si(struct enetc_ndev_priv *priv)
{
struct enetc_si *si = priv->si;
struct enetc_hw *hw = &si->hw;
int err;
- enetc_setup_cbdr(hw, &si->cbd_ring);
/* set SI cache attributes */
enetc_wr(hw, ENETC_SICAR0,
ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
@@ -1112,6 +1122,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
if (err)
return err;
+ enetc_setup_cbdr(&si->hw, &si->cbd_ring);
+
priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
GFP_KERNEL);
if (!priv->cls_rules) {
@@ -1119,14 +1131,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv)
goto err_alloc_cls;
}
- err = enetc_configure_si(priv);
- if (err)
- goto err_config_si;
-
return 0;
-err_config_si:
- kfree(priv->cls_rules);
err_alloc_cls:
enetc_clear_cbdr(&si->hw);
enetc_free_cbdr(priv->dev, &si->cbd_ring);
@@ -1212,7 +1218,8 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
rx_ring->idr = hw->reg + ENETC_SIRXIDR;
enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
- enetc_wr(hw, ENETC_SIRXIDR, rx_ring->next_to_use);
+ /* update ENETC's consumer index */
+ enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, rx_ring->next_to_use);
/* enable ring */
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 8532d23b54f5..8b380fc13314 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -292,6 +292,7 @@ void enetc_get_si_caps(struct enetc_si *si);
void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
void enetc_free_si_resources(struct enetc_ndev_priv *priv);
+int enetc_configure_si(struct enetc_ndev_priv *priv);
int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
@@ -309,6 +310,10 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void enetc_set_ethtool_ops(struct net_device *ndev);
/* control buffer descriptor ring (CBDR) */
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr);
+void enetc_clear_cbdr(struct enetc_hw *hw);
int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index c71fe8d751d5..00938f7960a4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -172,6 +172,8 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */
#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8)
#define ENETC_PVCLCTR 0x0208
+#define ENETC_PCVLANR1 0x0210
+#define ENETC_PCVLANR2 0x0214
#define ENETC_VLAN_TYPE_C BIT(0)
#define ENETC_VLAN_TYPE_S BIT(1)
#define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */
@@ -232,14 +234,23 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PM0_MAXFRM 0x8014
#define ENETC_SET_TX_MTU(val) ((val) << 16)
#define ENETC_SET_MAXFRM(val) ((val) & 0xffff)
+#define ENETC_PM0_RX_FIFO 0x801c
+#define ENETC_PM0_RX_FIFO_VAL 1
#define ENETC_PM_IMDIO_BASE 0x8030
#define ENETC_PM0_IF_MODE 0x8300
-#define ENETC_PMO_IFM_RG BIT(2)
+#define ENETC_PM0_IFM_RG BIT(2)
#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
-#define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
-#define ENETC_PM0_IFM_XGMII BIT(12)
+#define ENETC_PM0_IFM_EN_AUTO BIT(15)
+#define ENETC_PM0_IFM_SSP_MASK GENMASK(14, 13)
+#define ENETC_PM0_IFM_SSP_1000 (2 << 13)
+#define ENETC_PM0_IFM_SSP_100 (0 << 13)
+#define ENETC_PM0_IFM_SSP_10 (1 << 13)
+#define ENETC_PM0_IFM_FULL_DPX BIT(12)
+#define ENETC_PM0_IFM_IFMODE_MASK GENMASK(1, 0)
+#define ENETC_PM0_IFM_IFMODE_XGMII 0
+#define ENETC_PM0_IFM_IFMODE_GMII 2
#define ENETC_PSIDCAPR 0x1b08
#define ENETC_PSIDCAPR_MSK GENMASK(15, 0)
#define ENETC_PSFCAPR 0x1b18
@@ -453,6 +464,8 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
#define enetc_wr_reg(reg, val) _enetc_wr_reg_wa((reg), (val))
#define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off))
#define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val)
+#define enetc_rd_hot(hw, off) enetc_rd_reg_hot((hw)->reg + (off))
+#define enetc_wr_hot(hw, off, val) enetc_wr_reg_hot((hw)->reg + (off), val)
#define enetc_rd64(hw, off) _enetc_rd_reg64_wa((hw)->reg + (off))
/* port register accessors - PF only */
#define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off))
@@ -568,6 +581,7 @@ union enetc_rx_bd {
#define ENETC_RXBD_LSTATUS(flags) ((flags) << 16)
#define ENETC_RXBD_FLAG_VLAN BIT(9)
#define ENETC_RXBD_FLAG_TSTMP BIT(10)
+#define ENETC_RXBD_FLAG_TPID GENMASK(1, 0)
#define ENETC_MAC_ADDR_FILT_CNT 8 /* # of supported entries per port */
#define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 515c5b29d7aa..224fc37a6757 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -190,7 +190,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_pf *pf = enetc_si_priv(priv->si);
- char vlan_promisc_simap = pf->vlan_promisc_simap;
struct enetc_hw *hw = &priv->si->hw;
bool uprom = false, mprom = false;
struct enetc_mac_filter *filter;
@@ -203,16 +202,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
uprom = true;
mprom = true;
- /* Enable VLAN promiscuous mode for SI0 (PF) */
- vlan_promisc_simap |= BIT(0);
} else if (ndev->flags & IFF_ALLMULTI) {
/* enable multi cast promisc mode for SI0 (PF) */
psipmr = ENETC_PSIPMR_SET_MP(0);
mprom = true;
}
- enetc_set_vlan_promisc(&pf->si->hw, vlan_promisc_simap);
-
/* first 2 filter entries belong to PF */
if (!uprom) {
/* Update unicast filters */
@@ -320,7 +315,7 @@ static void enetc_set_loopback(struct net_device *ndev, bool en)
u32 reg;
reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
- if (reg & ENETC_PMO_IFM_RG) {
+ if (reg & ENETC_PM0_IFM_RG) {
/* RGMII mode */
reg = (reg & ~ENETC_PM0_IFM_RLP) |
(en ? ENETC_PM0_IFM_RLP : 0);
@@ -495,17 +490,30 @@ static void enetc_configure_port_mac(struct enetc_hw *hw)
enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC);
+
+ /* On LS1028A, the MAC RX FIFO defaults to 2, which is too high
+ * and may lead to RX lock-up under traffic. Set it to 1 instead,
+ * as recommended by the hardware team.
+ */
+ enetc_port_wr(hw, ENETC_PM0_RX_FIFO, ENETC_PM0_RX_FIFO_VAL);
}
static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode)
{
- /* set auto-speed for RGMII */
- if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG ||
- phy_interface_mode_is_rgmii(phy_mode))
- enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO);
+ u32 val;
+
+ if (phy_interface_mode_is_rgmii(phy_mode)) {
+ val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
+ val &= ~ENETC_PM0_IFM_EN_AUTO;
+ val &= ENETC_PM0_IFM_IFMODE_MASK;
+ val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG;
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+ }
- if (phy_mode == PHY_INTERFACE_MODE_USXGMII)
- enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII);
+ if (phy_mode == PHY_INTERFACE_MODE_USXGMII) {
+ val = ENETC_PM0_IFM_FULL_DPX | ENETC_PM0_IFM_IFMODE_XGMII;
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+ }
}
static void enetc_mac_enable(struct enetc_hw *hw, bool en)
@@ -937,6 +945,34 @@ static void enetc_pl_mac_config(struct phylink_config *config,
phylink_set_pcs(priv->phylink, &pf->pcs->pcs);
}
+static void enetc_force_rgmii_mac(struct enetc_hw *hw, int speed, int duplex)
+{
+ u32 old_val, val;
+
+ old_val = val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
+
+ if (speed == SPEED_1000) {
+ val &= ~ENETC_PM0_IFM_SSP_MASK;
+ val |= ENETC_PM0_IFM_SSP_1000;
+ } else if (speed == SPEED_100) {
+ val &= ~ENETC_PM0_IFM_SSP_MASK;
+ val |= ENETC_PM0_IFM_SSP_100;
+ } else if (speed == SPEED_10) {
+ val &= ~ENETC_PM0_IFM_SSP_MASK;
+ val |= ENETC_PM0_IFM_SSP_10;
+ }
+
+ if (duplex == DUPLEX_FULL)
+ val |= ENETC_PM0_IFM_FULL_DPX;
+ else
+ val &= ~ENETC_PM0_IFM_FULL_DPX;
+
+ if (val == old_val)
+ return;
+
+ enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
+}
+
static void enetc_pl_mac_link_up(struct phylink_config *config,
struct phy_device *phy, unsigned int mode,
phy_interface_t interface, int speed,
@@ -949,6 +985,10 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
if (priv->active_offloads & ENETC_F_QBV)
enetc_sched_speed_set(priv, speed);
+ if (!phylink_autoneg_inband(mode) &&
+ phy_interface_mode_is_rgmii(interface))
+ enetc_force_rgmii_mac(&pf->si->hw, speed, duplex);
+
enetc_mac_enable(&pf->si->hw, true);
}
@@ -1041,6 +1081,26 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
return err;
}
+static void enetc_init_unused_port(struct enetc_si *si)
+{
+ struct device *dev = &si->pdev->dev;
+ struct enetc_hw *hw = &si->hw;
+ int err;
+
+ si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
+ err = enetc_alloc_cbdr(dev, &si->cbd_ring);
+ if (err)
+ return;
+
+ enetc_setup_cbdr(hw, &si->cbd_ring);
+
+ enetc_init_port_rfs_memory(si);
+ enetc_init_port_rss_memory(si);
+
+ enetc_clear_cbdr(hw);
+ enetc_free_cbdr(dev, &si->cbd_ring);
+}
+
static int enetc_pf_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1051,11 +1111,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
struct enetc_pf *pf;
int err;
- if (node && !of_device_is_available(node)) {
- dev_info(&pdev->dev, "device is disabled, skipping\n");
- return -ENODEV;
- }
-
err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
if (err) {
dev_err(&pdev->dev, "PCI probing failed\n");
@@ -1069,6 +1124,13 @@ static int enetc_pf_probe(struct pci_dev *pdev,
goto err_map_pf_space;
}
+ if (node && !of_device_is_available(node)) {
+ enetc_init_unused_port(si);
+ dev_info(&pdev->dev, "device is disabled, skipping\n");
+ err = -ENODEV;
+ goto err_device_disabled;
+ }
+
pf = enetc_si_priv(si);
pf->si = si;
pf->total_vfs = pci_sriov_get_totalvfs(pdev);
@@ -1108,6 +1170,12 @@ static int enetc_pf_probe(struct pci_dev *pdev,
goto err_init_port_rss;
}
+ err = enetc_configure_si(priv);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to configure SI\n");
+ goto err_config_si;
+ }
+
err = enetc_alloc_msix(priv);
if (err) {
dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -1136,6 +1204,7 @@ err_phylink_create:
enetc_mdiobus_destroy(pf);
err_mdiobus_create:
enetc_free_msix(priv);
+err_config_si:
err_init_port_rss:
err_init_port_rfs:
err_alloc_msix:
@@ -1144,6 +1213,7 @@ err_alloc_si_res:
si->ndev = NULL;
free_netdev(ndev);
err_alloc_netdev:
+err_device_disabled:
err_map_pf_space:
enetc_pci_remove(pdev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 39c1a09e69a9..9b755a84c2d6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -171,6 +171,12 @@ static int enetc_vf_probe(struct pci_dev *pdev,
goto err_alloc_si_res;
}
+ err = enetc_configure_si(priv);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to configure SI\n");
+ goto err_config_si;
+ }
+
err = enetc_alloc_msix(priv);
if (err) {
dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -187,6 +193,7 @@ static int enetc_vf_probe(struct pci_dev *pdev,
err_reg_netdev:
enetc_free_msix(priv);
+err_config_si:
err_alloc_msix:
enetc_free_si_resources(priv);
err_alloc_si_res:
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 2e344aada4c6..1753807cbf97 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -377,9 +377,16 @@ static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
u64 ns;
unsigned long flags;
+ mutex_lock(&adapter->ptp_clk_mutex);
+ /* Check the ptp clock */
+ if (!adapter->ptp_clk_on) {
+ mutex_unlock(&adapter->ptp_clk_mutex);
+ return -EINVAL;
+ }
spin_lock_irqsave(&adapter->tmreg_lock, flags);
ns = timecounter_read(&adapter->tc);
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+ mutex_unlock(&adapter->ptp_clk_mutex);
*ts = ns_to_timespec64(ns);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 541de32ea662..1cf8ef717453 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2390,6 +2390,10 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus,
if (lstatus & BD_LFLAG(RXBD_LAST))
size -= skb->len;
+ WARN(size < 0, "gianfar: rx fragment size underflow");
+ if (size < 0)
+ return false;
+
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
rxb->page_offset + RXBUF_ALIGNMENT,
size, GFAR_RXB_TRUESIZE);
@@ -2552,6 +2556,17 @@ static int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
if (lstatus & BD_LFLAG(RXBD_EMPTY))
break;
+ /* lost RXBD_LAST descriptor due to overrun */
+ if (skb &&
+ (lstatus & BD_LFLAG(RXBD_FIRST))) {
+ /* discard faulty buffer */
+ dev_kfree_skb(skb);
+ skb = NULL;
+ rx_queue->stats.rx_dropped++;
+
+ /* can continue normally */
+ }
+
/* order rx buffer descriptor reads */
rmb();
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 5d7824d2b4d4..c66a7a51198e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1663,8 +1663,10 @@ static int hns_nic_clear_all_rx_fetch(struct net_device *ndev)
for (j = 0; j < fetch_num; j++) {
/* alloc one skb and init */
skb = hns_assemble_skb(ndev);
- if (!skb)
+ if (!skb) {
+ ret = -ENOMEM;
goto out;
+ }
rd = &tx_ring_data(priv, skb->queue_mapping);
hns_nic_net_xmit_hw(ndev, skb, rd);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index ff52a65b4cff..057dda735492 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -1053,16 +1053,16 @@ struct hclge_fd_tcam_config_3_cmd {
#define HCLGE_FD_AD_DROP_B 0
#define HCLGE_FD_AD_DIRECT_QID_B 1
#define HCLGE_FD_AD_QID_S 2
-#define HCLGE_FD_AD_QID_M GENMASK(12, 2)
+#define HCLGE_FD_AD_QID_M GENMASK(11, 2)
#define HCLGE_FD_AD_USE_COUNTER_B 12
#define HCLGE_FD_AD_COUNTER_NUM_S 13
#define HCLGE_FD_AD_COUNTER_NUM_M GENMASK(20, 13)
#define HCLGE_FD_AD_NXT_STEP_B 20
#define HCLGE_FD_AD_NXT_KEY_S 21
-#define HCLGE_FD_AD_NXT_KEY_M GENMASK(26, 21)
+#define HCLGE_FD_AD_NXT_KEY_M GENMASK(25, 21)
#define HCLGE_FD_AD_WR_RULE_ID_B 0
#define HCLGE_FD_AD_RULE_ID_S 1
-#define HCLGE_FD_AD_RULE_ID_M GENMASK(13, 1)
+#define HCLGE_FD_AD_RULE_ID_M GENMASK(12, 1)
#define HCLGE_FD_AD_TC_OVRD_B 16
#define HCLGE_FD_AD_TC_SIZE_S 17
#define HCLGE_FD_AD_TC_SIZE_M GENMASK(20, 17)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 34b744df6709..e3f81c7e0ce7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -5245,9 +5245,9 @@ static bool hclge_fd_convert_tuple(u32 tuple_bit, u8 *key_x, u8 *key_y,
case BIT(INNER_SRC_MAC):
for (i = 0; i < ETH_ALEN; i++) {
calc_x(key_x[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
- rule->tuples.src_mac[i]);
+ rule->tuples_mask.src_mac[i]);
calc_y(key_y[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
- rule->tuples.src_mac[i]);
+ rule->tuples_mask.src_mac[i]);
}
return true;
@@ -6330,8 +6330,7 @@ static void hclge_fd_get_ext_info(struct ethtool_rx_flow_spec *fs,
fs->h_ext.vlan_tci = cpu_to_be16(rule->tuples.vlan_tag1);
fs->m_ext.vlan_tci =
rule->unused_tuple & BIT(INNER_VLAN_TAG_FST) ?
- cpu_to_be16(VLAN_VID_MASK) :
- cpu_to_be16(rule->tuples_mask.vlan_tag1);
+ 0 : cpu_to_be16(rule->tuples_mask.vlan_tag1);
}
if (fs->flow_type & FLOW_MAC_EXT) {
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index c3ec9ceed833..7fea9ae60f13 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1758,7 +1758,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
return 0;
}
-static int ibmveth_remove(struct vio_dev *dev)
+static void ibmveth_remove(struct vio_dev *dev)
{
struct net_device *netdev = dev_get_drvdata(&dev->dev);
struct ibmveth_adapter *adapter = netdev_priv(netdev);
@@ -1771,8 +1771,6 @@ static int ibmveth_remove(struct vio_dev *dev)
free_netdev(netdev);
dev_set_drvdata(&dev->dev, NULL);
-
- return 0;
}
static struct attribute veth_active_attr;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 118a4bd3f877..9c6438d3b3a5 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -78,7 +78,6 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(IBMVNIC_DRIVER_VERSION);
static int ibmvnic_version = IBMVNIC_INITIAL_VERSION;
-static int ibmvnic_remove(struct vio_dev *);
static void release_sub_crqs(struct ibmvnic_adapter *, bool);
static int ibmvnic_reset_crq(struct ibmvnic_adapter *);
static int ibmvnic_send_crq_init(struct ibmvnic_adapter *);
@@ -1906,10 +1905,9 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- if (adapter->state != VNIC_PROBED) {
- ether_addr_copy(adapter->mac_addr, addr->sa_data);
+ ether_addr_copy(adapter->mac_addr, addr->sa_data);
+ if (adapter->state != VNIC_PROBED)
rc = __ibmvnic_set_mac(netdev, addr->sa_data);
- }
return rc;
}
@@ -5219,16 +5217,14 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
{
struct device *dev = &adapter->vdev->dev;
unsigned long timeout = msecs_to_jiffies(20000);
- u64 old_num_rx_queues, old_num_tx_queues;
+ u64 old_num_rx_queues = adapter->req_rx_queues;
+ u64 old_num_tx_queues = adapter->req_tx_queues;
int rc;
adapter->from_passive_init = false;
- if (reset) {
- old_num_rx_queues = adapter->req_rx_queues;
- old_num_tx_queues = adapter->req_tx_queues;
+ if (reset)
reinit_completion(&adapter->init_done);
- }
adapter->init_done_rc = 0;
rc = ibmvnic_send_crq_init(adapter);
@@ -5396,7 +5392,7 @@ ibmvnic_init_fail:
return rc;
}
-static int ibmvnic_remove(struct vio_dev *dev)
+static void ibmvnic_remove(struct vio_dev *dev)
{
struct net_device *netdev = dev_get_drvdata(&dev->dev);
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
@@ -5411,9 +5407,9 @@ static int ibmvnic_remove(struct vio_dev *dev)
* after setting state, so __ibmvnic_reset() which is called
* from the flush_work() below, can make progress.
*/
- spin_lock_irqsave(&adapter->rwi_lock, flags);
+ spin_lock(&adapter->rwi_lock);
adapter->state = VNIC_REMOVING;
- spin_unlock_irqrestore(&adapter->rwi_lock, flags);
+ spin_unlock(&adapter->rwi_lock);
spin_unlock_irqrestore(&adapter->state_lock, flags);
@@ -5437,8 +5433,6 @@ static int ibmvnic_remove(struct vio_dev *dev)
device_remove_file(&dev->dev, &dev_attr_failover);
free_netdev(netdev);
dev_set_drvdata(&dev->dev, NULL);
-
- return 0;
}
static ssize_t failover_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 0a867d64d467..dc5b3c06d1e0 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1776,7 +1776,8 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter)
goto err_alloc;
}
- if (iavf_process_config(adapter))
+ err = iavf_process_config(adapter);
+ if (err)
goto err_alloc;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index eca73526ac86..54d47265a7ac 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -575,6 +575,11 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
return -EINVAL;
}
+ if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+ netdev_err(dev, "Unsupported mode for ipsec offload\n");
+ return -EINVAL;
+ }
+
if (ixgbe_ipsec_check_mgmt_ip(xs)) {
netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");
return -EINVAL;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index fae84202d870..9f3f12e2ccf2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9565,8 +9565,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
input->sw_idx, queue);
- if (!err)
- ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+ if (err)
+ goto err_out_w_lock;
+
+ ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
spin_unlock(&adapter->fdir_perfect_lock);
if ((uhtid != 0x800) && (adapter->jump_tables[uhtid]))
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
index 5170dd9d8705..caaea2c920a6 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -272,6 +272,11 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)
return -EINVAL;
}
+ if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+ netdev_err(dev, "Unsupported mode for ipsec offload\n");
+ return -EINVAL;
+ }
+
if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
struct rx_sa rsa;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 9caa375d01b1..68deae529bc9 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -56,7 +56,9 @@ static bool is_dev_rpm(void *cgxd)
bool is_lmac_valid(struct cgx *cgx, int lmac_id)
{
- return cgx && test_bit(lmac_id, &cgx->lmac_bmap);
+ if (!cgx || lmac_id < 0 || lmac_id >= MAX_LMAC_PER_CGX)
+ return false;
+ return test_bit(lmac_id, &cgx->lmac_bmap);
}
struct mac_ops *get_mac_ops(void *cgxd)
diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c
index a8641a407c06..96d2891f1675 100644
--- a/drivers/net/ethernet/mediatek/mtk_star_emac.c
+++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c
@@ -1225,8 +1225,6 @@ static int mtk_star_receive_packet(struct mtk_star_priv *priv)
goto push_new_skb;
}
- desc_data.dma_addr = new_dma_addr;
-
/* We can't fail anymore at this point: it's safe to unmap the skb. */
mtk_star_dma_unmap_rx(priv, &desc_data);
@@ -1236,6 +1234,9 @@ static int mtk_star_receive_packet(struct mtk_star_priv *priv)
desc_data.skb->dev = ndev;
netif_receive_skb(desc_data.skb);
+ /* update dma_addr for new skb */
+ desc_data.dma_addr = new_dma_addr;
+
push_new_skb:
desc_data.len = skb_tailroom(new_skb);
desc_data.skb = new_skb;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 23849f2b9c25..1434df66fcf2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -47,7 +47,7 @@
#define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)
#define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff)
-static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
{
int i, t;
int err = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 51b9700fce83..5d0c9c62382d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3554,6 +3554,8 @@ int mlx4_en_reset_config(struct net_device *dev,
en_err(priv, "Failed starting port\n");
}
+ if (!err)
+ err = mlx4_en_moderation_update(priv);
out:
mutex_unlock(&mdev->state_lock);
kfree(tmp);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index e8ed23190de0..f3d1a20201ef 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -775,6 +775,7 @@ void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
#define DEV_FEATURE_CHANGED(dev, new_features, feature) \
((dev->features & feature) ^ (new_features & feature))
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv);
int mlx4_en_reset_config(struct net_device *dev,
struct hwtstamp_config ts_config,
netdev_features_t new_features);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 16e2df6ef2f4..c4adc7f740d3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -4430,6 +4430,7 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32);
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 BIT(20)
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 BIT(21)
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 BIT(22)
+#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4 BIT(23)
#define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR BIT(27)
#define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR BIT(28)
#define MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR BIT(29)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
index bd7f873f6290..0bd64169bf81 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
@@ -1169,6 +1169,11 @@ static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
.mask_ethtool = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
.speed = SPEED_100000,
},
+ {
+ .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
+ .mask_ethtool = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+ .speed = SPEED_100000,
+ },
};
#define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 9ce90841f92d..eda99d82766a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5951,6 +5951,10 @@ mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp->router->aborted)
return 0;
+ if (fen_info->fi->nh &&
+ !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, fen_info->fi->nh->id))
+ return 0;
+
fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
&fen_info->dst, sizeof(fen_info->dst),
fen_info->dst_len,
@@ -6601,6 +6605,9 @@ static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp_fib6_rt_should_ignore(rt))
return 0;
+ if (rt->nh && !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, rt->nh->id))
+ return 0;
+
fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
&rt->fib6_dst.addr,
sizeof(rt->fib6_dst.addr),
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 40e2e79d4517..131b2a53d261 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -613,7 +613,8 @@ static const struct mlxsw_sx_port_link_mode mlxsw_sx_port_link_mode[] = {
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
+ MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
.speed = 100000,
},
};
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index dbdfabff3b00..1c3e204d727c 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -2040,7 +2040,7 @@ lan743x_rx_trim_skb(struct sk_buff *skb, int frame_length)
dev_kfree_skb_irq(skb);
return NULL;
}
- frame_length = max_t(int, 0, frame_length - RX_HEAD_PADDING - 2);
+ frame_length = max_t(int, 0, frame_length - RX_HEAD_PADDING - 4);
if (skb->len > frame_length) {
skb->tail -= skb->len - frame_length;
skb->len = frame_length;
diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig
index c0ede0ca7115..05cb040c2677 100644
--- a/drivers/net/ethernet/mscc/Kconfig
+++ b/drivers/net/ethernet/mscc/Kconfig
@@ -13,6 +13,7 @@ if NET_VENDOR_MICROSEMI
# Users should depend on NET_SWITCHDEV, HAS_IOMEM
config MSCC_OCELOT_SWITCH_LIB
+ select NET_DEVLINK
select REGMAP_MMIO
select PACKING
select PHYLIB
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index c3ac026f6aea..a41b458b1b3e 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -540,13 +540,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
return -EOPNOTSUPP;
}
+ flow_rule_match_ipv4_addrs(rule, &match);
+
if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
NL_SET_ERR_MSG_MOD(extack,
"Key type S1_NORMAL cannot match on destination IP");
return -EOPNOTSUPP;
}
- flow_rule_match_ipv4_addrs(rule, &match);
tmp = &filter->key.ipv4.sip.value.addr[0];
memcpy(tmp, &match.key->src, 4);
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index f704da3f214c..7aad0ba53372 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -767,7 +767,7 @@ static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int typ
if (type == ERIAR_OOB &&
(tp->mac_version == RTL_GIGA_MAC_VER_52 ||
tp->mac_version == RTL_GIGA_MAC_VER_53))
- *cmd |= 0x7f0 << 18;
+ *cmd |= 0xf70 << 18;
}
DECLARE_RTL_COND(rtl_eriar_cond)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 590b088bc4c7..f029c7c03804 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -560,6 +560,8 @@ static struct sh_eth_cpu_data r7s72100_data = {
EESR_TDE,
.fdr_value = 0x0000070f,
+ .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
.no_psr = 1,
.apr = 1,
.mpr = 1,
@@ -780,6 +782,8 @@ static struct sh_eth_cpu_data r7s9210_data = {
.fdr_value = 0x0000070f,
+ .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
.apr = 1,
.mpr = 1,
.tpauser = 1,
@@ -1089,6 +1093,9 @@ static struct sh_eth_cpu_data sh771x_data = {
EESIPR_CEEFIP | EESIPR_CELFIP |
EESIPR_RRFIP | EESIPR_RTLFIP | EESIPR_RTSFIP |
EESIPR_PREIP | EESIPR_CERFIP,
+
+ .trscer_err_mask = DESC_I_RINT8,
+
.tsu = 1,
.dual_port = 1,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 751dfdeec41c..0b64f7710d17 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -233,6 +233,7 @@ static void common_default_data(struct plat_stmmacenet_data *plat)
static int intel_mgbe_common_data(struct pci_dev *pdev,
struct plat_stmmacenet_data *plat)
{
+ char clk_name[20];
int ret;
int i;
@@ -301,8 +302,10 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
plat->eee_usecs_rate = plat->clk_ptp_rate;
/* Set system clock */
+ sprintf(clk_name, "%s-%s", "stmmac", pci_name(pdev));
+
plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev,
- "stmmac-clk", NULL, 0,
+ clk_name, NULL, 0,
plat->clk_ptp_rate);
if (IS_ERR(plat->stmmac_clk)) {
@@ -446,8 +449,8 @@ static int tgl_common_data(struct pci_dev *pdev,
return intel_mgbe_common_data(pdev, plat);
}
-static int tgl_sgmii_data(struct pci_dev *pdev,
- struct plat_stmmacenet_data *plat)
+static int tgl_sgmii_phy0_data(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat)
{
plat->bus_id = 1;
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
@@ -456,12 +459,26 @@ static int tgl_sgmii_data(struct pci_dev *pdev,
return tgl_common_data(pdev, plat);
}
-static struct stmmac_pci_info tgl_sgmii1g_info = {
- .setup = tgl_sgmii_data,
+static struct stmmac_pci_info tgl_sgmii1g_phy0_info = {
+ .setup = tgl_sgmii_phy0_data,
};
-static int adls_sgmii_data(struct pci_dev *pdev,
- struct plat_stmmacenet_data *plat)
+static int tgl_sgmii_phy1_data(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ plat->bus_id = 2;
+ plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+ plat->serdes_powerup = intel_serdes_powerup;
+ plat->serdes_powerdown = intel_serdes_powerdown;
+ return tgl_common_data(pdev, plat);
+}
+
+static struct stmmac_pci_info tgl_sgmii1g_phy1_info = {
+ .setup = tgl_sgmii_phy1_data,
+};
+
+static int adls_sgmii_phy0_data(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat)
{
plat->bus_id = 1;
plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
@@ -471,10 +488,24 @@ static int adls_sgmii_data(struct pci_dev *pdev,
return tgl_common_data(pdev, plat);
}
-static struct stmmac_pci_info adls_sgmii1g_info = {
- .setup = adls_sgmii_data,
+static struct stmmac_pci_info adls_sgmii1g_phy0_info = {
+ .setup = adls_sgmii_phy0_data,
};
+static int adls_sgmii_phy1_data(struct pci_dev *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ plat->bus_id = 2;
+ plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
+
+ /* SerDes power up and power down are done in BIOS for ADL */
+
+ return tgl_common_data(pdev, plat);
+}
+
+static struct stmmac_pci_info adls_sgmii1g_phy1_info = {
+ .setup = adls_sgmii_phy1_data,
+};
static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
{
.func = 6,
@@ -756,11 +787,11 @@ static const struct pci_device_id intel_eth_pci_id_table[] = {
{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_RGMII1G_ID, &ehl_pse1_rgmii1g_info) },
{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII1G_ID, &ehl_pse1_sgmii1g_info) },
{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII2G5_ID, &ehl_pse1_sgmii1g_info) },
- { PCI_DEVICE_DATA(INTEL, TGL_SGMII1G_ID, &tgl_sgmii1g_info) },
- { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_0_ID, &tgl_sgmii1g_info) },
- { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_1_ID, &tgl_sgmii1g_info) },
- { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_0_ID, &adls_sgmii1g_info) },
- { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_1_ID, &adls_sgmii1g_info) },
+ { PCI_DEVICE_DATA(INTEL, TGL_SGMII1G_ID, &tgl_sgmii1g_phy0_info) },
+ { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_0_ID, &tgl_sgmii1g_phy0_info) },
+ { PCI_DEVICE_DATA(INTEL, TGLH_SGMII1G_1_ID, &tgl_sgmii1g_phy1_info) },
+ { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_0_ID, &adls_sgmii1g_phy0_info) },
+ { PCI_DEVICE_DATA(INTEL, ADLS_SGMII1G_1_ID, &adls_sgmii1g_phy1_info) },
{}
};
MODULE_DEVICE_TABLE(pci, intel_eth_pci_id_table);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index c6540b003b43..cbf4429fb1d2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -402,19 +402,53 @@ static void dwmac4_rd_set_tx_ic(struct dma_desc *p)
p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION);
}
-static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
+static void dwmac4_display_ring(void *head, unsigned int size, bool rx,
+ dma_addr_t dma_rx_phy, unsigned int desc_size)
{
- struct dma_desc *p = (struct dma_desc *)head;
+ dma_addr_t dma_addr;
int i;
pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
- for (i = 0; i < size; i++) {
- pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
- i, (unsigned int)virt_to_phys(p),
- le32_to_cpu(p->des0), le32_to_cpu(p->des1),
- le32_to_cpu(p->des2), le32_to_cpu(p->des3));
- p++;
+ if (desc_size == sizeof(struct dma_desc)) {
+ struct dma_desc *p = (struct dma_desc *)head;
+
+ for (i = 0; i < size; i++) {
+ dma_addr = dma_rx_phy + i * sizeof(*p);
+ pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
+ le32_to_cpu(p->des0), le32_to_cpu(p->des1),
+ le32_to_cpu(p->des2), le32_to_cpu(p->des3));
+ p++;
+ }
+ } else if (desc_size == sizeof(struct dma_extended_desc)) {
+ struct dma_extended_desc *extp = (struct dma_extended_desc *)head;
+
+ for (i = 0; i < size; i++) {
+ dma_addr = dma_rx_phy + i * sizeof(*extp);
+ pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
+ le32_to_cpu(extp->basic.des0), le32_to_cpu(extp->basic.des1),
+ le32_to_cpu(extp->basic.des2), le32_to_cpu(extp->basic.des3),
+ le32_to_cpu(extp->des4), le32_to_cpu(extp->des5),
+ le32_to_cpu(extp->des6), le32_to_cpu(extp->des7));
+ extp++;
+ }
+ } else if (desc_size == sizeof(struct dma_edesc)) {
+ struct dma_edesc *ep = (struct dma_edesc *)head;
+
+ for (i = 0; i < size; i++) {
+ dma_addr = dma_rx_phy + i * sizeof(*ep);
+ pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
+ le32_to_cpu(ep->des4), le32_to_cpu(ep->des5),
+ le32_to_cpu(ep->des6), le32_to_cpu(ep->des7),
+ le32_to_cpu(ep->basic.des0), le32_to_cpu(ep->basic.des1),
+ le32_to_cpu(ep->basic.des2), le32_to_cpu(ep->basic.des3));
+ ep++;
+ }
+ } else {
+ pr_err("unsupported descriptor!");
}
}
@@ -499,10 +533,15 @@ static void dwmac4_get_rx_header_len(struct dma_desc *p, unsigned int *len)
*len = le32_to_cpu(p->des2) & RDES2_HL;
}
-static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool buf2_valid)
{
p->des2 = cpu_to_le32(lower_32_bits(addr));
- p->des3 = cpu_to_le32(upper_32_bits(addr) | RDES3_BUFFER2_VALID_ADDR);
+ p->des3 = cpu_to_le32(upper_32_bits(addr));
+
+ if (buf2_valid)
+ p->des3 |= cpu_to_le32(RDES3_BUFFER2_VALID_ADDR);
+ else
+ p->des3 &= cpu_to_le32(~RDES3_BUFFER2_VALID_ADDR);
}
static void dwmac4_set_tbs(struct dma_edesc *p, u32 sec, u32 nsec)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index bb29bfcd62c3..62aa0e95beb7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -124,6 +124,23 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr,
ioaddr + DMA_CHAN_INTR_ENA(chan));
}
+static void dwmac410_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+ u32 value;
+
+ /* common channel control register config */
+ value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+ if (dma_cfg->pblx8)
+ value = value | DMA_BUS_MODE_PBL;
+
+ writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+
+ /* Mask interrupts by writing to CSR7 */
+ writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10,
+ ioaddr + DMA_CHAN_INTR_ENA(chan));
+}
+
static void dwmac4_dma_init(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg, int atds)
{
@@ -523,7 +540,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
const struct stmmac_dma_ops dwmac410_dma_ops = {
.reset = dwmac4_dma_reset,
.init = dwmac4_dma_init,
- .init_chan = dwmac4_dma_init_channel,
+ .init_chan = dwmac410_dma_init_channel,
.init_rx_chan = dwmac4_dma_init_rx_chan,
.init_tx_chan = dwmac4_dma_init_tx_chan,
.axi = dwmac4_dma_axi,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index 0b4ee2dbb691..71e50751ef2d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -53,10 +53,6 @@ void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan)
value &= ~DMA_CONTROL_ST;
writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
-
- value = readl(ioaddr + GMAC_CONFIG);
- value &= ~GMAC_CONFIG_TE;
- writel(value, ioaddr + GMAC_CONFIG);
}
void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
index 0aaf19ab5672..ccfb0102dde4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
@@ -292,7 +292,7 @@ static void dwxgmac2_get_rx_header_len(struct dma_desc *p, unsigned int *len)
*len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
}
-static void dwxgmac2_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
+static void dwxgmac2_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool is_valid)
{
p->des2 = cpu_to_le32(lower_32_bits(addr));
p->des3 = cpu_to_le32(upper_32_bits(addr));
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index d02cec296f51..6650edfab5bc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -417,19 +417,22 @@ static int enh_desc_get_rx_timestamp_status(void *desc, void *next_desc,
}
}
-static void enh_desc_display_ring(void *head, unsigned int size, bool rx)
+static void enh_desc_display_ring(void *head, unsigned int size, bool rx,
+ dma_addr_t dma_rx_phy, unsigned int desc_size)
{
struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
+ dma_addr_t dma_addr;
int i;
pr_info("Extended %s descriptor ring:\n", rx ? "RX" : "TX");
for (i = 0; i < size; i++) {
u64 x;
+ dma_addr = dma_rx_phy + i * sizeof(*ep);
x = *(u64 *)ep;
- pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
- i, (unsigned int)virt_to_phys(ep),
+ pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
(unsigned int)x, (unsigned int)(x >> 32),
ep->basic.des2, ep->basic.des3);
ep++;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index b40b2e0667bb..979ac9fca23c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -78,7 +78,8 @@ struct stmmac_desc_ops {
/* get rx timestamp status */
int (*get_rx_timestamp_status)(void *desc, void *next_desc, u32 ats);
/* Display ring */
- void (*display_ring)(void *head, unsigned int size, bool rx);
+ void (*display_ring)(void *head, unsigned int size, bool rx,
+ dma_addr_t dma_rx_phy, unsigned int desc_size);
/* set MSS via context descriptor */
void (*set_mss)(struct dma_desc *p, unsigned int mss);
/* get descriptor skbuff address */
@@ -91,7 +92,7 @@ struct stmmac_desc_ops {
int (*get_rx_hash)(struct dma_desc *p, u32 *hash,
enum pkt_hash_types *type);
void (*get_rx_header_len)(struct dma_desc *p, unsigned int *len);
- void (*set_sec_addr)(struct dma_desc *p, dma_addr_t addr);
+ void (*set_sec_addr)(struct dma_desc *p, dma_addr_t addr, bool buf2_valid);
void (*set_sarc)(struct dma_desc *p, u32 sarc_type);
void (*set_vlan_tag)(struct dma_desc *p, u16 tag, u16 inner_tag,
u32 inner_type);
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index f083360e4ba6..98ef43f35802 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -269,19 +269,22 @@ static int ndesc_get_rx_timestamp_status(void *desc, void *next_desc, u32 ats)
return 1;
}
-static void ndesc_display_ring(void *head, unsigned int size, bool rx)
+static void ndesc_display_ring(void *head, unsigned int size, bool rx,
+ dma_addr_t dma_rx_phy, unsigned int desc_size)
{
struct dma_desc *p = (struct dma_desc *)head;
+ dma_addr_t dma_addr;
int i;
pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
for (i = 0; i < size; i++) {
u64 x;
+ dma_addr = dma_rx_phy + i * sizeof(*p);
x = *(u64 *)p;
- pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
- i, (unsigned int)virt_to_phys(p),
+ pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x",
+ i, &dma_addr,
(unsigned int)x, (unsigned int)(x >> 32),
p->des2, p->des3);
p++;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 26b971cd4da5..208cae344ffa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1133,6 +1133,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
static void stmmac_display_rx_rings(struct stmmac_priv *priv)
{
u32 rx_cnt = priv->plat->rx_queues_to_use;
+ unsigned int desc_size;
void *head_rx;
u32 queue;
@@ -1142,19 +1143,24 @@ static void stmmac_display_rx_rings(struct stmmac_priv *priv)
pr_info("\tRX Queue %u rings\n", queue);
- if (priv->extend_desc)
+ if (priv->extend_desc) {
head_rx = (void *)rx_q->dma_erx;
- else
+ desc_size = sizeof(struct dma_extended_desc);
+ } else {
head_rx = (void *)rx_q->dma_rx;
+ desc_size = sizeof(struct dma_desc);
+ }
/* Display RX ring */
- stmmac_display_ring(priv, head_rx, priv->dma_rx_size, true);
+ stmmac_display_ring(priv, head_rx, priv->dma_rx_size, true,
+ rx_q->dma_rx_phy, desc_size);
}
}
static void stmmac_display_tx_rings(struct stmmac_priv *priv)
{
u32 tx_cnt = priv->plat->tx_queues_to_use;
+ unsigned int desc_size;
void *head_tx;
u32 queue;
@@ -1164,14 +1170,19 @@ static void stmmac_display_tx_rings(struct stmmac_priv *priv)
pr_info("\tTX Queue %d rings\n", queue);
- if (priv->extend_desc)
+ if (priv->extend_desc) {
head_tx = (void *)tx_q->dma_etx;
- else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+ desc_size = sizeof(struct dma_extended_desc);
+ } else if (tx_q->tbs & STMMAC_TBS_AVAIL) {
head_tx = (void *)tx_q->dma_entx;
- else
+ desc_size = sizeof(struct dma_edesc);
+ } else {
head_tx = (void *)tx_q->dma_tx;
+ desc_size = sizeof(struct dma_desc);
+ }
- stmmac_display_ring(priv, head_tx, priv->dma_tx_size, false);
+ stmmac_display_ring(priv, head_tx, priv->dma_tx_size, false,
+ tx_q->dma_tx_phy, desc_size);
}
}
@@ -1303,9 +1314,10 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
return -ENOMEM;
buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
- stmmac_set_desc_sec_addr(priv, p, buf->sec_addr);
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
} else {
buf->sec_page = NULL;
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
}
buf->addr = page_pool_get_dma_addr(buf->page);
@@ -1368,6 +1380,88 @@ static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i)
}
/**
+ * stmmac_reinit_rx_buffers - reinit the RX descriptor buffer.
+ * @priv: driver private structure
+ * Description: this function is called to re-allocate a receive buffer, perform
+ * the DMA mapping and init the descriptor.
+ */
+static void stmmac_reinit_rx_buffers(struct stmmac_priv *priv)
+{
+ u32 rx_count = priv->plat->rx_queues_to_use;
+ u32 queue;
+ int i;
+
+ for (queue = 0; queue < rx_count; queue++) {
+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+
+ for (i = 0; i < priv->dma_rx_size; i++) {
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
+
+ if (buf->page) {
+ page_pool_recycle_direct(rx_q->page_pool, buf->page);
+ buf->page = NULL;
+ }
+
+ if (priv->sph && buf->sec_page) {
+ page_pool_recycle_direct(rx_q->page_pool, buf->sec_page);
+ buf->sec_page = NULL;
+ }
+ }
+ }
+
+ for (queue = 0; queue < rx_count; queue++) {
+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+
+ for (i = 0; i < priv->dma_rx_size; i++) {
+ struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
+ struct dma_desc *p;
+
+ if (priv->extend_desc)
+ p = &((rx_q->dma_erx + i)->basic);
+ else
+ p = rx_q->dma_rx + i;
+
+ if (!buf->page) {
+ buf->page = page_pool_dev_alloc_pages(rx_q->page_pool);
+ if (!buf->page)
+ goto err_reinit_rx_buffers;
+
+ buf->addr = page_pool_get_dma_addr(buf->page);
+ }
+
+ if (priv->sph && !buf->sec_page) {
+ buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool);
+ if (!buf->sec_page)
+ goto err_reinit_rx_buffers;
+
+ buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
+ }
+
+ stmmac_set_desc_addr(priv, p, buf->addr);
+ if (priv->sph)
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
+ else
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
+ if (priv->dma_buf_sz == BUF_SIZE_16KiB)
+ stmmac_init_desc3(priv, p);
+ }
+ }
+
+ return;
+
+err_reinit_rx_buffers:
+ do {
+ while (--i >= 0)
+ stmmac_free_rx_buffer(priv, queue, i);
+
+ if (queue == 0)
+ break;
+
+ i = priv->dma_rx_size;
+ } while (queue-- > 0);
+}
+
+/**
* init_dma_rx_desc_rings - init the RX descriptor rings
* @dev: net device structure
* @flags: gfp flag.
@@ -3648,7 +3742,10 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
DMA_FROM_DEVICE);
stmmac_set_desc_addr(priv, p, buf->addr);
- stmmac_set_desc_sec_addr(priv, p, buf->sec_addr);
+ if (priv->sph)
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
+ else
+ stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
stmmac_refill_desc3(priv, rx_q, p);
rx_q->rx_count_frames++;
@@ -3736,18 +3833,23 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
unsigned int count = 0, error = 0, len = 0;
int status = 0, coe = priv->hw->rx_csum;
unsigned int next_entry = rx_q->cur_rx;
+ unsigned int desc_size;
struct sk_buff *skb = NULL;
if (netif_msg_rx_status(priv)) {
void *rx_head;
netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
- if (priv->extend_desc)
+ if (priv->extend_desc) {
rx_head = (void *)rx_q->dma_erx;
- else
+ desc_size = sizeof(struct dma_extended_desc);
+ } else {
rx_head = (void *)rx_q->dma_rx;
+ desc_size = sizeof(struct dma_desc);
+ }
- stmmac_display_ring(priv, rx_head, priv->dma_rx_size, true);
+ stmmac_display_ring(priv, rx_head, priv->dma_rx_size, true,
+ rx_q->dma_rx_phy, desc_size);
}
while (count < limit) {
unsigned int buf1_len = 0, buf2_len = 0;
@@ -4315,24 +4417,27 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
static struct dentry *stmmac_fs_dir;
static void sysfs_display_ring(void *head, int size, int extend_desc,
- struct seq_file *seq)
+ struct seq_file *seq, dma_addr_t dma_phy_addr)
{
int i;
struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
struct dma_desc *p = (struct dma_desc *)head;
+ dma_addr_t dma_addr;
for (i = 0; i < size; i++) {
if (extend_desc) {
- seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
- i, (unsigned int)virt_to_phys(ep),
+ dma_addr = dma_phy_addr + i * sizeof(*ep);
+ seq_printf(seq, "%d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
le32_to_cpu(ep->basic.des0),
le32_to_cpu(ep->basic.des1),
le32_to_cpu(ep->basic.des2),
le32_to_cpu(ep->basic.des3));
ep++;
} else {
- seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
- i, (unsigned int)virt_to_phys(p),
+ dma_addr = dma_phy_addr + i * sizeof(*p);
+ seq_printf(seq, "%d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
+ i, &dma_addr,
le32_to_cpu(p->des0), le32_to_cpu(p->des1),
le32_to_cpu(p->des2), le32_to_cpu(p->des3));
p++;
@@ -4360,11 +4465,11 @@ static int stmmac_rings_status_show(struct seq_file *seq, void *v)
if (priv->extend_desc) {
seq_printf(seq, "Extended descriptor ring:\n");
sysfs_display_ring((void *)rx_q->dma_erx,
- priv->dma_rx_size, 1, seq);
+ priv->dma_rx_size, 1, seq, rx_q->dma_rx_phy);
} else {
seq_printf(seq, "Descriptor ring:\n");
sysfs_display_ring((void *)rx_q->dma_rx,
- priv->dma_rx_size, 0, seq);
+ priv->dma_rx_size, 0, seq, rx_q->dma_rx_phy);
}
}
@@ -4376,11 +4481,11 @@ static int stmmac_rings_status_show(struct seq_file *seq, void *v)
if (priv->extend_desc) {
seq_printf(seq, "Extended descriptor ring:\n");
sysfs_display_ring((void *)tx_q->dma_etx,
- priv->dma_tx_size, 1, seq);
+ priv->dma_tx_size, 1, seq, tx_q->dma_tx_phy);
} else if (!(tx_q->tbs & STMMAC_TBS_AVAIL)) {
seq_printf(seq, "Descriptor ring:\n");
sysfs_display_ring((void *)tx_q->dma_tx,
- priv->dma_tx_size, 0, seq);
+ priv->dma_tx_size, 0, seq, tx_q->dma_tx_phy);
}
}
@@ -5144,13 +5249,16 @@ int stmmac_dvr_remove(struct device *dev)
netdev_info(priv->dev, "%s: removing driver", __func__);
stmmac_stop_all_dma(priv);
+ stmmac_mac_set(priv, priv->ioaddr, false);
+ netif_carrier_off(ndev);
+ unregister_netdev(ndev);
+ /* Serdes power down needs to happen after VLAN filter
+ * is deleted that is triggered by unregister_netdev().
+ */
if (priv->plat->serdes_powerdown)
priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
- stmmac_mac_set(priv, priv->ioaddr, false);
- netif_carrier_off(ndev);
- unregister_netdev(ndev);
#ifdef CONFIG_DEBUG_FS
stmmac_exit_fs(ndev);
#endif
@@ -5257,6 +5365,8 @@ static void stmmac_reset_queues_param(struct stmmac_priv *priv)
tx_q->cur_tx = 0;
tx_q->dirty_tx = 0;
tx_q->mss = 0;
+
+ netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue));
}
}
@@ -5318,7 +5428,7 @@ int stmmac_resume(struct device *dev)
mutex_lock(&priv->lock);
stmmac_reset_queues_param(priv);
-
+ stmmac_reinit_rx_buffers(priv);
stmmac_free_tx_skbufs(priv);
stmmac_clear_descriptors(priv);
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 68695d4afacd..707ccdd03b19 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -3931,8 +3931,6 @@ static void niu_xmac_interrupt(struct niu *np)
mp->rx_mcasts += RXMAC_MC_FRM_CNT_COUNT;
if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
- if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
- mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
if (val & XRXMAC_STATUS_RXHIST1_CNT_EXP)
mp->rx_hist_cnt1 += RXMAC_HIST_CNT1_COUNT;
if (val & XRXMAC_STATUS_RXHIST2_CNT_EXP)
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index b8f4f419173f..d054c6e83b1c 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -2044,6 +2044,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/*bdx_hw_reset(priv); */
if (bdx_read_mac(priv)) {
pr_err("load MAC address failed\n");
+ err = -EFAULT;
goto err_out_iomap;
}
SET_NETDEV_DEV(ndev, &pdev->dev);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 71d6629e65c9..9f5b5614a150 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -171,11 +171,6 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
goto out_drop;
}
- if (len > sp->mtu) { /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
- msg = "oversized transmit packet!";
- goto out_drop;
- }
-
if (p[0] > 5) {
msg = "invalid KISS command";
goto out_drop;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 36eeb80406f2..4690c6a59054 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -2167,7 +2167,6 @@ static void __exit scc_cleanup_driver(void)
MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
MODULE_DESCRIPTION("AX.25 Device Driver for Z8530 based HDLC cards");
-MODULE_SUPPORTED_DEVICE("Z8530 based SCC cards for Amateur Radio");
MODULE_LICENSE("GPL");
module_init(scc_init_driver);
module_exit(scc_cleanup_driver);
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index e1a497d3c9ba..59ac04a610ad 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -229,7 +229,7 @@ int netvsc_send(struct net_device *net,
bool xdp_tx);
void netvsc_linkstatus_callback(struct net_device *net,
struct rndis_message *resp,
- void *data);
+ void *data, u32 data_buflen);
int netvsc_recv_callback(struct net_device *net,
struct netvsc_device *nvdev,
struct netvsc_channel *nvchan);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 8176fa0c8b16..15f262b70489 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -744,7 +744,7 @@ static netdev_tx_t netvsc_start_xmit(struct sk_buff *skb,
*/
void netvsc_linkstatus_callback(struct net_device *net,
struct rndis_message *resp,
- void *data)
+ void *data, u32 data_buflen)
{
struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
struct net_device_context *ndev_ctx = netdev_priv(net);
@@ -765,11 +765,16 @@ void netvsc_linkstatus_callback(struct net_device *net,
if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) {
u32 speed;
- /* Validate status_buf_offset */
+ /* Validate status_buf_offset and status_buflen.
+ *
+ * Certain (pre-Fe) implementations of Hyper-V's vSwitch didn't account
+ * for the status buffer field in resp->msg_len; perform the validation
+ * using data_buflen (>= resp->msg_len).
+ */
if (indicate->status_buflen < sizeof(speed) ||
indicate->status_buf_offset < sizeof(*indicate) ||
- resp->msg_len - RNDIS_HEADER_SIZE < indicate->status_buf_offset ||
- resp->msg_len - RNDIS_HEADER_SIZE - indicate->status_buf_offset
+ data_buflen - RNDIS_HEADER_SIZE < indicate->status_buf_offset ||
+ data_buflen - RNDIS_HEADER_SIZE - indicate->status_buf_offset
< indicate->status_buflen) {
netdev_err(net, "invalid rndis_indicate_status packet\n");
return;
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 123cc9d25f5e..c0e89e107d57 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -620,7 +620,7 @@ int rndis_filter_receive(struct net_device *ndev,
case RNDIS_MSG_INDICATE:
/* notification msgs */
- netvsc_linkstatus_callback(ndev, rndis_msg, data);
+ netvsc_linkstatus_callback(ndev, rndis_msg, data, buflen);
break;
default:
netdev_err(ndev,
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index aec92440eef1..659d3dceb687 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -294,6 +294,7 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
dev_net_set(dev, nsim_dev_net(nsim_dev));
ns = netdev_priv(dev);
ns->netdev = dev;
+ u64_stats_init(&ns->syncp);
ns->nsim_dev = nsim_dev;
ns->nsim_dev_port = nsim_dev_port;
ns->nsim_bus_dev = nsim_dev->nsim_bus_dev;
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index be1224b4447b..f7a2ec150e54 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -290,6 +290,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
{
+ bool trigger_machine = false;
int irq_status;
/* The MISR1 and MISR2 registers are holding the interrupt status in
@@ -305,7 +306,7 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
- goto trigger_machine;
+ trigger_machine = true;
irq_status = phy_read(phydev, MII_DP83822_MISR2);
if (irq_status < 0) {
@@ -313,11 +314,11 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
- goto trigger_machine;
+ trigger_machine = true;
- return IRQ_NONE;
+ if (!trigger_machine)
+ return IRQ_NONE;
-trigger_machine:
phy_trigger_machine(phydev);
return IRQ_HANDLED;
diff --git a/drivers/net/phy/dp83tc811.c b/drivers/net/phy/dp83tc811.c
index 688fadffb249..7ea32fb77190 100644
--- a/drivers/net/phy/dp83tc811.c
+++ b/drivers/net/phy/dp83tc811.c
@@ -264,6 +264,7 @@ static int dp83811_config_intr(struct phy_device *phydev)
static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
{
+ bool trigger_machine = false;
int irq_status;
/* The INT_STAT registers 1, 2 and 3 are holding the interrupt status
@@ -279,7 +280,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
- goto trigger_machine;
+ trigger_machine = true;
irq_status = phy_read(phydev, MII_DP83811_INT_STAT2);
if (irq_status < 0) {
@@ -287,7 +288,7 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
- goto trigger_machine;
+ trigger_machine = true;
irq_status = phy_read(phydev, MII_DP83811_INT_STAT3);
if (irq_status < 0) {
@@ -295,11 +296,11 @@ static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
- goto trigger_machine;
+ trigger_machine = true;
- return IRQ_NONE;
+ if (!trigger_machine)
+ return IRQ_NONE;
-trigger_machine:
phy_trigger_machine(phydev);
return IRQ_HANDLED;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 1be07e45d314..fc2e7cb5b2e5 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -276,14 +276,16 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev,
phydev->autoneg = autoneg;
- phydev->speed = speed;
+ if (autoneg == AUTONEG_DISABLE) {
+ phydev->speed = speed;
+ phydev->duplex = duplex;
+ }
linkmode_copy(phydev->advertising, advertising);
linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->advertising, autoneg == AUTONEG_ENABLE);
- phydev->duplex = duplex;
phydev->master_slave_set = cmd->base.master_slave_cfg;
phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ce495473cd5d..cc38e326405a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -230,7 +230,6 @@ static struct phy_driver genphy_driver;
static LIST_HEAD(phy_fixup_list);
static DEFINE_MUTEX(phy_fixup_lock);
-#ifdef CONFIG_PM
static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
{
struct device_driver *drv = phydev->mdio.dev.driver;
@@ -270,7 +269,7 @@ out:
return !phydev->suspended;
}
-static int mdio_bus_phy_suspend(struct device *dev)
+static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
{
struct phy_device *phydev = to_phy_device(dev);
@@ -290,7 +289,7 @@ static int mdio_bus_phy_suspend(struct device *dev)
return phy_suspend(phydev);
}
-static int mdio_bus_phy_resume(struct device *dev)
+static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
{
struct phy_device *phydev = to_phy_device(dev);
int ret;
@@ -316,7 +315,6 @@ no_resume:
static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend,
mdio_bus_phy_resume);
-#endif /* CONFIG_PM */
/**
* phy_register_fixup - creates a new phy_fixup and adds it to the list
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 4087c9e33781..8acf30115428 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -851,17 +851,17 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
/* check if we got everything */
if (!ctx->data) {
- dev_dbg(&intf->dev, "CDC Union missing and no IAD found\n");
+ dev_err(&intf->dev, "CDC Union missing and no IAD found\n");
goto error;
}
if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) {
if (!ctx->mbim_desc) {
- dev_dbg(&intf->dev, "MBIM functional descriptor missing\n");
+ dev_err(&intf->dev, "MBIM functional descriptor missing\n");
goto error;
}
} else {
if (!ctx->ether_desc || !ctx->func_desc) {
- dev_dbg(&intf->dev, "NCM or ECM functional descriptors missing\n");
+ dev_err(&intf->dev, "NCM or ECM functional descriptors missing\n");
goto error;
}
}
@@ -870,7 +870,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
if (ctx->data != ctx->control) {
temp = usb_driver_claim_interface(driver, ctx->data, dev);
if (temp) {
- dev_dbg(&intf->dev, "failed to claim data intf\n");
+ dev_err(&intf->dev, "failed to claim data intf\n");
goto error;
}
}
@@ -926,7 +926,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
if (ctx->ether_desc) {
temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
if (temp) {
- dev_dbg(&intf->dev, "failed to get mac address\n");
+ dev_err(&intf->dev, "failed to get mac address\n");
goto error2;
}
dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 17a050521b86..6700f1970b24 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -429,13 +429,6 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c
goto err;
}
- /* we don't want to modify a running netdev */
- if (netif_running(dev->net)) {
- netdev_err(dev->net, "Cannot change a running device\n");
- ret = -EBUSY;
- goto err;
- }
-
ret = qmimux_register_device(dev->net, mux_id);
if (!ret) {
info->flags |= QMI_WWAN_FLAG_MUX;
@@ -465,13 +458,6 @@ static ssize_t del_mux_store(struct device *d, struct device_attribute *attr, c
if (!rtnl_trylock())
return restart_syscall();
- /* we don't want to modify a running netdev */
- if (netif_running(dev->net)) {
- netdev_err(dev->net, "Cannot change a running device\n");
- ret = -EBUSY;
- goto err;
- }
-
del_dev = qmimux_find_dev(dev, mux_id);
if (!del_dev) {
netdev_err(dev->net, "mux_id not present\n");
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index b246817f3405..90f1c0200042 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -3021,29 +3021,6 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
device_set_wakeup_enable(&tp->udev->dev, false);
}
-static void r8153_mac_clk_spd(struct r8152 *tp, bool enable)
-{
- /* MAC clock speed down */
- if (enable) {
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL,
- ALDPS_SPDWN_RATIO);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2,
- EEE_SPDWN_RATIO);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
- PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
- U1U2_SPDWN_EN | L1_SPDWN_EN);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
- PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
- TP100_SPDWN_EN | TP500_SPDWN_EN | EEE_SPDWN_EN |
- TP1000_SPDWN_EN);
- } else {
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
- }
-}
-
static void r8153_u1u2en(struct r8152 *tp, bool enable)
{
u8 u1u2[8];
@@ -3338,11 +3315,9 @@ static void rtl8153_runtime_enable(struct r8152 *tp, bool enable)
if (enable) {
r8153_u1u2en(tp, false);
r8153_u2p3en(tp, false);
- r8153_mac_clk_spd(tp, true);
rtl_runtime_suspend_enable(tp, true);
} else {
rtl_runtime_suspend_enable(tp, false);
- r8153_mac_clk_spd(tp, false);
switch (tp->version) {
case RTL_VER_03:
@@ -4718,7 +4693,6 @@ static void r8153_first_init(struct r8152 *tp)
{
u32 ocp_data;
- r8153_mac_clk_spd(tp, false);
rxdy_gated_en(tp, true);
r8153_teredo_off(tp);
@@ -4769,8 +4743,6 @@ static void r8153_enter_oob(struct r8152 *tp)
{
u32 ocp_data;
- r8153_mac_clk_spd(tp, true);
-
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
ocp_data &= ~NOW_IS_OOB;
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
@@ -5496,10 +5468,15 @@ static void r8153_init(struct r8152 *tp)
ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
+ /* MAC clock speed down */
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
+
r8153_power_cut_en(tp, false);
rtl_runtime_suspend_enable(tp, false);
r8153_u1u2en(tp, true);
- r8153_mac_clk_spd(tp, false);
usb_enable_lpm(tp->udev);
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index b4c8080e6f87..f4f37ecfed58 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -887,7 +887,7 @@ int usbnet_open (struct net_device *net)
// insist peer be connected
if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
- netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval);
+ netif_err(dev, ifup, dev->net, "can't open; %d\n", retval);
goto done;
}
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index dca97cd7c4e7..7eac6a3e1cde 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -204,14 +204,18 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
priv->rx_skbuff = kcalloc(priv->rx_ring_size,
sizeof(*priv->rx_skbuff),
GFP_KERNEL);
- if (!priv->rx_skbuff)
+ if (!priv->rx_skbuff) {
+ ret = -ENOMEM;
goto free_ucc_pram;
+ }
priv->tx_skbuff = kcalloc(priv->tx_ring_size,
sizeof(*priv->tx_skbuff),
GFP_KERNEL);
- if (!priv->tx_skbuff)
+ if (!priv->tx_skbuff) {
+ ret = -ENOMEM;
goto free_rx_skbuff;
+ }
priv->skb_curtx = 0;
priv->skb_dirtytx = 0;
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 605fe555e157..c3372498f4f1 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -292,7 +292,6 @@ static int lapbeth_open(struct net_device *dev)
return -ENODEV;
}
- netif_start_queue(dev);
return 0;
}
@@ -300,8 +299,6 @@ static int lapbeth_close(struct net_device *dev)
{
int err;
- netif_stop_queue(dev);
-
if ((err = lapb_unregister(dev)) != LAPB_OK)
pr_err("lapb_unregister error: %d\n", err);
diff --git a/drivers/net/wireless/admtek/adm8211.c b/drivers/net/wireless/admtek/adm8211.c
index c41e72508d3d..2db9c948c0fc 100644
--- a/drivers/net/wireless/admtek/adm8211.c
+++ b/drivers/net/wireless/admtek/adm8211.c
@@ -28,7 +28,6 @@
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_AUTHOR("Jouni Malinen <j@w1.fi>");
MODULE_DESCRIPTION("Driver for IEEE 802.11b wireless cards based on ADMtek ADM8211");
-MODULE_SUPPORTED_DEVICE("ADM8211");
MODULE_LICENSE("GPL");
static unsigned int tx_ring_size __read_mostly = 16;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index b391169576e2..faa2e678e63e 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -5450,8 +5450,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
}
if (ab->hw_params.vdev_start_delay &&
- (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
- arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {
+ arvif->vdev_type != WMI_VDEV_TYPE_AP &&
+ arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
param.vdev_id = arvif->vdev_id;
param.peer_type = WMI_PEER_TYPE_DEFAULT;
param.peer_addr = ar->mac_addr;
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index 1aca841cd147..7968fe4eda22 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1687,8 +1687,8 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi req mem_seg[%d] 0x%llx %u %u\n", i,
- ab->qmi.target_mem[i].paddr,
+ "qmi req mem_seg[%d] %pad %u %u\n", i,
+ &ab->qmi.target_mem[i].paddr,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].type);
}
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 4c6e57f9976d..cef17f33c69e 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -90,7 +90,6 @@ MODULE_PARM_DESC(no_hw_rfkill_switch, "Ignore the GPIO RFKill switch state");
MODULE_AUTHOR("Jiri Slaby");
MODULE_AUTHOR("Nick Kossifidis");
MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static int ath5k_init(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 13b4f5f50f8a..ef6f5ea06c1f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -177,7 +177,8 @@ struct ath_frame_info {
s8 txq;
u8 keyix;
u8 rtscts_rate;
- u8 retries : 7;
+ u8 retries : 6;
+ u8 dyn_smps : 1;
u8 baw_tracked : 1;
u8 tx_power;
enum ath9k_key_type keytype:2;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index b66eeb577272..5abc2a5526ec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -34,7 +34,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static void ath9k_hw_set_clockrate(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 42a208787f5a..01f9c26f9bf3 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -37,7 +37,6 @@ static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index e60d4737fc6e..5691bd6eb82c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1271,6 +1271,11 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+ if (rix >= 8 && fi->dyn_smps) {
+ info->rates[i].RateFlags |=
+ ATH9K_RATESERIES_RTS_CTS;
+ info->flags |= ATH9K_TXDESC_CTSENA;
+ }
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
is_40, false);
@@ -2114,6 +2119,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
fi->keyix = an->ps_key;
else
fi->keyix = ATH9K_TXKEYIX_INVALID;
+ fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC;
fi->keytype = keytype;
fi->framelen = framelen;
fi->tx_power = txpower;
diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c
index 707fe66727f8..febce4e8b3dd 100644
--- a/drivers/net/wireless/atmel/atmel.c
+++ b/drivers/net/wireless/atmel/atmel.c
@@ -75,7 +75,6 @@
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
/* The name of the firmware file to be loaded
over-rides any automatic selection */
diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c
index 368eebefa741..453bb84cb338 100644
--- a/drivers/net/wireless/atmel/atmel_cs.c
+++ b/drivers/net/wireless/atmel/atmel_cs.c
@@ -57,7 +57,6 @@
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
/*====================================================================*/
diff --git a/drivers/net/wireless/atmel/atmel_pci.c b/drivers/net/wireless/atmel/atmel_pci.c
index 47f7ccb32414..f428dc79d916 100644
--- a/drivers/net/wireless/atmel/atmel_pci.c
+++ b/drivers/net/wireless/atmel/atmel_pci.c
@@ -16,7 +16,6 @@
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards");
static const struct pci_device_id card_ids[] = {
{ 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID },
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
index 818e523f6025..39f3af2d0439 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
@@ -87,7 +87,6 @@ static int n_adapters_found;
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
/* This needs to be adjusted when brcms_firmwares changes */
MODULE_FIRMWARE("brcm/bcm43xx-0.fw");
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
index 4c84c3001c3f..e87e68cc46e2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
@@ -12,7 +12,6 @@
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
struct sk_buff *brcmu_pkt_buf_get_skb(uint len)
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index e35e1380ae43..60db38c38960 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -251,7 +251,6 @@ MODULE_AUTHOR("Benjamin Reed");
MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet cards. "
"Direct support for ISA/PCI/MPI cards and support for PCMCIA when used with airo_cs.");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
module_param_hw_array(io, int, ioport, NULL, 0);
module_param_hw_array(irq, int, irq, NULL, 0);
module_param_array(rates, int, NULL, 0);
diff --git a/drivers/net/wireless/cisco/airo_cs.c b/drivers/net/wireless/cisco/airo_cs.c
index 3718f958c0fc..fcfe4c6d62f0 100644
--- a/drivers/net/wireless/cisco/airo_cs.c
+++ b/drivers/net/wireless/cisco/airo_cs.c
@@ -47,7 +47,6 @@ MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet "
"cards. This is the module that links the PCMCIA card "
"with the airo module.");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
/*====================================================================*/
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index fd070ca5e517..40f2109a097f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -271,12 +271,12 @@ static int iwl_pnvm_get_from_efi(struct iwl_trans *trans,
err = efivar_entry_get(pnvm_efivar, NULL, &package_size, package);
if (err) {
IWL_DEBUG_FW(trans,
- "PNVM UEFI variable not found %d (len %zd)\n",
+ "PNVM UEFI variable not found %d (len %lu)\n",
err, package_size);
goto out;
}
- IWL_DEBUG_FW(trans, "Read PNVM fro UEFI with size %zd\n", package_size);
+ IWL_DEBUG_FW(trans, "Read PNVM fro UEFI with size %lu\n", package_size);
*data = kmemdup(package->data, *len, GFP_KERNEL);
if (!*data)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
index 868da7e79a45..e6d2e0994317 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
@@ -205,6 +205,8 @@ static inline void iwl_op_mode_time_point(struct iwl_op_mode *op_mode,
enum iwl_fw_ini_time_point tp_id,
union iwl_dbg_tlv_tp_data *tp_data)
{
+ if (!op_mode || !op_mode->ops || !op_mode->ops->time_point)
+ return;
op_mode->ops->time_point(op_mode, tp_id, tp_data);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 15e2773ce7e7..5ee64f7f3c85 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1083,6 +1083,7 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek COMPUTER INC."),
},
},
+ {}
};
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 314fec4a89ad..ffaf973dae94 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1106,6 +1106,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+#if IS_ENABLED(CONFIG_IWLMVM)
+
/*
* Workaround for problematic SnJ device: sometimes when
* certain RF modules are connected to SnJ, the device ID
@@ -1116,7 +1118,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_SNJ)
iwl_trans->trans_cfg = &iwl_so_trans_cfg;
-#if IS_ENABLED(CONFIG_IWLMVM)
/*
* special-case 7265D, it has the same PCI IDs.
*
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 42426e25cac6..2bec97133119 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1129,6 +1129,8 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
iwl_pcie_rx_init_rxb_lists(rxq);
+ spin_unlock_bh(&rxq->lock);
+
if (!rxq->napi.poll) {
int (*poll)(struct napi_struct *, int) = iwl_pcie_napi_poll;
@@ -1149,7 +1151,6 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
napi_enable(&rxq->napi);
}
- spin_unlock_bh(&rxq->lock);
}
/* move the pool to the default queue and allocator ownerships */
diff --git a/drivers/net/wireless/intersil/hostap/hostap_cs.c b/drivers/net/wireless/intersil/hostap/hostap_cs.c
index 1a748670835a..ec7db2badc40 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_cs.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_cs.c
@@ -26,7 +26,6 @@ static char *dev_info = "hostap_cs";
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PC Card).");
-MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/intersil/hostap/hostap_pci.c b/drivers/net/wireless/intersil/hostap/hostap_pci.c
index 101887e6bd0f..52d77506effd 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_pci.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_pci.c
@@ -27,7 +27,6 @@ static char *dev_info = "hostap_pci";
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
"PCI cards.");
-MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/intersil/hostap/hostap_plx.c b/drivers/net/wireless/intersil/hostap/hostap_plx.c
index 841cfc68ce84..58247290fcbc 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_plx.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_plx.c
@@ -30,7 +30,6 @@ static char *dev_info = "hostap_plx";
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PLX).");
-MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 19098b852d0a..2f27c43ad76d 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -345,7 +345,6 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
};
struct ieee80211_hw *hw;
int len, n = 0, ret = -ENOMEM;
- struct mt76_queue_entry e;
struct mt76_txwi_cache *t;
struct sk_buff *iter;
dma_addr_t addr;
@@ -387,6 +386,11 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
}
tx_info.nbuf = n;
+ if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
+ ret = -ENOMEM;
+ goto unmap;
+ }
+
dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,
DMA_TO_DEVICE);
ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
@@ -395,11 +399,6 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
if (ret < 0)
goto unmap;
- if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
- ret = -ENOMEM;
- goto unmap;
- }
-
return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
tx_info.info, tx_info.skb, t);
@@ -419,9 +418,7 @@ free:
}
#endif
- e.skb = tx_info.skb;
- e.txwi = t;
- dev->drv->tx_complete_skb(dev, &e);
+ dev_kfree_skb(tx_info.skb);
mt76_put_txwi(dev, t);
return ret;
}
@@ -515,13 +512,13 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
{
struct sk_buff *skb = q->rx_head;
struct skb_shared_info *shinfo = skb_shinfo(skb);
+ int nr_frags = shinfo->nr_frags;
- if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) {
+ if (nr_frags < ARRAY_SIZE(shinfo->frags)) {
struct page *page = virt_to_head_page(data);
int offset = data - page_address(page) + q->buf_offset;
- skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len,
- q->buf_size);
+ skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
} else {
skb_free_frag(data);
}
@@ -530,7 +527,10 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
return;
q->rx_head = NULL;
- dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+ if (nr_frags < ARRAY_SIZE(shinfo->frags))
+ dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+ else
+ dev_kfree_skb(skb);
}
static int
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index eb889f8d6fea..e5a258958ac9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -967,11 +967,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
}
txp->nbuf = nbuf;
- /* pass partial skb header to fw */
- tx_info->buf[1].len = MT_CT_PARSE_LEN;
- tx_info->buf[1].skip_unmap = true;
- tx_info->nbuf = MT_CT_DMA_BUF_NUM;
-
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST);
if (!key)
@@ -1009,6 +1004,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
txp->rept_wds_wcid = cpu_to_le16(0x3ff);
tx_info->skb = DMA_DUMMY_DATA;
+ /* pass partial skb header to fw */
+ tx_info->buf[1].len = MT_CT_PARSE_LEN;
+ tx_info->buf[1].skip_unmap = true;
+ tx_info->nbuf = MT_CT_DMA_BUF_NUM;
+
return 0;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
index 7fb2170a9561..bd798df748ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c
@@ -543,7 +543,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
tx_cont->bw = CMD_CBW_20MHZ;
break;
default:
- break;
+ return -EINVAL;
}
if (!en) {
@@ -591,7 +591,7 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
mode = MT_PHY_TYPE_HE_MU;
break;
default:
- break;
+ return -EINVAL;
}
rateval = mode << 6 | rate_idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index db125cd22b91..b5cc72e7e81c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -405,10 +405,8 @@ mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
if (wlan_idx >= MT76_N_WCIDS)
return;
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
- if (!wcid) {
- stats->tx_rate = rate;
+ if (!wcid)
return;
- }
msta = container_of(wcid, struct mt7921_sta, wcid);
stats = &msta->stats;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
index 8f860c14da58..dec6ffdf07c4 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
@@ -1821,7 +1821,6 @@ static const struct pci_device_id rt2400pci_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
index e940443c52ad..8faa0a80e73a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
@@ -2119,7 +2119,6 @@ static const struct pci_device_id rt2500pci_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2500 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index fce05fc88aaf..bb5ed6630645 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -1956,7 +1956,6 @@ static const struct usb_device_id rt2500usb_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 9a33baaa6184..1fde0e767ce3 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -439,7 +439,6 @@ static const struct pci_device_id rt2800pci_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards");
MODULE_FIRMWARE(FIRMWARE_RT2860);
MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index 36ac18ca8082..b5c67f656cfd 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -1248,7 +1248,6 @@ static const struct usb_device_id rt2800usb_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards");
MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2870);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
index 02da5dd37ddd..82cfc2aadc2b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
@@ -2993,8 +2993,6 @@ static const struct pci_device_id rt61pci_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT61 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2561, RT2561s & RT2661 "
- "PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt61pci_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2561);
MODULE_FIRMWARE(FIRMWARE_RT2561s);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
index e69793773d87..5ff2c740c3ea 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
@@ -2513,7 +2513,6 @@ static const struct usb_device_id rt73usb_device_table[] = {
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT73 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2571W & RT2671 USB chipset based cards");
MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2571);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 9a3d2439a8e7..d98483298555 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -441,6 +441,5 @@ module_init(rsi_91x_hal_module_init);
module_exit(rsi_91x_hal_module_exit);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("Station driver for RSI 91x devices");
-MODULE_SUPPORTED_DEVICE("RSI-91x");
MODULE_VERSION("0.1");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 592e9dadcb55..fe0287b22a25 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1571,7 +1571,6 @@ module_exit(rsi_module_exit);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("Common SDIO layer for RSI drivers");
-MODULE_SUPPORTED_DEVICE("RSI-91x");
MODULE_DEVICE_TABLE(sdio, rsi_dev_table);
MODULE_FIRMWARE(FIRMWARE_RSI9113);
MODULE_VERSION("0.1");
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index a4a533c2a783..3fbe2a3c1455 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -928,7 +928,6 @@ module_usb_driver(rsi_driver);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("Common USB layer for RSI drivers");
-MODULE_SUPPORTED_DEVICE("RSI-91x");
MODULE_DEVICE_TABLE(usb, rsi_dev_table);
MODULE_FIRMWARE(FIRMWARE_RSI9113);
MODULE_VERSION("0.1");
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 6afb5ca999c2..39a01c2a3058 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -557,8 +557,8 @@ check_frags:
}
if (skb_has_frag_list(skb) && !first_shinfo) {
- first_shinfo = skb_shinfo(skb);
- shinfo = skb_shinfo(skb_shinfo(skb)->frag_list);
+ first_shinfo = shinfo;
+ shinfo = skb_shinfo(shinfo->frag_list);
nr_frags = shinfo->nr_frags;
goto check_frags;
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index e68a8c4ac5a6..0896e21642be 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -380,6 +380,7 @@ bool nvme_cancel_request(struct request *req, void *data, bool reserved)
return true;
nvme_req(req)->status = NVME_SC_HOST_ABORTED_CMD;
+ nvme_req(req)->flags |= NVME_REQ_CANCELLED;
blk_mq_complete_request(req);
return true;
}
@@ -1225,28 +1226,12 @@ static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
}
-static int nvme_keep_alive(struct nvme_ctrl *ctrl)
-{
- struct request *rq;
-
- rq = nvme_alloc_request(ctrl->admin_q, &ctrl->ka_cmd,
- BLK_MQ_REQ_RESERVED);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
-
- rq->timeout = ctrl->kato * HZ;
- rq->end_io_data = ctrl;
-
- blk_execute_rq_nowait(NULL, rq, 0, nvme_keep_alive_end_io);
-
- return 0;
-}
-
static void nvme_keep_alive_work(struct work_struct *work)
{
struct nvme_ctrl *ctrl = container_of(to_delayed_work(work),
struct nvme_ctrl, ka_work);
bool comp_seen = ctrl->comp_seen;
+ struct request *rq;
if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) {
dev_dbg(ctrl->device,
@@ -1256,12 +1241,18 @@ static void nvme_keep_alive_work(struct work_struct *work)
return;
}
- if (nvme_keep_alive(ctrl)) {
+ rq = nvme_alloc_request(ctrl->admin_q, &ctrl->ka_cmd,
+ BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
+ if (IS_ERR(rq)) {
/* allocation failure, reset the controller */
- dev_err(ctrl->device, "keep-alive failed\n");
+ dev_err(ctrl->device, "keep-alive failed: %ld\n", PTR_ERR(rq));
nvme_reset_ctrl(ctrl);
return;
}
+
+ rq->timeout = ctrl->kato * HZ;
+ rq->end_io_data = ctrl;
+ blk_execute_rq_nowait(NULL, rq, 0, nvme_keep_alive_end_io);
}
static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
@@ -1440,7 +1431,7 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
goto out_free_id;
}
- error = -ENODEV;
+ error = NVME_SC_INVALID_NS | NVME_SC_DNR;
if ((*id)->ncap == 0) /* namespace not allocated or attached */
goto out_free_id;
@@ -1963,30 +1954,18 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
blk_queue_max_write_zeroes_sectors(queue, UINT_MAX);
}
-static void nvme_config_write_zeroes(struct gendisk *disk, struct nvme_ns *ns)
+/*
+ * Even though NVMe spec explicitly states that MDTS is not applicable to the
+ * write-zeroes, we are cautious and limit the size to the controllers
+ * max_hw_sectors value, which is based on the MDTS field and possibly other
+ * limiting factors.
+ */
+static void nvme_config_write_zeroes(struct request_queue *q,
+ struct nvme_ctrl *ctrl)
{
- u64 max_blocks;
-
- if (!(ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES) ||
- (ns->ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES))
- return;
- /*
- * Even though NVMe spec explicitly states that MDTS is not
- * applicable to the write-zeroes:- "The restriction does not apply to
- * commands that do not transfer data between the host and the
- * controller (e.g., Write Uncorrectable ro Write Zeroes command).".
- * In order to be more cautious use controller's max_hw_sectors value
- * to configure the maximum sectors for the write-zeroes which is
- * configured based on the controller's MDTS field in the
- * nvme_init_identify() if available.
- */
- if (ns->ctrl->max_hw_sectors == UINT_MAX)
- max_blocks = (u64)USHRT_MAX + 1;
- else
- max_blocks = ns->ctrl->max_hw_sectors + 1;
-
- blk_queue_max_write_zeroes_sectors(disk->queue,
- nvme_lba_to_sect(ns, max_blocks));
+ if ((ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES) &&
+ !(ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES))
+ blk_queue_max_write_zeroes_sectors(q, ctrl->max_hw_sectors);
}
static bool nvme_ns_ids_valid(struct nvme_ns_ids *ids)
@@ -2158,7 +2137,7 @@ static void nvme_update_disk_info(struct gendisk *disk,
set_capacity_and_notify(disk, capacity);
nvme_config_discard(disk, ns);
- nvme_config_write_zeroes(disk, ns);
+ nvme_config_write_zeroes(disk->queue, ns->ctrl);
set_disk_ro(disk, (id->nsattr & NVME_NS_ATTR_RO) ||
test_bit(NVME_NS_FORCE_RO, &ns->flags));
@@ -4038,7 +4017,7 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)
static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_ids *ids)
{
struct nvme_id_ns *id;
- int ret = -ENODEV;
+ int ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
if (test_bit(NVME_NS_DEAD, &ns->flags))
goto out;
@@ -4047,7 +4026,7 @@ static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_ids *ids)
if (ret)
goto out;
- ret = -ENODEV;
+ ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
if (!nvme_ns_ids_equal(&ns->head->ids, ids)) {
dev_err(ns->ctrl->device,
"identifiers changed for nsid %d\n", ns->head->ns_id);
@@ -4065,7 +4044,7 @@ out:
*
* TODO: we should probably schedule a delayed retry here.
*/
- if (ret && ret != -ENOMEM && !(ret > 0 && !(ret & NVME_SC_DNR)))
+ if (ret > 0 && (ret & NVME_SC_DNR))
nvme_ns_remove(ns);
}
@@ -4095,6 +4074,12 @@ static void nvme_validate_or_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
nsid);
break;
}
+ if (!nvme_multi_css(ctrl)) {
+ dev_warn(ctrl->device,
+ "command set not reported for nsid: %d\n",
+ nsid);
+ break;
+ }
nvme_alloc_ns(ctrl, nsid, &ids);
break;
default:
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index 733010d2eafd..888b108d87a4 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -19,6 +19,13 @@
#define NVMF_DEF_FAIL_FAST_TMO -1
/*
+ * Reserved one command for internal usage. This command is used for sending
+ * the connect command, as well as for the keep alive command on the admin
+ * queue once live.
+ */
+#define NVMF_RESERVED_TAGS 1
+
+/*
* Define a host as seen by the target. We allocate one at boot, but also
* allow the override it when creating controllers. This is both to provide
* persistence of the Host NQN over multiple boots, and to allow using
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 20dadd86e981..6ffa8de2a0d7 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1956,7 +1956,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
sizeof(op->rsp_iu), DMA_FROM_DEVICE);
if (opstate == FCPOP_STATE_ABORTED)
- status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+ status = cpu_to_le16(NVME_SC_HOST_ABORTED_CMD << 1);
else if (freq->status) {
status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
dev_info(ctrl->ctrl.device,
@@ -2055,7 +2055,7 @@ done:
nvme_fc_complete_rq(rq);
check_error:
- if (terminate_assoc)
+ if (terminate_assoc && ctrl->ctrl.state != NVME_CTRL_RESETTING)
queue_work(nvme_reset_wq, &ctrl->ioerr_work);
}
@@ -2443,6 +2443,7 @@ nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(req);
+ op->nreq.flags |= NVME_REQ_CANCELLED;
__nvme_fc_abort_op(ctrl, op);
return true;
}
@@ -2862,7 +2863,7 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
ctrl->tag_set.ops = &nvme_fc_mq_ops;
ctrl->tag_set.queue_depth = ctrl->ctrl.opts->queue_size;
- ctrl->tag_set.reserved_tags = 1; /* fabric connect */
+ ctrl->tag_set.reserved_tags = NVMF_RESERVED_TAGS;
ctrl->tag_set.numa_node = ctrl->ctrl.numa_node;
ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
ctrl->tag_set.cmd_size =
@@ -3484,7 +3485,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
memset(&ctrl->admin_tag_set, 0, sizeof(ctrl->admin_tag_set));
ctrl->admin_tag_set.ops = &nvme_fc_admin_mq_ops;
ctrl->admin_tag_set.queue_depth = NVME_AQ_MQ_TAG_DEPTH;
- ctrl->admin_tag_set.reserved_tags = 2; /* fabric connect + Keep-Alive */
+ ctrl->admin_tag_set.reserved_tags = NVMF_RESERVED_TAGS;
ctrl->admin_tag_set.numa_node = ctrl->ctrl.numa_node;
ctrl->admin_tag_set.cmd_size =
struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 17ab3320d28b..7249ae74f71f 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3246,6 +3246,7 @@ static const struct pci_device_id nvme_id_table[] = {
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
{ PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
+ NVME_QUIRK_DISABLE_WRITE_ZEROES|
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
{ PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
.driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 53ac4d7442ba..be905d4fdb47 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -736,8 +736,11 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
return ret;
ctrl->ctrl.queue_count = nr_io_queues + 1;
- if (ctrl->ctrl.queue_count < 2)
- return 0;
+ if (ctrl->ctrl.queue_count < 2) {
+ dev_err(ctrl->ctrl.device,
+ "unable to set any I/O queues\n");
+ return -ENOMEM;
+ }
dev_info(ctrl->ctrl.device,
"creating %d I/O queues.\n", nr_io_queues);
@@ -798,7 +801,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
memset(set, 0, sizeof(*set));
set->ops = &nvme_rdma_admin_mq_ops;
set->queue_depth = NVME_AQ_MQ_TAG_DEPTH;
- set->reserved_tags = 2; /* connect + keep-alive */
+ set->reserved_tags = NVMF_RESERVED_TAGS;
set->numa_node = nctrl->numa_node;
set->cmd_size = sizeof(struct nvme_rdma_request) +
NVME_RDMA_DATA_SGL_SIZE;
@@ -811,7 +814,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
memset(set, 0, sizeof(*set));
set->ops = &nvme_rdma_mq_ops;
set->queue_depth = nctrl->sqsize + 1;
- set->reserved_tags = 1; /* fabric connect */
+ set->reserved_tags = NVMF_RESERVED_TAGS;
set->numa_node = nctrl->numa_node;
set->flags = BLK_MQ_F_SHOULD_MERGE;
set->cmd_size = sizeof(struct nvme_rdma_request) +
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 69f59d2c5799..a0f00cb8f9f3 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -287,7 +287,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
* directly, otherwise queue io_work. Also, only do that if we
* are on the same cpu, so we don't introduce contention.
*/
- if (queue->io_cpu == __smp_processor_id() &&
+ if (queue->io_cpu == raw_smp_processor_id() &&
sync && empty && mutex_trylock(&queue->send_mutex)) {
queue->more_requests = !last;
nvme_tcp_send_all(queue);
@@ -568,6 +568,13 @@ static int nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req,
req->pdu_len = le32_to_cpu(pdu->r2t_length);
req->pdu_sent = 0;
+ if (unlikely(!req->pdu_len)) {
+ dev_err(queue->ctrl->ctrl.device,
+ "req %d r2t len is %u, probably a bug...\n",
+ rq->tag, req->pdu_len);
+ return -EPROTO;
+ }
+
if (unlikely(req->data_sent + req->pdu_len > req->data_len)) {
dev_err(queue->ctrl->ctrl.device,
"req %d r2t len %u exceeded data len %u (%zu sent)\n",
@@ -1575,7 +1582,7 @@ static struct blk_mq_tag_set *nvme_tcp_alloc_tagset(struct nvme_ctrl *nctrl,
memset(set, 0, sizeof(*set));
set->ops = &nvme_tcp_admin_mq_ops;
set->queue_depth = NVME_AQ_MQ_TAG_DEPTH;
- set->reserved_tags = 2; /* connect + keep-alive */
+ set->reserved_tags = NVMF_RESERVED_TAGS;
set->numa_node = nctrl->numa_node;
set->flags = BLK_MQ_F_BLOCKING;
set->cmd_size = sizeof(struct nvme_tcp_request);
@@ -1587,7 +1594,7 @@ static struct blk_mq_tag_set *nvme_tcp_alloc_tagset(struct nvme_ctrl *nctrl,
memset(set, 0, sizeof(*set));
set->ops = &nvme_tcp_mq_ops;
set->queue_depth = nctrl->sqsize + 1;
- set->reserved_tags = 1; /* fabric connect */
+ set->reserved_tags = NVMF_RESERVED_TAGS;
set->numa_node = nctrl->numa_node;
set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING;
set->cmd_size = sizeof(struct nvme_tcp_request);
@@ -1745,8 +1752,11 @@ static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
return ret;
ctrl->queue_count = nr_io_queues + 1;
- if (ctrl->queue_count < 2)
- return 0;
+ if (ctrl->queue_count < 2) {
+ dev_err(ctrl->device,
+ "unable to set any I/O queues\n");
+ return -ENOMEM;
+ }
dev_info(ctrl->device,
"creating %d I/O queues.\n", nr_io_queues);
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c
index c7e3ec561ba0..bc2f344f0ae0 100644
--- a/drivers/nvme/host/zns.c
+++ b/drivers/nvme/host/zns.c
@@ -9,7 +9,13 @@
int nvme_revalidate_zones(struct nvme_ns *ns)
{
- return blk_revalidate_disk_zones(ns->disk, NULL);
+ struct request_queue *q = ns->queue;
+ int ret;
+
+ ret = blk_revalidate_disk_zones(ns->disk, NULL);
+ if (!ret)
+ blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
+ return ret;
}
static int nvme_set_max_append(struct nvme_ctrl *ctrl)
@@ -107,7 +113,6 @@ int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf)
blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
blk_queue_max_open_zones(q, le32_to_cpu(id->mor) + 1);
blk_queue_max_active_zones(q, le32_to_cpu(id->mar) + 1);
- blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
free_data:
kfree(id);
return status;
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index be6fcdaf51a7..a027433b8be8 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1118,9 +1118,20 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl)
{
lockdep_assert_held(&ctrl->lock);
- if (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES ||
- nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES ||
- nvmet_cc_mps(ctrl->cc) != 0 ||
+ /*
+ * Only I/O controllers should verify iosqes,iocqes.
+ * Strictly speaking, the spec says a discovery controller
+ * should verify iosqes,iocqes are zeroed, however that
+ * would break backwards compatibility, so don't enforce it.
+ */
+ if (ctrl->subsys->type != NVME_NQN_DISC &&
+ (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES ||
+ nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES)) {
+ ctrl->csts = NVME_CSTS_CFS;
+ return;
+ }
+
+ if (nvmet_cc_mps(ctrl->cc) != 0 ||
nvmet_cc_ams(ctrl->cc) != 0 ||
nvmet_cc_css(ctrl->cc) != 0) {
ctrl->csts = NVME_CSTS_CFS;
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index cb6f86572b24..3e189e753bcf 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -349,7 +349,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
memset(&ctrl->admin_tag_set, 0, sizeof(ctrl->admin_tag_set));
ctrl->admin_tag_set.ops = &nvme_loop_admin_mq_ops;
ctrl->admin_tag_set.queue_depth = NVME_AQ_MQ_TAG_DEPTH;
- ctrl->admin_tag_set.reserved_tags = 2; /* connect + keep-alive */
+ ctrl->admin_tag_set.reserved_tags = NVMF_RESERVED_TAGS;
ctrl->admin_tag_set.numa_node = ctrl->ctrl.numa_node;
ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
@@ -520,7 +520,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
ctrl->tag_set.ops = &nvme_loop_mq_ops;
ctrl->tag_set.queue_depth = ctrl->ctrl.opts->queue_size;
- ctrl->tag_set.reserved_tags = 1; /* fabric connect */
+ ctrl->tag_set.reserved_tags = NVMF_RESERVED_TAGS;
ctrl->tag_set.numa_node = ctrl->ctrl.numa_node;
ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
ctrl->tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 26c587ccd152..2798944899b7 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -50,9 +50,9 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
/*
* nvmet_passthru_map_sg is limitted to using a single bio so limit
- * the mdts based on BIO_MAX_PAGES as well
+ * the mdts based on BIO_MAX_VECS as well
*/
- max_hw_sectors = min_not_zero(BIO_MAX_PAGES << (PAGE_SHIFT - 9),
+ max_hw_sectors = min_not_zero(BIO_MAX_VECS << (PAGE_SHIFT - 9),
max_hw_sectors);
page_shift = NVME_CAP_MPSMIN(ctrl->cap) + 12;
@@ -191,7 +191,7 @@ static int nvmet_passthru_map_sg(struct nvmet_req *req, struct request *rq)
struct bio *bio;
int i;
- if (req->sg_cnt > BIO_MAX_PAGES)
+ if (req->sg_cnt > BIO_MAX_VECS)
return -EINVAL;
if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) {
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index 06b6b742bb21..6c1f3ab7649c 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -802,9 +802,8 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc)
nvmet_req_uninit(&rsp->req);
nvmet_rdma_release_rsp(rsp);
if (wc->status != IB_WC_WR_FLUSH_ERR) {
- pr_info("RDMA WRITE for CQE 0x%p failed with status %s (%d).\n",
- wc->wr_cqe, ib_wc_status_msg(wc->status),
- wc->status);
+ pr_info("RDMA WRITE for CQE failed with status %s (%d).\n",
+ ib_wc_status_msg(wc->status), wc->status);
nvmet_rdma_error_comp(queue);
}
return;
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 8b0485ada315..d658c6e8263a 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1098,11 +1098,11 @@ static int nvmet_tcp_try_recv_data(struct nvmet_tcp_queue *queue)
cmd->rbytes_done += ret;
}
+ nvmet_tcp_unmap_pdu_iovec(cmd);
if (queue->data_digest) {
nvmet_tcp_prep_recv_ddgst(cmd);
return 0;
}
- nvmet_tcp_unmap_pdu_iovec(cmd);
if (!(cmd->flags & NVMET_TCP_F_INIT_FAILED) &&
cmd->rbytes_done == cmd->req.transfer_len) {
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index c2689386a906..1556998425d5 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1492,7 +1492,11 @@ static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table,
mutex_lock(&opp_table->lock);
list_for_each_entry(temp, &opp_table->opp_list, node) {
- if (dynamic == temp->dynamic) {
+ /*
+ * Refcount must be dropped only once for each OPP by OPP core,
+ * do that with help of "removed" flag.
+ */
+ if (!temp->removed && dynamic == temp->dynamic) {
opp = temp;
break;
}
@@ -1502,10 +1506,27 @@ static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table,
return opp;
}
-bool _opp_remove_all_static(struct opp_table *opp_table)
+/*
+ * Can't call dev_pm_opp_put() from under the lock as debugfs removal needs to
+ * happen lock less to avoid circular dependency issues. This routine must be
+ * called without the opp_table->lock held.
+ */
+static void _opp_remove_all(struct opp_table *opp_table, bool dynamic)
{
struct dev_pm_opp *opp;
+ while ((opp = _opp_get_next(opp_table, dynamic))) {
+ opp->removed = true;
+ dev_pm_opp_put(opp);
+
+ /* Drop the references taken by dev_pm_opp_add() */
+ if (dynamic)
+ dev_pm_opp_put_opp_table(opp_table);
+ }
+}
+
+bool _opp_remove_all_static(struct opp_table *opp_table)
+{
mutex_lock(&opp_table->lock);
if (!opp_table->parsed_static_opps) {
@@ -1520,13 +1541,7 @@ bool _opp_remove_all_static(struct opp_table *opp_table)
mutex_unlock(&opp_table->lock);
- /*
- * Can't remove the OPP from under the lock, debugfs removal needs to
- * happen lock less to avoid circular dependency issues.
- */
- while ((opp = _opp_get_next(opp_table, false)))
- dev_pm_opp_put(opp);
-
+ _opp_remove_all(opp_table, false);
return true;
}
@@ -1539,25 +1554,12 @@ bool _opp_remove_all_static(struct opp_table *opp_table)
void dev_pm_opp_remove_all_dynamic(struct device *dev)
{
struct opp_table *opp_table;
- struct dev_pm_opp *opp;
- int count = 0;
opp_table = _find_opp_table(dev);
if (IS_ERR(opp_table))
return;
- /*
- * Can't remove the OPP from under the lock, debugfs removal needs to
- * happen lock less to avoid circular dependency issues.
- */
- while ((opp = _opp_get_next(opp_table, true))) {
- dev_pm_opp_put(opp);
- count++;
- }
-
- /* Drop the references taken by dev_pm_opp_add() */
- while (count--)
- dev_pm_opp_put_opp_table(opp_table);
+ _opp_remove_all(opp_table, true);
/* Drop the reference taken by _find_opp_table() */
dev_pm_opp_put_opp_table(opp_table);
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index 50fb9dced3c5..407c3bfe51d9 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -56,6 +56,7 @@ extern struct list_head opp_tables, lazy_opp_tables;
* @dynamic: not-created from static DT entries.
* @turbo: true if turbo (boost) OPP
* @suspend: true if suspend OPP
+ * @removed: flag indicating that OPP's reference is dropped by OPP core.
* @pstate: Device's power domain's performance state.
* @rate: Frequency in hertz
* @level: Performance level
@@ -78,6 +79,7 @@ struct dev_pm_opp {
bool dynamic;
bool turbo;
bool suspend;
+ bool removed;
unsigned int pstate;
unsigned long rate;
unsigned int level;
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index 1e88bcfe0d7b..84d5701d606c 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -241,6 +241,5 @@ module_platform_driver_probe(amiga_parallel_driver, amiga_parallel_probe);
MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
-MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:amiga-parallel");
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index 2ff0fe053e6e..1623f010cdcc 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -218,7 +218,6 @@ static void __exit parport_atari_exit(void)
MODULE_AUTHOR("Andreas Schwab");
MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
-MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
MODULE_LICENSE("GPL");
module_init(parport_atari_init)
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 9228e8f90309..1e43b3f399a8 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -41,7 +41,6 @@
MODULE_AUTHOR("Helge Deller <deller@gmx.de>");
MODULE_DESCRIPTION("HP-PARISC PC-style parallel port driver");
-MODULE_SUPPORTED_DEVICE("integrated PC-style parallel port");
MODULE_LICENSE("GPL");
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index d6bbe8446301..f4d0da741e85 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -359,7 +359,6 @@ static void __exit parport_mfc3_exit(void)
MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Parallel Port");
-MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");
MODULE_LICENSE("GPL");
module_init(parport_mfc3_init)
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index e840c1b5ab90..865fc41dbb6c 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -377,6 +377,5 @@ module_platform_driver(bpp_sbus_driver);
MODULE_AUTHOR("Derrick J Brashear");
MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
-MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index cdbfa5df3a51..dbfa0b55d31a 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -34,12 +34,11 @@ static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
if (nbytes >= MAX_DRC_NAME_LEN)
return 0;
- memcpy(drc_name, buf, nbytes);
+ strscpy(drc_name, buf, nbytes + 1);
end = strchr(drc_name, '\n');
- if (!end)
- end = &drc_name[nbytes];
- *end = '\0';
+ if (end)
+ *end = '\0';
rc = dlpar_add_slot(drc_name);
if (rc)
@@ -65,12 +64,11 @@ static ssize_t remove_slot_store(struct kobject *kobj,
if (nbytes >= MAX_DRC_NAME_LEN)
return 0;
- memcpy(drc_name, buf, nbytes);
+ strscpy(drc_name, buf, nbytes + 1);
end = strchr(drc_name, '\n');
- if (!end)
- end = &drc_name[nbytes];
- *end = '\0';
+ if (end)
+ *end = '\0';
rc = dlpar_remove_slot(drc_name);
if (rc)
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index c9e790c74051..a047c421debe 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -93,8 +93,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
pci_dev_put(pdev);
return -EBUSY;
}
+ pci_dev_put(pdev);
- zpci_remove_device(zdev);
+ zpci_remove_device(zdev, false);
rc = zpci_disable_device(zdev);
if (rc)
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index c6fe0cfec0f6..2d7502648219 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -26,7 +26,7 @@
#include <xen/platform_pci.h>
#include <asm/xen/swiotlb-xen.h>
-#define INVALID_GRANT_REF (0)
+
#define INVALID_EVTCHN (-1)
struct pci_bus_entry {
@@ -42,7 +42,7 @@ struct pcifront_device {
struct list_head root_buses;
int evtchn;
- int gnt_ref;
+ grant_ref_t gnt_ref;
int irq;
diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c
index 66ad5b3ece19..f2a85500258d 100644
--- a/drivers/perf/arm_dmc620_pmu.c
+++ b/drivers/perf/arm_dmc620_pmu.c
@@ -681,6 +681,7 @@ static int dmc620_pmu_device_probe(struct platform_device *pdev)
if (!name) {
dev_err(&pdev->dev,
"Create name failed, PMU @%pa\n", &res->start);
+ ret = -ENOMEM;
goto out_teardown_dev;
}
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 006b95eca673..a910571e8d4f 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -698,7 +698,7 @@ config BATTERY_GAUGE_LTC2941
config AB8500_BM
bool "AB8500 Battery Management Driver"
- depends on AB8500_CORE && AB8500_GPADC && (IIO = y)
+ depends on AB8500_CORE && AB8500_GPADC && (IIO = y) && OF
help
Say Y to include support for AB8500 battery management.
diff --git a/drivers/power/supply/ab8500-bm.h b/drivers/power/supply/ab8500-bm.h
new file mode 100644
index 000000000000..41c69a4f2a1f
--- /dev/null
+++ b/drivers/power/supply/ab8500-bm.h
@@ -0,0 +1,733 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _AB8500_CHARGER_H_
+#define _AB8500_CHARGER_H_
+
+#include <linux/kernel.h>
+
+/*
+ * System control 2 register offsets.
+ * bank = 0x02
+ */
+#define AB8500_MAIN_WDOG_CTRL_REG 0x01
+#define AB8500_LOW_BAT_REG 0x03
+#define AB8500_BATT_OK_REG 0x04
+/*
+ * USB/ULPI register offsets
+ * Bank : 0x5
+ */
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8500_USB_LINE_CTRL2_REG 0x82
+#define AB8500_USB_LINK1_STAT_REG 0x94
+
+/*
+ * Charger / status register offfsets
+ * Bank : 0x0B
+ */
+#define AB8500_CH_STATUS1_REG 0x00
+#define AB8500_CH_STATUS2_REG 0x01
+#define AB8500_CH_USBCH_STAT1_REG 0x02
+#define AB8500_CH_USBCH_STAT2_REG 0x03
+#define AB8540_CH_USBCH_STAT3_REG 0x04
+#define AB8500_CH_STAT_REG 0x05
+
+/*
+ * Charger / control register offfsets
+ * Bank : 0x0B
+ */
+#define AB8500_CH_VOLT_LVL_REG 0x40
+#define AB8500_CH_VOLT_LVL_MAX_REG 0x41 /*Only in Cut2.0*/
+#define AB8500_CH_OPT_CRNTLVL_REG 0x42
+#define AB8500_CH_OPT_CRNTLVL_MAX_REG 0x43 /*Only in Cut2.0*/
+#define AB8500_CH_WD_TIMER_REG 0x50
+#define AB8500_CHARG_WD_CTRL 0x51
+#define AB8500_BTEMP_HIGH_TH 0x52
+#define AB8500_LED_INDICATOR_PWM_CTRL 0x53
+#define AB8500_LED_INDICATOR_PWM_DUTY 0x54
+#define AB8500_BATT_OVV 0x55
+#define AB8500_CHARGER_CTRL 0x56
+#define AB8500_BAT_CTRL_CURRENT_SOURCE 0x60 /*Only in Cut2.0*/
+
+/*
+ * Charger / main control register offsets
+ * Bank : 0x0B
+ */
+#define AB8500_MCH_CTRL1 0x80
+#define AB8500_MCH_CTRL2 0x81
+#define AB8500_MCH_IPT_CURLVL_REG 0x82
+#define AB8500_CH_WD_REG 0x83
+
+/*
+ * Charger / USB control register offsets
+ * Bank : 0x0B
+ */
+#define AB8500_USBCH_CTRL1_REG 0xC0
+#define AB8500_USBCH_CTRL2_REG 0xC1
+#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2
+#define AB8540_USB_PP_MODE_REG 0xC5
+#define AB8540_USB_PP_CHR_REG 0xC6
+
+/*
+ * Gas Gauge register offsets
+ * Bank : 0x0C
+ */
+#define AB8500_GASG_CC_CTRL_REG 0x00
+#define AB8500_GASG_CC_ACCU1_REG 0x01
+#define AB8500_GASG_CC_ACCU2_REG 0x02
+#define AB8500_GASG_CC_ACCU3_REG 0x03
+#define AB8500_GASG_CC_ACCU4_REG 0x04
+#define AB8500_GASG_CC_SMPL_CNTRL_REG 0x05
+#define AB8500_GASG_CC_SMPL_CNTRH_REG 0x06
+#define AB8500_GASG_CC_SMPL_CNVL_REG 0x07
+#define AB8500_GASG_CC_SMPL_CNVH_REG 0x08
+#define AB8500_GASG_CC_CNTR_AVGOFF_REG 0x09
+#define AB8500_GASG_CC_OFFSET_REG 0x0A
+#define AB8500_GASG_CC_NCOV_ACCU 0x10
+#define AB8500_GASG_CC_NCOV_ACCU_CTRL 0x11
+#define AB8500_GASG_CC_NCOV_ACCU_LOW 0x12
+#define AB8500_GASG_CC_NCOV_ACCU_MED 0x13
+#define AB8500_GASG_CC_NCOV_ACCU_HIGH 0x14
+
+/*
+ * Interrupt register offsets
+ * Bank : 0x0E
+ */
+#define AB8500_IT_SOURCE2_REG 0x01
+#define AB8500_IT_SOURCE21_REG 0x14
+
+/*
+ * RTC register offsets
+ * Bank: 0x0F
+ */
+#define AB8500_RTC_BACKUP_CHG_REG 0x0C
+#define AB8500_RTC_CC_CONF_REG 0x01
+#define AB8500_RTC_CTRL_REG 0x0B
+#define AB8500_RTC_CTRL1_REG 0x11
+
+/*
+ * OTP register offsets
+ * Bank : 0x15
+ */
+#define AB8500_OTP_CONF_15 0x0E
+
+/* GPADC constants from AB8500 spec, UM0836 */
+#define ADC_RESOLUTION 1024
+#define ADC_CH_MAIN_MIN 0
+#define ADC_CH_MAIN_MAX 20030
+#define ADC_CH_VBUS_MIN 0
+#define ADC_CH_VBUS_MAX 20030
+#define ADC_CH_VBAT_MIN 2300
+#define ADC_CH_VBAT_MAX 4800
+#define ADC_CH_BKBAT_MIN 0
+#define ADC_CH_BKBAT_MAX 3200
+
+/* Main charge i/p current */
+#define MAIN_CH_IP_CUR_0P9A 0x80
+#define MAIN_CH_IP_CUR_1P0A 0x90
+#define MAIN_CH_IP_CUR_1P1A 0xA0
+#define MAIN_CH_IP_CUR_1P2A 0xB0
+#define MAIN_CH_IP_CUR_1P3A 0xC0
+#define MAIN_CH_IP_CUR_1P4A 0xD0
+#define MAIN_CH_IP_CUR_1P5A 0xE0
+
+/* ChVoltLevel */
+#define CH_VOL_LVL_3P5 0x00
+#define CH_VOL_LVL_4P0 0x14
+#define CH_VOL_LVL_4P05 0x16
+#define CH_VOL_LVL_4P1 0x1B
+#define CH_VOL_LVL_4P15 0x20
+#define CH_VOL_LVL_4P2 0x25
+#define CH_VOL_LVL_4P6 0x4D
+
+/* ChOutputCurrentLevel */
+#define CH_OP_CUR_LVL_0P1 0x00
+#define CH_OP_CUR_LVL_0P2 0x01
+#define CH_OP_CUR_LVL_0P3 0x02
+#define CH_OP_CUR_LVL_0P4 0x03
+#define CH_OP_CUR_LVL_0P5 0x04
+#define CH_OP_CUR_LVL_0P6 0x05
+#define CH_OP_CUR_LVL_0P7 0x06
+#define CH_OP_CUR_LVL_0P8 0x07
+#define CH_OP_CUR_LVL_0P9 0x08
+#define CH_OP_CUR_LVL_1P4 0x0D
+#define CH_OP_CUR_LVL_1P5 0x0E
+#define CH_OP_CUR_LVL_1P6 0x0F
+#define CH_OP_CUR_LVL_2P 0x3F
+
+/* BTEMP High thermal limits */
+#define BTEMP_HIGH_TH_57_0 0x00
+#define BTEMP_HIGH_TH_52 0x01
+#define BTEMP_HIGH_TH_57_1 0x02
+#define BTEMP_HIGH_TH_62 0x03
+
+/* current is mA */
+#define USB_0P1A 100
+#define USB_0P2A 200
+#define USB_0P3A 300
+#define USB_0P4A 400
+#define USB_0P5A 500
+
+#define LOW_BAT_3P1V 0x20
+#define LOW_BAT_2P3V 0x00
+#define LOW_BAT_RESET 0x01
+#define LOW_BAT_ENABLE 0x01
+
+/* Backup battery constants */
+#define BUP_ICH_SEL_50UA 0x00
+#define BUP_ICH_SEL_150UA 0x04
+#define BUP_ICH_SEL_300UA 0x08
+#define BUP_ICH_SEL_700UA 0x0C
+
+enum bup_vch_sel {
+ BUP_VCH_SEL_2P5V,
+ BUP_VCH_SEL_2P6V,
+ BUP_VCH_SEL_2P8V,
+ BUP_VCH_SEL_3P1V,
+ /*
+ * Note that the following 5 values 2.7v, 2.9v, 3.0v, 3.2v, 3.3v
+ * are only available on ab8540. You can't choose these 5
+ * voltage on ab8500/ab8505/ab9540.
+ */
+ BUP_VCH_SEL_2P7V,
+ BUP_VCH_SEL_2P9V,
+ BUP_VCH_SEL_3P0V,
+ BUP_VCH_SEL_3P2V,
+ BUP_VCH_SEL_3P3V,
+};
+
+#define BUP_VCH_RANGE 0x02
+#define VBUP33_VRTCN 0x01
+
+/* Battery OVV constants */
+#define BATT_OVV_ENA 0x02
+#define BATT_OVV_TH_3P7 0x00
+#define BATT_OVV_TH_4P75 0x01
+
+/* A value to indicate over voltage */
+#define BATT_OVV_VALUE 4750
+
+/* VBUS OVV constants */
+#define VBUS_OVV_SELECT_MASK 0x78
+#define VBUS_OVV_SELECT_5P6V 0x00
+#define VBUS_OVV_SELECT_5P7V 0x08
+#define VBUS_OVV_SELECT_5P8V 0x10
+#define VBUS_OVV_SELECT_5P9V 0x18
+#define VBUS_OVV_SELECT_6P0V 0x20
+#define VBUS_OVV_SELECT_6P1V 0x28
+#define VBUS_OVV_SELECT_6P2V 0x30
+#define VBUS_OVV_SELECT_6P3V 0x38
+
+#define VBUS_AUTO_IN_CURR_LIM_ENA 0x04
+
+/* Fuel Gauge constants */
+#define RESET_ACCU 0x02
+#define READ_REQ 0x01
+#define CC_DEEP_SLEEP_ENA 0x02
+#define CC_PWR_UP_ENA 0x01
+#define CC_SAMPLES_40 0x28
+#define RD_NCONV_ACCU_REQ 0x01
+#define CC_CALIB 0x08
+#define CC_INTAVGOFFSET_ENA 0x10
+#define CC_MUXOFFSET 0x80
+#define CC_INT_CAL_N_AVG_MASK 0x60
+#define CC_INT_CAL_SAMPLES_16 0x40
+#define CC_INT_CAL_SAMPLES_8 0x20
+#define CC_INT_CAL_SAMPLES_4 0x00
+
+/* RTC constants */
+#define RTC_BUP_CH_ENA 0x10
+
+/* BatCtrl Current Source Constants */
+#define BAT_CTRL_7U_ENA 0x01
+#define BAT_CTRL_20U_ENA 0x02
+#define BAT_CTRL_18U_ENA 0x01
+#define BAT_CTRL_16U_ENA 0x02
+#define BAT_CTRL_CMP_ENA 0x04
+#define FORCE_BAT_CTRL_CMP_HIGH 0x08
+#define BAT_CTRL_PULL_UP_ENA 0x10
+
+/* Battery type */
+#define BATTERY_UNKNOWN 00
+
+/* Registers for pcut feature in ab8505 and ab9540 */
+#define AB8505_RTC_PCUT_CTL_STATUS_REG 0x12
+#define AB8505_RTC_PCUT_TIME_REG 0x13
+#define AB8505_RTC_PCUT_MAX_TIME_REG 0x14
+#define AB8505_RTC_PCUT_FLAG_TIME_REG 0x15
+#define AB8505_RTC_PCUT_RESTART_REG 0x16
+#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17
+
+/* USB Power Path constants for ab8540 */
+#define BUS_VSYS_VOL_SELECT_MASK 0x06
+#define BUS_VSYS_VOL_SELECT_3P6V 0x00
+#define BUS_VSYS_VOL_SELECT_3P325V 0x02
+#define BUS_VSYS_VOL_SELECT_3P9V 0x04
+#define BUS_VSYS_VOL_SELECT_4P3V 0x06
+#define BUS_POWER_PATH_MODE_ENA 0x01
+#define BUS_PP_PRECHG_CURRENT_MASK 0x0E
+#define BUS_POWER_PATH_PRECHG_ENA 0x01
+
+/*
+ * ADC for the battery thermistor.
+ * When using the ABx500_ADC_THERM_BATCTRL the battery ID resistor is combined
+ * with a NTC resistor to both identify the battery and to measure its
+ * temperature. Different phone manufactures uses different techniques to both
+ * identify the battery and to read its temperature.
+ */
+enum abx500_adc_therm {
+ ABx500_ADC_THERM_BATCTRL,
+ ABx500_ADC_THERM_BATTEMP,
+};
+
+/**
+ * struct abx500_res_to_temp - defines one point in a temp to res curve. To
+ * be used in battery packs that combines the identification resistor with a
+ * NTC resistor.
+ * @temp: battery pack temperature in Celsius
+ * @resist: NTC resistor net total resistance
+ */
+struct abx500_res_to_temp {
+ int temp;
+ int resist;
+};
+
+/**
+ * struct abx500_v_to_cap - Table for translating voltage to capacity
+ * @voltage: Voltage in mV
+ * @capacity: Capacity in percent
+ */
+struct abx500_v_to_cap {
+ int voltage;
+ int capacity;
+};
+
+/* Forward declaration */
+struct abx500_fg;
+
+/**
+ * struct abx500_fg_parameters - Fuel gauge algorithm parameters, in seconds
+ * if not specified
+ * @recovery_sleep_timer: Time between measurements while recovering
+ * @recovery_total_time: Total recovery time
+ * @init_timer: Measurement interval during startup
+ * @init_discard_time: Time we discard voltage measurement at startup
+ * @init_total_time: Total init time during startup
+ * @high_curr_time: Time current has to be high to go to recovery
+ * @accu_charging: FG accumulation time while charging
+ * @accu_high_curr: FG accumulation time in high current mode
+ * @high_curr_threshold: High current threshold, in mA
+ * @lowbat_threshold: Low battery threshold, in mV
+ * @overbat_threshold: Over battery threshold, in mV
+ * @battok_falling_th_sel0 Threshold in mV for battOk signal sel0
+ * Resolution in 50 mV step.
+ * @battok_raising_th_sel1 Threshold in mV for battOk signal sel1
+ * Resolution in 50 mV step.
+ * @user_cap_limit Capacity reported from user must be within this
+ * limit to be considered as sane, in percentage
+ * points.
+ * @maint_thres This is the threshold where we stop reporting
+ * battery full while in maintenance, in per cent
+ * @pcut_enable: Enable power cut feature in ab8505
+ * @pcut_max_time: Max time threshold
+ * @pcut_flag_time: Flagtime threshold
+ * @pcut_max_restart: Max number of restarts
+ * @pcut_debounce_time: Sets battery debounce time
+ */
+struct abx500_fg_parameters {
+ int recovery_sleep_timer;
+ int recovery_total_time;
+ int init_timer;
+ int init_discard_time;
+ int init_total_time;
+ int high_curr_time;
+ int accu_charging;
+ int accu_high_curr;
+ int high_curr_threshold;
+ int lowbat_threshold;
+ int overbat_threshold;
+ int battok_falling_th_sel0;
+ int battok_raising_th_sel1;
+ int user_cap_limit;
+ int maint_thres;
+ bool pcut_enable;
+ u8 pcut_max_time;
+ u8 pcut_flag_time;
+ u8 pcut_max_restart;
+ u8 pcut_debounce_time;
+};
+
+/**
+ * struct abx500_charger_maximization - struct used by the board config.
+ * @use_maxi: Enable maximization for this battery type
+ * @maxi_chg_curr: Maximum charger current allowed
+ * @maxi_wait_cycles: cycles to wait before setting charger current
+ * @charger_curr_step delta between two charger current settings (mA)
+ */
+struct abx500_maxim_parameters {
+ bool ena_maxi;
+ int chg_curr;
+ int wait_cycles;
+ int charger_curr_step;
+};
+
+/**
+ * struct abx500_battery_type - different batteries supported
+ * @name: battery technology
+ * @resis_high: battery upper resistance limit
+ * @resis_low: battery lower resistance limit
+ * @charge_full_design: Maximum battery capacity in mAh
+ * @nominal_voltage: Nominal voltage of the battery in mV
+ * @termination_vol: max voltage upto which battery can be charged
+ * @termination_curr battery charging termination current in mA
+ * @recharge_cap battery capacity limit that will trigger a new
+ * full charging cycle in the case where maintenan-
+ * -ce charging has been disabled
+ * @normal_cur_lvl: charger current in normal state in mA
+ * @normal_vol_lvl: charger voltage in normal state in mV
+ * @maint_a_cur_lvl: charger current in maintenance A state in mA
+ * @maint_a_vol_lvl: charger voltage in maintenance A state in mV
+ * @maint_a_chg_timer_h: charge time in maintenance A state
+ * @maint_b_cur_lvl: charger current in maintenance B state in mA
+ * @maint_b_vol_lvl: charger voltage in maintenance B state in mV
+ * @maint_b_chg_timer_h: charge time in maintenance B state
+ * @low_high_cur_lvl: charger current in temp low/high state in mA
+ * @low_high_vol_lvl: charger voltage in temp low/high state in mV'
+ * @battery_resistance: battery inner resistance in mOhm.
+ * @n_r_t_tbl_elements: number of elements in r_to_t_tbl
+ * @r_to_t_tbl: table containing resistance to temp points
+ * @n_v_cap_tbl_elements: number of elements in v_to_cap_tbl
+ * @v_to_cap_tbl: Voltage to capacity (in %) table
+ * @n_batres_tbl_elements number of elements in the batres_tbl
+ * @batres_tbl battery internal resistance vs temperature table
+ */
+struct abx500_battery_type {
+ int name;
+ int resis_high;
+ int resis_low;
+ int charge_full_design;
+ int nominal_voltage;
+ int termination_vol;
+ int termination_curr;
+ int recharge_cap;
+ int normal_cur_lvl;
+ int normal_vol_lvl;
+ int maint_a_cur_lvl;
+ int maint_a_vol_lvl;
+ int maint_a_chg_timer_h;
+ int maint_b_cur_lvl;
+ int maint_b_vol_lvl;
+ int maint_b_chg_timer_h;
+ int low_high_cur_lvl;
+ int low_high_vol_lvl;
+ int battery_resistance;
+ int n_temp_tbl_elements;
+ const struct abx500_res_to_temp *r_to_t_tbl;
+ int n_v_cap_tbl_elements;
+ const struct abx500_v_to_cap *v_to_cap_tbl;
+ int n_batres_tbl_elements;
+ const struct batres_vs_temp *batres_tbl;
+};
+
+/**
+ * struct abx500_bm_capacity_levels - abx500 capacity level data
+ * @critical: critical capacity level in percent
+ * @low: low capacity level in percent
+ * @normal: normal capacity level in percent
+ * @high: high capacity level in percent
+ * @full: full capacity level in percent
+ */
+struct abx500_bm_capacity_levels {
+ int critical;
+ int low;
+ int normal;
+ int high;
+ int full;
+};
+
+/**
+ * struct abx500_bm_charger_parameters - Charger specific parameters
+ * @usb_volt_max: maximum allowed USB charger voltage in mV
+ * @usb_curr_max: maximum allowed USB charger current in mA
+ * @ac_volt_max: maximum allowed AC charger voltage in mV
+ * @ac_curr_max: maximum allowed AC charger current in mA
+ */
+struct abx500_bm_charger_parameters {
+ int usb_volt_max;
+ int usb_curr_max;
+ int ac_volt_max;
+ int ac_curr_max;
+};
+
+/**
+ * struct abx500_bm_data - abx500 battery management data
+ * @temp_under under this temp, charging is stopped
+ * @temp_low between this temp and temp_under charging is reduced
+ * @temp_high between this temp and temp_over charging is reduced
+ * @temp_over over this temp, charging is stopped
+ * @temp_now present battery temperature
+ * @temp_interval_chg temperature measurement interval in s when charging
+ * @temp_interval_nochg temperature measurement interval in s when not charging
+ * @main_safety_tmr_h safety timer for main charger
+ * @usb_safety_tmr_h safety timer for usb charger
+ * @bkup_bat_v voltage which we charge the backup battery with
+ * @bkup_bat_i current which we charge the backup battery with
+ * @no_maintenance indicates that maintenance charging is disabled
+ * @capacity_scaling indicates whether capacity scaling is to be used
+ * @abx500_adc_therm placement of thermistor, batctrl or battemp adc
+ * @chg_unknown_bat flag to enable charging of unknown batteries
+ * @enable_overshoot flag to enable VBAT overshoot control
+ * @auto_trig flag to enable auto adc trigger
+ * @fg_res resistance of FG resistor in 0.1mOhm
+ * @n_btypes number of elements in array bat_type
+ * @batt_id index of the identified battery in array bat_type
+ * @interval_charging charge alg cycle period time when charging (sec)
+ * @interval_not_charging charge alg cycle period time when not charging (sec)
+ * @temp_hysteresis temperature hysteresis
+ * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
+ * @n_chg_out_curr number of elements in array chg_output_curr
+ * @n_chg_in_curr number of elements in array chg_input_curr
+ * @chg_output_curr charger output current level map
+ * @chg_input_curr charger input current level map
+ * @maxi maximization parameters
+ * @cap_levels capacity in percent for the different capacity levels
+ * @bat_type table of supported battery types
+ * @chg_params charger parameters
+ * @fg_params fuel gauge parameters
+ */
+struct abx500_bm_data {
+ int temp_under;
+ int temp_low;
+ int temp_high;
+ int temp_over;
+ int temp_now;
+ int temp_interval_chg;
+ int temp_interval_nochg;
+ int main_safety_tmr_h;
+ int usb_safety_tmr_h;
+ int bkup_bat_v;
+ int bkup_bat_i;
+ bool autopower_cfg;
+ bool ac_enabled;
+ bool usb_enabled;
+ bool no_maintenance;
+ bool capacity_scaling;
+ bool chg_unknown_bat;
+ bool enable_overshoot;
+ bool auto_trig;
+ enum abx500_adc_therm adc_therm;
+ int fg_res;
+ int n_btypes;
+ int batt_id;
+ int interval_charging;
+ int interval_not_charging;
+ int temp_hysteresis;
+ int gnd_lift_resistance;
+ int n_chg_out_curr;
+ int n_chg_in_curr;
+ int *chg_output_curr;
+ int *chg_input_curr;
+ const struct abx500_maxim_parameters *maxi;
+ const struct abx500_bm_capacity_levels *cap_levels;
+ struct abx500_battery_type *bat_type;
+ const struct abx500_bm_charger_parameters *chg_params;
+ const struct abx500_fg_parameters *fg_params;
+};
+
+enum {
+ NTC_EXTERNAL = 0,
+ NTC_INTERNAL,
+};
+
+/**
+ * struct res_to_temp - defines one point in a temp to res curve. To
+ * be used in battery packs that combines the identification resistor with a
+ * NTC resistor.
+ * @temp: battery pack temperature in Celsius
+ * @resist: NTC resistor net total resistance
+ */
+struct res_to_temp {
+ int temp;
+ int resist;
+};
+
+/**
+ * struct batres_vs_temp - defines one point in a temp vs battery internal
+ * resistance curve.
+ * @temp: battery pack temperature in Celsius
+ * @resist: battery internal reistance in mOhm
+ */
+struct batres_vs_temp {
+ int temp;
+ int resist;
+};
+
+/* Forward declaration */
+struct ab8500_fg;
+
+/**
+ * struct ab8500_fg_parameters - Fuel gauge algorithm parameters, in seconds
+ * if not specified
+ * @recovery_sleep_timer: Time between measurements while recovering
+ * @recovery_total_time: Total recovery time
+ * @init_timer: Measurement interval during startup
+ * @init_discard_time: Time we discard voltage measurement at startup
+ * @init_total_time: Total init time during startup
+ * @high_curr_time: Time current has to be high to go to recovery
+ * @accu_charging: FG accumulation time while charging
+ * @accu_high_curr: FG accumulation time in high current mode
+ * @high_curr_threshold: High current threshold, in mA
+ * @lowbat_threshold: Low battery threshold, in mV
+ * @battok_falling_th_sel0 Threshold in mV for battOk signal sel0
+ * Resolution in 50 mV step.
+ * @battok_raising_th_sel1 Threshold in mV for battOk signal sel1
+ * Resolution in 50 mV step.
+ * @user_cap_limit Capacity reported from user must be within this
+ * limit to be considered as sane, in percentage
+ * points.
+ * @maint_thres This is the threshold where we stop reporting
+ * battery full while in maintenance, in per cent
+ * @pcut_enable: Enable power cut feature in ab8505
+ * @pcut_max_time: Max time threshold
+ * @pcut_flag_time: Flagtime threshold
+ * @pcut_max_restart: Max number of restarts
+ * @pcut_debunce_time: Sets battery debounce time
+ */
+struct ab8500_fg_parameters {
+ int recovery_sleep_timer;
+ int recovery_total_time;
+ int init_timer;
+ int init_discard_time;
+ int init_total_time;
+ int high_curr_time;
+ int accu_charging;
+ int accu_high_curr;
+ int high_curr_threshold;
+ int lowbat_threshold;
+ int battok_falling_th_sel0;
+ int battok_raising_th_sel1;
+ int user_cap_limit;
+ int maint_thres;
+ bool pcut_enable;
+ u8 pcut_max_time;
+ u8 pcut_flag_time;
+ u8 pcut_max_restart;
+ u8 pcut_debunce_time;
+};
+
+/**
+ * struct ab8500_charger_maximization - struct used by the board config.
+ * @use_maxi: Enable maximization for this battery type
+ * @maxi_chg_curr: Maximum charger current allowed
+ * @maxi_wait_cycles: cycles to wait before setting charger current
+ * @charger_curr_step delta between two charger current settings (mA)
+ */
+struct ab8500_maxim_parameters {
+ bool ena_maxi;
+ int chg_curr;
+ int wait_cycles;
+ int charger_curr_step;
+};
+
+/**
+ * struct ab8500_bm_capacity_levels - ab8500 capacity level data
+ * @critical: critical capacity level in percent
+ * @low: low capacity level in percent
+ * @normal: normal capacity level in percent
+ * @high: high capacity level in percent
+ * @full: full capacity level in percent
+ */
+struct ab8500_bm_capacity_levels {
+ int critical;
+ int low;
+ int normal;
+ int high;
+ int full;
+};
+
+/**
+ * struct ab8500_bm_charger_parameters - Charger specific parameters
+ * @usb_volt_max: maximum allowed USB charger voltage in mV
+ * @usb_curr_max: maximum allowed USB charger current in mA
+ * @ac_volt_max: maximum allowed AC charger voltage in mV
+ * @ac_curr_max: maximum allowed AC charger current in mA
+ */
+struct ab8500_bm_charger_parameters {
+ int usb_volt_max;
+ int usb_curr_max;
+ int ac_volt_max;
+ int ac_curr_max;
+};
+
+/**
+ * struct ab8500_bm_data - ab8500 battery management data
+ * @temp_under under this temp, charging is stopped
+ * @temp_low between this temp and temp_under charging is reduced
+ * @temp_high between this temp and temp_over charging is reduced
+ * @temp_over over this temp, charging is stopped
+ * @temp_interval_chg temperature measurement interval in s when charging
+ * @temp_interval_nochg temperature measurement interval in s when not charging
+ * @main_safety_tmr_h safety timer for main charger
+ * @usb_safety_tmr_h safety timer for usb charger
+ * @bkup_bat_v voltage which we charge the backup battery with
+ * @bkup_bat_i current which we charge the backup battery with
+ * @no_maintenance indicates that maintenance charging is disabled
+ * @capacity_scaling indicates whether capacity scaling is to be used
+ * @adc_therm placement of thermistor, batctrl or battemp adc
+ * @chg_unknown_bat flag to enable charging of unknown batteries
+ * @enable_overshoot flag to enable VBAT overshoot control
+ * @fg_res resistance of FG resistor in 0.1mOhm
+ * @n_btypes number of elements in array bat_type
+ * @batt_id index of the identified battery in array bat_type
+ * @interval_charging charge alg cycle period time when charging (sec)
+ * @interval_not_charging charge alg cycle period time when not charging (sec)
+ * @temp_hysteresis temperature hysteresis
+ * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
+ * @maxi: maximization parameters
+ * @cap_levels capacity in percent for the different capacity levels
+ * @bat_type table of supported battery types
+ * @chg_params charger parameters
+ * @fg_params fuel gauge parameters
+ */
+struct ab8500_bm_data {
+ int temp_under;
+ int temp_low;
+ int temp_high;
+ int temp_over;
+ int temp_interval_chg;
+ int temp_interval_nochg;
+ int main_safety_tmr_h;
+ int usb_safety_tmr_h;
+ int bkup_bat_v;
+ int bkup_bat_i;
+ bool no_maintenance;
+ bool capacity_scaling;
+ bool chg_unknown_bat;
+ bool enable_overshoot;
+ enum abx500_adc_therm adc_therm;
+ int fg_res;
+ int n_btypes;
+ int batt_id;
+ int interval_charging;
+ int interval_not_charging;
+ int temp_hysteresis;
+ int gnd_lift_resistance;
+ const struct ab8500_maxim_parameters *maxi;
+ const struct ab8500_bm_capacity_levels *cap_levels;
+ const struct ab8500_bm_charger_parameters *chg_params;
+ const struct ab8500_fg_parameters *fg_params;
+};
+
+extern struct abx500_bm_data ab8500_bm_data;
+
+void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
+struct ab8500_fg *ab8500_fg_get(void);
+int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev);
+int ab8500_fg_inst_curr_start(struct ab8500_fg *di);
+int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res);
+int ab8500_fg_inst_curr_started(struct ab8500_fg *di);
+int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
+int ab8500_bm_of_probe(struct device *dev,
+ struct device_node *np,
+ struct abx500_bm_data *bm);
+
+#endif /* _AB8500_CHARGER_H_ */
diff --git a/drivers/power/supply/ab8500-chargalg.h b/drivers/power/supply/ab8500-chargalg.h
new file mode 100644
index 000000000000..94a6f9068bc5
--- /dev/null
+++ b/drivers/power/supply/ab8500-chargalg.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson.
+ */
+
+#ifndef _AB8500_CHARGALG_H_
+#define _AB8500_CHARGALG_H_
+
+#include <linux/power_supply.h>
+
+/*
+ * Valid only for supplies of type:
+ * - POWER_SUPPLY_TYPE_MAINS,
+ * - POWER_SUPPLY_TYPE_USB,
+ * because only them store as drv_data pointer to struct ux500_charger.
+ */
+#define psy_to_ux500_charger(x) power_supply_get_drvdata(psy)
+
+/* Forward declaration */
+struct ux500_charger;
+
+struct ux500_charger_ops {
+ int (*enable) (struct ux500_charger *, int, int, int);
+ int (*check_enable) (struct ux500_charger *, int, int);
+ int (*kick_wd) (struct ux500_charger *);
+ int (*update_curr) (struct ux500_charger *, int);
+};
+
+/**
+ * struct ux500_charger - power supply ux500 charger sub class
+ * @psy power supply base class
+ * @ops ux500 charger operations
+ * @max_out_volt maximum output charger voltage in mV
+ * @max_out_curr maximum output charger current in mA
+ * @enabled indicates if this charger is used or not
+ * @external external charger unit (pm2xxx)
+ */
+struct ux500_charger {
+ struct power_supply *psy;
+ struct ux500_charger_ops ops;
+ int max_out_volt;
+ int max_out_curr;
+ int wdt_refresh;
+ bool enabled;
+ bool external;
+};
+
+extern struct blocking_notifier_head charger_notifier_list;
+
+#endif /* _AB8500_CHARGALG_H_ */
diff --git a/drivers/power/supply/ab8500_bmdata.c b/drivers/power/supply/ab8500_bmdata.c
index f6a66979cbb5..c2b8c0bb77e2 100644
--- a/drivers/power/supply/ab8500_bmdata.c
+++ b/drivers/power/supply/ab8500_bmdata.c
@@ -4,7 +4,8 @@
#include <linux/of.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
+
+#include "ab8500-bm.h"
/*
* These are the defined batteries that uses a NTC and ID resistor placed
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index d20345386b1e..fdfcd59fc43e 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -25,9 +25,10 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/iio/consumer.h>
+#include "ab8500-bm.h"
+
#define VTVOUT_V 1800
#define BTEMP_THERMAL_LOW_LIMIT -10
@@ -120,16 +121,6 @@ static enum power_supply_property ab8500_btemp_props[] = {
static LIST_HEAD(ab8500_btemp_list);
/**
- * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
- * (i.e. the first BTEMP in the instance list)
- */
-struct ab8500_btemp *ab8500_btemp_get(void)
-{
- return list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
-}
-EXPORT_SYMBOL(ab8500_btemp_get);
-
-/**
* ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
* @di: pointer to the ab8500_btemp structure
* @v_batctrl: measured batctrl voltage
@@ -754,7 +745,7 @@ static void ab8500_btemp_periodic(struct ab8500_btemp *di,
*
* Returns battery temperature
*/
-int ab8500_btemp_get_temp(struct ab8500_btemp *di)
+static int ab8500_btemp_get_temp(struct ab8500_btemp *di)
{
int temp = 0;
@@ -790,19 +781,6 @@ int ab8500_btemp_get_temp(struct ab8500_btemp *di)
}
return temp;
}
-EXPORT_SYMBOL(ab8500_btemp_get_temp);
-
-/**
- * ab8500_btemp_get_batctrl_temp() - get the temperature
- * @btemp: pointer to the btemp structure
- *
- * Returns the batctrl temperature in millidegrees
- */
-int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
-{
- return btemp->bat_temp * 1000;
-}
-EXPORT_SYMBOL(ab8500_btemp_get_batctrl_temp);
/**
* ab8500_btemp_get_property() - get the btemp properties
@@ -991,7 +969,6 @@ static const struct power_supply_desc ab8500_btemp_desc = {
static int ab8500_btemp_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct abx500_bm_data *plat = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {};
struct device *dev = &pdev->dev;
struct ab8500_btemp *di;
@@ -1002,18 +979,12 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
if (!di)
return -ENOMEM;
- if (!plat) {
- dev_err(dev, "no battery management data supplied\n");
- return -EINVAL;
- }
- di->bm = plat;
+ di->bm = &ab8500_bm_data;
- if (np) {
- ret = ab8500_bm_of_probe(dev, np, di->bm);
- if (ret) {
- dev_err(dev, "failed to get battery information\n");
- return ret;
- }
+ ret = ab8500_bm_of_probe(dev, np, di->bm);
+ if (ret) {
+ dev_err(dev, "failed to get battery information\n");
+ return ret;
}
/* get parent data */
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index ac77c8882d17..a9be10eb2c22 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -28,12 +28,13 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/usb/otg.h>
#include <linux/mutex.h>
#include <linux/iio/consumer.h>
+#include "ab8500-bm.h"
+#include "ab8500-chargalg.h"
+
/* Charger constants */
#define NO_PW_CONN 0
#define AC_PW_CONN 1
@@ -3344,7 +3345,6 @@ static const struct power_supply_desc ab8500_usb_chg_desc = {
static int ab8500_charger_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct abx500_bm_data *plat = pdev->dev.platform_data;
struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
struct ab8500_charger *di;
int irq, i, charger_status, ret = 0, ch_stat;
@@ -3354,21 +3354,14 @@ static int ab8500_charger_probe(struct platform_device *pdev)
if (!di)
return -ENOMEM;
- if (!plat) {
- dev_err(dev, "no battery management data supplied\n");
- return -EINVAL;
- }
- di->bm = plat;
+ di->bm = &ab8500_bm_data;
- if (np) {
- ret = ab8500_bm_of_probe(dev, np, di->bm);
- if (ret) {
- dev_err(dev, "failed to get battery information\n");
- return ret;
- }
- di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
- } else
- di->autopower_cfg = false;
+ ret = ab8500_bm_of_probe(dev, np, di->bm);
+ if (ret) {
+ dev_err(dev, "failed to get battery information\n");
+ return ret;
+ }
+ di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
/* get parent data */
di->dev = dev;
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 06ff42c71f24..0c7c01a0d979 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -31,10 +31,11 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/iio/consumer.h>
#include <linux/kernel.h>
+#include "ab8500-bm.h"
+
#define MILLI_TO_MICRO 1000
#define FG_LSB_IN_MA 1627
#define QLSB_NANO_AMP_HOURS_X10 1071
@@ -3026,7 +3027,6 @@ static const struct power_supply_desc ab8500_fg_desc = {
static int ab8500_fg_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct abx500_bm_data *plat = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {};
struct device *dev = &pdev->dev;
struct ab8500_fg *di;
@@ -3037,18 +3037,12 @@ static int ab8500_fg_probe(struct platform_device *pdev)
if (!di)
return -ENOMEM;
- if (!plat) {
- dev_err(dev, "no battery management data supplied\n");
- return -EINVAL;
- }
- di->bm = plat;
+ di->bm = &ab8500_bm_data;
- if (np) {
- ret = ab8500_bm_of_probe(dev, np, di->bm);
- if (ret) {
- dev_err(dev, "failed to get battery information\n");
- return ret;
- }
+ ret = ab8500_bm_of_probe(dev, np, di->bm);
+ if (ret) {
+ dev_err(dev, "failed to get battery information\n");
+ return ret;
}
mutex_init(&di->cc_lock);
diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c
index a9d84d845f24..f5b792243727 100644
--- a/drivers/power/supply/abx500_chargalg.c
+++ b/drivers/power/supply/abx500_chargalg.c
@@ -28,10 +28,11 @@
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ux500_chargalg.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/notifier.h>
+#include "ab8500-bm.h"
+#include "ab8500-chargalg.h"
+
/* Watchdog kick interval */
#define CHG_WD_INTERVAL (6 * HZ)
@@ -1980,7 +1981,6 @@ static const struct power_supply_desc abx500_chargalg_desc = {
static int abx500_chargalg_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct abx500_bm_data *plat = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {};
struct abx500_chargalg *di;
int ret = 0;
@@ -1991,18 +1991,12 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
return -ENOMEM;
}
- if (!plat) {
- dev_err(&pdev->dev, "no battery management data supplied\n");
- return -EINVAL;
- }
- di->bm = plat;
+ di->bm = &ab8500_bm_data;
- if (np) {
- ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
- if (ret) {
- dev_err(&pdev->dev, "failed to get battery information\n");
- return ret;
- }
+ ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get battery information\n");
+ return ret;
}
/* get device struct and parent */
diff --git a/drivers/power/supply/pm2301_charger.c b/drivers/power/supply/pm2301_charger.c
index ac06ecf7fc9c..d53e0c37c059 100644
--- a/drivers/power/supply/pm2301_charger.c
+++ b/drivers/power/supply/pm2301_charger.c
@@ -18,13 +18,13 @@
#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/pm2301_charger.h>
#include <linux/gpio.h>
#include <linux/pm_runtime.h>
#include <linux/pm.h>
+#include "ab8500-bm.h"
+#include "ab8500-chargalg.h"
#include "pm2301_charger.h"
#define to_pm2xxx_charger_ac_device_info(x) container_of((x), \
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 9a4f66ae8070..a7a7a9f26aef 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -393,6 +393,14 @@ config PWM_MXS
To compile this driver as a module, choose M here: the module
will be called pwm-mxs.
+config PWM_NTXEC
+ tristate "Netronix embedded controller PWM support"
+ depends on MFD_NTXEC
+ help
+ Say yes here if you want to support the PWM output of the embedded
+ controller found in certain e-book readers designed by the original
+ design manufacturer Netronix.
+
config PWM_OMAP_DMTIMER
tristate "OMAP Dual-Mode Timer PWM support"
depends on OF
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 6374d3b1d6f3..4e35a55fa7b6 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PWM_MESON) += pwm-meson.o
obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
+obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
diff --git a/drivers/pwm/pwm-ntxec.c b/drivers/pwm/pwm-ntxec.c
new file mode 100644
index 000000000000..50c454c553c4
--- /dev/null
+++ b/drivers/pwm/pwm-ntxec.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The Netronix embedded controller is a microcontroller found in some
+ * e-book readers designed by the original design manufacturer Netronix, Inc.
+ * It contains RTC, battery monitoring, system power management, and PWM
+ * functionality.
+ *
+ * This driver implements PWM output.
+ *
+ * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+ *
+ * Limitations:
+ * - The get_state callback is not implemented, because the current state of
+ * the PWM output can't be read back from the hardware.
+ * - The hardware can only generate normal polarity output.
+ * - The period and duty cycle can't be changed together in one atomic action.
+ */
+
+#include <linux/mfd/ntxec.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+struct ntxec_pwm {
+ struct device *dev;
+ struct ntxec *ec;
+ struct pwm_chip chip;
+};
+
+static struct ntxec_pwm *ntxec_pwm_from_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct ntxec_pwm, chip);
+}
+
+#define NTXEC_REG_AUTO_OFF_HI 0xa1
+#define NTXEC_REG_AUTO_OFF_LO 0xa2
+#define NTXEC_REG_ENABLE 0xa3
+#define NTXEC_REG_PERIOD_LOW 0xa4
+#define NTXEC_REG_PERIOD_HIGH 0xa5
+#define NTXEC_REG_DUTY_LOW 0xa6
+#define NTXEC_REG_DUTY_HIGH 0xa7
+
+/*
+ * The time base used in the EC is 8MHz, or 125ns. Period and duty cycle are
+ * measured in this unit.
+ */
+#define TIME_BASE_NS 125
+
+/*
+ * The maximum input value (in nanoseconds) is determined by the time base and
+ * the range of the hardware registers that hold the converted value.
+ * It fits into 32 bits, so we can do our calculations in 32 bits as well.
+ */
+#define MAX_PERIOD_NS (TIME_BASE_NS * 0xffff)
+
+static int ntxec_pwm_set_raw_period_and_duty_cycle(struct pwm_chip *chip,
+ int period, int duty)
+{
+ struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
+
+ /*
+ * Changes to the period and duty cycle take effect as soon as the
+ * corresponding low byte is written, so the hardware may be configured
+ * to an inconsistent state after the period is written and before the
+ * duty cycle is fully written. If, in such a case, the old duty cycle
+ * is longer than the new period, the EC may output 100% for a moment.
+ *
+ * To minimize the time between the changes to period and duty cycle
+ * taking effect, the writes are interleaved.
+ */
+
+ struct reg_sequence regs[] = {
+ { NTXEC_REG_PERIOD_HIGH, ntxec_reg8(period >> 8) },
+ { NTXEC_REG_DUTY_HIGH, ntxec_reg8(duty >> 8) },
+ { NTXEC_REG_PERIOD_LOW, ntxec_reg8(period) },
+ { NTXEC_REG_DUTY_LOW, ntxec_reg8(duty) },
+ };
+
+ return regmap_multi_reg_write(priv->ec->regmap, regs, ARRAY_SIZE(regs));
+}
+
+static int ntxec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm_dev,
+ const struct pwm_state *state)
+{
+ struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
+ unsigned int period, duty;
+ int res;
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ period = min_t(u64, state->period, MAX_PERIOD_NS);
+ duty = min_t(u64, state->duty_cycle, period);
+
+ period /= TIME_BASE_NS;
+ duty /= TIME_BASE_NS;
+
+ /*
+ * Writing a duty cycle of zero puts the device into a state where
+ * writing a higher duty cycle doesn't result in the brightness that it
+ * usually results in. This can be fixed by cycling the ENABLE register.
+ *
+ * As a workaround, write ENABLE=0 when the duty cycle is zero.
+ * The case that something has previously set the duty cycle to zero
+ * but ENABLE=1, is not handled.
+ */
+ if (state->enabled && duty != 0) {
+ res = ntxec_pwm_set_raw_period_and_duty_cycle(chip, period, duty);
+ if (res)
+ return res;
+
+ res = regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(1));
+ if (res)
+ return res;
+
+ /* Disable the auto-off timer */
+ res = regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_HI, ntxec_reg8(0xff));
+ if (res)
+ return res;
+
+ return regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_LO, ntxec_reg8(0xff));
+ } else {
+ return regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(0));
+ }
+}
+
+static const struct pwm_ops ntxec_pwm_ops = {
+ .owner = THIS_MODULE,
+ .apply = ntxec_pwm_apply,
+ /*
+ * No .get_state callback, because the current state cannot be read
+ * back from the hardware.
+ */
+};
+
+static int ntxec_pwm_probe(struct platform_device *pdev)
+{
+ struct ntxec *ec = dev_get_drvdata(pdev->dev.parent);
+ struct ntxec_pwm *priv;
+ struct pwm_chip *chip;
+
+ pdev->dev.of_node = pdev->dev.parent->of_node;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->ec = ec;
+ priv->dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, priv);
+
+ chip = &priv->chip;
+ chip->dev = &pdev->dev;
+ chip->ops = &ntxec_pwm_ops;
+ chip->base = -1;
+ chip->npwm = 1;
+
+ return pwmchip_add(chip);
+}
+
+static int ntxec_pwm_remove(struct platform_device *pdev)
+{
+ struct ntxec_pwm *priv = platform_get_drvdata(pdev);
+ struct pwm_chip *chip = &priv->chip;
+
+ return pwmchip_remove(chip);
+}
+
+static struct platform_driver ntxec_pwm_driver = {
+ .driver = {
+ .name = "ntxec-pwm",
+ },
+ .probe = ntxec_pwm_probe,
+ .remove = ntxec_pwm_remove,
+};
+module_platform_driver(ntxec_pwm_driver);
+
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("PWM driver for Netronix EC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ntxec-pwm");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 77c43134bc9e..6437348ce862 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -204,6 +204,17 @@ config REGULATOR_BD70528
This driver can also be built as a module. If so, the module
will be called bd70528-regulator.
+config REGULATOR_BD71815
+ tristate "ROHM BD71815 Power Regulator"
+ depends on MFD_ROHM_BD71828
+ help
+ This driver supports voltage regulators on ROHM BD71815 PMIC.
+ This will enable support for the software controllable buck
+ and LDO regulators and a current regulator for LEDs.
+
+ This driver can also be built as a module. If so, the module
+ will be called bd71815-regulator.
+
config REGULATOR_BD71828
tristate "ROHM BD71828 Power Regulator"
depends on MFD_ROHM_BD71828
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 44d2f8bf4b74..c6f84a332fdd 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_ATC260X) += atc260x-regulator.o
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
+obj-$(CONFIG_REGULATOR_BD71815) += bd71815-regulator.o
obj-$(CONFIG_REGULATOR_BD71828) += bd71828-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
diff --git a/drivers/regulator/bd71815-regulator.c b/drivers/regulator/bd71815-regulator.c
new file mode 100644
index 000000000000..a4e8d5e36b40
--- /dev/null
+++ b/drivers/regulator/bd71815-regulator.c
@@ -0,0 +1,652 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright 2014 Embest Technology Co. Ltd. Inc.
+// bd71815-regulator.c ROHM BD71815 regulator driver
+//
+// Author: Tony Luo <luofc@embedinfo.com>
+//
+// Partially rewritten at 2021 by
+// Matti Vaittinen <matti.vaitinen@fi.rohmeurope.com>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rohm-generic.h>
+#include <linux/mfd/rohm-bd71815.h>
+#include <linux/regulator/of_regulator.h>
+
+struct bd71815_regulator {
+ struct regulator_desc desc;
+ const struct rohm_dvs_config *dvs;
+};
+
+struct bd71815_pmic {
+ struct bd71815_regulator descs[BD71815_REGULATOR_CNT];
+ struct regmap *regmap;
+ struct device *dev;
+ struct gpio_descs *gps;
+ struct regulator_dev *rdev[BD71815_REGULATOR_CNT];
+};
+
+static const int bd7181x_wled_currents[] = {
+ 10, 20, 30, 50, 70, 100, 200, 300, 500, 700, 1000, 2000, 3000, 4000,
+ 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000,
+ 16000, 17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000, 25000,
+};
+
+static const struct rohm_dvs_config buck1_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_BUCK1_VOLT_H,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = BD71815_BUCK_RUN_ON,
+ .snvs_on_mask = BD71815_BUCK_SNVS_ON,
+ .suspend_reg = BD71815_REG_BUCK1_VOLT_L,
+ .suspend_mask = BD71815_VOLT_MASK,
+ .suspend_on_mask = BD71815_BUCK_SUSP_ON,
+ .lpsr_reg = BD71815_REG_BUCK1_VOLT_L,
+ .lpsr_mask = BD71815_VOLT_MASK,
+ .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
+};
+
+static const struct rohm_dvs_config buck2_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_BUCK2_VOLT_H,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = BD71815_BUCK_RUN_ON,
+ .snvs_on_mask = BD71815_BUCK_SNVS_ON,
+ .suspend_reg = BD71815_REG_BUCK2_VOLT_L,
+ .suspend_mask = BD71815_VOLT_MASK,
+ .suspend_on_mask = BD71815_BUCK_SUSP_ON,
+ .lpsr_reg = BD71815_REG_BUCK2_VOLT_L,
+ .lpsr_mask = BD71815_VOLT_MASK,
+ .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
+};
+
+static const struct rohm_dvs_config buck3_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_BUCK3_VOLT,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = BD71815_BUCK_RUN_ON,
+ .snvs_on_mask = BD71815_BUCK_SNVS_ON,
+ .suspend_on_mask = BD71815_BUCK_SUSP_ON,
+ .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
+};
+
+static const struct rohm_dvs_config buck4_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_BUCK4_VOLT,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = BD71815_BUCK_RUN_ON,
+ .snvs_on_mask = BD71815_BUCK_SNVS_ON,
+ .suspend_on_mask = BD71815_BUCK_SUSP_ON,
+ .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldo1_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_LDO_MODE1,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = LDO1_RUN_ON,
+ .snvs_on_mask = LDO1_SNVS_ON,
+ .suspend_on_mask = LDO1_SUSP_ON,
+ .lpsr_on_mask = LDO1_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldo2_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_LDO_MODE2,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = LDO2_RUN_ON,
+ .snvs_on_mask = LDO2_SNVS_ON,
+ .suspend_on_mask = LDO2_SUSP_ON,
+ .lpsr_on_mask = LDO2_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldo3_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_LDO_MODE2,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = LDO3_RUN_ON,
+ .snvs_on_mask = LDO3_SNVS_ON,
+ .suspend_on_mask = LDO3_SUSP_ON,
+ .lpsr_on_mask = LDO3_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldo4_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_LDO_MODE3,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = LDO4_RUN_ON,
+ .snvs_on_mask = LDO4_SNVS_ON,
+ .suspend_on_mask = LDO4_SUSP_ON,
+ .lpsr_on_mask = LDO4_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldo5_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_LDO_MODE3,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = LDO5_RUN_ON,
+ .snvs_on_mask = LDO5_SNVS_ON,
+ .suspend_on_mask = LDO5_SUSP_ON,
+ .lpsr_on_mask = LDO5_LPSR_ON,
+};
+
+static const struct rohm_dvs_config dvref_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_on_mask = DVREF_RUN_ON,
+ .snvs_on_mask = DVREF_SNVS_ON,
+ .suspend_on_mask = DVREF_SUSP_ON,
+ .lpsr_on_mask = DVREF_LPSR_ON,
+};
+
+static const struct rohm_dvs_config ldolpsr_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_on_mask = DVREF_RUN_ON,
+ .snvs_on_mask = DVREF_SNVS_ON,
+ .suspend_on_mask = DVREF_SUSP_ON,
+ .lpsr_on_mask = DVREF_LPSR_ON,
+};
+
+static const struct rohm_dvs_config buck5_dvs = {
+ .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
+ ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
+ .run_reg = BD71815_REG_BUCK5_VOLT,
+ .run_mask = BD71815_VOLT_MASK,
+ .run_on_mask = BD71815_BUCK_RUN_ON,
+ .snvs_on_mask = BD71815_BUCK_SNVS_ON,
+ .suspend_on_mask = BD71815_BUCK_SUSP_ON,
+ .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
+};
+
+static int set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct bd71815_regulator *data;
+
+ data = container_of(desc, struct bd71815_regulator, desc);
+ return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap);
+}
+
+/*
+ * Bucks 1 and 2 have two voltage selection registers where selected
+ * voltage can be set. Which of the registers is used can be either controlled
+ * by a control bit in register - or by HW state. If HW state specific voltages
+ * are given - then we assume HW state based control should be used.
+ *
+ * If volatge value is updated to currently selected register - then output
+ * voltage is immediately changed no matter what is set as ramp rate. Thus we
+ * default changing voltage by writing new value to inactive register and
+ * then updating the 'register selection' bit. This naturally only works when
+ * HW state machine is not used to select the voltage.
+ */
+static int buck12_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ struct bd71815_regulator *data;
+ int ret = 0, val;
+
+ data = container_of(desc, struct bd71815_regulator, desc);
+
+ if (of_find_property(np, "rohm,dvs-run-voltage", NULL) ||
+ of_find_property(np, "rohm,dvs-suspend-voltage", NULL) ||
+ of_find_property(np, "rohm,dvs-lpsr-voltage", NULL) ||
+ of_find_property(np, "rohm,dvs-snvs-voltage", NULL)) {
+ ret = regmap_read(cfg->regmap, desc->vsel_reg, &val);
+ if (ret)
+ return ret;
+
+ if (!(BD71815_BUCK_STBY_DVS & val) &&
+ !(BD71815_BUCK_DVSSEL & val)) {
+ int val2;
+
+ /*
+ * We are currently using voltage from _L.
+ * We'd better copy it to _H and switch to it to
+ * avoid shutting us down if LPSR or SUSPEND is set to
+ * disabled. _L value is at reg _H + 1
+ */
+ ret = regmap_read(cfg->regmap, desc->vsel_reg + 1,
+ &val2);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
+ BD71815_VOLT_MASK |
+ BD71815_BUCK_DVSSEL,
+ val2 | BD71815_BUCK_DVSSEL);
+ if (ret)
+ return ret;
+ }
+ ret = rohm_regulator_set_dvs_levels(data->dvs, np, desc,
+ cfg->regmap);
+ if (ret)
+ return ret;
+ /*
+ * DVS levels were given => use HW-state machine for voltage
+ * controls. NOTE: AFAIK, This means that if voltage is changed
+ * by SW the ramp-rate is not respected. Should we disable
+ * SW voltage control when the HW state machine is used?
+ */
+ ret = regmap_update_bits(cfg->regmap, desc->vsel_reg,
+ BD71815_BUCK_STBY_DVS,
+ BD71815_BUCK_STBY_DVS);
+ }
+
+ return ret;
+}
+
+/*
+ * BUCK1/2
+ * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
+ * 00: 10.00mV/usec 10mV 1uS
+ * 01: 5.00mV/usec 10mV 2uS
+ * 10: 2.50mV/usec 10mV 4uS
+ * 11: 1.25mV/usec 10mV 8uS
+ */
+static const unsigned int bd7181x_ramp_table[] = { 1250, 2500, 5000, 10000 };
+
+static int bd7181x_led_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ int ret;
+ int onstatus;
+
+ onstatus = regulator_is_enabled_regmap(rdev);
+
+ ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
+ if (!ret) {
+ int newstatus;
+
+ newstatus = regulator_is_enabled_regmap(rdev);
+ if (onstatus != newstatus) {
+ /*
+ * HW FIX: spurious led status change detected. Toggle
+ * state as a workaround
+ */
+ if (onstatus)
+ ret = regulator_enable_regmap(rdev);
+ else
+ ret = regulator_disable_regmap(rdev);
+
+ if (ret)
+ dev_err(rdev_get_dev(rdev),
+ "failed to revert the LED state (%d)\n",
+ ret);
+ }
+ }
+
+ return ret;
+}
+
+static int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct bd71815_pmic *pmic = rdev_get_drvdata(rdev);
+ int rid = rdev_get_id(rdev);
+ int ret, regh, regl, val;
+
+ regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2;
+ regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2;
+
+ ret = regmap_read(pmic->regmap, regh, &val);
+ if (ret)
+ return ret;
+
+ /*
+ * If we use HW state machine based voltage reg selection - then we
+ * return BD71815_REG_BUCK1_VOLT_H which is used at RUN.
+ * Else we do return the BD71815_REG_BUCK1_VOLT_H or
+ * BD71815_REG_BUCK1_VOLT_L depending on which is selected to be used
+ * by BD71815_BUCK_DVSSEL bit
+ */
+ if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL)))
+ ret = regmap_read(pmic->regmap, regl, &val);
+
+ if (ret)
+ return ret;
+
+ return val & BD71815_VOLT_MASK;
+}
+
+/*
+ * For Buck 1/2.
+ */
+static int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ struct bd71815_pmic *pmic = rdev_get_drvdata(rdev);
+ int rid = rdev_get_id(rdev);
+ int ret, val, reg, regh, regl;
+
+ regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2;
+ regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2;
+
+ ret = regmap_read(pmic->regmap, regh, &val);
+ if (ret)
+ return ret;
+
+ /*
+ * If bucks 1 & 2 are controlled by state machine - then the RUN state
+ * voltage is set to BD71815_REG_BUCK1_VOLT_H. Changing SUSPEND/LPSR
+ * voltages at runtime is not supported by this driver.
+ */
+ if (((val & BD71815_BUCK_STBY_DVS))) {
+ return regmap_update_bits(pmic->regmap, regh, BD71815_VOLT_MASK,
+ sel);
+ }
+ /* Update new voltage to the register which is not selected now */
+ if (val & BD71815_BUCK_DVSSEL)
+ reg = regl;
+ else
+ reg = regh;
+
+ ret = regmap_update_bits(pmic->regmap, reg, BD71815_VOLT_MASK, sel);
+ if (ret)
+ return ret;
+
+ /* Select the other DVS register to be used */
+ return regmap_update_bits(pmic->regmap, regh, BD71815_BUCK_DVSSEL, ~val);
+}
+
+static const struct regulator_ops bd7181x_ldo_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops bd7181x_fixed_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+};
+
+static const struct regulator_ops bd7181x_buck_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
+static const struct regulator_ops bd7181x_buck12_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_voltage_sel = bd7181x_buck12_set_voltage_sel,
+ .get_voltage_sel = bd7181x_buck12_get_voltage_sel,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
+};
+
+static const struct regulator_ops bd7181x_led_regulator_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_current_limit = bd7181x_led_set_current_limit,
+ .get_current_limit = regulator_get_current_limit_regmap,
+};
+
+#define BD71815_FIXED_REG(_name, _id, ereg, emsk, voltage, _dvs) \
+ [(_id)] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = 1, \
+ .ops = &bd7181x_fixed_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = (_id), \
+ .owner = THIS_MODULE, \
+ .min_uV = (voltage), \
+ .enable_reg = (ereg), \
+ .enable_mask = (emsk), \
+ .of_parse_cb = set_hw_dvs_levels, \
+ }, \
+ .dvs = (_dvs), \
+ }
+
+#define BD71815_BUCK_REG(_name, _id, vsel, ereg, min, max, step, _dvs) \
+ [(_id)] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .ops = &bd7181x_buck_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = (_id), \
+ .owner = THIS_MODULE, \
+ .min_uV = (min), \
+ .uV_step = (step), \
+ .vsel_reg = (vsel), \
+ .vsel_mask = BD71815_VOLT_MASK, \
+ .enable_reg = (ereg), \
+ .enable_mask = BD71815_BUCK_RUN_ON, \
+ .of_parse_cb = set_hw_dvs_levels, \
+ }, \
+ .dvs = (_dvs), \
+ }
+
+#define BD71815_BUCK12_REG(_name, _id, vsel, ereg, min, max, step, \
+ _dvs) \
+ [(_id)] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .ops = &bd7181x_buck12_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = (_id), \
+ .owner = THIS_MODULE, \
+ .min_uV = (min), \
+ .uV_step = (step), \
+ .vsel_reg = (vsel), \
+ .vsel_mask = 0x3f, \
+ .enable_reg = (ereg), \
+ .enable_mask = 0x04, \
+ .ramp_reg = (ereg), \
+ .ramp_mask = BD71815_BUCK_RAMPRATE_MASK, \
+ .ramp_delay_table = bd7181x_ramp_table, \
+ .n_ramp_values = ARRAY_SIZE(bd7181x_ramp_table),\
+ .of_parse_cb = buck12_set_hw_dvs_levels, \
+ }, \
+ .dvs = (_dvs), \
+ }
+
+#define BD71815_LED_REG(_name, _id, csel, mask, ereg, emsk, currents) \
+ [(_id)] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_current_limits = ARRAY_SIZE(currents), \
+ .ops = &bd7181x_led_regulator_ops, \
+ .type = REGULATOR_CURRENT, \
+ .id = (_id), \
+ .owner = THIS_MODULE, \
+ .curr_table = currents, \
+ .csel_reg = (csel), \
+ .csel_mask = (mask), \
+ .enable_reg = (ereg), \
+ .enable_mask = (emsk), \
+ }, \
+ }
+
+#define BD71815_LDO_REG(_name, _id, vsel, ereg, emsk, min, max, step, \
+ _dvs) \
+ [(_id)] = { \
+ .desc = { \
+ .name = #_name, \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .n_voltages = ((max) - (min)) / (step) + 1, \
+ .ops = &bd7181x_ldo_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = (_id), \
+ .owner = THIS_MODULE, \
+ .min_uV = (min), \
+ .uV_step = (step), \
+ .vsel_reg = (vsel), \
+ .vsel_mask = BD71815_VOLT_MASK, \
+ .enable_reg = (ereg), \
+ .enable_mask = (emsk), \
+ .of_parse_cb = set_hw_dvs_levels, \
+ }, \
+ .dvs = (_dvs), \
+ }
+
+static struct bd71815_regulator bd71815_regulators[] = {
+ BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H,
+ BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000,
+ &buck1_dvs),
+ BD71815_BUCK12_REG(buck2, BD71815_BUCK2, BD71815_REG_BUCK2_VOLT_H,
+ BD71815_REG_BUCK2_MODE, 800000, 2000000, 25000,
+ &buck2_dvs),
+ BD71815_BUCK_REG(buck3, BD71815_BUCK3, BD71815_REG_BUCK3_VOLT,
+ BD71815_REG_BUCK3_MODE, 1200000, 2700000, 50000,
+ &buck3_dvs),
+ BD71815_BUCK_REG(buck4, BD71815_BUCK4, BD71815_REG_BUCK4_VOLT,
+ BD71815_REG_BUCK4_MODE, 1100000, 1850000, 25000,
+ &buck4_dvs),
+ BD71815_BUCK_REG(buck5, BD71815_BUCK5, BD71815_REG_BUCK5_VOLT,
+ BD71815_REG_BUCK5_MODE, 1800000, 3300000, 50000,
+ &buck5_dvs),
+ BD71815_LDO_REG(ldo1, BD71815_LDO1, BD71815_REG_LDO1_VOLT,
+ BD71815_REG_LDO_MODE1, LDO1_RUN_ON, 800000, 3300000,
+ 50000, &ldo1_dvs),
+ BD71815_LDO_REG(ldo2, BD71815_LDO2, BD71815_REG_LDO2_VOLT,
+ BD71815_REG_LDO_MODE2, LDO2_RUN_ON, 800000, 3300000,
+ 50000, &ldo2_dvs),
+ /*
+ * Let's default LDO3 to be enabled by SW. We can override ops if DT
+ * says LDO3 should be enabled by HW when DCIN is connected.
+ */
+ BD71815_LDO_REG(ldo3, BD71815_LDO3, BD71815_REG_LDO3_VOLT,
+ BD71815_REG_LDO_MODE2, LDO3_RUN_ON, 800000, 3300000,
+ 50000, &ldo3_dvs),
+ BD71815_LDO_REG(ldo4, BD71815_LDO4, BD71815_REG_LDO4_VOLT,
+ BD71815_REG_LDO_MODE3, LDO4_RUN_ON, 800000, 3300000,
+ 50000, &ldo4_dvs),
+ BD71815_LDO_REG(ldo5, BD71815_LDO5, BD71815_REG_LDO5_VOLT_H,
+ BD71815_REG_LDO_MODE3, LDO5_RUN_ON, 800000, 3300000,
+ 50000, &ldo5_dvs),
+ BD71815_FIXED_REG(ldodvref, BD71815_LDODVREF, BD71815_REG_LDO_MODE4,
+ DVREF_RUN_ON, 3000000, &dvref_dvs),
+ BD71815_FIXED_REG(ldolpsr, BD71815_LDOLPSR, BD71815_REG_LDO_MODE4,
+ LDO_LPSR_RUN_ON, 1800000, &ldolpsr_dvs),
+ BD71815_LED_REG(wled, BD71815_WLED, BD71815_REG_LED_DIMM, LED_DIMM_MASK,
+ BD71815_REG_LED_CTRL, LED_RUN_ON,
+ bd7181x_wled_currents),
+};
+
+static int bd7181x_probe(struct platform_device *pdev)
+{
+ struct bd71815_pmic *pmic;
+ struct regulator_config config = {};
+ int i, ret;
+ struct gpio_desc *ldo4_en;
+
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ memcpy(pmic->descs, bd71815_regulators, sizeof(pmic->descs));
+
+ pmic->dev = &pdev->dev;
+ pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!pmic->regmap) {
+ dev_err(pmic->dev, "No parent regmap\n");
+ return -ENODEV;
+ }
+ platform_set_drvdata(pdev, pmic);
+ ldo4_en = devm_gpiod_get_from_of_node(&pdev->dev,
+ pdev->dev.parent->of_node,
+ "rohm,vsel-gpios", 0,
+ GPIOD_ASIS, "ldo4-en");
+
+ if (IS_ERR(ldo4_en)) {
+ ret = PTR_ERR(ldo4_en);
+ if (ret != -ENOENT)
+ return ret;
+ ldo4_en = NULL;
+ }
+
+ /* Disable to go to ship-mode */
+ ret = regmap_update_bits(pmic->regmap, BD71815_REG_PWRCTRL,
+ RESTARTEN, 0);
+ if (ret)
+ return ret;
+
+ config.dev = pdev->dev.parent;
+ config.regmap = pmic->regmap;
+
+ for (i = 0; i < BD71815_REGULATOR_CNT; i++) {
+ struct regulator_desc *desc;
+ struct regulator_dev *rdev;
+
+ desc = &pmic->descs[i].desc;
+ if (i == BD71815_LDO4)
+ config.ena_gpiod = ldo4_en;
+
+ config.driver_data = pmic;
+
+ rdev = devm_regulator_register(&pdev->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ desc->name);
+ return PTR_ERR(rdev);
+ }
+ config.ena_gpiod = NULL;
+ pmic->rdev[i] = rdev;
+ }
+ return 0;
+}
+
+static const struct platform_device_id bd7181x_pmic_id[] = {
+ { "bd71815-pmic", ROHM_CHIP_TYPE_BD71815 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, bd7181x_pmic_id);
+
+static struct platform_driver bd7181x_regulator = {
+ .driver = {
+ .name = "bd7181x-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = bd7181x_probe,
+ .id_table = bd7181x_pmic_id,
+};
+module_platform_driver(bd7181x_regulator);
+
+MODULE_AUTHOR("Tony Luo <luofc@embedinfo.com>");
+MODULE_DESCRIPTION("BD71815 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bd7181x-pmic");
diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c
index 6b12e963ed8f..a4f09a5a30ca 100644
--- a/drivers/regulator/bd71828-regulator.c
+++ b/drivers/regulator/bd71828-regulator.c
@@ -90,38 +90,7 @@ static const struct linear_range bd71828_ldo_volts[] = {
REGULATOR_LINEAR_RANGE(3300000, 0x32, 0x3f, 0),
};
-static int bd71828_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
-{
- unsigned int val;
-
- switch (ramp_delay) {
- case 1 ... 2500:
- val = 0;
- break;
- case 2501 ... 5000:
- val = 1;
- break;
- case 5001 ... 10000:
- val = 2;
- break;
- case 10001 ... 20000:
- val = 3;
- break;
- default:
- val = 3;
- dev_err(&rdev->dev,
- "ramp_delay: %d not supported, setting 20mV/uS",
- ramp_delay);
- }
-
- /*
- * On BD71828 the ramp delay level control reg is at offset +2 to
- * enable reg
- */
- return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg + 2,
- BD71828_MASK_RAMP_DELAY,
- val << (ffs(BD71828_MASK_RAMP_DELAY) - 1));
-}
+static const unsigned int bd71828_ramp_delay[] = { 2500, 5000, 10000, 20000 };
static int buck_set_hw_dvs_levels(struct device_node *np,
const struct regulator_desc *desc,
@@ -185,7 +154,7 @@ static const struct regulator_ops bd71828_dvs_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
- .set_ramp_delay = bd71828_set_ramp_delay,
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
};
static const struct regulator_ops bd71828_ldo_ops = {
@@ -219,6 +188,10 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
.enable_mask = BD71828_MASK_RUN_EN,
.vsel_reg = BD71828_REG_BUCK1_VOLT,
.vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .ramp_delay_table = bd71828_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+ .ramp_reg = BD71828_REG_BUCK1_MODE,
+ .ramp_mask = BD71828_MASK_RAMP_DELAY,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -261,6 +234,10 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
.enable_mask = BD71828_MASK_RUN_EN,
.vsel_reg = BD71828_REG_BUCK2_VOLT,
.vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .ramp_delay_table = bd71828_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+ .ramp_reg = BD71828_REG_BUCK2_MODE,
+ .ramp_mask = BD71828_MASK_RAMP_DELAY,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -421,6 +398,10 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
.enable_mask = BD71828_MASK_RUN_EN,
.vsel_reg = BD71828_REG_BUCK6_VOLT,
.vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .ramp_delay_table = bd71828_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+ .ramp_reg = BD71828_REG_BUCK6_MODE,
+ .ramp_mask = BD71828_MASK_RAMP_DELAY,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -458,6 +439,10 @@ static const struct bd71828_regulator_data bd71828_rdata[] = {
.enable_mask = BD71828_MASK_RUN_EN,
.vsel_reg = BD71828_REG_BUCK7_VOLT,
.vsel_mask = BD71828_MASK_BUCK1267_VOLT,
+ .ramp_delay_table = bd71828_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+ .ramp_reg = BD71828_REG_BUCK7_MODE,
+ .ramp_mask = BD71828_MASK_RAMP_DELAY,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index 8ff47ea522d6..e61295b30503 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -86,37 +86,7 @@ static const struct regulator_ops BD718XX_HWOPNAME(name) = { \
* 10: 2.50mV/usec 10mV 4uS
* 11: 1.25mV/usec 10mV 8uS
*/
-static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev,
- int ramp_delay)
-{
- int id = rdev_get_id(rdev);
- unsigned int ramp_value;
-
- dev_dbg(&rdev->dev, "Buck[%d] Set Ramp = %d\n", id + 1,
- ramp_delay);
- switch (ramp_delay) {
- case 1 ... 1250:
- ramp_value = BUCK_RAMPRATE_1P25MV;
- break;
- case 1251 ... 2500:
- ramp_value = BUCK_RAMPRATE_2P50MV;
- break;
- case 2501 ... 5000:
- ramp_value = BUCK_RAMPRATE_5P00MV;
- break;
- case 5001 ... 10000:
- ramp_value = BUCK_RAMPRATE_10P00MV;
- break;
- default:
- ramp_value = BUCK_RAMPRATE_10P00MV;
- dev_err(&rdev->dev,
- "%s: ramp_delay: %d not supported, setting 10000mV//us\n",
- rdev->desc->name, ramp_delay);
- }
-
- return regmap_update_bits(rdev->regmap, BD718XX_REG_BUCK1_CTRL + id,
- BUCK_RAMPRATE_MASK, ramp_value << 6);
-}
+static const unsigned int bd718xx_ramp_delay[] = { 10000, 5000, 2500, 1250 };
/* These functions are used when regulators are under HW state machine control.
* We assume PMIC is in RUN state because SW running and able to query the
@@ -378,7 +348,7 @@ static const struct regulator_ops bd71837_buck34_ops_hwctrl = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
- .set_ramp_delay = bd718xx_buck1234_set_ramp_delay,
+ .set_ramp_delay = regulator_set_ramp_delay_regmap,
};
/*
@@ -387,7 +357,7 @@ static const struct regulator_ops bd71837_buck34_ops_hwctrl = {
BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
- bd718xx_buck1234_set_ramp_delay);
+ /* bd718xx_buck1234_set_ramp_delay */ regulator_set_ramp_delay_regmap);
/*
* BD71837 BUCK1/2/3/4
@@ -645,6 +615,10 @@ static struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71847_BUCK1_STARTUP_TIME,
.owner = THIS_MODULE,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD718XX_REG_BUCK1_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.of_parse_cb = buck_set_hw_dvs_levels,
},
.dvs = {
@@ -678,6 +652,10 @@ static struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71847_BUCK2_STARTUP_TIME,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD718XX_REG_BUCK2_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -985,6 +963,10 @@ static struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK1_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK1_STARTUP_TIME,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD718XX_REG_BUCK1_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -1019,6 +1001,10 @@ static struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK2_STARTUP_TIME,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD718XX_REG_BUCK2_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -1050,6 +1036,10 @@ static struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK3_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK3_STARTUP_TIME,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD71837_REG_BUCK3_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
@@ -1079,6 +1069,10 @@ static struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK4_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.enable_time = BD71837_BUCK4_STARTUP_TIME,
+ .ramp_delay_table = bd718xx_ramp_delay,
+ .n_ramp_values = ARRAY_SIZE(bd718xx_ramp_delay),
+ .ramp_reg = BD71837_REG_BUCK4_CTRL,
+ .ramp_mask = BUCK_RAMPRATE_MASK,
.owner = THIS_MODULE,
.of_parse_cb = buck_set_hw_dvs_levels,
},
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index f42b394a0c46..0e16e31c968f 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -509,6 +509,33 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
/**
+ * regulator_desc_list_voltage_linear - List voltages with simple calculation
+ *
+ * @desc: Regulator desc for regulator which volatges are to be listed
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a simple linear mapping between voltages and
+ * selectors can set min_uV and uV_step in the regulator descriptor
+ * and then use this function prior regulator registration to list
+ * the voltages. This is useful when voltages need to be listed during
+ * device-tree parsing.
+ */
+int regulator_desc_list_voltage_linear(const struct regulator_desc *desc,
+ unsigned int selector)
+{
+ if (selector >= desc->n_voltages)
+ return -EINVAL;
+
+ if (selector < desc->linear_min_sel)
+ return 0;
+
+ selector -= desc->linear_min_sel;
+
+ return desc->min_uV + (desc->uV_step * selector);
+}
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear);
+
+/**
* regulator_list_voltage_linear - List voltages with simple calculation
*
* @rdev: Regulator device
@@ -521,14 +548,7 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
int regulator_list_voltage_linear(struct regulator_dev *rdev,
unsigned int selector)
{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
- if (selector < rdev->desc->linear_min_sel)
- return 0;
-
- selector -= rdev->desc->linear_min_sel;
-
- return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+ return regulator_desc_list_voltage_linear(rdev->desc, selector);
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
@@ -881,3 +901,68 @@ bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2)
return reg1->rdev == reg2->rdev;
}
EXPORT_SYMBOL_GPL(regulator_is_equal);
+
+static int find_closest_bigger(unsigned int target, const unsigned int *table,
+ unsigned int num_sel, unsigned int *sel)
+{
+ unsigned int s, tmp, max, maxsel = 0;
+ bool found = false;
+
+ max = table[0];
+
+ for (s = 0; s < num_sel; s++) {
+ if (table[s] > max) {
+ max = table[s];
+ maxsel = s;
+ }
+ if (table[s] >= target) {
+ if (!found || table[s] - target < tmp - target) {
+ tmp = table[s];
+ *sel = s;
+ found = true;
+ if (tmp == target)
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ *sel = maxsel;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * regulator_set_ramp_delay_regmap - set_ramp_delay() helper
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the ramp_reg
+ * and ramp_mask fields in their descriptor and then use this as their
+ * set_ramp_delay operation, saving some code.
+ */
+int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
+{
+ int ret;
+ unsigned int sel;
+
+ if (!rdev->desc->n_ramp_values)
+ return -EINVAL;
+
+ ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
+ rdev->desc->n_ramp_values, &sel);
+
+ if (ret) {
+ dev_warn(rdev_get_dev(rdev),
+ "Can't set ramp-delay %u, setting %u\n", ramp_delay,
+ rdev->desc->ramp_delay_table[sel]);
+ }
+
+ sel <<= ffs(rdev->desc->ramp_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg,
+ rdev->desc->ramp_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_ramp_delay_regmap);
diff --git a/drivers/regulator/mt6315-regulator.c b/drivers/regulator/mt6315-regulator.c
index d49a1534d8e9..9edc34981ee0 100644
--- a/drivers/regulator/mt6315-regulator.c
+++ b/drivers/regulator/mt6315-regulator.c
@@ -41,7 +41,7 @@ struct mt6315_chip {
.type = REGULATOR_VOLTAGE, \
.id = _bid, \
.owner = THIS_MODULE, \
- .n_voltages = 0xbf, \
+ .n_voltages = 0xc0, \
.linear_ranges = mt_volt_range1, \
.n_linear_ranges = ARRAY_SIZE(mt_volt_range1), \
.vsel_reg = _vsel, \
@@ -69,7 +69,7 @@ static unsigned int mt6315_map_mode(u32 mode)
case MT6315_BUCK_MODE_LP:
return REGULATOR_MODE_IDLE;
default:
- return -EINVAL;
+ return REGULATOR_MODE_INVALID;
}
}
diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c
index 833d398c6aa2..2f7ee212cb8c 100644
--- a/drivers/regulator/pca9450-regulator.c
+++ b/drivers/regulator/pca9450-regulator.c
@@ -797,6 +797,14 @@ static int pca9450_i2c_probe(struct i2c_client *i2c,
return ret;
}
+ /* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */
+ ret = regmap_clear_bits(pca9450->regmap, PCA9450_REG_BUCK123_DVS,
+ BUCK123_PRESET_EN);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to clear PRESET_EN bit: %d\n", ret);
+ return ret;
+ }
+
/* Set reset behavior on assertion of WDOG_B signal */
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
WDOG_B_CFG_MASK, WDOG_B_CFG_COLD_LDO12);
@@ -814,7 +822,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c,
if (IS_ERR(pca9450->sd_vsel_gpio)) {
dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
- return ret;
+ return PTR_ERR(pca9450->sd_vsel_gpio);
}
dev_info(&i2c->dev, "%s probed.\n",
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index 79a554f1029d..65a108c9121f 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -726,8 +726,8 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = {
static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
.regulator_type = VRM,
.ops = &rpmh_regulator_vrm_ops,
- .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 16000),
- .n_voltages = 5,
+ .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 235, 16000),
+ .n_voltages = 236,
.pmic_mode_map = pmic_mode_map_pmic5_smps,
.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
};
@@ -901,7 +901,7 @@ static const struct rpmh_vreg_init_data pm8350_vreg_data[] = {
};
static const struct rpmh_vreg_init_data pm8350c_vreg_data[] = {
- RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"),
+ RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps515, "vdd-s1"),
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"),
diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c
index 5c558b153d55..6e0d9c08ec1c 100644
--- a/drivers/regulator/rohm-regulator.c
+++ b/drivers/regulator/rohm-regulator.c
@@ -22,13 +22,26 @@ static int set_dvs_level(const struct regulator_desc *desc,
return ret;
return 0;
}
-
+ /* If voltage is set to 0 => disable */
if (uv == 0) {
if (omask)
return regmap_update_bits(regmap, oreg, omask, 0);
}
+ /* Some setups don't allow setting own voltage but do allow enabling */
+ if (!mask) {
+ if (omask)
+ return regmap_update_bits(regmap, oreg, omask, omask);
+
+ return -EINVAL;
+ }
for (i = 0; i < desc->n_voltages; i++) {
- ret = regulator_desc_list_voltage_linear_range(desc, i);
+ /* NOTE to next hacker - Does not support pickable ranges */
+ if (desc->linear_range_selectors)
+ return -EINVAL;
+ if (desc->n_linear_ranges)
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ else
+ ret = regulator_desc_list_voltage_linear(desc, i);
if (ret < 0)
continue;
if (ret == uv) {
@@ -82,6 +95,12 @@ int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
mask = dvs->lpsr_mask;
omask = dvs->lpsr_on_mask;
break;
+ case ROHM_DVS_LEVEL_SNVS:
+ prop = "rohm,dvs-snvs-voltage";
+ reg = dvs->snvs_reg;
+ mask = dvs->snvs_mask;
+ omask = dvs->snvs_on_mask;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/regulator/rt4831-regulator.c b/drivers/regulator/rt4831-regulator.c
index 3d4695ded629..e3aaac90d238 100644
--- a/drivers/regulator/rt4831-regulator.c
+++ b/drivers/regulator/rt4831-regulator.c
@@ -153,9 +153,9 @@ static int rt4831_regulator_probe(struct platform_device *pdev)
int i, ret;
regmap = dev_get_regmap(pdev->dev.parent, NULL);
- if (IS_ERR(regmap)) {
+ if (!regmap) {
dev_err(&pdev->dev, "Failed to init regmap\n");
- return PTR_ERR(regmap);
+ return -ENODEV;
}
/* Configure DSV mode to normal by default */
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ce723dc54aa4..773386b4aeb7 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -501,11 +501,11 @@ config RTC_DRV_M41T80_WDT
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
config RTC_DRV_BD70528
- tristate "ROHM BD70528 PMIC RTC"
- depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
+ tristate "ROHM BD70528, BD71815 and BD71828 PMIC RTC"
+ depends on MFD_ROHM_BD71828 || MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG)
help
If you say Y here you will get support for the RTC
- block on ROHM BD70528 and BD71828 Power Management IC.
+ block on ROHM BD70528, BD71815 and BD71828 Power Management IC.
This driver can also be built as a module. If so, the module
will be called rtc-bd70528.
@@ -1296,6 +1296,14 @@ config RTC_DRV_CROS_EC
This driver can also be built as a module. If so, the module
will be called rtc-cros-ec.
+config RTC_DRV_NTXEC
+ tristate "Netronix embedded controller RTC"
+ depends on MFD_NTXEC
+ help
+ Say yes here if you want to support the RTC functionality of the
+ embedded controller found in certain e-book readers designed by the
+ original design manufacturer Netronix.
+
comment "on-CPU RTC drivers"
config RTC_DRV_ASM9260
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 4e930183c170..2dd0dd956b0e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o
+obj-$(CONFIG_RTC_DRV_NTXEC) += rtc-ntxec.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o
obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o
diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c
index 17cb67f5bf6e..6454afca02a6 100644
--- a/drivers/rtc/rtc-bd70528.c
+++ b/drivers/rtc/rtc-bd70528.c
@@ -6,6 +6,7 @@
#include <linux/bcd.h>
#include <linux/mfd/rohm-bd70528.h>
+#include <linux/mfd/rohm-bd71815.h>
#include <linux/mfd/rohm-bd71828.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -14,6 +15,12 @@
#include <linux/rtc.h>
/*
+ * On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0
+ * block start
+ */
+#define BD718XX_ALM_EN_OFFSET 14
+
+/*
* We read regs RTC_SEC => RTC_YEAR
* this struct is ordered according to chip registers.
* Keep it u8 only (or packed) to avoid padding issues.
@@ -52,8 +59,10 @@ struct bd70528_rtc_alm {
struct bd70528_rtc {
struct rohm_regmap_dev *parent;
+ struct regmap *regmap;
struct device *dev;
u8 reg_time_start;
+ u8 bd718xx_alm_block_start;
bool has_rtc_timers;
};
@@ -234,10 +243,9 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
int ret;
struct bd71828_rtc_alm alm;
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
- ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
+ sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
@@ -250,8 +258,8 @@ static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
else
alm.alm_mask |= BD70528_MASK_ALM_EN;
- ret = regmap_bulk_write(parent->regmap, BD71828_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm,
+ sizeof(alm));
if (ret)
dev_err(dev, "Failed to set alarm time\n");
@@ -265,17 +273,16 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
struct bd70528_rtc_alm alm;
int ret;
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
- ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_WAKE_START,
- &wake, sizeof(wake));
+ ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,
+ sizeof(wake));
if (ret) {
dev_err(dev, "Failed to read wake regs\n");
return ret;
}
- ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
+ sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
@@ -292,15 +299,14 @@ static int bd70528_set_alarm(struct device *dev, struct rtc_wkalrm *a)
wake.ctrl &= ~BD70528_MASK_WAKE_EN;
}
- ret = regmap_bulk_write(parent->regmap,
- BD70528_REG_RTC_WAKE_START, &wake,
+ ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_WAKE_START, &wake,
sizeof(wake));
if (ret) {
dev_err(dev, "Failed to set wake time\n");
return ret;
}
- ret = regmap_bulk_write(parent->regmap, BD70528_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_write(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
+ sizeof(alm));
if (ret)
dev_err(dev, "Failed to set alarm time\n");
@@ -312,10 +318,9 @@ static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
int ret;
struct bd71828_rtc_alm alm;
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
- ret = regmap_bulk_read(parent->regmap, BD71828_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
+ sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
@@ -336,10 +341,9 @@ static int bd70528_read_alarm(struct device *dev, struct rtc_wkalrm *a)
struct bd70528_rtc_alm alm;
int ret;
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
- ret = regmap_bulk_read(parent->regmap, BD70528_REG_RTC_ALM_START,
- &alm, sizeof(alm));
+ ret = regmap_bulk_read(r->regmap, BD70528_REG_RTC_ALM_START, &alm,
+ sizeof(alm));
if (ret) {
dev_err(dev, "Failed to read alarm regs\n");
return ret;
@@ -360,14 +364,12 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
int ret, tmpret, old_states;
struct bd70528_rtc_data rtc_data;
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
ret = bd70528_disable_rtc_based_timers(r, &old_states);
if (ret)
return ret;
- tmpret = regmap_bulk_read(parent->regmap,
- r->reg_time_start, &rtc_data,
+ tmpret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
sizeof(rtc_data));
if (tmpret) {
dev_err(dev, "Failed to read RTC time registers\n");
@@ -375,8 +377,7 @@ static int bd70528_set_time_locked(struct device *dev, struct rtc_time *t)
}
tm2rtc(t, &rtc_data);
- tmpret = regmap_bulk_write(parent->regmap,
- r->reg_time_start, &rtc_data,
+ tmpret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,
sizeof(rtc_data));
if (tmpret) {
dev_err(dev, "Failed to set RTC time\n");
@@ -410,13 +411,11 @@ static int bd70528_set_time(struct device *dev, struct rtc_time *t)
static int bd70528_get_time(struct device *dev, struct rtc_time *t)
{
struct bd70528_rtc *r = dev_get_drvdata(dev);
- struct rohm_regmap_dev *parent = r->parent;
struct bd70528_rtc_data rtc_data;
int ret;
/* read the RTC date and time registers all at once */
- ret = regmap_bulk_read(parent->regmap,
- r->reg_time_start, &rtc_data,
+ ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
sizeof(rtc_data));
if (ret) {
dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
@@ -443,7 +442,7 @@ static int bd70528_alm_enable(struct device *dev, unsigned int enabled)
dev_err(dev, "Failed to change wake state\n");
goto out_unlock;
}
- ret = regmap_update_bits(r->parent->regmap, BD70528_REG_RTC_ALM_MASK,
+ ret = regmap_update_bits(r->regmap, BD70528_REG_RTC_ALM_MASK,
BD70528_MASK_ALM_EN, enableval);
if (ret)
dev_err(dev, "Failed to change alarm state\n");
@@ -462,8 +461,9 @@ static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
if (!enabled)
enableval = 0;
- ret = regmap_update_bits(r->parent->regmap, BD71828_REG_RTC_ALM0_MASK,
- BD70528_MASK_ALM_EN, enableval);
+ ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start +
+ BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN,
+ enableval);
if (ret)
dev_err(dev, "Failed to change alarm state\n");
@@ -498,7 +498,6 @@ static int bd70528_probe(struct platform_device *pdev)
{
struct bd70528_rtc *bd_rtc;
const struct rtc_class_ops *rtc_ops;
- struct rohm_regmap_dev *parent;
const char *irq_name;
int ret;
struct rtc_device *rtc;
@@ -508,20 +507,25 @@ static int bd70528_probe(struct platform_device *pdev)
u8 hour_reg;
enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
- parent = dev_get_drvdata(pdev->dev.parent);
- if (!parent) {
- dev_err(&pdev->dev, "No MFD driver data\n");
- return -EINVAL;
- }
bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);
if (!bd_rtc)
return -ENOMEM;
- bd_rtc->parent = parent;
+ bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!bd_rtc->regmap) {
+ dev_err(&pdev->dev, "No regmap\n");
+ return -EINVAL;
+ }
+
bd_rtc->dev = &pdev->dev;
switch (chip) {
case ROHM_CHIP_TYPE_BD70528:
+ bd_rtc->parent = dev_get_drvdata(pdev->dev.parent);
+ if (!bd_rtc->parent) {
+ dev_err(&pdev->dev, "No MFD data\n");
+ return -EINVAL;
+ }
irq_name = "bd70528-rtc-alm";
bd_rtc->has_rtc_timers = true;
bd_rtc->reg_time_start = BD70528_REG_RTC_START;
@@ -529,9 +533,28 @@ static int bd70528_probe(struct platform_device *pdev)
enable_main_irq = true;
rtc_ops = &bd70528_rtc_ops;
break;
+ case ROHM_CHIP_TYPE_BD71815:
+ irq_name = "bd71815-rtc-alm-0";
+ bd_rtc->reg_time_start = BD71815_REG_RTC_START;
+
+ /*
+ * See also BD718XX_ALM_EN_OFFSET:
+ * This works for BD71828 and BD71815 as they have same offset
+ * between ALM0 start and ALM0_MASK. If new ICs are to be
+ * added this requires proper check as ALM0_MASK is not located
+ * at the end of ALM0 block - but after all ALM blocks so if
+ * amount of ALMs differ the offset to enable/disable is likely
+ * to be incorrect and enable/disable must be given as own
+ * reg address here.
+ */
+ bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START;
+ hour_reg = BD71815_REG_HOUR;
+ rtc_ops = &bd71828_rtc_ops;
+ break;
case ROHM_CHIP_TYPE_BD71828:
irq_name = "bd71828-rtc-alm-0";
bd_rtc->reg_time_start = BD71828_REG_RTC_START;
+ bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;
hour_reg = BD71828_REG_RTC_HOUR;
rtc_ops = &bd71828_rtc_ops;
break;
@@ -547,7 +570,7 @@ static int bd70528_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, bd_rtc);
- ret = regmap_read(parent->regmap, hour_reg, &hr);
+ ret = regmap_read(bd_rtc->regmap, hour_reg, &hr);
if (ret) {
dev_err(&pdev->dev, "Failed to reag RTC clock\n");
@@ -595,7 +618,7 @@ static int bd70528_probe(struct platform_device *pdev)
* from sub-registers when IRQ is disabled or freed.
*/
if (enable_main_irq) {
- ret = regmap_update_bits(parent->regmap,
+ ret = regmap_update_bits(bd_rtc->regmap,
BD70528_REG_INT_MAIN_MASK,
BD70528_INT_RTC_MASK, 0);
if (ret) {
@@ -610,6 +633,7 @@ static int bd70528_probe(struct platform_device *pdev)
static const struct platform_device_id bd718x7_rtc_id[] = {
{ "bd70528-rtc", ROHM_CHIP_TYPE_BD70528 },
{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
+ { "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
{ },
};
MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
diff --git a/drivers/rtc/rtc-ntxec.c b/drivers/rtc/rtc-ntxec.c
new file mode 100644
index 000000000000..850ca49186fd
--- /dev/null
+++ b/drivers/rtc/rtc-ntxec.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The Netronix embedded controller is a microcontroller found in some
+ * e-book readers designed by the original design manufacturer Netronix, Inc.
+ * It contains RTC, battery monitoring, system power management, and PWM
+ * functionality.
+ *
+ * This driver implements access to the RTC time and date.
+ *
+ * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+ */
+
+#include <linux/mfd/ntxec.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+
+struct ntxec_rtc {
+ struct device *dev;
+ struct ntxec *ec;
+};
+
+#define NTXEC_REG_WRITE_YEAR 0x10
+#define NTXEC_REG_WRITE_MONTH 0x11
+#define NTXEC_REG_WRITE_DAY 0x12
+#define NTXEC_REG_WRITE_HOUR 0x13
+#define NTXEC_REG_WRITE_MINUTE 0x14
+#define NTXEC_REG_WRITE_SECOND 0x15
+
+#define NTXEC_REG_READ_YEAR_MONTH 0x20
+#define NTXEC_REG_READ_MDAY_HOUR 0x21
+#define NTXEC_REG_READ_MINUTE_SECOND 0x23
+
+static int ntxec_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct ntxec_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int value;
+ int res;
+
+retry:
+ res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value);
+ if (res < 0)
+ return res;
+
+ tm->tm_min = value >> 8;
+ tm->tm_sec = value & 0xff;
+
+ res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MDAY_HOUR, &value);
+ if (res < 0)
+ return res;
+
+ tm->tm_mday = value >> 8;
+ tm->tm_hour = value & 0xff;
+
+ res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_YEAR_MONTH, &value);
+ if (res < 0)
+ return res;
+
+ tm->tm_year = (value >> 8) + 100;
+ tm->tm_mon = (value & 0xff) - 1;
+
+ /*
+ * Read the minutes/seconds field again. If it changed since the first
+ * read, we can't assume that the values read so far are consistent,
+ * and should start from the beginning.
+ */
+ res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value);
+ if (res < 0)
+ return res;
+
+ if (tm->tm_min != value >> 8 || tm->tm_sec != (value & 0xff))
+ goto retry;
+
+ return 0;
+}
+
+static int ntxec_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct ntxec_rtc *rtc = dev_get_drvdata(dev);
+
+ /*
+ * To avoid time overflows while we're writing the full date/time,
+ * set the seconds field to zero before doing anything else. For the
+ * next 59 seconds (plus however long it takes until the RTC's next
+ * update of the second field), the seconds field will not overflow
+ * into the other fields.
+ */
+ struct reg_sequence regs[] = {
+ { NTXEC_REG_WRITE_SECOND, ntxec_reg8(0) },
+ { NTXEC_REG_WRITE_YEAR, ntxec_reg8(tm->tm_year - 100) },
+ { NTXEC_REG_WRITE_MONTH, ntxec_reg8(tm->tm_mon + 1) },
+ { NTXEC_REG_WRITE_DAY, ntxec_reg8(tm->tm_mday) },
+ { NTXEC_REG_WRITE_HOUR, ntxec_reg8(tm->tm_hour) },
+ { NTXEC_REG_WRITE_MINUTE, ntxec_reg8(tm->tm_min) },
+ { NTXEC_REG_WRITE_SECOND, ntxec_reg8(tm->tm_sec) },
+ };
+
+ return regmap_multi_reg_write(rtc->ec->regmap, regs, ARRAY_SIZE(regs));
+}
+
+static const struct rtc_class_ops ntxec_rtc_ops = {
+ .read_time = ntxec_read_time,
+ .set_time = ntxec_set_time,
+};
+
+static int ntxec_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *dev;
+ struct ntxec_rtc *rtc;
+
+ pdev->dev.of_node = pdev->dev.parent->of_node;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->dev = &pdev->dev;
+ rtc->ec = dev_get_drvdata(pdev->dev.parent);
+ platform_set_drvdata(pdev, rtc);
+
+ dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
+ dev->ops = &ntxec_rtc_ops;
+ dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ dev->range_max = 9025257599LL; /* 2255-12-31 23:59:59 */
+
+ return devm_rtc_register_device(dev);
+}
+
+static struct platform_driver ntxec_rtc_driver = {
+ .driver = {
+ .name = "ntxec-rtc",
+ },
+ .probe = ntxec_rtc_probe,
+};
+module_platform_driver(ntxec_rtc_driver);
+
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("RTC driver for Netronix EC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ntxec-rtc");
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 28c04a4efa66..3a945abf268c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -63,7 +63,6 @@ void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
" Copyright IBM Corp. 2000");
-MODULE_SUPPORTED_DEVICE("dasd");
MODULE_LICENSE("GPL");
/*
@@ -3052,7 +3051,8 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx,
basedev = block->base;
spin_lock_irq(&dq->lock);
- if (basedev->state < DASD_STATE_READY) {
+ if (basedev->state < DASD_STATE_READY ||
+ test_bit(DASD_FLAG_OFFLINE, &basedev->flags)) {
DBF_DEV_EVENT(DBF_ERR, basedev,
"device not ready for request %p", req);
rc = BLK_STS_IOERR;
@@ -3487,8 +3487,6 @@ void dasd_generic_remove(struct ccw_device *cdev)
struct dasd_device *device;
struct dasd_block *block;
- cdev->handler = NULL;
-
device = dasd_device_from_cdev(cdev);
if (IS_ERR(device)) {
dasd_remove_sysfs_files(cdev);
@@ -3507,6 +3505,7 @@ void dasd_generic_remove(struct ccw_device *cdev)
* no quite down yet.
*/
dasd_set_target_state(device, DASD_STATE_NEW);
+ cdev->handler = NULL;
/* dasd_delete_device destroys the device reference. */
block = device->block;
dasd_delete_device(device);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 15692449a1c3..307a80f85c07 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -424,8 +424,10 @@ tty3270_update(struct timer_list *t)
* last output position matches the start address
* of this line.
*/
- if (s->string[1] == sba[0] && s->string[2] == sba[1])
- str += 3, len -= 3;
+ if (s->string[1] == sba[0] && s->string[2] == sba[1]) {
+ str += 3;
+ len -= 3;
+ }
if (raw3270_request_add_data(wrq, str, len) != 0)
break;
list_del_init(&s->update);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 1515fdc3c1ab..bd3c724bf695 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
+#include <linux/reboot.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
@@ -238,6 +239,28 @@ static int __init zcore_reipl_init(void)
return 0;
}
+static int zcore_reboot_and_on_panic_handler(struct notifier_block *self,
+ unsigned long event,
+ void *data)
+{
+ if (hsa_available)
+ release_hsa();
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block zcore_reboot_notifier = {
+ .notifier_call = zcore_reboot_and_on_panic_handler,
+ /* we need to be notified before reipl and kdump */
+ .priority = INT_MAX,
+};
+
+static struct notifier_block zcore_on_panic_notifier = {
+ .notifier_call = zcore_reboot_and_on_panic_handler,
+ /* we need to be notified before reipl and kdump */
+ .priority = INT_MAX,
+};
+
static int __init zcore_init(void)
{
unsigned char arch;
@@ -293,28 +316,15 @@ static int __init zcore_init(void)
goto fail;
zcore_dir = debugfs_create_dir("zcore" , NULL);
- if (!zcore_dir) {
- rc = -ENOMEM;
- goto fail;
- }
zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir,
NULL, &zcore_reipl_fops);
- if (!zcore_reipl_file) {
- rc = -ENOMEM;
- goto fail_dir;
- }
zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir,
NULL, &zcore_hsa_fops);
- if (!zcore_hsa_file) {
- rc = -ENOMEM;
- goto fail_reipl_file;
- }
- return 0;
-fail_reipl_file:
- debugfs_remove(zcore_reipl_file);
-fail_dir:
- debugfs_remove(zcore_dir);
+ register_reboot_notifier(&zcore_reboot_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list, &zcore_on_panic_notifier);
+
+ return 0;
fail:
diag308(DIAG308_REL_HSA, NULL);
return rc;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 6420b197bb05..05e136cfb8be 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -47,7 +47,7 @@ static void ccw_timeout_log(struct ccw_device *cdev)
orb = &private->orb;
cc = stsch(sch->schid, &schib);
- printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
+ printk(KERN_WARNING "cio: ccw device timeout occurred at %lx, "
"device information:\n", get_tod_clock());
printk(KERN_WARNING "cio: orb:\n");
print_hex_dump(KERN_WARNING, "cio: ", DUMP_PREFIX_NONE, 16, 1,
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 68106be4ba7a..767ac41686fe 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -543,7 +543,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
if (ret)
return ret;
- return copy_to_user((void __user *)arg, &info, minsz);
+ return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
case VFIO_DEVICE_GET_REGION_INFO:
{
@@ -561,7 +561,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
if (ret)
return ret;
- return copy_to_user((void __user *)arg, &info, minsz);
+ return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
case VFIO_DEVICE_GET_IRQ_INFO:
{
@@ -582,7 +582,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
if (info.count == -1)
return -EINVAL;
- return copy_to_user((void __user *)arg, &info, minsz);
+ return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
case VFIO_DEVICE_SET_IRQS:
{
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 41fc2e4135fe..1ffdd411201c 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -1286,7 +1286,7 @@ static int vfio_ap_mdev_get_device_info(unsigned long arg)
info.num_regions = 0;
info.num_irqs = 0;
- return copy_to_user((void __user *)arg, &info, minsz);
+ return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
}
static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index a1da83b0b0ef..91acff493612 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -436,7 +436,7 @@ struct qeth_qdio_out_buffer {
int is_header[QDIO_MAX_ELEMENTS_PER_BUFFER];
struct qeth_qdio_out_q *q;
- struct qeth_qdio_out_buffer *next_pending;
+ struct list_head list_entry;
};
struct qeth_card;
@@ -500,6 +500,7 @@ struct qeth_qdio_out_q {
struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qdio_outbuf_state *bufstates; /* convenience pointer */
+ struct list_head pending_bufs;
struct qeth_out_q_stats stats;
spinlock_t lock;
unsigned int priority;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index b71b8902d1c4..a814698387bc 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -73,8 +73,6 @@ static void qeth_free_qdio_queues(struct qeth_card *card);
static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
struct qeth_qdio_out_buffer *buf,
enum iucv_tx_notify notification);
-static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error,
- int budget);
static void qeth_close_dev_handler(struct work_struct *work)
{
@@ -465,41 +463,6 @@ static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
return n;
}
-static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx,
- int forced_cleanup)
-{
- if (q->card->options.cq != QETH_CQ_ENABLED)
- return;
-
- if (q->bufs[bidx]->next_pending != NULL) {
- struct qeth_qdio_out_buffer *head = q->bufs[bidx];
- struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending;
-
- while (c) {
- if (forced_cleanup ||
- atomic_read(&c->state) == QETH_QDIO_BUF_EMPTY) {
- struct qeth_qdio_out_buffer *f = c;
-
- QETH_CARD_TEXT(f->q->card, 5, "fp");
- QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f);
- /* release here to avoid interleaving between
- outbound tasklet and inbound tasklet
- regarding notifications and lifecycle */
- qeth_tx_complete_buf(c, forced_cleanup, 0);
-
- c = f->next_pending;
- WARN_ON_ONCE(head->next_pending != f);
- head->next_pending = c;
- kmem_cache_free(qeth_qdio_outbuf_cache, f);
- } else {
- head = c;
- c = c->next_pending;
- }
-
- }
- }
-}
-
static void qeth_qdio_handle_aob(struct qeth_card *card,
unsigned long phys_aob_addr)
{
@@ -507,6 +470,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
struct qaob *aob;
struct qeth_qdio_out_buffer *buffer;
enum iucv_tx_notify notification;
+ struct qeth_qdio_out_q *queue;
unsigned int i;
aob = (struct qaob *) phys_to_virt(phys_aob_addr);
@@ -537,7 +501,7 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
qeth_notify_skbs(buffer->q, buffer, notification);
/* Free dangling allocations. The attached skbs are handled by
- * qeth_cleanup_handled_pending().
+ * qeth_tx_complete_pending_bufs().
*/
for (i = 0;
i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card);
@@ -549,7 +513,9 @@ static void qeth_qdio_handle_aob(struct qeth_card *card,
buffer->is_header[i] = 0;
}
+ queue = buffer->q;
atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY);
+ napi_schedule(&queue->napi);
break;
default:
WARN_ON_ONCE(1);
@@ -1424,9 +1390,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error,
struct qeth_qdio_out_q *queue = buf->q;
struct sk_buff *skb;
- if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
- qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR);
-
/* Empty buffer? */
if (buf->next_element_to_fill == 0)
return;
@@ -1488,14 +1451,38 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
}
+static void qeth_tx_complete_pending_bufs(struct qeth_card *card,
+ struct qeth_qdio_out_q *queue,
+ bool drain)
+{
+ struct qeth_qdio_out_buffer *buf, *tmp;
+
+ list_for_each_entry_safe(buf, tmp, &queue->pending_bufs, list_entry) {
+ if (drain || atomic_read(&buf->state) == QETH_QDIO_BUF_EMPTY) {
+ QETH_CARD_TEXT(card, 5, "fp");
+ QETH_CARD_TEXT_(card, 5, "%lx", (long) buf);
+
+ if (drain)
+ qeth_notify_skbs(queue, buf,
+ TX_NOTIFY_GENERALERROR);
+ qeth_tx_complete_buf(buf, drain, 0);
+
+ list_del(&buf->list_entry);
+ kmem_cache_free(qeth_qdio_outbuf_cache, buf);
+ }
+ }
+}
+
static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free)
{
int j;
+ qeth_tx_complete_pending_bufs(q->card, q, true);
+
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
if (!q->bufs[j])
continue;
- qeth_cleanup_handled_pending(q, j, 1);
+
qeth_clear_output_buffer(q, q->bufs[j], true, 0);
if (free) {
kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]);
@@ -2615,7 +2602,6 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
skb_queue_head_init(&newbuf->skb_list);
lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
newbuf->q = q;
- newbuf->next_pending = q->bufs[bidx];
atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY);
q->bufs[bidx] = newbuf;
return 0;
@@ -2634,15 +2620,28 @@ static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
static struct qeth_qdio_out_q *qeth_alloc_output_queue(void)
{
struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+ unsigned int i;
if (!q)
return NULL;
- if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
- kfree(q);
- return NULL;
+ if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q))
+ goto err_qdio_bufs;
+
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
+ if (qeth_init_qdio_out_buf(q, i))
+ goto err_out_bufs;
}
+
return q;
+
+err_out_bufs:
+ while (i > 0)
+ kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[--i]);
+ qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+err_qdio_bufs:
+ kfree(q);
+ return NULL;
}
static void qeth_tx_completion_timer(struct timer_list *timer)
@@ -2655,7 +2654,7 @@ static void qeth_tx_completion_timer(struct timer_list *timer)
static int qeth_alloc_qdio_queues(struct qeth_card *card)
{
- int i, j;
+ unsigned int i;
QETH_CARD_TEXT(card, 2, "allcqdbf");
@@ -2684,18 +2683,12 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
card->qdio.out_qs[i] = queue;
queue->card = card;
queue->queue_no = i;
+ INIT_LIST_HEAD(&queue->pending_bufs);
spin_lock_init(&queue->lock);
timer_setup(&queue->timer, qeth_tx_completion_timer, 0);
queue->coalesce_usecs = QETH_TX_COALESCE_USECS;
queue->max_coalesced_frames = QETH_TX_MAX_COALESCED_FRAMES;
queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT;
-
- /* give outbound qeth_qdio_buffers their qdio_buffers */
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
- WARN_ON(queue->bufs[j]);
- if (qeth_init_qdio_out_buf(queue, j))
- goto out_freeoutqbufs;
- }
}
/* completion */
@@ -2704,13 +2697,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
return 0;
-out_freeoutqbufs:
- while (j > 0) {
- --j;
- kmem_cache_free(qeth_qdio_outbuf_cache,
- card->qdio.out_qs[i]->bufs[j]);
- card->qdio.out_qs[i]->bufs[j] = NULL;
- }
out_freeoutq:
while (i > 0) {
qeth_free_output_queue(card->qdio.out_qs[--i]);
@@ -6107,6 +6093,8 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue,
qeth_schedule_recovery(card);
}
+ list_add(&buffer->list_entry,
+ &queue->pending_bufs);
/* Skip clearing the buffer: */
return;
case QETH_QDIO_BUF_QAOB_OK:
@@ -6162,6 +6150,8 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget)
unsigned int bytes = 0;
int completed;
+ qeth_tx_complete_pending_bufs(card, queue, false);
+
if (qeth_out_queue_is_empty(queue)) {
napi_complete(napi);
return 0;
@@ -6194,7 +6184,6 @@ static int qeth_tx_poll(struct napi_struct *napi, int budget)
qeth_handle_send_error(card, buffer, error);
qeth_iqd_tx_complete(queue, bidx, error, budget);
- qeth_cleanup_handled_pending(queue, bidx, false);
}
netdev_tx_completed_queue(txq, packets, bytes);
@@ -7249,9 +7238,7 @@ int qeth_open(struct net_device *dev)
card->data.state = CH_STATE_UP;
netif_tx_start_all_queues(dev);
- napi_enable(&card->napi);
local_bh_disable();
- napi_schedule(&card->napi);
if (IS_IQD(card)) {
struct qeth_qdio_out_q *queue;
unsigned int i;
@@ -7263,8 +7250,12 @@ int qeth_open(struct net_device *dev)
napi_schedule(&queue->napi);
}
}
+
+ napi_enable(&card->napi);
+ napi_schedule(&card->napi);
/* kick-start the NAPI softirq: */
local_bh_enable();
+
return 0;
}
EXPORT_SYMBOL_GPL(qeth_open);
@@ -7274,6 +7265,11 @@ int qeth_stop(struct net_device *dev)
struct qeth_card *card = dev->ml_priv;
QETH_CARD_TEXT(card, 4, "qethstop");
+
+ napi_disable(&card->napi);
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
+ qdio_stop_irq(CARD_DDEV(card));
+
if (IS_IQD(card)) {
struct qeth_qdio_out_q *queue;
unsigned int i;
@@ -7294,10 +7290,6 @@ int qeth_stop(struct net_device *dev)
netif_tx_disable(dev);
}
- napi_disable(&card->napi);
- cancel_delayed_work_sync(&card->buffer_reclaim_work);
- qdio_stop_irq(CARD_DDEV(card));
-
return 0;
}
EXPORT_SYMBOL_GPL(qeth_stop);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 00e72b97d0b6..d93595b39afa 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(sol_compat,
MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
MODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("d7s");
struct d7s {
void __iomem *regs;
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 38369766511c..f135a10f582b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -80,7 +80,6 @@
MODULE_AUTHOR("Hewlett-Packard Company");
MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \
HPSA_DRIVER_VERSION);
-MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
MODULE_VERSION(HPSA_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("cciss");
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 755313b766b9..f140eafc0d6a 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -21,6 +21,7 @@
#include <linux/bsg-lib.h>
#include <asm/firmware.h>
#include <asm/irq.h>
+#include <asm/rtas.h>
#include <asm/vio.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -158,6 +159,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *);
static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *);
static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
+static void ibmvfc_release_sub_crqs(struct ibmvfc_host *);
+static void ibmvfc_init_sub_crqs(struct ibmvfc_host *);
+
static const char *unknown_error = "unknown error";
static long h_reg_sub_crq(unsigned long unit_address, unsigned long ioba,
@@ -899,6 +903,9 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
{
int rc = 0;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
+ unsigned long flags;
+
+ ibmvfc_release_sub_crqs(vhost);
/* Re-enable the CRQ */
do {
@@ -910,6 +917,15 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
if (rc)
dev_err(vhost->dev, "Error enabling adapter (rc=%d)\n", rc);
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock(vhost->crq.q_lock);
+ vhost->do_enquiry = 1;
+ vhost->using_channels = 0;
+ spin_unlock(vhost->crq.q_lock);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+
+ ibmvfc_init_sub_crqs(vhost);
+
return rc;
}
@@ -926,8 +942,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
unsigned long flags;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_queue *crq = &vhost->crq;
- struct ibmvfc_queue *scrq;
- int i;
+
+ ibmvfc_release_sub_crqs(vhost);
/* Close the CRQ */
do {
@@ -947,16 +963,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
memset(crq->msgs.crq, 0, PAGE_SIZE);
crq->cur = 0;
- if (vhost->scsi_scrqs.scrqs) {
- for (i = 0; i < nr_scsi_hw_queues; i++) {
- scrq = &vhost->scsi_scrqs.scrqs[i];
- spin_lock(scrq->q_lock);
- memset(scrq->msgs.scrq, 0, PAGE_SIZE);
- scrq->cur = 0;
- spin_unlock(scrq->q_lock);
- }
- }
-
/* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
crq->msg_token, PAGE_SIZE);
@@ -966,9 +972,12 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
dev_warn(vhost->dev, "Partner adapter not ready\n");
else if (rc != 0)
dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc);
+
spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_init_sub_crqs(vhost);
+
return rc;
}
@@ -5642,7 +5651,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE,
&scrq->cookie, &scrq->hw_irq);
- if (rc) {
+ /* H_CLOSED indicates successful register, but no CRQ partner */
+ if (rc && rc != H_CLOSED) {
dev_warn(dev, "Error registering sub-crq: %d\n", rc);
if (rc == H_PARAMETER)
dev_warn_once(dev, "Firmware may not support MQ\n");
@@ -5675,8 +5685,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
irq_failed:
do {
- plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie);
- } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+ rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie);
+ } while (rtas_busy_delay(rc));
reg_failed:
ibmvfc_free_queue(vhost, scrq);
LEAVE;
@@ -5694,6 +5704,7 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
free_irq(scrq->irq, scrq);
irq_dispose_mapping(scrq->irq);
+ scrq->irq = 0;
do {
rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,
@@ -5707,17 +5718,21 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
LEAVE;
}
-static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
+static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
{
int i, j;
ENTER;
+ if (!vhost->mq_enabled)
+ return;
vhost->scsi_scrqs.scrqs = kcalloc(nr_scsi_hw_queues,
sizeof(*vhost->scsi_scrqs.scrqs),
GFP_KERNEL);
- if (!vhost->scsi_scrqs.scrqs)
- return -1;
+ if (!vhost->scsi_scrqs.scrqs) {
+ vhost->do_enquiry = 0;
+ return;
+ }
for (i = 0; i < nr_scsi_hw_queues; i++) {
if (ibmvfc_register_scsi_channel(vhost, i)) {
@@ -5726,13 +5741,12 @@ static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
kfree(vhost->scsi_scrqs.scrqs);
vhost->scsi_scrqs.scrqs = NULL;
vhost->scsi_scrqs.active_queues = 0;
- LEAVE;
- return -1;
+ vhost->do_enquiry = 0;
+ break;
}
}
LEAVE;
- return 0;
}
static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost)
@@ -5770,6 +5784,8 @@ static void ibmvfc_free_mem(struct ibmvfc_host *vhost)
vhost->disc_buf_dma);
dma_free_coherent(vhost->dev, sizeof(*vhost->login_buf),
vhost->login_buf, vhost->login_buf_dma);
+ dma_free_coherent(vhost->dev, sizeof(*vhost->channel_setup_buf),
+ vhost->channel_setup_buf, vhost->channel_setup_dma);
dma_pool_destroy(vhost->sg_pool);
ibmvfc_free_queue(vhost, async_q);
LEAVE;
@@ -5999,11 +6015,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
goto remove_shost;
}
- if (vhost->mq_enabled) {
- rc = ibmvfc_init_sub_crqs(vhost);
- if (rc)
- dev_warn(dev, "Failed to allocate Sub-CRQs. rc=%d\n", rc);
- }
+ ibmvfc_init_sub_crqs(vhost);
if (shost_to_fc_host(shost)->rqst_q)
blk_queue_max_segments(shost_to_fc_host(shost)->rqst_q, 1);
@@ -6038,7 +6050,7 @@ out:
* Return value:
* 0
**/
-static int ibmvfc_remove(struct vio_dev *vdev)
+static void ibmvfc_remove(struct vio_dev *vdev)
{
struct ibmvfc_host *vhost = dev_get_drvdata(&vdev->dev);
LIST_HEAD(purge);
@@ -6070,7 +6082,6 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_unlock(&ibmvfc_driver_lock);
scsi_host_put(vhost->host);
LEAVE;
- return 0;
}
/**
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 29fcc44be2d5..77fafb1bc173 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -2335,7 +2335,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
return -1;
}
-static int ibmvscsi_remove(struct vio_dev *vdev)
+static void ibmvscsi_remove(struct vio_dev *vdev)
{
struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev);
@@ -2356,8 +2356,6 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
spin_unlock(&ibmvscsi_driver_lock);
scsi_host_put(hostdata->host);
-
- return 0;
}
/**
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index cc3908c2d2f9..9abd9e253af6 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -3595,7 +3595,7 @@ free_adapter:
return rc;
}
-static int ibmvscsis_remove(struct vio_dev *vdev)
+static void ibmvscsis_remove(struct vio_dev *vdev)
{
struct scsi_info *vscsi = dev_get_drvdata(&vdev->dev);
@@ -3622,8 +3622,6 @@ static int ibmvscsis_remove(struct vio_dev *vdev)
list_del(&vscsi->list);
spin_unlock_bh(&ibmvscsis_dev_lock);
kfree(vscsi);
-
- return 0;
}
static ssize_t system_id_show(struct device *dev,
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index bc79a017e1a2..46a8f2d1d2b8 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2421,7 +2421,7 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
memset(dstbuf, 0, 33);
size = (nbytes < 32) ? nbytes : 32;
if (copy_from_user(dstbuf, buf, size))
- return 0;
+ return -EFAULT;
if (dent == phba->debug_InjErrLBA) {
if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
@@ -2430,7 +2430,7 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
}
if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
- return 0;
+ return -EINVAL;
if (dent == phba->debug_writeGuard)
phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index ffca03064797..6aa6de729187 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -413,7 +413,7 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc,
* And add this object to port_table_list.
*/
if (!ioc->multipath_on_hba) {
- port = kzalloc(sizeof(struct hba_port), GFP_KERNEL);
+ port = kzalloc(sizeof(struct hba_port), GFP_ATOMIC);
if (!port)
return NULL;
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index 4adf9ded296a..329fd025c718 100644
--- a/drivers/scsi/myrs.c
+++ b/drivers/scsi/myrs.c
@@ -2273,12 +2273,12 @@ static void myrs_cleanup(struct myrs_hba *cs)
if (cs->mmio_base) {
cs->disable_intr(cs);
iounmap(cs->mmio_base);
+ cs->mmio_base = NULL;
}
if (cs->irq)
free_irq(cs->irq, cs);
if (cs->io_addr)
release_region(cs->io_addr, 0x80);
- iounmap(cs->mmio_base);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
scsi_host_put(cs->host);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 5d5f50d6a02d..ac89002646a3 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -55,7 +55,6 @@
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
-MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
MODULE_LICENSE("GPL");
#include "nsp_io.h"
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 10e5e6c8087d..01620f3eab39 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -116,7 +116,6 @@
(min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \
QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0))
#endif
-#endif
#define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \
? le16_to_cpu((iocb)->u.isp2x.target.extended) \
@@ -244,6 +243,7 @@ struct ctio_to_2xxx {
#ifndef CTIO_RET_TYPE
#define CTIO_RET_TYPE 0x17 /* CTIO return entry */
#define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */
+#endif
struct fcp_hdr {
uint8_t r_ctl;
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index ee558675eab4..994f1b8e3504 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -280,27 +280,28 @@ static int sd_zbc_update_wp_offset_cb(struct blk_zone *zone, unsigned int idx,
static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
{
struct scsi_disk *sdkp;
+ unsigned long flags;
unsigned int zno;
int ret;
sdkp = container_of(work, struct scsi_disk, zone_wp_offset_work);
- spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
for (zno = 0; zno < sdkp->nr_zones; zno++) {
if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
continue;
- spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf,
SD_BUF_SIZE,
zno * sdkp->zone_blocks, true);
- spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
if (!ret)
sd_zbc_parse_report(sdkp, sdkp->zone_wp_update_buf + 64,
zno, sd_zbc_update_wp_offset_cb,
sdkp);
}
- spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
scsi_device_put(sdkp->device);
}
@@ -324,6 +325,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
struct request *rq = cmd->request;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
unsigned int wp_offset, zno = blk_rq_zone_no(rq);
+ unsigned long flags;
blk_status_t ret;
ret = sd_zbc_cmnd_checks(cmd);
@@ -337,7 +339,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
if (!blk_req_zone_write_trylock(rq))
return BLK_STS_ZONE_RESOURCE;
- spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
wp_offset = sdkp->zones_wp_offset[zno];
switch (wp_offset) {
case SD_ZBC_INVALID_WP_OFST:
@@ -366,7 +368,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
*lba += wp_offset;
}
- spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
if (ret)
blk_req_zone_write_unlock(rq);
return ret;
@@ -445,6 +447,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
unsigned int zno = blk_rq_zone_no(rq);
enum req_opf op = req_op(rq);
+ unsigned long flags;
/*
* If we got an error for a command that needs updating the write
@@ -452,7 +455,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
* invalid to force an update from disk the next time a zone append
* command is issued.
*/
- spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
if (result && op != REQ_OP_ZONE_RESET_ALL) {
if (op == REQ_OP_ZONE_APPEND) {
@@ -496,7 +499,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
}
unlock_wp_offset:
- spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
return good_bytes;
}
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index c53f456fbd09..a1dacb6e993e 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -48,7 +48,6 @@
MODULE_AUTHOR("Microsemi");
MODULE_DESCRIPTION("Driver for Microsemi Smart Family Controller version "
DRIVER_VERSION);
-MODULE_SUPPORTED_DEVICE("Microsemi Smart Family Controllers");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 841ad2fc369a..9ca536aae784 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -1269,8 +1269,8 @@ static int st_open(struct inode *inode, struct file *filp)
spin_lock(&st_use_lock);
if (STp->in_use) {
spin_unlock(&st_use_lock);
- scsi_tape_put(STp);
DEBC_printk(STp, "Device already in use.\n");
+ scsi_tape_put(STp);
return (-EBUSY);
}
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index c55202b92a43..a981f261b304 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -911,7 +911,7 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc)
return;
- if (lpm & !hba->vreg_info.vcc->enabled)
+ if (lpm && !hba->vreg_info.vcc->enabled)
regulator_set_mode(hba->vreg_info.vccq2->reg,
REGULATOR_MODE_IDLE);
else if (!lpm)
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index f97d7b0ae3b6..a9dc8d7c9f78 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -253,12 +253,17 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba)
{
int ret = 0;
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ bool reenable_intr = false;
if (!host->core_reset) {
dev_warn(hba->dev, "%s: reset control not set\n", __func__);
goto out;
}
+ reenable_intr = hba->is_irq_enabled;
+ disable_irq(hba->irq);
+ hba->is_irq_enabled = false;
+
ret = reset_control_assert(host->core_reset);
if (ret) {
dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
@@ -280,6 +285,11 @@ static int ufs_qcom_host_reset(struct ufs_hba *hba)
usleep_range(1000, 1100);
+ if (reenable_intr) {
+ enable_irq(hba->irq);
+ hba->is_irq_enabled = true;
+ }
+
out:
return ret;
}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 77161750c9fb..c86760788c72 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -95,8 +95,6 @@
16, 4, buf, __len, false); \
} while (0)
-static bool early_suspend;
-
int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
const char *prefix)
{
@@ -1535,7 +1533,7 @@ static ssize_t ufshcd_clkscale_enable_show(struct device *dev,
{
struct ufs_hba *hba = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", hba->clk_scaling.is_enabled);
+ return sysfs_emit(buf, "%d\n", hba->clk_scaling.is_enabled);
}
static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
@@ -4987,6 +4985,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
* UFS device needs urgent BKOPs.
*/
if (!hba->pm_op_in_progress &&
+ !ufshcd_eh_in_progress(hba) &&
ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&
schedule_work(&hba->eeh_work)) {
/*
@@ -5784,13 +5783,20 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
ufshcd_suspend_clkscaling(hba);
ufshcd_clk_scaling_allow(hba, false);
}
+ ufshcd_scsi_block_requests(hba);
+ /* Drain ufshcd_queuecommand() */
+ down_write(&hba->clk_scaling_lock);
+ up_write(&hba->clk_scaling_lock);
+ cancel_work_sync(&hba->eeh_work);
}
static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
{
+ ufshcd_scsi_unblock_requests(hba);
ufshcd_release(hba);
if (ufshcd_is_clkscaling_supported(hba))
ufshcd_clk_scaling_suspend(hba, false);
+ ufshcd_clear_ua_wluns(hba);
pm_runtime_put(hba->dev);
}
@@ -5882,8 +5888,8 @@ static void ufshcd_err_handler(struct work_struct *work)
spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_err_handling_prepare(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_scsi_block_requests(hba);
- hba->ufshcd_state = UFSHCD_STATE_RESET;
+ if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
+ hba->ufshcd_state = UFSHCD_STATE_RESET;
/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);
@@ -6042,12 +6048,8 @@ skip_err_handling:
}
ufshcd_clear_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
- ufshcd_scsi_unblock_requests(hba);
ufshcd_err_handling_unprepare(hba);
up(&hba->host_sem);
-
- if (!err && needs_reset)
- ufshcd_clear_ua_wluns(hba);
}
/**
@@ -7858,6 +7860,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
unsigned long flags;
ktime_t start = ktime_get();
+ hba->ufshcd_state = UFSHCD_STATE_RESET;
+
ret = ufshcd_link_startup(hba);
if (ret)
goto out;
@@ -8972,11 +8976,6 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
int ret = 0;
ktime_t start = ktime_get();
- if (!hba) {
- early_suspend = true;
- return 0;
- }
-
down(&hba->host_sem);
if (!hba->is_powered)
@@ -9028,14 +9027,6 @@ int ufshcd_system_resume(struct ufs_hba *hba)
int ret = 0;
ktime_t start = ktime_get();
- if (!hba)
- return -EINVAL;
-
- if (unlikely(early_suspend)) {
- early_suspend = false;
- down(&hba->host_sem);
- }
-
if (!hba->is_powered || pm_runtime_suspended(hba->dev))
/*
* Let the runtime resume take care of resuming
@@ -9068,9 +9059,6 @@ int ufshcd_runtime_suspend(struct ufs_hba *hba)
int ret = 0;
ktime_t start = ktime_get();
- if (!hba)
- return -EINVAL;
-
if (!hba->is_powered)
goto out;
else
@@ -9109,9 +9097,6 @@ int ufshcd_runtime_resume(struct ufs_hba *hba)
int ret = 0;
ktime_t start = ktime_get();
- if (!hba)
- return -EINVAL;
-
if (!hba->is_powered)
goto out;
else
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 081f54ab7d86..8a79605d9652 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * Maintained by: Jim Gill <jgill@vmware.com>
- *
*/
#include <linux/kernel.h>
diff --git a/drivers/scsi/vmw_pvscsi.h b/drivers/scsi/vmw_pvscsi.h
index 75966d3f326e..51a82f7803d3 100644
--- a/drivers/scsi/vmw_pvscsi.h
+++ b/drivers/scsi/vmw_pvscsi.h
@@ -17,8 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * Maintained by: Jim Gill <jgill@vmware.com>
- *
*/
#ifndef _VMW_PVSCSI_H_
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index e5d7fb81ad66..bd0fbcdbdefe 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -30,7 +30,6 @@
MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}");
static void maple_dma_handler(struct work_struct *work);
static void maple_vblank_handler(struct work_struct *work);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 442cc7c53a47..52ddb3255d88 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -1433,6 +1433,7 @@ static int cqspi_probe(struct platform_device *pdev)
cqspi = spi_master_get_devdata(master);
cqspi->pdev = pdev;
+ platform_set_drvdata(pdev, cqspi);
/* Obtain configuration from OF. */
ret = cqspi_of_get_pdata(cqspi);
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index 35b75f0c9200..81a246fbcc01 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -260,6 +260,7 @@ static irqreturn_t apci1032_interrupt(int irq, void *d)
struct apci1032_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int ctrl;
+ unsigned short val;
/* check interrupt is from this device */
if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
@@ -275,7 +276,8 @@ static irqreturn_t apci1032_interrupt(int irq, void *d)
outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG);
s->state = inl(dev->iobase + APCI1032_STATUS_REG) & 0xffff;
- comedi_buf_write_samples(s, &s->state, 1);
+ val = s->state;
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
/* enable the interrupt */
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index 11efb21555e3..b04c15dcfb57 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -208,7 +208,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct apci1500_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- unsigned int status = 0;
+ unsigned short status = 0;
unsigned int val;
val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
@@ -238,14 +238,14 @@ static irqreturn_t apci1500_interrupt(int irq, void *d)
*
* Mask Meaning
* ---------- ------------------------------------------
- * 0x00000001 Event 1 has occurred
- * 0x00000010 Event 2 has occurred
- * 0x00000100 Counter/timer 1 has run down (not implemented)
- * 0x00001000 Counter/timer 2 has run down (not implemented)
- * 0x00010000 Counter 3 has run down (not implemented)
- * 0x00100000 Watchdog has run down (not implemented)
- * 0x01000000 Voltage error
- * 0x10000000 Short-circuit error
+ * 0b00000001 Event 1 has occurred
+ * 0b00000010 Event 2 has occurred
+ * 0b00000100 Counter/timer 1 has run down (not implemented)
+ * 0b00001000 Counter/timer 2 has run down (not implemented)
+ * 0b00010000 Counter 3 has run down (not implemented)
+ * 0b00100000 Watchdog has run down (not implemented)
+ * 0b01000000 Voltage error
+ * 0b10000000 Short-circuit error
*/
comedi_buf_write_samples(s, &status, 1);
comedi_handle_events(dev, s);
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 692893c7e5c3..090607760be6 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -300,11 +300,11 @@ static int pci1710_ai_eoc(struct comedi_device *dev,
static int pci1710_ai_read_sample(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int cur_chan,
- unsigned int *val)
+ unsigned short *val)
{
const struct boardtype *board = dev->board_ptr;
struct pci1710_private *devpriv = dev->private;
- unsigned int sample;
+ unsigned short sample;
unsigned int chan;
sample = inw(dev->iobase + PCI171X_AD_DATA_REG);
@@ -345,7 +345,7 @@ static int pci1710_ai_insn_read(struct comedi_device *dev,
pci1710_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1);
for (i = 0; i < insn->n; i++) {
- unsigned int val;
+ unsigned short val;
/* start conversion */
outw(0, dev->iobase + PCI171X_SOFTTRG_REG);
@@ -395,7 +395,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev,
{
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int status;
- unsigned int val;
+ unsigned short val;
int ret;
status = inw(dev->iobase + PCI171X_STATUS_REG);
@@ -455,7 +455,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev,
}
for (i = 0; i < devpriv->max_samples; i++) {
- unsigned int val;
+ unsigned short val;
int ret;
ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val);
diff --git a/drivers/staging/comedi/drivers/amplc_pc236_common.c b/drivers/staging/comedi/drivers/amplc_pc236_common.c
index 043752663188..981d281e87a1 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236_common.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236_common.c
@@ -126,7 +126,9 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
handled = pc236_intr_check(dev);
if (dev->attached && handled) {
- comedi_buf_write_samples(s, &s->state, 1);
+ unsigned short val = 0;
+
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
}
return IRQ_RETVAL(handled);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index d740c4782775..2f20bd56ec6c 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -1281,7 +1281,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
devpriv->amcc + AMCC_OP_REG_INTCSR);
ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
- dev->board_name, dev);
+ "cb_pcidas", dev);
if (ret) {
dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
pcidev->irq);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index fa987bb0e7cd..6d3ba399a7f0 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -4035,7 +4035,7 @@ static int auto_attach(struct comedi_device *dev,
init_stc_registers(dev);
retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
- dev->board_name, dev);
+ "cb_pcidas64", dev);
if (retval) {
dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
pcidev->irq);
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index 9361b2dcf949..5338b5eea440 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -210,12 +210,13 @@ static irqreturn_t parport_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int ctrl;
+ unsigned short val = 0;
ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
return IRQ_NONE;
- comedi_buf_write_samples(s, &s->state, 1);
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
return IRQ_HANDLED;
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index 04e224f8b779..96f4107b8054 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -186,7 +186,7 @@ static irqreturn_t das6402_interrupt(int irq, void *d)
if (status & DAS6402_STATUS_FFULL) {
async->events |= COMEDI_CB_OVERFLOW;
} else if (status & DAS6402_STATUS_FFNE) {
- unsigned int val;
+ unsigned short val;
val = das6402_ai_read_sample(dev, s);
comedi_buf_write_samples(s, &val, 1);
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 4ea100ff6930..2881808d6606 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -427,7 +427,7 @@ static irqreturn_t das800_interrupt(int irq, void *d)
struct comedi_cmd *cmd;
unsigned long irq_flags;
unsigned int status;
- unsigned int val;
+ unsigned short val;
bool fifo_empty;
bool fifo_overflow;
int i;
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 17e6018918bb..56682f01242f 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -404,7 +404,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d)
{
struct comedi_device *dev = d;
unsigned char intstat;
- unsigned int val;
+ unsigned short val;
int i;
if (!dev->attached) {
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 726e40dc17b6..0d3d4cafce2e 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -924,7 +924,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
struct comedi_subdevice *s = dev->read_subdev;
int i;
int c = 0;
- unsigned int lval;
+ unsigned short lval;
if (!dev->attached)
return IRQ_NONE;
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index 99e744172f4d..f1a45cf7342a 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -195,7 +195,9 @@ static irqreturn_t ni6527_interrupt(int irq, void *d)
return IRQ_NONE;
if (status & NI6527_STATUS_EDGE) {
- comedi_buf_write_samples(s, &s->state, 1);
+ unsigned short val = 0;
+
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
}
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index eb3f9f7109da..7cd8497420f2 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -472,6 +472,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int status;
+ unsigned short val = 0;
status = readb(dev->mmio + NI_65XX_STATUS_REG);
if ((status & NI_65XX_STATUS_INT) == 0)
@@ -482,7 +483,7 @@ static irqreturn_t ni_65xx_interrupt(int irq, void *d)
writeb(NI_65XX_CLR_EDGE_INT | NI_65XX_CLR_OVERFLOW_INT,
dev->mmio + NI_65XX_CLR_REG);
- comedi_buf_write_samples(s, &s->state, 1);
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
return IRQ_HANDLED;
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 2dbf69e30965..bd6f42fe9e3c 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -184,7 +184,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d)
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int data;
+ unsigned short data;
if (!dev->attached) {
dev_err(dev->class_dev, "spurious interrupt\n");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index 64eb649c9813..88f25d7e76f7 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -220,9 +220,11 @@ static irqreturn_t pcl726_interrupt(int irq, void *d)
struct pcl726_private *devpriv = dev->private;
if (devpriv->cmd_running) {
+ unsigned short val = 0;
+
pcl726_intr_cancel(dev, s);
- comedi_buf_write_samples(s, &s->state, 1);
+ comedi_buf_write_samples(s, &val, 1);
comedi_handle_events(dev, s);
}
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 63e3011158f2..f4b4a686c710 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -423,7 +423,7 @@ static int pcl818_ai_eoc(struct comedi_device *dev,
static bool pcl818_ai_write_sample(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int chan, unsigned int val)
+ unsigned int chan, unsigned short val)
{
struct pcl818_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 7956abcbae22..9f920819cd74 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -877,5 +877,4 @@ module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver);
MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
-MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c
index dc09cc6e1c47..09e7b4cd0138 100644
--- a/drivers/staging/ks7010/ks_wlan_net.c
+++ b/drivers/staging/ks7010/ks_wlan_net.c
@@ -1120,6 +1120,7 @@ static int ks_wlan_set_scan(struct net_device *dev,
{
struct ks_wlan_private *priv = netdev_priv(dev);
struct iw_scan_req *req = NULL;
+ int len;
if (priv->sleep_mode == SLP_SLEEP)
return -EPERM;
@@ -1129,8 +1130,9 @@ static int ks_wlan_set_scan(struct net_device *dev,
if (wrqu->data.length == sizeof(struct iw_scan_req) &&
wrqu->data.flags & IW_SCAN_THIS_ESSID) {
req = (struct iw_scan_req *)extra;
- priv->scan_ssid_len = req->essid_len;
- memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
+ len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
+ priv->scan_ssid_len = len;
+ memcpy(priv->scan_ssid, req->essid, len);
} else {
priv->scan_ssid_len = 0;
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index fa1e34a0d456..182bb944c9b3 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -791,6 +791,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SSID, &ie_len,
pbss_network->ie_length - _BEACON_IE_OFFSET_);
if (p && ie_len > 0) {
+ ie_len = min_t(int, ie_len, sizeof(pbss_network->ssid.ssid));
memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
memcpy(pbss_network->ssid.ssid, p + 2, ie_len);
pbss_network->ssid.ssid_length = ie_len;
@@ -811,6 +812,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_SUPP_RATES, &ie_len,
pbss_network->ie_length - _BEACON_IE_OFFSET_);
if (p) {
+ ie_len = min_t(int, ie_len, NDIS_802_11_LENGTH_RATES_EX);
memcpy(supportRate, p + 2, ie_len);
supportRateNum = ie_len;
}
@@ -819,6 +821,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES,
&ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);
if (p) {
+ ie_len = min_t(int, ie_len,
+ NDIS_802_11_LENGTH_RATES_EX - supportRateNum);
memcpy(supportRate + supportRateNum, p + 2, ie_len);
supportRateNum += ie_len;
}
@@ -934,6 +938,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
pht_cap->mcs.rx_mask[0] = 0xff;
pht_cap->mcs.rx_mask[1] = 0x0;
+ ie_len = min_t(int, ie_len, sizeof(pmlmepriv->htpriv.ht_cap));
memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
}
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index bf22f130d3e1..58954b88a817 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -1133,9 +1133,11 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
break;
}
sec_len = *(pos++); len -= 1;
- if (sec_len > 0 && sec_len <= len) {
+ if (sec_len > 0 &&
+ sec_len <= len &&
+ sec_len <= 32) {
ssid[ssid_index].ssid_length = sec_len;
- memcpy(ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length);
+ memcpy(ssid[ssid_index].ssid, pos, sec_len);
ssid_index++;
}
pos += sec_len;
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig
index 963a2ffbc1fb..39f5a6a7346a 100644
--- a/drivers/staging/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/Kconfig
@@ -27,6 +27,7 @@ config RTLLIB_CRYPTO_CCMP
config RTLLIB_CRYPTO_TKIP
tristate "Support for rtllib TKIP crypto"
depends on RTLLIB
+ select CRYPTO
select CRYPTO_LIB_ARC4
select CRYPTO_MICHAEL_MIC
default y
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index 16bcee13f64b..407effde5e71 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -406,9 +406,10 @@ static int _rtl92e_wx_set_scan(struct net_device *dev,
struct iw_scan_req *req = (struct iw_scan_req *)b;
if (req->essid_len) {
- ieee->current_network.ssid_len = req->essid_len;
- memcpy(ieee->current_network.ssid, req->essid,
- req->essid_len);
+ int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
+
+ ieee->current_network.ssid_len = len;
+ memcpy(ieee->current_network.ssid, req->essid, len);
}
}
diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c
index d853586705fc..77bf88696a84 100644
--- a/drivers/staging/rtl8192u/r8192U_wx.c
+++ b/drivers/staging/rtl8192u/r8192U_wx.c
@@ -331,8 +331,10 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
struct iw_scan_req *req = (struct iw_scan_req *)b;
if (req->essid_len) {
- ieee->current_network.ssid_len = req->essid_len;
- memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
+ int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
+
+ ieee->current_network.ssid_len = len;
+ memcpy(ieee->current_network.ssid, req->essid, len);
}
}
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index 18116469bd31..75716f59044d 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -192,8 +192,10 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
psurveyPara->ss_ssidlen = 0;
memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
if (pssid && pssid->SsidLength) {
- memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength);
- psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength);
+ int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE);
+
+ memcpy(psurveyPara->ss_ssid, pssid->Ssid, len);
+ psurveyPara->ss_ssidlen = cpu_to_le32(len);
}
set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
r8712_enqueue_cmd(pcmdpriv, ph2c);
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index 81de5a9e6b67..60dd798a6e51 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -924,7 +924,7 @@ static int r871x_wx_set_priv(struct net_device *dev,
struct iw_point *dwrq = (struct iw_point *)awrq;
len = dwrq->length;
- ext = memdup_user(dwrq->pointer, len);
+ ext = strndup_user(dwrq->pointer, len);
if (IS_ERR(ext))
return PTR_ERR(ext);
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
index e7061d383306..c3c2c1566882 100644
--- a/drivers/staging/vt6655/rxtx.h
+++ b/drivers/staging/vt6655/rxtx.h
@@ -150,7 +150,7 @@ struct vnt_cts {
u16 reserved;
struct ieee80211_cts data;
u16 reserved2;
-} __packed;
+} __packed __aligned(2);
struct vnt_cts_fb {
struct vnt_phy_field b;
@@ -160,7 +160,7 @@ struct vnt_cts_fb {
__le16 cts_duration_ba_f1;
struct ieee80211_cts data;
u16 reserved2;
-} __packed;
+} __packed __aligned(2);
struct vnt_tx_fifo_head {
u8 tx_key[WLAN_KEY_LEN_CCMP];
diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c
index cd6bcfdfbe9a..ed53d0b45592 100644
--- a/drivers/staging/wfx/bh.c
+++ b/drivers/staging/wfx/bh.c
@@ -5,6 +5,7 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/gpio/consumer.h>
#include <net/mac80211.h>
#include "bh.h"
diff --git a/drivers/staging/wfx/bh.h b/drivers/staging/wfx/bh.h
index 92ef3298d4ac..78c49329e22a 100644
--- a/drivers/staging/wfx/bh.h
+++ b/drivers/staging/wfx/bh.h
@@ -8,6 +8,10 @@
#ifndef WFX_BH_H
#define WFX_BH_H
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
struct wfx_dev;
struct wfx_hif {
diff --git a/drivers/staging/wfx/bus.h b/drivers/staging/wfx/bus.h
index ea3911485307..ca04b3da6204 100644
--- a/drivers/staging/wfx/bus.h
+++ b/drivers/staging/wfx/bus.h
@@ -8,6 +8,9 @@
#ifndef WFX_BUS_H
#define WFX_BUS_H
+#include <linux/mmc/sdio_func.h>
+#include <linux/spi/spi.h>
+
#define WFX_REG_CONFIG 0x0
#define WFX_REG_CONTROL 0x1
#define WFX_REG_IN_OUT_QUEUE 0x2
diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c
index 588edce44854..e06d7e1ebe9c 100644
--- a/drivers/staging/wfx/bus_sdio.c
+++ b/drivers/staging/wfx/bus_sdio.c
@@ -5,13 +5,19 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/module.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/interrupt.h>
#include <linux/of_irq.h>
+#include <linux/irq.h>
#include "bus.h"
#include "wfx.h"
+#include "hwio.h"
+#include "main.h"
+#include "bh.h"
static const struct wfx_platform_data wfx_sdio_pdata = {
.file_fw = "wfm_wf200",
diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c
index f89855abe9f8..a99125d1a30d 100644
--- a/drivers/staging/wfx/bus_spi.c
+++ b/drivers/staging/wfx/bus_spi.c
@@ -6,12 +6,19 @@
* Copyright (c) 2011, Sagrad Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>
#include "bus.h"
#include "wfx.h"
+#include "hwio.h"
+#include "main.h"
+#include "bh.h"
#define SET_WRITE 0x7FFF /* usage: and operation */
#define SET_READ 0x8000 /* usage: or operation */
diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c
index 2cfa16279220..385f2d42a0e2 100644
--- a/drivers/staging/wfx/data_rx.c
+++ b/drivers/staging/wfx/data_rx.c
@@ -5,8 +5,13 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
#include "data_rx.h"
#include "wfx.h"
+#include "bh.h"
+#include "sta.h"
static void wfx_rx_handle_ba(struct wfx_vif *wvif, struct ieee80211_mgmt *mgmt)
{
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c
index 76f26e3c4381..77fb104efdec 100644
--- a/drivers/staging/wfx/data_tx.c
+++ b/drivers/staging/wfx/data_tx.c
@@ -6,9 +6,14 @@
* Copyright (c) 2010, ST-Ericsson
*/
#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include "data_tx.h"
#include "wfx.h"
+#include "bh.h"
#include "sta.h"
+#include "queue.h"
+#include "debug.h"
#include "traces.h"
#include "hif_tx_mib.h"
diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h
index 6b3020097efa..401363d6b563 100644
--- a/drivers/staging/wfx/data_tx.h
+++ b/drivers/staging/wfx/data_tx.h
@@ -8,6 +8,9 @@
#ifndef WFX_DATA_TX_H
#define WFX_DATA_TX_H
+#include <linux/list.h>
+#include <net/mac80211.h>
+
#include "hif_api_cmd.h"
#include "hif_api_mib.h"
diff --git a/drivers/staging/wfx/debug.c b/drivers/staging/wfx/debug.c
index 3e87d13eb358..eedada78c25f 100644
--- a/drivers/staging/wfx/debug.c
+++ b/drivers/staging/wfx/debug.c
@@ -5,9 +5,15 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/crc32.h>
+
#include "debug.h"
#include "wfx.h"
#include "sta.h"
+#include "main.h"
+#include "hif_tx.h"
#include "hif_tx_mib.h"
#define CREATE_TRACE_POINTS
diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c
index 1bb9054871c4..1b8aec02d169 100644
--- a/drivers/staging/wfx/fwio.c
+++ b/drivers/staging/wfx/fwio.c
@@ -6,6 +6,8 @@
* Copyright (c) 2010, ST-Ericsson
*/
#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/bitfield.h>
#include "fwio.h"
diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h
index 8b671c9ab97c..58c9bb036011 100644
--- a/drivers/staging/wfx/hif_api_cmd.h
+++ b/drivers/staging/wfx/hif_api_cmd.h
@@ -8,6 +8,10 @@
#ifndef WFX_HIF_API_CMD_H
#define WFX_HIF_API_CMD_H
+#include <linux/ieee80211.h>
+
+#include "hif_api_general.h"
+
enum hif_requests_ids {
HIF_REQ_ID_RESET = 0x0a,
HIF_REQ_ID_READ_MIB = 0x05,
diff --git a/drivers/staging/wfx/hif_api_general.h b/drivers/staging/wfx/hif_api_general.h
index 70b253d0265d..24188945718d 100644
--- a/drivers/staging/wfx/hif_api_general.h
+++ b/drivers/staging/wfx/hif_api_general.h
@@ -8,6 +8,15 @@
#ifndef WFX_HIF_API_GENERAL_H
#define WFX_HIF_API_GENERAL_H
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#else
+#include <net/ethernet.h>
+#include <stdint.h>
+#define __packed __attribute__((__packed__))
+#endif
+
#define HIF_ID_IS_INDICATION 0x80
#define HIF_COUNTER_MAX 7
diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c
index 17dc13321978..63b437261eb7 100644
--- a/drivers/staging/wfx/hif_tx.c
+++ b/drivers/staging/wfx/hif_tx.c
@@ -6,7 +6,11 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/etherdevice.h>
+
+#include "hif_tx.h"
#include "wfx.h"
+#include "bh.h"
#include "hwio.h"
#include "debug.h"
#include "sta.h"
diff --git a/drivers/staging/wfx/hif_tx_mib.c b/drivers/staging/wfx/hif_tx_mib.c
index 6432ed86505c..1926cf1b62be 100644
--- a/drivers/staging/wfx/hif_tx_mib.c
+++ b/drivers/staging/wfx/hif_tx_mib.c
@@ -6,8 +6,13 @@
* Copyright (c) 2010, ST-Ericsson
* Copyright (C) 2010, ST-Ericsson SA
*/
+
+#include <linux/etherdevice.h>
+
#include "wfx.h"
+#include "hif_tx.h"
#include "hif_tx_mib.h"
+#include "hif_api_mib.h"
int hif_set_output_power(struct wfx_vif *wvif, int val)
{
diff --git a/drivers/staging/wfx/hwio.c b/drivers/staging/wfx/hwio.c
index 089bb41be149..36fbc5b5d64c 100644
--- a/drivers/staging/wfx/hwio.c
+++ b/drivers/staging/wfx/hwio.c
@@ -5,10 +5,13 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/kernel.h>
+#include <linux/delay.h>
#include <linux/slab.h>
#include "hwio.h"
#include "wfx.h"
+#include "bus.h"
#include "traces.h"
/*
diff --git a/drivers/staging/wfx/hwio.h b/drivers/staging/wfx/hwio.h
index 8bb9bcfc3182..0b8e4f7157df 100644
--- a/drivers/staging/wfx/hwio.h
+++ b/drivers/staging/wfx/hwio.h
@@ -8,6 +8,8 @@
#ifndef WFX_HWIO_H
#define WFX_HWIO_H
+#include <linux/types.h>
+
struct wfx_dev;
int wfx_data_read(struct wfx_dev *wdev, void *buf, size_t buf_len);
diff --git a/drivers/staging/wfx/key.c b/drivers/staging/wfx/key.c
index c93d07dcdc10..2ab82bed4c1b 100644
--- a/drivers/staging/wfx/key.c
+++ b/drivers/staging/wfx/key.c
@@ -5,10 +5,12 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "key.h"
#include "wfx.h"
+#include "hif_tx_mib.h"
static int wfx_alloc_key(struct wfx_dev *wdev)
{
diff --git a/drivers/staging/wfx/key.h b/drivers/staging/wfx/key.h
index 4dc9feadaba2..70a44d0ca35e 100644
--- a/drivers/staging/wfx/key.h
+++ b/drivers/staging/wfx/key.h
@@ -8,6 +8,8 @@
#ifndef WFX_KEY_H
#define WFX_KEY_H
+#include <net/mac80211.h>
+
struct wfx_dev;
struct wfx_vif;
diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c
index b9ea9a93fe1a..e7bc1988124a 100644
--- a/drivers/staging/wfx/main.c
+++ b/drivers/staging/wfx/main.c
@@ -10,21 +10,28 @@
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
*/
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
+#include <linux/gpio/consumer.h>
#include <linux/mmc/sdio_func.h>
#include <linux/spi/spi.h>
+#include <linux/etherdevice.h>
#include <linux/firmware.h>
+#include "main.h"
#include "wfx.h"
#include "fwio.h"
#include "hwio.h"
#include "bus.h"
+#include "bh.h"
#include "sta.h"
#include "key.h"
#include "scan.h"
#include "debug.h"
+#include "data_tx.h"
#include "hif_tx_mib.h"
+#include "hif_api_cmd.h"
#define WFX_PDS_MAX_SIZE 1500
diff --git a/drivers/staging/wfx/main.h b/drivers/staging/wfx/main.h
index 086bcc041b90..a0db322383a3 100644
--- a/drivers/staging/wfx/main.h
+++ b/drivers/staging/wfx/main.h
@@ -10,8 +10,11 @@
#ifndef WFX_MAIN_H
#define WFX_MAIN_H
+#include <linux/device.h>
#include <linux/gpio/consumer.h>
+#include "hif_api_general.h"
+
struct wfx_dev;
struct hwbus_ops;
diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c
index 3bddf282a4ce..31c37f69c295 100644
--- a/drivers/staging/wfx/queue.c
+++ b/drivers/staging/wfx/queue.c
@@ -5,9 +5,13 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/sched.h>
#include <net/mac80211.h>
+#include "queue.h"
#include "wfx.h"
+#include "sta.h"
+#include "data_tx.h"
#include "traces.h"
void wfx_tx_lock(struct wfx_dev *wdev)
diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h
index e43aa9dfbc45..80ba19455ef3 100644
--- a/drivers/staging/wfx/queue.h
+++ b/drivers/staging/wfx/queue.h
@@ -8,6 +8,9 @@
#ifndef WFX_QUEUE_H
#define WFX_QUEUE_H
+#include <linux/skbuff.h>
+#include <linux/atomic.h>
+
struct wfx_dev;
struct wfx_vif;
diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h
index e5b7eef78858..c7496a766478 100644
--- a/drivers/staging/wfx/scan.h
+++ b/drivers/staging/wfx/scan.h
@@ -8,6 +8,8 @@
#ifndef WFX_SCAN_H
#define WFX_SCAN_H
+#include <net/mac80211.h>
+
struct wfx_dev;
struct wfx_vif;
diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c
index 5585f9e876e1..196779a1b89a 100644
--- a/drivers/staging/wfx/sta.c
+++ b/drivers/staging/wfx/sta.c
@@ -5,11 +5,17 @@
* Copyright (c) 2017-2020, Silicon Laboratories, Inc.
* Copyright (c) 2010, ST-Ericsson
*/
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
#include "sta.h"
#include "wfx.h"
+#include "fwio.h"
+#include "bh.h"
+#include "key.h"
#include "scan.h"
+#include "debug.h"
+#include "hif_tx.h"
#include "hif_tx_mib.h"
#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h
index a3fb9fc93fa4..d7b5df5ea4e6 100644
--- a/drivers/staging/wfx/sta.h
+++ b/drivers/staging/wfx/sta.h
@@ -8,6 +8,8 @@
#ifndef WFX_STA_H
#define WFX_STA_H
+#include <net/mac80211.h>
+
struct wfx_dev;
struct wfx_vif;
diff --git a/drivers/staging/wfx/traces.h b/drivers/staging/wfx/traces.h
index afe1074e09b3..e34c7a538c65 100644
--- a/drivers/staging/wfx/traces.h
+++ b/drivers/staging/wfx/traces.h
@@ -12,8 +12,11 @@
#define _WFX_TRACE_H
#include <linux/tracepoint.h>
+#include <net/mac80211.h>
#include "bus.h"
+#include "hif_api_cmd.h"
+#include "hif_api_mib.h"
/* The hell below need some explanations. For each symbolic number, we need to
* define it with TRACE_DEFINE_ENUM() and in a list for __print_symbolic.
diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h
index a185b82795c4..94898680ccde 100644
--- a/drivers/staging/wfx/wfx.h
+++ b/drivers/staging/wfx/wfx.h
@@ -10,6 +10,9 @@
#ifndef WFX_H
#define WFX_H
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
#include <linux/nospec.h>
#include <net/mac80211.h>
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index cf4718c6d35d..319a1e701163 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -747,7 +747,6 @@ module_platform_driver(optee_driver);
MODULE_AUTHOR("Linaro");
MODULE_DESCRIPTION("OP-TEE driver");
-MODULE_SUPPORTED_DEVICE("");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:optee");
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 345917a58f2f..1c4aac8464a7 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -674,6 +674,9 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
{
struct cooling_dev_stats *stats = cdev->stats;
+ if (!stats)
+ return;
+
spin_lock(&stats->lock);
if (stats->state == new_state)
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index b63fecca6c2a..2a95b4ce06c0 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -768,12 +768,6 @@ static int tb_init_port(struct tb_port *port)
tb_dump_port(port->sw->tb, &port->config);
- /* Control port does not need HopID allocation */
- if (port->port) {
- ida_init(&port->in_hopids);
- ida_init(&port->out_hopids);
- }
-
INIT_LIST_HEAD(&port->list);
return 0;
@@ -1842,10 +1836,8 @@ static void tb_switch_release(struct device *dev)
dma_port_free(sw->dma_port);
tb_switch_for_each_port(sw, port) {
- if (!port->disabled) {
- ida_destroy(&port->in_hopids);
- ida_destroy(&port->out_hopids);
- }
+ ida_destroy(&port->in_hopids);
+ ida_destroy(&port->out_hopids);
}
kfree(sw->uuid);
@@ -2025,6 +2017,12 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
/* minimum setup for tb_find_cap and tb_drom_read to work */
sw->ports[i].sw = sw;
sw->ports[i].port = i;
+
+ /* Control port does not need HopID allocation */
+ if (i) {
+ ida_init(&sw->ports[i].in_hopids);
+ ida_init(&sw->ports[i].out_hopids);
+ }
}
ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS);
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 1f000ac1728b..c348b1fc0efc 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -138,6 +138,10 @@ static void tb_discover_tunnels(struct tb_switch *sw)
parent->boot = true;
parent = tb_switch_parent(parent);
}
+ } else if (tb_tunnel_is_dp(tunnel)) {
+ /* Keep the domain from powering down */
+ pm_runtime_get_sync(&tunnel->src_port->sw->dev);
+ pm_runtime_get_sync(&tunnel->dst_port->sw->dev);
}
list_add_tail(&tunnel->list, &tcm->tunnel_list);
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index c90848919644..9afa1dcef2c2 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -317,7 +317,6 @@ static void hvcs_hangup(struct tty_struct * tty);
static int hvcs_probe(struct vio_dev *dev,
const struct vio_device_id *id);
-static int hvcs_remove(struct vio_dev *dev);
static int __init hvcs_module_init(void);
static void __exit hvcs_module_exit(void);
static int hvcs_initialize(void);
@@ -819,7 +818,7 @@ static int hvcs_probe(
return 0;
}
-static int hvcs_remove(struct vio_dev *dev)
+static void hvcs_remove(struct vio_dev *dev)
{
struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
unsigned long flags;
@@ -849,7 +848,6 @@ static int hvcs_remove(struct vio_dev *dev)
printk(KERN_INFO "HVCS: vty-server@%X removed from the"
" vio bus.\n", dev->unit_address);
- return 0;
};
static struct vio_driver hvcs_vio_driver = {
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 8b2797b6ee44..5e2374580e27 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -66,8 +66,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait);
if (tty->driver->subtype == PTY_TYPE_MASTER) {
- struct file *f;
-
+ set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver) {
mutex_lock(&devpts_mutex);
@@ -76,17 +75,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
mutex_unlock(&devpts_mutex);
}
#endif
-
- /*
- * This hack is required because a program can open a
- * pty and redirect a console to it, but if the pty is
- * closed and the console is not released, then the
- * slave side will never close. So release the
- * redirect when the master closes.
- */
- f = tty_release_redirect(tty->link);
- if (f)
- fput(f);
+ tty_vhangup(tty->link);
}
}
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 9a872750581c..94af7a5ea497 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -1639,8 +1639,6 @@ module_exit(icom_exit);
MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
-MODULE_SUPPORTED_DEVICE
- ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("icom_call_setup.bin");
MODULE_FIRMWARE("icom_res_dce.bin");
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index cd30da0ef083..0ea799bf8dbb 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -19,7 +19,6 @@
MODULE_AUTHOR("Digi International, https://www.digi.com");
MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("jsm");
#define JSM_DRIVER_NAME "jsm"
#define NR_PORTS 32
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 9795b2e8b0b2..1b61d26bb7af 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1056,9 +1056,9 @@ static int max310x_startup(struct uart_port *port)
max310x_port_update(port, MAX310X_MODE1_REG,
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
- /* Reset FIFOs */
- max310x_port_write(port, MAX310X_MODE2_REG,
- MAX310X_MODE2_FIFORST_BIT);
+ /* Configure MODE2 register & Reset FIFOs*/
+ val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
+ max310x_port_write(port, MAX310X_MODE2_REG, val);
max310x_port_update(port, MAX310X_MODE2_REG,
MAX310X_MODE2_FIFORST_BIT, 0);
@@ -1086,27 +1086,8 @@ static int max310x_startup(struct uart_port *port)
/* Clear IRQ status register */
max310x_port_read(port, MAX310X_IRQSTS_REG);
- /*
- * Let's ask for an interrupt after a timeout equivalent to
- * the receiving time of 4 characters after the last character
- * has been received.
- */
- max310x_port_write(port, MAX310X_RXTO_REG, 4);
-
- /*
- * Make sure we also get RX interrupts when the RX FIFO is
- * filling up quickly, so get an interrupt when half of the RX
- * FIFO has been filled in.
- */
- max310x_port_write(port, MAX310X_FIFOTRIGLVL_REG,
- MAX310X_FIFOTRIGLVL_RX(MAX310X_FIFO_SIZE / 2));
-
- /* Enable RX timeout interrupt in LSR */
- max310x_port_write(port, MAX310X_LSR_IRQEN_REG,
- MAX310X_LSR_RXTO_BIT);
-
- /* Enable LSR, RX FIFO trigger, CTS change interrupts */
- val = MAX310X_IRQ_LSR_BIT | MAX310X_IRQ_RXFIFO_BIT | MAX310X_IRQ_TXEMPTY_BIT;
+ /* Enable RX, TX, CTS change interrupts */
+ val = MAX310X_IRQ_RXEMPTY_BIT | MAX310X_IRQ_TXEMPTY_BIT;
max310x_port_write(port, MAX310X_IRQEN_REG, val | MAX310X_IRQ_CTS_BIT);
return 0;
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 74733ec8f565..391bada4cedb 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -544,9 +544,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* @tty: tty device
*
* This is available to the pty code so if the master closes, if the
- * slave is a redirect it can release the redirect. It returns the
- * filp for the redirect, which must be fput when the operations on
- * the tty are completed.
+ * slave is a redirect it can release the redirect.
*/
struct file *tty_release_redirect(struct tty_struct *tty)
{
@@ -561,6 +559,7 @@ struct file *tty_release_redirect(struct tty_struct *tty)
return f;
}
+EXPORT_SYMBOL_GPL(tty_release_redirect);
/**
* __tty_hangup - actual handler for hangup events
diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c
index f9170d177a89..5f0513c96c04 100644
--- a/drivers/usb/cdns3/cdnsp-ring.c
+++ b/drivers/usb/cdns3/cdnsp-ring.c
@@ -2197,7 +2197,10 @@ static int cdnsp_queue_isoc_tx(struct cdnsp_device *pdev,
* inverted in the first TDs isoc TRB.
*/
field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt) |
- start_cycle ? 0 : 1 | TRB_SIA | TRB_TBC(burst_count);
+ TRB_SIA | TRB_TBC(burst_count);
+
+ if (!start_cycle)
+ field |= TRB_CYCLE;
/* Fill the rest of the TRB fields, and remaining normal TRBs. */
for (i = 0; i < trbs_per_td; i++) {
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 37f824b59daa..39ddb5585ded 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1935,6 +1935,11 @@ static const struct usb_device_id acm_ids[] = {
.driver_info = SEND_ZERO_PACKET,
},
+ /* Exclude Goodix Fingerprint Reader */
+ { USB_DEVICE(0x27c6, 0x5395),
+ .driver_info = IGNORE_DEVICE,
+ },
+
/* control interfaces without any protocol set */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_PROTO_NONE) },
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index c9f6e9758288..f27b4aecff3d 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -494,16 +494,24 @@ static int usblp_release(struct inode *inode, struct file *file)
/* No kernel lock - fine */
static __poll_t usblp_poll(struct file *file, struct poll_table_struct *wait)
{
- __poll_t ret;
+ struct usblp *usblp = file->private_data;
+ __poll_t ret = 0;
unsigned long flags;
- struct usblp *usblp = file->private_data;
/* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
poll_wait(file, &usblp->rwait, wait);
poll_wait(file, &usblp->wwait, wait);
+
+ mutex_lock(&usblp->mut);
+ if (!usblp->present)
+ ret |= EPOLLHUP;
+ mutex_unlock(&usblp->mut);
+
spin_lock_irqsave(&usblp->lock, flags);
- ret = ((usblp->bidir && usblp->rcomplete) ? EPOLLIN | EPOLLRDNORM : 0) |
- ((usblp->no_paper || usblp->wcomplete) ? EPOLLOUT | EPOLLWRNORM : 0);
+ if (usblp->bidir && usblp->rcomplete)
+ ret |= EPOLLIN | EPOLLRDNORM;
+ if (usblp->no_paper || usblp->wcomplete)
+ ret |= EPOLLOUT | EPOLLWRNORM;
spin_unlock_irqrestore(&usblp->lock, flags);
return ret;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8f07b0516100..a566bb494e24 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -748,6 +748,38 @@ void usb_put_intf(struct usb_interface *intf)
}
EXPORT_SYMBOL_GPL(usb_put_intf);
+/**
+ * usb_intf_get_dma_device - acquire a reference on the usb interface's DMA endpoint
+ * @intf: the usb interface
+ *
+ * While a USB device cannot perform DMA operations by itself, many USB
+ * controllers can. A call to usb_intf_get_dma_device() returns the DMA endpoint
+ * for the given USB interface, if any. The returned device structure must be
+ * released with put_device().
+ *
+ * See also usb_get_dma_device().
+ *
+ * Returns: A reference to the usb interface's DMA endpoint; or NULL if none
+ * exists.
+ */
+struct device *usb_intf_get_dma_device(struct usb_interface *intf)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct device *dmadev;
+
+ if (!udev->bus)
+ return NULL;
+
+ dmadev = get_device(udev->bus->sysdev);
+ if (!dmadev || !dmadev->dma_mask) {
+ put_device(dmadev);
+ return NULL;
+ }
+
+ return dmadev;
+}
+EXPORT_SYMBOL_GPL(usb_intf_get_dma_device);
+
/* USB device locking
*
* USB devices and interfaces are locked using the semaphore in their
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 846a47be6df7..fcaf04483ad0 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -358,8 +358,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
if (ret)
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
+ if (device_may_wakeup(qcom->dev))
+ dwc3_qcom_enable_interrupts(qcom);
+
qcom->is_suspended = true;
- dwc3_qcom_enable_interrupts(qcom);
return 0;
}
@@ -372,7 +374,8 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
if (!qcom->is_suspended)
return 0;
- dwc3_qcom_disable_interrupts(qcom);
+ if (device_may_wakeup(qcom->dev))
+ dwc3_qcom_disable_interrupts(qcom);
for (i = 0; i < qcom->num_clocks; i++) {
ret = clk_prepare_enable(qcom->clks[i]);
@@ -650,16 +653,19 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
- return ret;
+ goto node_put;
}
qcom->dwc3 = of_find_device_by_node(dwc3_np);
if (!qcom->dwc3) {
+ ret = -ENODEV;
dev_err(dev, "failed to get dwc3 platform device\n");
- return -ENODEV;
}
- return 0;
+node_put:
+ of_node_put(dwc3_np);
+
+ return ret;
}
static struct platform_device *
@@ -938,6 +944,8 @@ static const struct dwc3_acpi_pdata sdm845_acpi_urs_pdata = {
static const struct acpi_device_id dwc3_qcom_acpi_match[] = {
{ "QCOM2430", (unsigned long)&sdm845_acpi_pdata },
{ "QCOM0304", (unsigned long)&sdm845_acpi_urs_pdata },
+ { "QCOM0497", (unsigned long)&sdm845_acpi_urs_pdata },
+ { "QCOM04A6", (unsigned long)&sdm845_acpi_pdata },
{ },
};
MODULE_DEVICE_TABLE(acpi, dwc3_qcom_acpi_match);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index aebcf8ec0716..4a337f348651 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
trace_dwc3_gadget_ep_disable(dep);
- dwc3_remove_requests(dwc, dep);
-
/* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0, false);
@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
}
+ dwc3_remove_requests(dwc, dep);
+
return 0;
}
@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- if (!dep->endpoint.desc || !dwc->pullups_connected) {
+ if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
if (!is_on) {
u32 count;
+ dwc->connected = false;
/*
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
* Section 4.1.8 Table 4-7, it states that for a device-initiated
@@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
- dwc->connected = false;
} else {
__dwc3_gadget_start(dwc);
}
@@ -3321,8 +3321,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
{
u32 reg;
- dwc->connected = true;
-
/*
* WORKAROUND: DWC3 revisions <1.88a have an issue which
* would cause a missing Disconnect Event if there's a
@@ -3362,6 +3360,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
* transfers."
*/
dwc3_stop_active_transfers(dwc);
+ dwc->connected = true;
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 0d56f33d63c2..15a607ccef8a 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -97,6 +97,8 @@ struct gadget_config_name {
struct list_head list;
};
+#define USB_MAX_STRING_WITH_NULL_LEN (USB_MAX_STRING_LEN+1)
+
static int usb_string_copy(const char *s, char **s_copy)
{
int ret;
@@ -106,12 +108,16 @@ static int usb_string_copy(const char *s, char **s_copy)
if (ret > USB_MAX_STRING_LEN)
return -EOVERFLOW;
- str = kstrdup(s, GFP_KERNEL);
- if (!str)
- return -ENOMEM;
+ if (copy) {
+ str = copy;
+ } else {
+ str = kmalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+ }
+ strcpy(str, s);
if (str[ret - 1] == '\n')
str[ret - 1] = '\0';
- kfree(copy);
*s_copy = str;
return 0;
}
diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c
index 00d346965f7a..560382e0a8f3 100644
--- a/drivers/usb/gadget/function/f_uac1.c
+++ b/drivers/usb/gadget/function/f_uac1.c
@@ -499,6 +499,7 @@ static void f_audio_disable(struct usb_function *f)
uac1->as_out_alt = 0;
uac1->as_in_alt = 0;
+ u_audio_stop_playback(&uac1->g_audio);
u_audio_stop_capture(&uac1->g_audio);
}
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 5d960b6603b6..6f03e944e0e3 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -478,7 +478,7 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
}
max_size_bw = num_channels(chmask) * ssize *
- DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
+ ((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
max_size_ep));
diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h
index 3dfb460908fa..f558c3139ebe 100644
--- a/drivers/usb/gadget/function/u_ether_configfs.h
+++ b/drivers/usb/gadget/function/u_ether_configfs.h
@@ -182,12 +182,11 @@ out: \
size_t len) \
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
- int ret; \
+ int ret = -EINVAL; \
u8 val; \
\
mutex_lock(&opts->lock); \
- ret = sscanf(page, "%02hhx", &val); \
- if (ret > 0) { \
+ if (sscanf(page, "%02hhx", &val) > 0) { \
opts->_n_ = val; \
ret = len; \
} \
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index f1ea51476add..1d3ebb07ccd4 100644
--- a/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1773,8 +1773,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
udc_info = dev_get_platdata(&pdev->dev);
base_addr = devm_platform_ioremap_resource(pdev, 0);
- if (!base_addr) {
- retval = -ENOMEM;
+ if (IS_ERR(base_addr)) {
+ retval = PTR_ERR(base_addr);
goto err_mem;
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 84da8406d5b4..5bbccc9a0179 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -66,6 +66,7 @@
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242
#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142
+#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242
static const char hcd_name[] = "xhci_hcd";
@@ -276,11 +277,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI)
xhci->quirks |= XHCI_BROKEN_STREAMS;
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
- pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
+ pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) {
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+ xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
+ }
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
(pdev->device == PCI_DEVICE_ID_ASMEDIA_1142_XHCI ||
- pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI))
+ pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI ||
+ pdev->device == PCI_DEVICE_ID_ASMEDIA_3242_XHCI))
xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
@@ -295,6 +299,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == 0x9026)
xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
+ if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+ (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2 ||
+ pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4))
+ xhci->quirks |= XHCI_NO_SOFT_RETRY;
+
if (xhci->quirks & XHCI_RESET_ON_RESUME)
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
"QUIRK: Resetting on resume");
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5e548a1c93ab..ce38076901e2 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2484,7 +2484,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
remaining = 0;
break;
case COMP_USB_TRANSACTION_ERROR:
- if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
+ if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
+ (ep_ring->err_count++ > MAX_SOFT_RETRY) ||
le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
break;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index bd27bd670104..1975016f46bf 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -883,44 +883,42 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
xhci_set_cmd_ring_deq(xhci);
}
-static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
+/*
+ * Disable port wake bits if do_wakeup is not set.
+ *
+ * Also clear a possible internal port wake state left hanging for ports that
+ * detected termination but never successfully enumerated (trained to 0U).
+ * Internal wake causes immediate xHCI wake after suspend. PORT_CSC write done
+ * at enumeration clears this wake, force one here as well for unconnected ports
+ */
+
+static void xhci_disable_hub_port_wake(struct xhci_hcd *xhci,
+ struct xhci_hub *rhub,
+ bool do_wakeup)
{
- struct xhci_port **ports;
- int port_index;
unsigned long flags;
u32 t1, t2, portsc;
+ int i;
spin_lock_irqsave(&xhci->lock, flags);
- /* disable usb3 ports Wake bits */
- port_index = xhci->usb3_rhub.num_ports;
- ports = xhci->usb3_rhub.ports;
- while (port_index--) {
- t1 = readl(ports[port_index]->addr);
- portsc = t1;
- t1 = xhci_port_state_to_neutral(t1);
- t2 = t1 & ~PORT_WAKE_BITS;
- if (t1 != t2) {
- writel(t2, ports[port_index]->addr);
- xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
- xhci->usb3_rhub.hcd->self.busnum,
- port_index + 1, portsc, t2);
- }
- }
+ for (i = 0; i < rhub->num_ports; i++) {
+ portsc = readl(rhub->ports[i]->addr);
+ t1 = xhci_port_state_to_neutral(portsc);
+ t2 = t1;
+
+ /* clear wake bits if do_wake is not set */
+ if (!do_wakeup)
+ t2 &= ~PORT_WAKE_BITS;
+
+ /* Don't touch csc bit if connected or connect change is set */
+ if (!(portsc & (PORT_CSC | PORT_CONNECT)))
+ t2 |= PORT_CSC;
- /* disable usb2 ports Wake bits */
- port_index = xhci->usb2_rhub.num_ports;
- ports = xhci->usb2_rhub.ports;
- while (port_index--) {
- t1 = readl(ports[port_index]->addr);
- portsc = t1;
- t1 = xhci_port_state_to_neutral(t1);
- t2 = t1 & ~PORT_WAKE_BITS;
if (t1 != t2) {
- writel(t2, ports[port_index]->addr);
- xhci_dbg(xhci, "disable wake bits port %d-%d, portsc: 0x%x, write: 0x%x\n",
- xhci->usb2_rhub.hcd->self.busnum,
- port_index + 1, portsc, t2);
+ writel(t2, rhub->ports[i]->addr);
+ xhci_dbg(xhci, "config port %d-%d wake bits, portsc: 0x%x, write: 0x%x\n",
+ rhub->hcd->self.busnum, i + 1, portsc, t2);
}
}
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -983,8 +981,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
return -EINVAL;
/* Clear root port wake on bits if wakeup not allowed. */
- if (!do_wakeup)
- xhci_disable_port_wake_on_bits(xhci);
+ xhci_disable_hub_port_wake(xhci, &xhci->usb3_rhub, do_wakeup);
+ xhci_disable_hub_port_wake(xhci, &xhci->usb2_rhub, do_wakeup);
if (!HCD_HW_ACCESSIBLE(hcd))
return 0;
@@ -1088,6 +1086,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
struct usb_hcd *secondary_hcd;
int retval = 0;
bool comp_timer_running = false;
+ bool pending_portevent = false;
if (!hcd->state)
return 0;
@@ -1226,13 +1225,22 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
done:
if (retval == 0) {
- /* Resume root hubs only when have pending events. */
- if (xhci_pending_portevent(xhci)) {
+ /*
+ * Resume roothubs only if there are pending events.
+ * USB 3 devices resend U3 LFPS wake after a 100ms delay if
+ * the first wake signalling failed, give it that chance.
+ */
+ pending_portevent = xhci_pending_portevent(xhci);
+ if (!pending_portevent) {
+ msleep(120);
+ pending_portevent = xhci_pending_portevent(xhci);
+ }
+
+ if (pending_portevent) {
usb_hcd_resume_root_hub(xhci->shared_hcd);
usb_hcd_resume_root_hub(hcd);
}
}
-
/*
* If system is subject to the Quirk, Compliance Mode Timer needs to
* be re-initialized Always after a system resume. Ports are subject
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index d41de5dc0452..ca822ad3b65b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1891,6 +1891,7 @@ struct xhci_hcd {
#define XHCI_SKIP_PHY_INIT BIT_ULL(37)
#define XHCI_DISABLE_SPARSE BIT_ULL(38)
#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)
+#define XHCI_NO_SOFT_RETRY BIT_ULL(40)
unsigned int num_active_eps;
unsigned int limit_active_eps;
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 670e4d91e9ca..dcc88df72df4 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -117,7 +117,6 @@ MODULE_DEVICE_TABLE(usb, ld_usb_table);
MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
MODULE_DESCRIPTION("LD USB Driver");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("LD USB Devices");
/* All interrupt in transfers are collected in a ring buffer to
* avoid racing conditions and get better performance of the driver.
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index e7334b7fb3a6..75fff2e4cbc6 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -746,6 +746,8 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
void usbhs_pipe_free(struct usbhs_pipe *pipe)
{
+ usbhsp_pipe_select(pipe);
+ usbhsp_pipe_cfg_set(pipe, 0xFFFF, 0);
usbhsp_put_pipe(pipe);
}
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 8d997b71056f..2db917eab799 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -86,6 +86,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1a86, 0x7522) },
{ USB_DEVICE(0x1a86, 0x7523) },
{ USB_DEVICE(0x4348, 0x5523) },
+ { USB_DEVICE(0x9986, 0x7523) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 9e1c609792fb..a373cd63b3a4 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -145,6 +145,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
{ USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
+ { USB_DEVICE(0x10C4, 0x88D8) }, /* Acuity Brands nLight Air Adapter */
{ USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */
{ USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */
{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
@@ -201,6 +202,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
{ USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */
{ USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
+ { USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */
+ { USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */
{ USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index a493670c06e6..68401adcffde 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -3003,26 +3003,32 @@ static int edge_startup(struct usb_serial *serial)
response = -ENODEV;
}
- usb_free_urb(edge_serial->interrupt_read_urb);
- kfree(edge_serial->interrupt_in_buffer);
-
- usb_free_urb(edge_serial->read_urb);
- kfree(edge_serial->bulk_in_buffer);
-
- kfree(edge_serial);
-
- return response;
+ goto error;
}
/* start interrupt read for this edgeport this interrupt will
* continue as long as the edgeport is connected */
response = usb_submit_urb(edge_serial->interrupt_read_urb,
GFP_KERNEL);
- if (response)
+ if (response) {
dev_err(ddev, "%s - Error %d submitting control urb\n",
__func__, response);
+
+ goto error;
+ }
}
return response;
+
+error:
+ usb_free_urb(edge_serial->interrupt_read_urb);
+ kfree(edge_serial->interrupt_in_buffer);
+
+ usb_free_urb(edge_serial->read_urb);
+ kfree(edge_serial->bulk_in_buffer);
+
+ kfree(edge_serial);
+
+ return response;
}
diff --git a/drivers/usb/serial/xr_serial.c b/drivers/usb/serial/xr_serial.c
index 483d07dee19d..0ca04906da4b 100644
--- a/drivers/usb/serial/xr_serial.c
+++ b/drivers/usb/serial/xr_serial.c
@@ -545,37 +545,13 @@ static void xr_close(struct usb_serial_port *port)
static int xr_probe(struct usb_serial *serial, const struct usb_device_id *id)
{
- struct usb_driver *driver = serial->type->usb_driver;
- struct usb_interface *control_interface;
- int ret;
-
/* Don't bind to control interface */
if (serial->interface->cur_altsetting->desc.bInterfaceNumber == 0)
return -ENODEV;
- /* But claim the control interface during data interface probe */
- control_interface = usb_ifnum_to_if(serial->dev, 0);
- if (!control_interface)
- return -ENODEV;
-
- ret = usb_driver_claim_interface(driver, control_interface, NULL);
- if (ret) {
- dev_err(&serial->interface->dev, "Failed to claim control interface\n");
- return ret;
- }
-
return 0;
}
-static void xr_disconnect(struct usb_serial *serial)
-{
- struct usb_driver *driver = serial->type->usb_driver;
- struct usb_interface *control_interface;
-
- control_interface = usb_ifnum_to_if(serial->dev, 0);
- usb_driver_release_interface(driver, control_interface);
-}
-
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x04e2, 0x1410) }, /* XR21V141X */
{ }
@@ -590,7 +566,6 @@ static struct usb_serial_driver xr_device = {
.id_table = id_table,
.num_ports = 1,
.probe = xr_probe,
- .disconnect = xr_disconnect,
.open = xr_open,
.close = xr_close,
.break_ctl = xr_break_ctl,
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 5eb895b19c55..f4304ce69350 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -656,6 +656,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
need_auto_sense = 1;
}
+ /* Some devices (Kindle) require another command after SYNC CACHE */
+ if ((us->fflags & US_FL_SENSE_AFTER_SYNC) &&
+ srb->cmnd[0] == SYNCHRONIZE_CACHE) {
+ usb_stor_dbg(us, "-- sense after SYNC CACHE\n");
+ need_auto_sense = 1;
+ }
+
/*
* If we have a failure, we're going to do a REQUEST_SENSE
* automatically. Note that we differentiate between a command
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 5732e9691f08..efa972be2ee3 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2212,6 +2212,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
US_FL_NO_READ_DISC_INFO ),
/*
+ * Reported by Matthias Schwarzott <zzam@gentoo.org>
+ * The Amazon Kindle treats SYNCHRONIZE CACHE as an indication that
+ * the host may be finished with it, and automatically ejects its
+ * emulated media unless it receives another command within one second.
+ */
+UNUSUAL_DEV( 0x1949, 0x0004, 0x0000, 0x9999,
+ "Amazon",
+ "Kindle",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_SENSE_AFTER_SYNC ),
+
+/*
* Reported by Oliver Neukum <oneukum@suse.com>
* This device morphes spontaneously into another device if the access
* pattern of Windows isn't followed. Thus writable media would be dirty
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index be0b6469dd3d..ce7af398c7c1 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -942,6 +942,7 @@ static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
port->supply_voltage = mv;
port->current_limit = max_ma;
+ power_supply_changed(port->psy);
if (port->tcpc->set_current_limit)
ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv);
@@ -2928,6 +2929,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
port->pps_data.supported = false;
port->usb_type = POWER_SUPPLY_USB_TYPE_PD;
+ power_supply_changed(port->psy);
/*
* Select the source PDO providing the most power which has a
@@ -2952,6 +2954,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
port->pps_data.supported = true;
port->usb_type =
POWER_SUPPLY_USB_TYPE_PD_PPS;
+ power_supply_changed(port->psy);
}
continue;
default:
@@ -3109,6 +3112,7 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
port->pps_data.out_volt));
port->pps_data.op_curr = min(port->pps_data.max_curr,
port->pps_data.op_curr);
+ power_supply_changed(port->psy);
}
return src_pdo;
@@ -3344,6 +3348,7 @@ static int tcpm_set_charge(struct tcpm_port *port, bool charge)
return ret;
}
port->vbus_charge = charge;
+ power_supply_changed(port->psy);
return 0;
}
@@ -3523,6 +3528,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
port->try_src_count = 0;
port->try_snk_count = 0;
port->usb_type = POWER_SUPPLY_USB_TYPE_C;
+ power_supply_changed(port->psy);
port->nr_sink_caps = 0;
port->sink_cap_done = false;
if (port->tcpc->enable_frs)
@@ -5167,7 +5173,7 @@ static void tcpm_enable_frs_work(struct kthread_work *work)
goto unlock;
/* Send when the state machine is idle */
- if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover)
+ if (port->state != SNK_READY || port->vdm_sm_running || port->send_discover)
goto resched;
port->upcoming_state = GET_SINK_CAP;
@@ -5905,7 +5911,7 @@ static int tcpm_psy_set_prop(struct power_supply *psy,
ret = -EINVAL;
break;
}
-
+ power_supply_changed(port->psy);
return ret;
}
@@ -6058,6 +6064,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
err = devm_tcpm_psy_register(port);
if (err)
goto out_role_sw_put;
+ power_supply_changed(port->psy);
port->typec_port = typec_register_port(port->dev, &port->typec_caps);
if (IS_ERR(port->typec_port)) {
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 6e6ef6317523..29bd1c5a283c 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -64,7 +64,6 @@ enum {
struct tps6598x_rx_identity_reg {
u8 status;
struct usb_pd_identity identity;
- u32 vdo[3];
} __packed;
/* Standard Task return codes */
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index 2305d425e6c9..8f1de1fbbeed 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -46,6 +46,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
int sockfd = 0;
struct socket *socket;
int rv;
+ struct task_struct *tcp_rx = NULL;
+ struct task_struct *tcp_tx = NULL;
if (!sdev) {
dev_err(dev, "sdev is null\n");
@@ -69,23 +71,47 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
}
socket = sockfd_lookup(sockfd, &err);
- if (!socket)
+ if (!socket) {
+ dev_err(dev, "failed to lookup sock");
goto err;
+ }
- sdev->ud.tcp_socket = socket;
- sdev->ud.sockfd = sockfd;
+ if (socket->type != SOCK_STREAM) {
+ dev_err(dev, "Expecting SOCK_STREAM - found %d",
+ socket->type);
+ goto sock_err;
+ }
+ /* unlock and create threads and get tasks */
spin_unlock_irq(&sdev->ud.lock);
+ tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
+ if (IS_ERR(tcp_rx)) {
+ sockfd_put(socket);
+ return -EINVAL;
+ }
+ tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
+ if (IS_ERR(tcp_tx)) {
+ kthread_stop(tcp_rx);
+ sockfd_put(socket);
+ return -EINVAL;
+ }
- sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
- "stub_rx");
- sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
- "stub_tx");
+ /* get task structs now */
+ get_task_struct(tcp_rx);
+ get_task_struct(tcp_tx);
+ /* lock and update sdev->ud state */
spin_lock_irq(&sdev->ud.lock);
+ sdev->ud.tcp_socket = socket;
+ sdev->ud.sockfd = sockfd;
+ sdev->ud.tcp_rx = tcp_rx;
+ sdev->ud.tcp_tx = tcp_tx;
sdev->ud.status = SDEV_ST_USED;
spin_unlock_irq(&sdev->ud.lock);
+ wake_up_process(sdev->ud.tcp_rx);
+ wake_up_process(sdev->ud.tcp_tx);
+
} else {
dev_info(dev, "stub down\n");
@@ -100,6 +126,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
return count;
+sock_err:
+ sockfd_put(socket);
err:
spin_unlock_irq(&sdev->ud.lock);
return -EINVAL;
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
index 96e5371dc335..c4b4256e5dad 100644
--- a/drivers/usb/usbip/vhci_sysfs.c
+++ b/drivers/usb/usbip/vhci_sysfs.c
@@ -312,6 +312,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
struct vhci *vhci;
int err;
unsigned long flags;
+ struct task_struct *tcp_rx = NULL;
+ struct task_struct *tcp_tx = NULL;
/*
* @rhport: port number of vhci_hcd
@@ -349,12 +351,35 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
/* Extract socket from fd. */
socket = sockfd_lookup(sockfd, &err);
- if (!socket)
+ if (!socket) {
+ dev_err(dev, "failed to lookup sock");
return -EINVAL;
+ }
+ if (socket->type != SOCK_STREAM) {
+ dev_err(dev, "Expecting SOCK_STREAM - found %d",
+ socket->type);
+ sockfd_put(socket);
+ return -EINVAL;
+ }
+
+ /* create threads before locking */
+ tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
+ if (IS_ERR(tcp_rx)) {
+ sockfd_put(socket);
+ return -EINVAL;
+ }
+ tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
+ if (IS_ERR(tcp_tx)) {
+ kthread_stop(tcp_rx);
+ sockfd_put(socket);
+ return -EINVAL;
+ }
- /* now need lock until setting vdev status as used */
+ /* get task structs now */
+ get_task_struct(tcp_rx);
+ get_task_struct(tcp_tx);
- /* begin a lock */
+ /* now begin lock until setting vdev status set */
spin_lock_irqsave(&vhci->lock, flags);
spin_lock(&vdev->ud.lock);
@@ -364,6 +389,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
spin_unlock_irqrestore(&vhci->lock, flags);
sockfd_put(socket);
+ kthread_stop_put(tcp_rx);
+ kthread_stop_put(tcp_tx);
dev_err(dev, "port %d already used\n", rhport);
/*
@@ -382,6 +409,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
vdev->speed = speed;
vdev->ud.sockfd = sockfd;
vdev->ud.tcp_socket = socket;
+ vdev->ud.tcp_rx = tcp_rx;
+ vdev->ud.tcp_tx = tcp_tx;
vdev->ud.status = VDEV_ST_NOTASSIGNED;
usbip_kcov_handle_init(&vdev->ud);
@@ -389,8 +418,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
spin_unlock_irqrestore(&vhci->lock, flags);
/* end the lock */
- vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
- vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
+ wake_up_process(vdev->ud.tcp_rx);
+ wake_up_process(vdev->ud.tcp_tx);
rh_port_connect(vdev, speed);
diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c
index 100f680c572a..7383a543c6d1 100644
--- a/drivers/usb/usbip/vudc_sysfs.c
+++ b/drivers/usb/usbip/vudc_sysfs.c
@@ -90,8 +90,9 @@ unlock:
}
static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
-static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr,
- const char *in, size_t count)
+static ssize_t usbip_sockfd_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *in, size_t count)
{
struct vudc *udc = (struct vudc *) dev_get_drvdata(dev);
int rv;
@@ -100,6 +101,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
struct socket *socket;
unsigned long flags;
int ret;
+ struct task_struct *tcp_rx = NULL;
+ struct task_struct *tcp_tx = NULL;
rv = kstrtoint(in, 0, &sockfd);
if (rv != 0)
@@ -138,24 +141,54 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
goto unlock_ud;
}
- udc->ud.tcp_socket = socket;
+ if (socket->type != SOCK_STREAM) {
+ dev_err(dev, "Expecting SOCK_STREAM - found %d",
+ socket->type);
+ ret = -EINVAL;
+ goto sock_err;
+ }
+ /* unlock and create threads and get tasks */
spin_unlock_irq(&udc->ud.lock);
spin_unlock_irqrestore(&udc->lock, flags);
- udc->ud.tcp_rx = kthread_get_run(&v_rx_loop,
- &udc->ud, "vudc_rx");
- udc->ud.tcp_tx = kthread_get_run(&v_tx_loop,
- &udc->ud, "vudc_tx");
+ tcp_rx = kthread_create(&v_rx_loop, &udc->ud, "vudc_rx");
+ if (IS_ERR(tcp_rx)) {
+ sockfd_put(socket);
+ return -EINVAL;
+ }
+ tcp_tx = kthread_create(&v_tx_loop, &udc->ud, "vudc_tx");
+ if (IS_ERR(tcp_tx)) {
+ kthread_stop(tcp_rx);
+ sockfd_put(socket);
+ return -EINVAL;
+ }
+
+ /* get task structs now */
+ get_task_struct(tcp_rx);
+ get_task_struct(tcp_tx);
+ /* lock and update udc->ud state */
spin_lock_irqsave(&udc->lock, flags);
spin_lock_irq(&udc->ud.lock);
+
+ udc->ud.tcp_socket = socket;
+ udc->ud.tcp_rx = tcp_rx;
+ udc->ud.tcp_tx = tcp_tx;
udc->ud.status = SDEV_ST_USED;
+
spin_unlock_irq(&udc->ud.lock);
ktime_get_ts64(&udc->start_time);
v_start_timer(udc);
udc->connected = 1;
+
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ wake_up_process(udc->ud.tcp_rx);
+ wake_up_process(udc->ud.tcp_tx);
+ return count;
+
} else {
if (!udc->connected) {
dev_err(dev, "Device not connected");
@@ -177,6 +210,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a
return count;
+sock_err:
+ sockfd_put(socket);
unlock_ud:
spin_unlock_irq(&udc->ud.lock);
unlock:
diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c
index 7c8bbfcf6c3e..d555a6a5d1ba 100644
--- a/drivers/vdpa/ifcvf/ifcvf_main.c
+++ b/drivers/vdpa/ifcvf/ifcvf_main.c
@@ -431,8 +431,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
adapter = vdpa_alloc_device(struct ifcvf_adapter, vdpa,
- dev, &ifc_vdpa_ops,
- IFCVF_MAX_QUEUE_PAIRS * 2, NULL);
+ dev, &ifc_vdpa_ops, NULL);
if (adapter == NULL) {
IFCVF_ERR(pdev, "Failed to allocate vDPA structure");
return -ENOMEM;
@@ -456,7 +455,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
for (i = 0; i < IFCVF_MAX_QUEUE_PAIRS * 2; i++)
vf->vring[i].irq = -EINVAL;
- ret = vdpa_register_device(&adapter->vdpa);
+ ret = vdpa_register_device(&adapter->vdpa, IFCVF_MAX_QUEUE_PAIRS * 2);
if (ret) {
IFCVF_ERR(pdev, "Failed to register ifcvf to vdpa bus");
goto err;
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 10e9b09932eb..71397fdafa6a 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1982,7 +1982,7 @@ static int mlx5v_probe(struct auxiliary_device *adev,
max_vqs = min_t(u32, max_vqs, MLX5_MAX_SUPPORTED_VQS);
ndev = vdpa_alloc_device(struct mlx5_vdpa_net, mvdev.vdev, mdev->device, &mlx5_vdpa_ops,
- 2 * mlx5_vdpa_max_qps(max_vqs), NULL);
+ NULL);
if (IS_ERR(ndev))
return PTR_ERR(ndev);
@@ -2009,7 +2009,7 @@ static int mlx5v_probe(struct auxiliary_device *adev,
if (err)
goto err_res;
- err = vdpa_register_device(&mvdev->vdev);
+ err = vdpa_register_device(&mvdev->vdev, 2 * mlx5_vdpa_max_qps(max_vqs));
if (err)
goto err_reg;
diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
index da67f07e24fd..5cffce67cab0 100644
--- a/drivers/vdpa/vdpa.c
+++ b/drivers/vdpa/vdpa.c
@@ -69,7 +69,6 @@ static void vdpa_release_dev(struct device *d)
* initialized but before registered.
* @parent: the parent device
* @config: the bus operations that is supported by this device
- * @nvqs: number of virtqueues supported by this device
* @size: size of the parent structure that contains private data
* @name: name of the vdpa device; optional.
*
@@ -81,7 +80,7 @@ static void vdpa_release_dev(struct device *d)
*/
struct vdpa_device *__vdpa_alloc_device(struct device *parent,
const struct vdpa_config_ops *config,
- int nvqs, size_t size, const char *name)
+ size_t size, const char *name)
{
struct vdpa_device *vdev;
int err = -EINVAL;
@@ -107,7 +106,6 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
vdev->index = err;
vdev->config = config;
vdev->features_valid = false;
- vdev->nvqs = nvqs;
if (name)
err = dev_set_name(&vdev->dev, "%s", name);
@@ -136,10 +134,12 @@ static int vdpa_name_match(struct device *dev, const void *data)
return (strcmp(dev_name(&vdev->dev), data) == 0);
}
-static int __vdpa_register_device(struct vdpa_device *vdev)
+static int __vdpa_register_device(struct vdpa_device *vdev, int nvqs)
{
struct device *dev;
+ vdev->nvqs = nvqs;
+
lockdep_assert_held(&vdpa_dev_mutex);
dev = bus_find_device(&vdpa_bus, NULL, dev_name(&vdev->dev), vdpa_name_match);
if (dev) {
@@ -155,15 +155,16 @@ static int __vdpa_register_device(struct vdpa_device *vdev)
* Caller must invoke this routine in the management device dev_add()
* callback after setting up valid mgmtdev for this vdpa device.
* @vdev: the vdpa device to be registered to vDPA bus
+ * @nvqs: number of virtqueues supported by this device
*
* Returns an error when fail to add device to vDPA bus
*/
-int _vdpa_register_device(struct vdpa_device *vdev)
+int _vdpa_register_device(struct vdpa_device *vdev, int nvqs)
{
if (!vdev->mdev)
return -EINVAL;
- return __vdpa_register_device(vdev);
+ return __vdpa_register_device(vdev, nvqs);
}
EXPORT_SYMBOL_GPL(_vdpa_register_device);
@@ -171,15 +172,16 @@ EXPORT_SYMBOL_GPL(_vdpa_register_device);
* vdpa_register_device - register a vDPA device
* Callers must have a succeed call of vdpa_alloc_device() before.
* @vdev: the vdpa device to be registered to vDPA bus
+ * @nvqs: number of virtqueues supported by this device
*
* Returns an error when fail to add to vDPA bus
*/
-int vdpa_register_device(struct vdpa_device *vdev)
+int vdpa_register_device(struct vdpa_device *vdev, int nvqs)
{
int err;
mutex_lock(&vdpa_dev_mutex);
- err = __vdpa_register_device(vdev);
+ err = __vdpa_register_device(vdev, nvqs);
mutex_unlock(&vdpa_dev_mutex);
return err;
}
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index d5942842432d..5b6b2f87d40c 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -235,7 +235,7 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
ops = &vdpasim_config_ops;
vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops,
- dev_attr->nvqs, dev_attr->name);
+ dev_attr->name);
if (!vdpasim)
goto err_alloc;
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
index d344c5b7c914..a1ab6163f7d1 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
@@ -110,8 +110,7 @@ out:
static void vdpasim_net_get_config(struct vdpasim *vdpasim, void *config)
{
- struct virtio_net_config *net_config =
- (struct virtio_net_config *)config;
+ struct virtio_net_config *net_config = config;
net_config->mtu = cpu_to_vdpasim16(vdpasim, 1500);
net_config->status = cpu_to_vdpasim16(vdpasim, VIRTIO_NET_S_LINK_UP);
@@ -147,7 +146,7 @@ static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name)
if (IS_ERR(simdev))
return PTR_ERR(simdev);
- ret = _vdpa_register_device(&simdev->vdpa);
+ ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_NET_VQ_NUM);
if (ret)
goto reg_err;
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 5533df91b257..67d0bf4efa16 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -21,8 +21,8 @@ config VFIO_VIRQFD
menuconfig VFIO
tristate "VFIO Non-Privileged userspace driver framework"
- depends on IOMMU_API
- select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM || ARM64)
+ select IOMMU_API
+ select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64)
help
VFIO provides a framework for secure userspace device drivers.
See Documentation/driver-api/vfio.rst for more details.
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index dc1a3c44f2c6..ab341108a0be 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config VFIO_PLATFORM
tristate "VFIO support for platform devices"
- depends on VFIO && EVENTFD && (ARM || ARM64)
+ depends on VFIO && EVENTFD && (ARM || ARM64 || COMPILE_TEST)
select VFIO_VIRQFD
help
Support for platform devices with VFIO. This is required to make
@@ -12,7 +12,7 @@ config VFIO_PLATFORM
config VFIO_AMBA
tristate "VFIO support for AMBA devices"
- depends on VFIO_PLATFORM && ARM_AMBA
+ depends on VFIO_PLATFORM && (ARM_AMBA || COMPILE_TEST)
help
Support for ARM AMBA devices with VFIO. This is required to make
use of ARM AMBA devices present on the system using the VFIO
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 4bb162c1d649..be444407664a 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -189,7 +189,7 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
}
static struct rb_node *vfio_find_dma_first_node(struct vfio_iommu *iommu,
- dma_addr_t start, size_t size)
+ dma_addr_t start, u64 size)
{
struct rb_node *res = NULL;
struct rb_node *node = iommu->dma_list.rb_node;
@@ -785,7 +785,12 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
return -ENODEV;
ret = vaddr_get_pfns(mm, vaddr, 1, dma->prot, pfn_base, pages);
- if (ret == 1 && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) {
+ if (ret != 1)
+ goto out;
+
+ ret = 0;
+
+ if (do_accounting && !is_invalid_reserved_pfn(*pfn_base)) {
ret = vfio_lock_acct(dma, 1, true);
if (ret) {
put_pfn(*pfn_base, dma->prot);
@@ -797,6 +802,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
}
}
+out:
mmput(mm);
return ret;
}
@@ -1288,7 +1294,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
int ret = -EINVAL, retries = 0;
unsigned long pgshift;
dma_addr_t iova = unmap->iova;
- unsigned long size = unmap->size;
+ u64 size = unmap->size;
bool unmap_all = unmap->flags & VFIO_DMA_UNMAP_FLAG_ALL;
bool invalidate_vaddr = unmap->flags & VFIO_DMA_UNMAP_FLAG_VADDR;
struct rb_node *n, *first_n;
@@ -1304,14 +1310,12 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
if (unmap_all) {
if (iova || size)
goto unlock;
- size = SIZE_MAX;
- } else if (!size || size & (pgsize - 1)) {
+ size = U64_MAX;
+ } else if (!size || size & (pgsize - 1) ||
+ iova + size - 1 < iova || size > SIZE_MAX) {
goto unlock;
}
- if (iova + size - 1 < iova || size > SIZE_MAX)
- goto unlock;
-
/* When dirty tracking is enabled, allow only min supported pgsize */
if ((unmap->flags & VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP) &&
(!iommu->dirty_page_tracking || (bitmap->pgsize != pgsize))) {
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index ef688c8c0e0e..e0a27e336293 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -308,8 +308,10 @@ static long vhost_vdpa_get_vring_num(struct vhost_vdpa *v, u16 __user *argp)
static void vhost_vdpa_config_put(struct vhost_vdpa *v)
{
- if (v->config_ctx)
+ if (v->config_ctx) {
eventfd_ctx_put(v->config_ctx);
+ v->config_ctx = NULL;
+ }
}
static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
@@ -329,8 +331,12 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
if (!IS_ERR_OR_NULL(ctx))
eventfd_ctx_put(ctx);
- if (IS_ERR(v->config_ctx))
- return PTR_ERR(v->config_ctx);
+ if (IS_ERR(v->config_ctx)) {
+ long ret = PTR_ERR(v->config_ctx);
+
+ v->config_ctx = NULL;
+ return ret;
+ }
v->vdpa->config->set_config_cb(v->vdpa, &cb);
@@ -900,14 +906,10 @@ err:
static void vhost_vdpa_clean_irq(struct vhost_vdpa *v)
{
- struct vhost_virtqueue *vq;
int i;
- for (i = 0; i < v->nvqs; i++) {
- vq = &v->vqs[i];
- if (vq->call_ctx.producer.irq)
- irq_bypass_unregister_producer(&vq->call_ctx.producer);
- }
+ for (i = 0; i < v->nvqs; i++)
+ vhost_vdpa_unsetup_vq_irq(v, i);
}
static int vhost_vdpa_release(struct inode *inode, struct file *filep)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index a262e12c6dc2..5ccb0705beae 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -332,8 +332,8 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->error_ctx = NULL;
vq->kick = NULL;
vq->log_ctx = NULL;
- vhost_reset_is_le(vq);
vhost_disable_cross_endian(vq);
+ vhost_reset_is_le(vq);
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
diff --git a/drivers/video/fbdev/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h
index 551372f9b9aa..465f55beb97f 100644
--- a/drivers/video/fbdev/aty/atyfb.h
+++ b/drivers/video/fbdev/aty/atyfb.h
@@ -287,11 +287,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
#endif
}
-#if defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) || \
-defined (CONFIG_FB_ATY_BACKLIGHT)
extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
-#endif
/*
* DAC operations
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
index e946903a86c2..1aef3d6ebd88 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -133,7 +133,7 @@
#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
#if defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_GENERIC_LCD) || \
-defined(CONFIG_FB_ATY_BACKLIGHT)
+defined(CONFIG_FB_ATY_BACKLIGHT) || defined (CONFIG_PPC_PMAC)
static const u32 lt_lcd_regs[] = {
CNFG_PANEL_LG,
LCD_GEN_CNTL_LG,
@@ -175,8 +175,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par)
return aty_ld_le32(LCD_DATA, par);
}
}
-#else /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) \
- defined(CONFIG_FB_ATY_GENERIC_LCD) */
+#else /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
+ defined(CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
{ }
@@ -184,7 +184,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par)
{
return 0;
}
-#endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
+#endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
+ defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
#ifdef CONFIG_FB_ATY_GENERIC_LCD
/*
diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index 1f6b7c54a1a4..130e12b8652a 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -333,7 +333,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
acrn_ioreq_request_clear(vm);
break;
case ACRN_IOCTL_PM_GET_CPU_STATE:
- if (copy_from_user(&cstate_cmd, (void *)ioctl_param,
+ if (copy_from_user(&cstate_cmd, (void __user *)ioctl_param,
sizeof(cstate_cmd)))
return -EFAULT;
@@ -404,6 +404,14 @@ fail_remove:
}
static DEVICE_ATTR_WO(remove_cpu);
+static umode_t acrn_attr_visible(struct kobject *kobj, struct attribute *a, int n)
+{
+ if (a == &dev_attr_remove_cpu.attr)
+ return IS_ENABLED(CONFIG_HOTPLUG_CPU) ? a->mode : 0;
+
+ return a->mode;
+}
+
static struct attribute *acrn_attrs[] = {
&dev_attr_remove_cpu.attr,
NULL
@@ -411,6 +419,7 @@ static struct attribute *acrn_attrs[] = {
static struct attribute_group acrn_attr_group = {
.attrs = acrn_attrs,
+ .is_visible = acrn_attr_visible,
};
static const struct attribute_group *acrn_attr_groups[] = {
diff --git a/drivers/virt/acrn/irqfd.c b/drivers/virt/acrn/irqfd.c
index a8766d528e29..df5184979b28 100644
--- a/drivers/virt/acrn/irqfd.c
+++ b/drivers/virt/acrn/irqfd.c
@@ -112,7 +112,7 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
{
struct eventfd_ctx *eventfd = NULL;
struct hsm_irqfd *irqfd, *tmp;
- unsigned int events;
+ __poll_t events;
struct fd f;
int ret = 0;
@@ -158,9 +158,9 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
mutex_unlock(&vm->irqfds_lock);
/* Check the pending event in this stage */
- events = f.file->f_op->poll(f.file, &irqfd->pt);
+ events = vfs_poll(f.file, &irqfd->pt);
- if (events & POLLIN)
+ if (events & EPOLLIN)
acrn_irqfd_inject(irqfd);
fdput(f);
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 42e09cc1b8ac..4b15c00c0a0a 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -141,15 +141,14 @@ void virtio_config_changed(struct virtio_device *dev)
}
EXPORT_SYMBOL_GPL(virtio_config_changed);
-void virtio_config_disable(struct virtio_device *dev)
+static void virtio_config_disable(struct virtio_device *dev)
{
spin_lock_irq(&dev->config_lock);
dev->config_enabled = false;
spin_unlock_irq(&dev->config_lock);
}
-EXPORT_SYMBOL_GPL(virtio_config_disable);
-void virtio_config_enable(struct virtio_device *dev)
+static void virtio_config_enable(struct virtio_device *dev)
{
spin_lock_irq(&dev->config_lock);
dev->config_enabled = true;
@@ -158,7 +157,6 @@ void virtio_config_enable(struct virtio_device *dev)
dev->config_change_pending = false;
spin_unlock_irq(&dev->config_lock);
}
-EXPORT_SYMBOL_GPL(virtio_config_enable);
void virtio_add_status(struct virtio_device *dev, unsigned int status)
{
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a286d22b6551..56128b9c46eb 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -548,8 +548,7 @@ static void virtio_mmio_release_dev(struct device *_d)
{
struct virtio_device *vdev =
container_of(_d, struct virtio_device, dev);
- struct virtio_mmio_device *vm_dev =
- container_of(vdev, struct virtio_mmio_device, vdev);
+ struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
struct platform_device *pdev = vm_dev->pdev;
devm_kfree(&pdev->dev, vm_dev);
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 9867a3a936df..688b112e712b 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -273,7 +273,6 @@ module_exit(cpu5wdt_exit_module);
MODULE_AUTHOR("Heiko Ronsdorf <hero@ihg.uni-duisburg.de>");
MODULE_DESCRIPTION("sma cpu5 watchdog driver");
-MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
MODULE_LICENSE("GPL");
module_param_hw(port, int, ioport, 0);
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 808eeb4779e4..1eafe0b4d71c 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -172,7 +172,6 @@ MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs");
MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
MODULE_DESCRIPTION("Hardware watchdog driver for Sun Microsystems CP1400/1500");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("watchdog");
static void cpwd_writew(u16 val, void __iomem *addr)
{
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 7008596a575f..747e346ed06c 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -46,7 +46,6 @@
MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO");
-MODULE_SUPPORTED_DEVICE("watchdog");
MODULE_LICENSE("GPL");
#define DRIVER_NAME "riowd"
diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c
index da87f3a1e351..b8f2f971c2f0 100644
--- a/drivers/xen/events/events_2l.c
+++ b/drivers/xen/events/events_2l.c
@@ -47,6 +47,11 @@ static unsigned evtchn_2l_max_channels(void)
return EVTCHN_2L_NR_CHANNELS;
}
+static void evtchn_2l_remove(evtchn_port_t evtchn, unsigned int cpu)
+{
+ clear_bit(evtchn, BM(per_cpu(cpu_evtchn_mask, cpu)));
+}
+
static void evtchn_2l_bind_to_cpu(evtchn_port_t evtchn, unsigned int cpu,
unsigned int old_cpu)
{
@@ -72,12 +77,6 @@ static bool evtchn_2l_is_pending(evtchn_port_t port)
return sync_test_bit(port, BM(&s->evtchn_pending[0]));
}
-static bool evtchn_2l_test_and_set_mask(evtchn_port_t port)
-{
- struct shared_info *s = HYPERVISOR_shared_info;
- return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0]));
-}
-
static void evtchn_2l_mask(evtchn_port_t port)
{
struct shared_info *s = HYPERVISOR_shared_info;
@@ -355,18 +354,27 @@ static void evtchn_2l_resume(void)
EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
}
+static int evtchn_2l_percpu_deinit(unsigned int cpu)
+{
+ memset(per_cpu(cpu_evtchn_mask, cpu), 0, sizeof(xen_ulong_t) *
+ EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
+
+ return 0;
+}
+
static const struct evtchn_ops evtchn_ops_2l = {
.max_channels = evtchn_2l_max_channels,
.nr_channels = evtchn_2l_max_channels,
+ .remove = evtchn_2l_remove,
.bind_to_cpu = evtchn_2l_bind_to_cpu,
.clear_pending = evtchn_2l_clear_pending,
.set_pending = evtchn_2l_set_pending,
.is_pending = evtchn_2l_is_pending,
- .test_and_set_mask = evtchn_2l_test_and_set_mask,
.mask = evtchn_2l_mask,
.unmask = evtchn_2l_unmask,
.handle_events = evtchn_2l_handle_events,
.resume = evtchn_2l_resume,
+ .percpu_deinit = evtchn_2l_percpu_deinit,
};
void __init xen_evtchn_2l_init(void)
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index adb7260e94b2..8236e2364eeb 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -98,13 +98,19 @@ struct irq_info {
short refcnt;
u8 spurious_cnt;
u8 is_accounted;
- enum xen_irq_type type; /* type */
+ short type; /* type: IRQT_* */
+ u8 mask_reason; /* Why is event channel masked */
+#define EVT_MASK_REASON_EXPLICIT 0x01
+#define EVT_MASK_REASON_TEMPORARY 0x02
+#define EVT_MASK_REASON_EOI_PENDING 0x04
+ u8 is_active; /* Is event just being handled? */
unsigned irq;
evtchn_port_t evtchn; /* event channel */
unsigned short cpu; /* cpu bound */
unsigned short eoi_cpu; /* EOI must happen on this cpu-1 */
unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */
u64 eoi_time; /* Time in jiffies when to EOI. */
+ spinlock_t lock;
union {
unsigned short virq;
@@ -154,6 +160,7 @@ static DEFINE_RWLOCK(evtchn_rwlock);
* evtchn_rwlock
* IRQ-desc lock
* percpu eoi_list_lock
+ * irq_info->lock
*/
static LIST_HEAD(xen_irq_list_head);
@@ -304,6 +311,8 @@ static int xen_irq_info_common_setup(struct irq_info *info,
info->irq = irq;
info->evtchn = evtchn;
info->cpu = cpu;
+ info->mask_reason = EVT_MASK_REASON_EXPLICIT;
+ spin_lock_init(&info->lock);
ret = set_evtchn_to_irq(evtchn, irq);
if (ret < 0)
@@ -377,6 +386,7 @@ static int xen_irq_info_pirq_setup(unsigned irq,
static void xen_irq_info_cleanup(struct irq_info *info)
{
set_evtchn_to_irq(info->evtchn, -1);
+ xen_evtchn_port_remove(info->evtchn, info->cpu);
info->evtchn = 0;
channels_on_cpu_dec(info);
}
@@ -458,6 +468,34 @@ unsigned int cpu_from_evtchn(evtchn_port_t evtchn)
return ret;
}
+static void do_mask(struct irq_info *info, u8 reason)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock, flags);
+
+ if (!info->mask_reason)
+ mask_evtchn(info->evtchn);
+
+ info->mask_reason |= reason;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
+static void do_unmask(struct irq_info *info, u8 reason)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock, flags);
+
+ info->mask_reason &= ~reason;
+
+ if (!info->mask_reason)
+ unmask_evtchn(info->evtchn);
+
+ spin_unlock_irqrestore(&info->lock, flags);
+}
+
#ifdef CONFIG_X86
static bool pirq_check_eoi_map(unsigned irq)
{
@@ -604,7 +642,7 @@ static void xen_irq_lateeoi_locked(struct irq_info *info, bool spurious)
}
info->eoi_time = 0;
- unmask_evtchn(evtchn);
+ do_unmask(info, EVT_MASK_REASON_EOI_PENDING);
}
static void xen_irq_lateeoi_worker(struct work_struct *work)
@@ -773,6 +811,12 @@ static void xen_evtchn_close(evtchn_port_t port)
BUG();
}
+static void event_handler_exit(struct irq_info *info)
+{
+ smp_store_release(&info->is_active, 0);
+ clear_evtchn(info->evtchn);
+}
+
static void pirq_query_unmask(int irq)
{
struct physdev_irq_status_query irq_status;
@@ -791,14 +835,15 @@ static void pirq_query_unmask(int irq)
static void eoi_pirq(struct irq_data *data)
{
- evtchn_port_t evtchn = evtchn_from_irq(data->irq);
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) };
int rc = 0;
if (!VALID_EVTCHN(evtchn))
return;
- clear_evtchn(evtchn);
+ event_handler_exit(info);
if (pirq_needs_eoi(data->irq)) {
rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
@@ -849,7 +894,8 @@ static unsigned int __startup_pirq(unsigned int irq)
goto err;
out:
- unmask_evtchn(evtchn);
+ do_unmask(info, EVT_MASK_REASON_EXPLICIT);
+
eoi_pirq(irq_get_irq_data(irq));
return 0;
@@ -876,7 +922,7 @@ static void shutdown_pirq(struct irq_data *data)
if (!VALID_EVTCHN(evtchn))
return;
- mask_evtchn(evtchn);
+ do_mask(info, EVT_MASK_REASON_EXPLICIT);
xen_evtchn_close(evtchn);
xen_irq_info_cleanup(info);
}
@@ -1628,6 +1674,8 @@ void handle_irq_for_port(evtchn_port_t port, struct evtchn_loop_ctrl *ctrl)
}
info = info_for_irq(irq);
+ if (xchg_acquire(&info->is_active, 1))
+ return;
dev = (info->type == IRQT_EVTCHN) ? info->u.interdomain : NULL;
if (dev)
@@ -1720,10 +1768,10 @@ void rebind_evtchn_irq(evtchn_port_t evtchn, int irq)
}
/* Rebind an evtchn so that it gets delivered to a specific cpu */
-static int xen_rebind_evtchn_to_cpu(evtchn_port_t evtchn, unsigned int tcpu)
+static int xen_rebind_evtchn_to_cpu(struct irq_info *info, unsigned int tcpu)
{
struct evtchn_bind_vcpu bind_vcpu;
- int masked;
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
if (!VALID_EVTCHN(evtchn))
return -1;
@@ -1739,7 +1787,7 @@ static int xen_rebind_evtchn_to_cpu(evtchn_port_t evtchn, unsigned int tcpu)
* Mask the event while changing the VCPU binding to prevent
* it being delivered on an unexpected VCPU.
*/
- masked = test_and_set_mask(evtchn);
+ do_mask(info, EVT_MASK_REASON_TEMPORARY);
/*
* If this fails, it usually just indicates that we're dealing with a
@@ -1749,8 +1797,7 @@ static int xen_rebind_evtchn_to_cpu(evtchn_port_t evtchn, unsigned int tcpu)
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
bind_evtchn_to_cpu(evtchn, tcpu, false);
- if (!masked)
- unmask_evtchn(evtchn);
+ do_unmask(info, EVT_MASK_REASON_TEMPORARY);
return 0;
}
@@ -1789,7 +1836,7 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
unsigned int tcpu = select_target_cpu(dest);
int ret;
- ret = xen_rebind_evtchn_to_cpu(evtchn_from_irq(data->irq), tcpu);
+ ret = xen_rebind_evtchn_to_cpu(info_for_irq(data->irq), tcpu);
if (!ret)
irq_data_update_effective_affinity(data, cpumask_of(tcpu));
@@ -1798,28 +1845,29 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
static void enable_dynirq(struct irq_data *data)
{
- evtchn_port_t evtchn = evtchn_from_irq(data->irq);
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
if (VALID_EVTCHN(evtchn))
- unmask_evtchn(evtchn);
+ do_unmask(info, EVT_MASK_REASON_EXPLICIT);
}
static void disable_dynirq(struct irq_data *data)
{
- evtchn_port_t evtchn = evtchn_from_irq(data->irq);
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
if (VALID_EVTCHN(evtchn))
- mask_evtchn(evtchn);
+ do_mask(info, EVT_MASK_REASON_EXPLICIT);
}
static void ack_dynirq(struct irq_data *data)
{
- evtchn_port_t evtchn = evtchn_from_irq(data->irq);
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
- if (!VALID_EVTCHN(evtchn))
- return;
-
- clear_evtchn(evtchn);
+ if (VALID_EVTCHN(evtchn))
+ event_handler_exit(info);
}
static void mask_ack_dynirq(struct irq_data *data)
@@ -1828,18 +1876,39 @@ static void mask_ack_dynirq(struct irq_data *data)
ack_dynirq(data);
}
+static void lateeoi_ack_dynirq(struct irq_data *data)
+{
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
+
+ if (VALID_EVTCHN(evtchn)) {
+ do_mask(info, EVT_MASK_REASON_EOI_PENDING);
+ event_handler_exit(info);
+ }
+}
+
+static void lateeoi_mask_ack_dynirq(struct irq_data *data)
+{
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
+
+ if (VALID_EVTCHN(evtchn)) {
+ do_mask(info, EVT_MASK_REASON_EXPLICIT);
+ event_handler_exit(info);
+ }
+}
+
static int retrigger_dynirq(struct irq_data *data)
{
- evtchn_port_t evtchn = evtchn_from_irq(data->irq);
- int masked;
+ struct irq_info *info = info_for_irq(data->irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
if (!VALID_EVTCHN(evtchn))
return 0;
- masked = test_and_set_mask(evtchn);
+ do_mask(info, EVT_MASK_REASON_TEMPORARY);
set_evtchn(evtchn);
- if (!masked)
- unmask_evtchn(evtchn);
+ do_unmask(info, EVT_MASK_REASON_TEMPORARY);
return 1;
}
@@ -1938,10 +2007,11 @@ static void restore_cpu_ipis(unsigned int cpu)
/* Clear an irq's pending state, in preparation for polling on it */
void xen_clear_irq_pending(int irq)
{
- evtchn_port_t evtchn = evtchn_from_irq(irq);
+ struct irq_info *info = info_for_irq(irq);
+ evtchn_port_t evtchn = info ? info->evtchn : 0;
if (VALID_EVTCHN(evtchn))
- clear_evtchn(evtchn);
+ event_handler_exit(info);
}
EXPORT_SYMBOL(xen_clear_irq_pending);
void xen_set_irq_pending(int irq)
@@ -2053,8 +2123,8 @@ static struct irq_chip xen_lateeoi_chip __read_mostly = {
.irq_mask = disable_dynirq,
.irq_unmask = enable_dynirq,
- .irq_ack = mask_ack_dynirq,
- .irq_mask_ack = mask_ack_dynirq,
+ .irq_ack = lateeoi_ack_dynirq,
+ .irq_mask_ack = lateeoi_mask_ack_dynirq,
.irq_set_affinity = set_affinity_irq,
.irq_retrigger = retrigger_dynirq,
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index b234f1766810..ad9fe51d3fb3 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -209,12 +209,6 @@ static bool evtchn_fifo_is_pending(evtchn_port_t port)
return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
}
-static bool evtchn_fifo_test_and_set_mask(evtchn_port_t port)
-{
- event_word_t *word = event_word_from_port(port);
- return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
-}
-
static void evtchn_fifo_mask(evtchn_port_t port)
{
event_word_t *word = event_word_from_port(port);
@@ -423,7 +417,6 @@ static const struct evtchn_ops evtchn_ops_fifo = {
.clear_pending = evtchn_fifo_clear_pending,
.set_pending = evtchn_fifo_set_pending,
.is_pending = evtchn_fifo_is_pending,
- .test_and_set_mask = evtchn_fifo_test_and_set_mask,
.mask = evtchn_fifo_mask,
.unmask = evtchn_fifo_unmask,
.handle_events = evtchn_fifo_handle_events,
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h
index 0a97c0549db7..4d3398eff9cd 100644
--- a/drivers/xen/events/events_internal.h
+++ b/drivers/xen/events/events_internal.h
@@ -14,13 +14,13 @@ struct evtchn_ops {
unsigned (*nr_channels)(void);
int (*setup)(evtchn_port_t port);
+ void (*remove)(evtchn_port_t port, unsigned int cpu);
void (*bind_to_cpu)(evtchn_port_t evtchn, unsigned int cpu,
unsigned int old_cpu);
void (*clear_pending)(evtchn_port_t port);
void (*set_pending)(evtchn_port_t port);
bool (*is_pending)(evtchn_port_t port);
- bool (*test_and_set_mask)(evtchn_port_t port);
void (*mask)(evtchn_port_t port);
void (*unmask)(evtchn_port_t port);
@@ -54,6 +54,13 @@ static inline int xen_evtchn_port_setup(evtchn_port_t evtchn)
return 0;
}
+static inline void xen_evtchn_port_remove(evtchn_port_t evtchn,
+ unsigned int cpu)
+{
+ if (evtchn_ops->remove)
+ evtchn_ops->remove(evtchn, cpu);
+}
+
static inline void xen_evtchn_port_bind_to_cpu(evtchn_port_t evtchn,
unsigned int cpu,
unsigned int old_cpu)
@@ -76,11 +83,6 @@ static inline bool test_evtchn(evtchn_port_t port)
return evtchn_ops->is_pending(port);
}
-static inline bool test_and_set_mask(evtchn_port_t port)
-{
- return evtchn_ops->test_and_set_mask(port);
-}
-
static inline void mask_evtchn(evtchn_port_t port)
{
return evtchn_ops->mask(port);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 5447c5156b2e..f01d58c7a042 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -133,20 +133,26 @@ struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count,
if (NULL == add)
return NULL;
- add->grants = kvcalloc(count, sizeof(add->grants[0]), GFP_KERNEL);
- add->map_ops = kvcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
- add->unmap_ops = kvcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
- add->kmap_ops = kvcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
- add->kunmap_ops = kvcalloc(count,
- sizeof(add->kunmap_ops[0]), GFP_KERNEL);
+ add->grants = kvmalloc_array(count, sizeof(add->grants[0]),
+ GFP_KERNEL);
+ add->map_ops = kvmalloc_array(count, sizeof(add->map_ops[0]),
+ GFP_KERNEL);
+ add->unmap_ops = kvmalloc_array(count, sizeof(add->unmap_ops[0]),
+ GFP_KERNEL);
add->pages = kvcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
if (NULL == add->grants ||
NULL == add->map_ops ||
NULL == add->unmap_ops ||
- NULL == add->kmap_ops ||
- NULL == add->kunmap_ops ||
NULL == add->pages)
goto err;
+ if (use_ptemod) {
+ add->kmap_ops = kvmalloc_array(count, sizeof(add->kmap_ops[0]),
+ GFP_KERNEL);
+ add->kunmap_ops = kvmalloc_array(count, sizeof(add->kunmap_ops[0]),
+ GFP_KERNEL);
+ if (NULL == add->kmap_ops || NULL == add->kunmap_ops)
+ goto err;
+ }
#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
add->dma_flags = dma_flags;
@@ -183,10 +189,14 @@ struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count,
goto err;
for (i = 0; i < count; i++) {
- add->map_ops[i].handle = -1;
- add->unmap_ops[i].handle = -1;
- add->kmap_ops[i].handle = -1;
- add->kunmap_ops[i].handle = -1;
+ add->grants[i].domid = DOMID_INVALID;
+ add->grants[i].ref = INVALID_GRANT_REF;
+ add->map_ops[i].handle = INVALID_GRANT_HANDLE;
+ add->unmap_ops[i].handle = INVALID_GRANT_HANDLE;
+ if (use_ptemod) {
+ add->kmap_ops[i].handle = INVALID_GRANT_HANDLE;
+ add->kunmap_ops[i].handle = INVALID_GRANT_HANDLE;
+ }
}
add->index = 0;
@@ -274,7 +284,7 @@ static int find_grant_ptes(pte_t *pte, unsigned long addr, void *data)
map->grants[pgnr].ref,
map->grants[pgnr].domid);
gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, flags,
- -1 /* handle */);
+ INVALID_GRANT_HANDLE);
return 0;
}
@@ -292,7 +302,7 @@ int gntdev_map_grant_pages(struct gntdev_grant_map *map)
if (!use_ptemod) {
/* Note: it could already be mapped */
- if (map->map_ops[0].handle != -1)
+ if (map->map_ops[0].handle != INVALID_GRANT_HANDLE)
return 0;
for (i = 0; i < map->count; i++) {
unsigned long addr = (unsigned long)
@@ -301,7 +311,7 @@ int gntdev_map_grant_pages(struct gntdev_grant_map *map)
map->grants[i].ref,
map->grants[i].domid);
gnttab_set_unmap_op(&map->unmap_ops[i], addr,
- map->flags, -1 /* handle */);
+ map->flags, INVALID_GRANT_HANDLE);
}
} else {
/*
@@ -327,13 +337,13 @@ int gntdev_map_grant_pages(struct gntdev_grant_map *map)
map->grants[i].ref,
map->grants[i].domid);
gnttab_set_unmap_op(&map->kunmap_ops[i], address,
- flags, -1);
+ flags, INVALID_GRANT_HANDLE);
}
}
pr_debug("map %d+%d\n", map->index, map->count);
- err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
- map->pages, map->count);
+ err = gnttab_map_refs(map->map_ops, map->kmap_ops, map->pages,
+ map->count);
for (i = 0; i < map->count; i++) {
if (map->map_ops[i].status == GNTST_okay)
@@ -385,7 +395,7 @@ static int __unmap_grant_pages(struct gntdev_grant_map *map, int offset,
pr_debug("unmap handle=%d st=%d\n",
map->unmap_ops[offset+i].handle,
map->unmap_ops[offset+i].status);
- map->unmap_ops[offset+i].handle = -1;
+ map->unmap_ops[offset+i].handle = INVALID_GRANT_HANDLE;
}
return err;
}
@@ -401,13 +411,15 @@ static int unmap_grant_pages(struct gntdev_grant_map *map, int offset,
* already unmapped some of the grants. Only unmap valid ranges.
*/
while (pages && !err) {
- while (pages && map->unmap_ops[offset].handle == -1) {
+ while (pages &&
+ map->unmap_ops[offset].handle == INVALID_GRANT_HANDLE) {
offset++;
pages--;
}
range = 0;
while (range < pages) {
- if (map->unmap_ops[offset+range].handle == -1)
+ if (map->unmap_ops[offset + range].handle ==
+ INVALID_GRANT_HANDLE)
break;
range++;
}